From 426871440ee34fcefd33b7311415795f907e9e2e Mon Sep 17 00:00:00 2001 From: Alain Zscheile Date: Tue, 3 Jan 2023 23:13:32 +0100 Subject: [PATCH] implement rough cli --- bin/main.c | 217 +++++++++++++++++++++++++ bin/meson.build | 6 + db.c => lib/db.c | 45 ++--- hilbert.c => lib/hilbert.c | 0 idx.c => lib/idx.c | 0 lib/meson.build | 16 ++ pall.c => lib/pall.c | 0 y16t_db.h => lib/y16t_db.h | 6 +- y16t_idx.h => lib/y16t_idx.h | 0 y16t_internal.h => lib/y16t_internal.h | 0 meson.build | 21 +-- 11 files changed, 271 insertions(+), 40 deletions(-) create mode 100644 bin/main.c create mode 100644 bin/meson.build rename db.c => lib/db.c (80%) rename hilbert.c => lib/hilbert.c (100%) rename idx.c => lib/idx.c (100%) create mode 100644 lib/meson.build rename pall.c => lib/pall.c (100%) rename y16t_db.h => lib/y16t_db.h (91%) rename y16t_idx.h => lib/y16t_idx.h (100%) rename y16t_internal.h => lib/y16t_internal.h (100%) diff --git a/bin/main.c b/bin/main.c new file mode 100644 index 0000000..0e5c644 --- /dev/null +++ b/bin/main.c @@ -0,0 +1,217 @@ +#include + +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/bin/meson.build b/bin/meson.build new file mode 100644 index 0000000..a82245d --- /dev/null +++ b/bin/meson.build @@ -0,0 +1,6 @@ +executable('y16t', + files('main.c'), + c_args : [c_base_args], + include_directories : include_directories('../lib'), + link_with : [liby16t], + install : true) diff --git a/db.c b/lib/db.c similarity index 80% rename from db.c rename to lib/db.c index 8d71ca4..da8a0f0 100644 --- a/db.c +++ b/lib/db.c @@ -4,6 +4,7 @@ #include "y16t_internal.h" #include "y16t_idx.h" +#include #include #include #include @@ -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); } diff --git a/hilbert.c b/lib/hilbert.c similarity index 100% rename from hilbert.c rename to lib/hilbert.c diff --git a/idx.c b/lib/idx.c similarity index 100% rename from idx.c rename to lib/idx.c diff --git a/lib/meson.build b/lib/meson.build new file mode 100644 index 0000000..585f159 --- /dev/null +++ b/lib/meson.build @@ -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') diff --git a/pall.c b/lib/pall.c similarity index 100% rename from pall.c rename to lib/pall.c diff --git a/y16t_db.h b/lib/y16t_db.h similarity index 91% rename from y16t_db.h rename to lib/y16t_db.h index 3f1a5ff..28e7a97 100644 --- a/y16t_db.h +++ b/lib/y16t_db.h @@ -3,12 +3,11 @@ #include #include -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, diff --git a/y16t_idx.h b/lib/y16t_idx.h similarity index 100% rename from y16t_idx.h rename to lib/y16t_idx.h diff --git a/y16t_internal.h b/lib/y16t_internal.h similarity index 100% rename from y16t_internal.h rename to lib/y16t_internal.h diff --git a/meson.build b/meson.build index 44c4c50..b6cefea 100644 --- a/meson.build +++ b/meson.build @@ -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')