cepheid

An Aurora 4X clone
Log | Files | Refs | README

commit d49d69ae2863575a010f675facf8858a18f7461d
parent 431f797275d6d047c75b8bfb0461dace809ebe92
Author: hhvn <dev@hhvn.uk>
Date:   Wed, 16 Nov 2022 03:51:28 +0000

Bulk db interface

Diffstat:
Asrc/bdb.c | 188+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/db.c | 26--------------------------
Msrc/main.h | 14++++++--------
Msrc/str.c | 31+++++++++++++++++++++++++++++++
Msrc/system.c | 55++++++++++++++++++++++++++++++-------------------------
5 files changed, 255 insertions(+), 59 deletions(-)

diff --git a/src/bdb.c b/src/bdb.c @@ -0,0 +1,188 @@ +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include "main.h" + +/* Bulk db interface + * + * Set: 't', key, val + * Set: 'T', key, val[], n + * + * Get: 't', key, &val + * Get: 'T', key, &val[], &n + * + * Where 't'/'T' is: + * 's' - string + * 'i' - int + * 'f' - float + * 'v' - vector + * 'S' - array of strings + * 'I' - array of ints + * 'F' - array of floats + * + * The functions themselves require a NULL value at the end, + * but this is appended by a macro in main.h */ + +#define NUMBUF 64 + +void +_bdbset(char *dir, char *group, ...) { + va_list ap; + char type; + char *key; + char *array; + char buf[NUMBUF]; + union { + char *s; + int i; + float f; + Vector v; + char **S; + int *I; + float *F; + } v; + int n, i; + + va_start(ap, group); + + for (;;) { + type = (char)va_arg(ap, int); + if (type == 0) return; + key = va_arg(ap, char *); + + array = NULL; + + switch (type) { + case 's': + v.s = va_arg(ap, char *); + dbset(dir, group, key, v.s); + break; + case 'i': + v.i = va_arg(ap, int); + dbsetf(dir, group, key, "%d", v.i); + break; + case 'f': + v.f = (float)va_arg(ap, double); + dbsetf(dir, group, key, "%f", v.f); + break; + case 'v': + v.v = va_arg(ap, Vector); + dbsetf(dir, group, key, "%f\t%f", v.v.x, v.v.y); + break; + case 'S': + v.S = va_arg(ap, char **); + n = va_arg(ap, int); + array = strjoin("\t", v.S, n); + dbset(dir, group, key, array); + free(array); + break; + case 'I': + v.I = va_arg(ap, int *); + n = va_arg(ap, int); + for (i = 0, array = NULL; i < n; i++) { + snprintf(buf, sizeof(buf), "%d", v.I[i]); + strjoinl("\t", &array, buf); + } + dbset(dir, group, key, array); + free(array); + break; + case 'F': + v.F = va_arg(ap, float *); + n = va_arg(ap, int); + for (i = 0, array = NULL; i < n; i++) { + snprintf(buf, sizeof(buf), "%f", v.F[i]); + strjoinl("\t", &array, buf); + } + dbset(dir, group, key, array); + free(array); + break; + default: + error(1, "invalid bdb type: '%c' (%d)\n", type, (int)type); + } + } + + va_end(ap); +} + +#define ARRAYMAX 64 + +void +_bdbget(char *dir, char *group, ...) { + va_list ap; + char type; + char *key; + char *str; + char *list[ARRAYMAX]; + size_t len; + union { + char **s; + int *i; + float *f; + Vector *v; + char ***S; + int **I; + float **F; + } v; + int i; + + va_start(ap, group); + + for (;;) { + type = va_arg(ap, int); + if (type == 0) return; + key = va_arg(ap, char *); + + if (isupper(type)) { + str = nstrdup(dbget(dir, group, key)); + len = strsplit(str, "\t", list, ARRAYMAX); + } + + switch (type) { + case 's': + v.s = va_arg(ap, char **); + dbgetf(dir, group, key, "%s", v.s); + break; + case 'i': + v.i = va_arg(ap, int *); + dbgetf(dir, group, key, "%d", v.i); + break; + case 'f': + v.f = va_arg(ap, float *); + dbgetf(dir, group, key, "%f", v.f); + break; + case 'v': + v.v = va_arg(ap, Vector *); + dbgetf(dir, group, key, "%f\t%f", + &(*v.v).x, &(*v.v).y); + break; + case 'S': + v.S = va_arg(ap, char ***); + *v.S = malloc(len * sizeof(char *)); + for (i = 0; i < len; i++) + (*v.S)[i] = nstrdup(list[i]); + *va_arg(ap, int *) = len; + break; + case 'I': + v.I = va_arg(ap, int **); + *v.I = malloc(len * sizeof(int)); + for (i = 0; i < len; i++) + (*v.I)[i] = atoi(list[i]); + *va_arg(ap, int *) = len; + break; + case 'F': + v.F = va_arg(ap, float **); + *v.F = malloc(len * sizeof(float)); + for (i = 0; i < len; i++) + (*v.F)[i] = strtol(list[i], NULL, 10); + *va_arg(ap, int *) = len; + break; + default: + error(1, "invalid bdb type: '%c'\n", type); + } + + if (isupper(type)) + free(str); + } +} diff --git a/src/db.c b/src/db.c @@ -30,16 +30,6 @@ dbsetf(char *dir, char *group, char *key, char *fmt, ...) { } int -dbsetint(char *dir, char *group, char *key, int val) { - return dbsetf(dir, group, key, "%d", val); -} - -int -dbsetfloat(char *dir, char *group, char *key, float val) { - return dbsetf(dir, group, key, "%f", val); -} - -int vdbgetf(char *dir, char *group, char *key, char *fmt, va_list args) { va_list ap; char *str; @@ -65,22 +55,6 @@ dbgetf(char *dir, char *group, char *key, char *fmt, ...) { return ret; } -int -dbgetint(char *dir, char *group, char *key) { - int ret; - - dbgetf(dir, group, key, "%d", &ret); - return ret; -} - -float -dbgetfloat(char *dir, char *group, char *key) { - float ret; - - dbgetf(dir, group, key, "%f", &ret); - return ret; -} - static int dbtree_concat(char *path[TREEMAX], size_t depth, char *group, int index) { size_t sl = PATH_MAX; diff --git a/src/main.h b/src/main.h @@ -41,6 +41,8 @@ int strlistpos(char *str, char **list, size_t len); float strnum(char *str); size_t strlistcmp(char **l1, size_t s1, char **l2, size_t s2); size_t strsplit(char *str, char *sep, char **list, size_t len); +void strjoinl(char *sep, char **ret, char *append); +char * strjoin(char *sep, char **list, size_t len); char * strtrunc(char *str, int w); void edittrunc(wchar_t *str, int *len, int *cur); void editrm(wchar_t *str, int *len, int *cur); @@ -191,20 +193,16 @@ void data_load(void); void data_unload(void); /* bdb.c */ -#define bdset(d, g, ...) _bdset(d, g, __VA_ARGS__, NULL) -#define bdget(d, g, ...) _bdget(d, g, __VA_ARGS__, NULL) -void _bdset(char *dir, char *group, ...); -void _bdget(char *dir, char *group, ...); +#define bdbset(d, g, ...) _bdbset(d, g, __VA_ARGS__, NULL) +#define bdbget(d, g, ...) _bdbget(d, g, __VA_ARGS__, NULL) +void _bdbset(char *dir, char *group, ...); +void _bdbget(char *dir, char *group, ...); /* db.c */ int vdbsetf(char *dir, char *group, char *key, char *fmt, va_list args); int dbsetf(char *dir, char *group, char *key, char *fmt, ...); -int dbsetint(char *dir, char *group, char *key, int val); -int dbsetfloat(char *dir, char *group, char *key, float val); int vdbgetf(char *dir, char *group, char *key, char *fmt, va_list args); int dbgetf(char *dir, char *group, char *key, char *fmt, ...); -int dbgetint(char *dir, char *group, char *key); -float dbgetfloat(char *dir, char *group, char *key); int dbgettree(char *dir, Tree *t, Treegetter func); int dbsettree(char *dir, Tree *t, Treesetter func); diff --git a/src/str.c b/src/str.c @@ -217,6 +217,37 @@ strsplit(char *str, char *sep, char **list, size_t len) { return i; } +void +strjoinl(char *sep, char **ret, char *append) { + char *tmp; + + if (*ret == NULL) { + *ret = nstrdup(append); + return; + } + + tmp = smprintf("%s%s%s", *ret, sep, append); + free(*ret); + *ret = tmp; +} + +char * +strjoin(char *sep, char **list, size_t len) { + size_t i; + char *ret; + + if (!len || !list) + return NULL; + + if (len == 1) + return nstrdup(*list); + + for (i = 0, ret = NULL; list && *list && i < len; i++) + strjoinl(sep, &ret, list[i]); + + return ret; +} + #define TRUNCSTR "…" #define TRUNCLEN strlen(TRUNCSTR) diff --git a/src/system.c b/src/system.c @@ -146,8 +146,7 @@ sys_tree_getter(char *dir, char *group, char *name, int depth, Tree *t) { s = sys_init(name); s->t = t; - s->lypos.x = dbgetfloat(dir, group, "x"); - s->lypos.y = dbgetfloat(dir, group, "y"); + bdbget(dir, group, 'v', "lypos", &s->lypos); t->type = SYSTREE_SYS; t->data = s; @@ -170,19 +169,21 @@ sys_tree_getter(char *dir, char *group, char *name, int depth, Tree *t) { case BODY_LAST: /* shut up compiler */ break; } - b->radius = dbgetfloat(dir, group, "radius"); - b->mass = dbgetfloat(dir, group, "mass"); - b->orbdays = dbgetfloat(dir, group, "orbdays"); + bdbget(dir, group, + 'f', "radius", &b->radius, + 'f', "mass", &b->mass, + 'f', "orbdays", &b->orbdays); if (b->type == BODY_COMET) { - /* mindist is on opposite side of parent */ - b->mindist = 0 - dbgetfloat(dir, group, "mindist"); - b->maxdist = dbgetfloat(dir, group, "maxdist"); - b->curdist = dbgetfloat(dir, group, "curdist"); - b->theta = dbgetfloat(dir, group, "theta"); - b->inward = dbgetfloat(dir, group, "inward"); + bdbget(dir, group, + 'f', "mindist", &b->mindist, + 'f', "maxdist", &b->maxdist, + 'f', "curdist", &b->curdist, + 'f', "theta", &b->theta, + 'i', "inward", &b->inward); } else { - b->dist = dbgetfloat(dir, group, "dist"); - b->curtheta = dbgetfloat(dir, group, "curtheta"); + bdbget(dir, group, + 'f', "dist", &b->dist, + 'f', "curtheta", &b->curtheta); } t->type = SYSTREE_BODY; @@ -199,27 +200,31 @@ sys_tree_setter(char *dir, char *group, char *name, int depth, Tree *t) { switch (t->type) { case SYSTREE_SYS: s = t->data; - dbsetfloat(dir, group, "x", s->lypos.x); - dbsetfloat(dir, group, "y", s->lypos.y); + bdbset(dir, group, 'v', "lypos", s->lypos); + break; case SYSTREE_BODY: b = t->data; if (b->parent) dbset(save->db.systems, group, "parent", b->parent->name); - dbsetfloat(dir, group, "radius", b->radius); - dbsetfloat(dir, group, "mass", b->mass); - dbsetfloat(dir, group, "orbdays", b->orbdays); + bdbset(dir, group, + 'f', "radius", b->radius, + 'f', "mass", b->mass, + 'f', "orbdays", b->orbdays); if (b->type == BODY_COMET) { - dbsetfloat(dir, group, "mindist", b->mindist); - dbsetfloat(dir, group, "maxdist", b->maxdist); - dbsetfloat(dir, group, "curdist", b->curdist); - dbsetfloat(dir, group, "theta", b->theta); - dbsetfloat(dir, group, "inward", b->inward); + bdbset(dir, group, + 'f', "mindist", b->mindist, + 'f', "maxdist", b->maxdist, + 'f', "curdist", b->curdist, + 'f', "theta", b->theta, + 'i', "inward", b->inward); } else { - dbsetfloat(dir, group, "dist", b->dist); - dbsetfloat(dir, group, "curtheta", b->curtheta); + bdbset(dir, group, + 'f', "dist", b->dist, + 'f', "curtheta", b->curtheta); } + break; } }