commit d49d69ae2863575a010f675facf8858a18f7461d
parent 431f797275d6d047c75b8bfb0461dace809ebe92
Author: hhvn <dev@hhvn.uk>
Date: Wed, 16 Nov 2022 03:51:28 +0000
Bulk db interface
Diffstat:
A | src/bdb.c | | | 188 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/db.c | | | 26 | -------------------------- |
M | src/main.h | | | 14 | ++++++-------- |
M | src/str.c | | | 31 | +++++++++++++++++++++++++++++++ |
M | src/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;
}
}