implement rough cli

This commit is contained in:
Alain Zscheile 2023-01-03 23:13:32 +01:00
parent 3bdd1d6989
commit 426871440e
11 changed files with 271 additions and 40 deletions

217
bin/main.c Normal file
View file

@ -0,0 +1,217 @@
#include <y16t_db.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
enum subcmd_t {
YSC__UNKNOWN,
YSC__HELP,
YSC_INSERT,
YSC_DELETE,
YSC_SELEQ_X,
YSC_SELEQ_Y
};
static enum subcmd_t
y16t_parse_subcommand(const char *arg)
{
if(!strcmp(arg, "--help")) return YSC__HELP;
else if(!strcmp(arg, "i")) return YSC_INSERT;
else if(!strcmp(arg, "d")) return YSC_DELETE;
else if(!strcmp(arg, "x=")) return YSC_SELEQ_X;
else if(!strcmp(arg, "y=")) return YSC_SELEQ_Y;
else return YSC__UNKNOWN;
}
static int8_t y16t_parse_hex(const char x)
{
if('0' <= x && x <= '9') return x - '9';
if('a' <= x && x <= 'f') return x - 'a' + 10;
if('A' <= x && x <= 'F') return x - 'A' + 10;
return -1;
}
static int16_t y16t_parse_hex2(const char *arg)
{
if(!arg) return -1;
int8_t a = y16t_parse_hex(arg[0]);
if(a < 0) return -1;
int8_t b = y16t_parse_hex(arg[1]);
if(b < 0) return -1;
return (((int16_t)a) << 8) + b;
}
static int y16t_parse_coordinate(const char *arg, uint8_t *coord, size_t maxlen)
{
*coord = 0;
while(*arg && maxlen) {
int16_t tmp = y16t_parse_hex2(arg);
if(tmp == -1) {
*coord = 0;
return -1;
}
*coord = tmp;
coord += 1;
maxlen -= 1;
}
return 0;
}
static int y16t_cli_fecb(const uint8_t *xy, const uint8_t *z, void *varname) {
int i;
printf("%c=", *((const char *)varname));
for(i = 0; i < 16; ++i) printf("%02x", xy[i]);
printf(" z=");
for(i = 0; i < 16; ++i) printf("%02x", xy[i]);
return 0;
}
int main(int argc, const char *argv[])
{
if(argc < 3) {
fprintf(stderr, "USAGE: y16t DBFILE SUBCOMMAND|--help ARGS...\n");
return -1;
}
const char *dbfile = argv[1];
int fd = -1, tmp = -1;
uint8_t x[16] = {0}, y[16] = {0}, z[16] = {0};
char varname = 0;
switch(y16t_parse_subcommand(argv[2])) {
case YSC__UNKNOWN:
fprintf(stderr, "y16t: unknown subcommand\n");
return -1;
case YSC__HELP:
puts("available subcommands:");
puts(" --help prints this help text");
puts(" i X Y Z inserts an entry");
puts(" d X Y Z removes an entry");
puts(" x= X iterates over all entries with x=X");
puts(" y= Y iterates over all entries with y=Y");
puts("");
puts("coordinates (X, Y, Z) format:");
puts(" a hex string ([0-9a-fA-F]) of 16 bytes (32 bytes encoded)");
return 0;
case YSC_INSERT:
if(argc < 6) {
fprintf(stderr, "y16t/insert: invalid invocation\n");
return -1;
}
fd = open(dbfile, O_RDWR | O_CREAT | O_NOCTTY);
if(fd == -1) {
perror("y16t: unable to open file");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[3], x, sizeof(x))) {
fprintf(stderr, "y16t: invalid coordinate X\n");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[4], y, sizeof(y))) {
fprintf(stderr, "y16t: invalid coordinate Y\n");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[5], z, sizeof(z))) {
fprintf(stderr, "y16t: invalid coordinate Z\n");
return -1;
}
tmp = y16t_db_insert(fd, x, y, z);
if(tmp < 0) {
fprintf(stderr, "y16t: insert failed with %s\n", strerror(-tmp));
return -1;
}
break;
case YSC_DELETE:
if(argc < 6) {
fprintf(stderr, "y16t/delete: invalid invocation\n");
return -1;
}
fd = open(dbfile, O_RDWR | O_NOCTTY);
if(fd == -1) {
perror("y16t: unable to open file");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[3], x, sizeof(x))) {
fprintf(stderr, "y16t: invalid coordinate X\n");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[4], y, sizeof(y))) {
fprintf(stderr, "y16t: invalid coordinate Y\n");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[5], z, sizeof(z))) {
fprintf(stderr, "y16t: invalid coordinate Z\n");
return -1;
}
//tmp = y16t_db_remove(fd, x, y, z);
tmp = -EOPNOTSUPP;
if(tmp < 0) {
fprintf(stderr, "y16t: insert failed with %s\n", strerror(-tmp));
return -1;
}
break;
case YSC_SELEQ_X:
if(argc < 4) {
fprintf(stderr, "y16t/x=: invalid invocation\n");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[3], x, sizeof(x))) {
fprintf(stderr, "y16t: invalid coordinate X\n");
return -1;
}
fd = open(dbfile, O_RDWR | O_NOCTTY);
if(fd == -1) {
perror("y16t: unable to open file");
return -1;
}
varname = 'y';
y16t_db_foreach_y(fd, x, y16t_cli_fecb, &varname);
break;
case YSC_SELEQ_Y:
if(argc < 4) {
fprintf(stderr, "y16t/y=: invalid invocation\n");
return -1;
}
if(-1 == y16t_parse_coordinate(argv[3], y, sizeof(y))) {
fprintf(stderr, "y16t: invalid coordinate Y\n");
return -1;
}
fd = open(dbfile, O_RDWR | O_NOCTTY);
if(fd == -1) {
perror("y16t: unable to open file");
return -1;
}
varname = 'x';
y16t_db_foreach_x(fd, y, y16t_cli_fecb, &varname);
break;
default:
fprintf(stderr, "y16t: invalid invocation\n");
}
//if(fd != -1)
// close(fd);
return 0;
}

6
bin/meson.build Normal file
View file

@ -0,0 +1,6 @@
executable('y16t',
files('main.c'),
c_args : [c_base_args],
include_directories : include_directories('../lib'),
link_with : [liby16t],
install : true)

View file

@ -4,6 +4,7 @@
#include "y16t_internal.h"
#include "y16t_idx.h"
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
@ -17,8 +18,9 @@ static uint32_t y16t_db_palloc(void * context_)
{
y16t_db_actx_t *context = context_;
const int fd = context->fd;
const off_t eoffs = lseek(fd, 0, SEEK_END);
if(eoffs == -1) return 0;
const off_t eoffs_orig = lseek(fd, 0, SEEK_END);
if(eoffs_orig == -1) return 0;
const off_t eoffs = (eoffs_orig >= (1 << 18)) ? eoffs_orig : (1 << 18);
int tmp = posix_fallocate(fd, eoffs, 1 << 18);
if(tmp < 0) {
errno = tmp;
@ -78,9 +80,9 @@ int y16t_db_insert(
// first table
uint32_t offset = 0;
int tmp = 0;
y16t_db_actx_t actx = { db.fd };
y16t_db_actx_t actx = { db };
{
const y16t_idx_t idx = { db.fd, 0 };
const y16t_idx_t idx = { db, 0 };
tmp = y16t_idx_get_or_insert(
idx, x[0], y[0], &offset,
y16t_db_palloc, (void*)&actx
@ -90,7 +92,7 @@ int y16t_db_insert(
// second table
{
const y16t_idx_t idx = { db.fd, offset };
const y16t_idx_t idx = { db, offset };
tmp = y16t_idx_get_or_insert(
idx, x[1], y[1], &offset,
y16t_db_palloc2, (void*)&actx
@ -107,13 +109,13 @@ int y16t_db_insert(
// sequential data, read complete page
const off_t start_offset = ((off_t)offset) << 10;
uint32_t i;
tmp = y16t_db_intern_pgsearch(db.fd, start_offset, bufexp, &i);
tmp = y16t_db_intern_pgsearch(db, start_offset, bufexp, &i);
switch(tmp) {
case 1:
return 0;
case 0:
if(i >= 4052) return -ENOMEM;
return y16t_pwrite_all(db.fd, bufexp, sizeof(bufexp), start_offset + i);
return y16t_pwrite_all(db, bufexp, sizeof(bufexp), start_offset + i);
default:
return tmp;
}
@ -132,7 +134,7 @@ int y16t_db_lookup(
int tmp = 0;
// first table
y16t_idx_t idx = { db.fd, 0 };
y16t_idx_t idx = { db, 0 };
tmp = y16t_idx_lookup(idx, x[0], y[0], &offset);
if(tmp < 0) return tmp;
if(!offset) return 0;
@ -143,7 +145,6 @@ int y16t_db_lookup(
if(tmp < 0) return tmp;
if(!offset) return 0;
// sequential data, read complete page
// prepare entry
uint8_t bufexp[44];
memcpy(bufexp, &x[2], 14);
@ -152,7 +153,7 @@ int y16t_db_lookup(
// sequential data, read complete page
uint32_t i;
return y16t_db_intern_pgsearch(db.fd, ((off_t)offset) << 10, bufexp, &i);
return y16t_db_intern_pgsearch(db, ((off_t)offset) << 10, bufexp, &i);
}
// iterate over the database
@ -165,13 +166,14 @@ typedef struct {
static int y16t_db_foreach_x3(uint32_t offset, void *context_)
{
const y16t_db_fectx_t *context = context_;
if(!offset) return 0;
const y16t_db_fectx_t *context = context_;
// sequential data, read complete page
uint8_t buf[4096] = {0};
const uint8_t zeros[44] = {0};
ssize_t tmp = y16t_pread_all(fd, buf, sizeof(buf), start_offset);
const off_t start_offset = ((off_t)offset) << 10;
ssize_t tmp = y16t_pread_all(context->db, buf, sizeof(buf), start_offset);
if(tmp < 0) return (int)tmp;
uint32_t i;
@ -189,13 +191,14 @@ static int y16t_db_foreach_x3(uint32_t offset, void *context_)
static int y16t_db_foreach_y3(uint32_t offset, void *context_)
{
const y16t_db_fectx_t *context = context_;
if(!offset) return 0;
const y16t_db_fectx_t *context = context_;
// sequential data, read complete page
uint8_t buf[4096] = {0};
const uint8_t zeros[44] = {0};
ssize_t tmp = y16t_pread_all(fd, buf, sizeof(buf), start_offset);
const off_t start_offset = ((off_t)offset) << 10;
ssize_t tmp = y16t_pread_all(context->db, buf, sizeof(buf), start_offset);
if(tmp < 0) return (int)tmp;
uint32_t i;
@ -214,14 +217,16 @@ static int y16t_db_foreach_y3(uint32_t offset, void *context_)
static int y16t_db_foreach_x2(uint32_t offset, void *context_) {
const y16t_db_fectx_t *context = context_;
if(!offset) return 0;
return y16t_idx_foreach_x({context->db.fd, offset}, context->xy[1],
const y16t_idx_t idx = { context->db, offset };
return y16t_idx_foreach_x(idx, context->xy[1],
y16t_db_foreach_x3, context_);
}
static int y16t_db_foreach_y2(uint32_t offset, void *context_) {
const y16t_db_fectx_t *context = context_;
if(!offset) return 0;
return y16t_idx_foreach_y({context->db.fd, offset}, context->xy[1],
const y16t_idx_t idx = { context->db, offset };
return y16t_idx_foreach_y(idx, context->xy[1],
y16t_db_foreach_y3, context_);
}
@ -231,8 +236,8 @@ int y16t_db_foreach_x(
void *context
) {
y16t_db_fectx_t fectx = { db, y, callback, context };
return y16t_idx_foreach_x({db.fd, 0}, y[0],
y16t_db_foreach_x2, (void*) &fectx);
const y16t_idx_t idx = { db, 0 };
return y16t_idx_foreach_x(idx, y[0], y16t_db_foreach_x2, (void*) &fectx);
}
int y16t_db_foreach_y(
@ -241,6 +246,6 @@ int y16t_db_foreach_y(
void *context
) {
y16t_db_fectx_t fectx = { db, x, callback, context };
return y16t_idx_foreach_y({db.fd, 0}, x[0],
y16t_db_foreach_y2, (void*) &fectx);
const y16t_idx_t idx = { db, 0 };
return y16t_idx_foreach_y(idx, x[0], y16t_db_foreach_y2, (void*) &fectx);
}

View file

16
lib/meson.build Normal file
View file

@ -0,0 +1,16 @@
install_headers('y16t_db.h', 'y16t_idx.h')
liby16t = shared_library('y16t',
files('db.c', 'hilbert.c', 'idx.c', 'pall.c'),
version : '0.0.0',
c_args : [c_base_args],
include_directories : include_directories('.'),
install : true)
pkg_mod = import('pkgconfig')
pkg_mod.generate(
libraries : [liby16t],
version : meson.project_version(),
name : 'liby16t',
filebase : 'y16t',
description : 'y16t 16bit-field quad tree library')

View file

View file

@ -3,12 +3,11 @@
#include <inttypes.h>
#include <stddef.h>
typedef struct {
int fd;
} y16t_db_t;
typedef int y16t_db_t;
// inserts a database entry
// x, y, z should point to arrays of 16 bytes each
__attribute__((nonnull))
int y16t_db_insert(
y16t_db_t db,
const uint8_t *x,
@ -19,6 +18,7 @@ int y16t_db_insert(
// lookup a database entry
// @return 1 means found, 0 means not found, negative is a negated errno value
// x, y, z should point to arrays of 16 bytes each
__attribute__((nonnull))
int y16t_db_lookup(
y16t_db_t db,
const uint8_t *x,

View file

@ -4,27 +4,14 @@ project('y16t 16bit-field quad tree library', 'c',
license : 'Apache-2.0',
meson_version : '>=0.50')
install_headers('y16t_db.h', 'y16t_idx.h')
c_base_args = [
'-fno-plt',
'-fno-unwind-tables',
'-fno-exceptions',
'-Werror=return-type',
'-Werror=implicit-function-declaration',
'-D_XOPEN_SOURCE=500']
'-D_XOPEN_SOURCE=500',
'-D_POSIX_C_SOURCE=200112L']
liby16t = shared_library('y16t',
files('hilbert.c', 'idx.c', 'pall.c'),
version : '0.0.0',
c_args : [c_base_args],
include_directories : include_directories('.'),
install : true)
pkg_mod = import('pkgconfig')
pkg_mod.generate(
libraries : [liby16t],
version : meson.project_version(),
name : 'liby16t',
filebase : 'y16t',
description : 'y16t 16bit-field quad tree library')
subdir('lib')
subdir('bin')