implement rough cli
This commit is contained in:
parent
3bdd1d6989
commit
426871440e
217
bin/main.c
Normal file
217
bin/main.c
Normal 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
6
bin/meson.build
Normal 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)
|
|
@ -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);
|
||||
}
|
16
lib/meson.build
Normal file
16
lib/meson.build
Normal 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')
|
|
@ -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,
|
21
meson.build
21
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')
|
||||
|
|
Loading…
Reference in a new issue