summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorbpc2003 <wpesfriendnva@gmail.com>2025-03-10 16:31:37 -0400
committerbpc2003 <wpesfriendnva@gmail.com>2025-03-10 16:31:37 -0400
commit2011c1e008055005bf980acbff549c8f46a34f25 (patch)
tree54f6b74a190637fa2303bd6db4089bc60e419f2e /src/lib
parentde52acd37ea5634712ed78c624f77566e3ac634e (diff)
moved mdb.h and associated files int lib
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/file.c92
-rw-r--r--src/lib/keytab.c113
-rw-r--r--src/lib/mdb.h31
-rw-r--r--src/lib/test.c39
4 files changed, 275 insertions, 0 deletions
diff --git a/src/lib/file.c b/src/lib/file.c
new file mode 100644
index 0000000..5011e45
--- /dev/null
+++ b/src/lib/file.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mdb.h"
+
+static char *getpair(int *c, FILE *fp);
+
+struct keytablist *readdb(char *filename)
+{
+ int len = 2;
+ struct keytablist *list = calloc(len, sizeof(struct keytablist));
+ FILE *fp = fopen(filename, "rb");
+ if (fp == NULL)
+ return list;
+
+ int c, i = 0, open = 0;
+ char *p;
+ while ((c = fgetc(fp)) != EOF) {
+ switch (c) {
+ case 250:
+ p = getpair(&c, fp);
+ if (p == NULL) {
+ fprintf(stderr, "missing pair closing byte!\n");
+ return NULL;
+ }
+ setkey(&list, &len, i, p);
+ free(p);
+ break;
+ case 251:
+ if (open == 1) {
+ fprintf(stderr, "missing object closing byte!\n");
+ return NULL;
+ }
+ open = 1;
+ break;
+ case 254:
+ open = 0;
+ i++;
+ break;
+ default:
+ fprintf(stderr, "Unknown byte: %d\n", c);
+ return NULL;
+ }
+ }
+ fclose(fp);
+ return list;
+}
+
+void writedb(char *filename, struct keytablist *list)
+{
+ FILE *fp = fopen(filename, "wb");
+ for (int i = 0; i < list[0].len; ++i) {
+ fprintf(fp, "\xfb");
+ int *indexes = getkeys(list, i);
+ for (int j = 0; indexes[j]; ++j) {
+ fprintf(fp, "\xfa%s:", list[i].tab[indexes[j]].key);
+ switch (list[i].tab[indexes[j]].flag) {
+ case 1:
+ fprintf(fp, "%.2lf\xfc", list[i].tab[indexes[j]].v.num);
+ break;
+ case 2:
+ fprintf(fp, "%s\xfc", list[i].tab[indexes[j]].v.b == 1 ? "true" : "false");
+ break;
+ case 3:
+ fprintf(fp, "%s\xfc", list[i].tab[indexes[j]].v.str);
+ break;
+ }
+ }
+ free(indexes);
+ fprintf(fp, "\xfe");
+ }
+ fclose(fp);
+}
+
+static char *getpair(int *c, FILE *fp)
+{
+ char *pair = calloc(3, sizeof(char));
+ int i = 0, len = 3;
+ while ((*c = fgetc(fp)) != 252 && *c != EOF) {
+ if (i >= len)
+ pair = realloc(pair, ++len * sizeof(char));
+ pair[i++] = *c;
+ }
+ pair = realloc(pair, ++len * sizeof(char));
+ pair[i] = '\0';
+ if (*c != 252) {
+ free(pair);
+ return NULL;
+ }
+ return pair;
+}
diff --git a/src/lib/keytab.c b/src/lib/keytab.c
new file mode 100644
index 0000000..61f94af
--- /dev/null
+++ b/src/lib/keytab.c
@@ -0,0 +1,113 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "mdb.h"
+
+static const struct keytablist empty;
+
+static int hash(char *key);
+
+int *getkeys(struct keytablist *list, int id)
+{
+ int len = 2;
+ int *indexes = calloc(len, sizeof(int));
+ for (int i = 0, j = 0; i < TABLEN; ++i) {
+ if (j >= len) {
+ indexes = realloc(indexes, ++len * sizeof(int));
+ indexes[len - 1] = 0;
+ }
+ if (list[id].tab[i].key)
+ indexes[j++] = i;
+ }
+ return indexes;
+}
+
+struct keytab getkey(struct keytablist *list, int id, char *key)
+{
+ int idx = hash(key);
+ if (list[id].tab[idx].key == NULL)
+ return (struct keytab) { .key = NULL, .flag = 0, .v = 0 };
+
+ while (strcmp(list[id].tab[idx].key, key) && idx < TABLEN)
+ idx++;
+ if (idx >= TABLEN)
+ return (struct keytab) { .key = NULL, .flag = 0, .v = 0 };
+ return list[id].tab[idx];
+}
+
+int setkey(struct keytablist **list, int *len, int id, char *pair)
+{
+ if (id >= *len) {
+ *list = realloc(*list, (id + 1) * sizeof(struct keytablist));
+ for (int i = *len; i <= id; ++i)
+ (*list)[i] = empty;
+ *len = id + 1;
+ (*list)[0].len = *len;
+ }
+ char *tok = strtok(pair, ":");
+ char *key = calloc(strlen(tok) + 1, sizeof(char));
+ strcpy(key, tok);
+
+ tok = strtok(NULL, ":");
+ if (tok == NULL) {
+ fprintf(stderr, "Invalid key-value pair\n");
+ return 1;
+ }
+ union value v;
+ int flag;
+ if (isdigit(*tok)) {
+ flag = 1;
+ v.num = atof(tok);
+ } else if (!strcmp(tok, "true") || !strcmp(tok, "false")) {
+ flag = 2;
+ v.b = !strcmp(tok, "true");
+ } else {
+ flag = 3;
+ v.str = calloc(strlen(tok) + 1, sizeof(char));
+ strcpy(v.str, tok);
+ }
+
+ int idx = hash(key);
+ while ((*list)[id].tab[idx].key != NULL &&
+ strcmp((*list)[id].tab[idx].key, key) &&
+ idx < TABLEN) idx++;
+ if (idx >= TABLEN) {
+ fprintf(stderr, "No more room in table\n");
+ return 2;
+ }
+ if (!(*list)[id].tab[idx].key)
+ (*list)[id].tab[idx].key = key;
+ else
+ free(key);
+ (*list)[id].tab[idx].v = v;
+ (*list)[id].tab[idx].flag = flag;
+ return 0;
+}
+
+void delkey(struct keytablist *list, int id, char *key)
+{
+ int idx = hash(key);
+ while (strcmp(list[id].tab[idx].key, key) && idx < TABLEN)
+ idx++;
+ if (idx >= TABLEN) {
+ fprintf(stderr, "Invalid key: %s\n", key);
+ return;
+ }
+ free(list[id].tab[idx].key);
+ list[id].tab[idx].key = NULL;
+ if (list[id].tab[idx].flag == 3) {
+ free(list[id].tab[idx].v.str);
+ list[id].tab[idx].v.str = NULL;
+ }
+ list[id].tab[idx].flag = 0;
+}
+
+static int hash(char *key)
+{
+ unsigned long h = 5381;
+ for (int i = 0; i < strlen(key); ++i)
+ h = ((h << 5) + h) + key[i];
+ return h % TABLEN;
+}
diff --git a/src/lib/mdb.h b/src/lib/mdb.h
new file mode 100644
index 0000000..49f5903
--- /dev/null
+++ b/src/lib/mdb.h
@@ -0,0 +1,31 @@
+#ifndef MDB_H
+#define MDB_H
+
+#define TABLEN 1024
+
+union value {
+ char *str;
+ double num;
+ unsigned int b : 1;
+};
+
+struct keytab {
+ char *key;
+ int flag;
+ union value v;
+};
+
+struct keytablist {
+ int len;
+ struct keytab tab[TABLEN];
+};
+
+int *getkeys(struct keytablist *list, int id);
+struct keytab getkey(struct keytablist *list, int id, char *key);
+int setkey(struct keytablist **list, int *len, int id, char *pair);
+void delkey(struct keytablist *list, int id, char *key);
+
+struct keytablist *readdb(char *filename);
+void writedb(char *filename, struct keytablist *list);
+
+#endif
diff --git a/src/lib/test.c b/src/lib/test.c
new file mode 100644
index 0000000..5fb9f8b
--- /dev/null
+++ b/src/lib/test.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "src/mdb.h"
+
+int main(int argc, char **argv)
+{
+ if (argc != 2)
+ exit(1);
+ char *filename = argv[1];
+ struct keytablist *list = readdb(filename);
+ if (list == NULL)
+ exit(2);
+
+ writedb(filename, list);
+ for (int i = 0; i < list[0].len; ++i) {
+ int *indexes = getkeys(list, i);
+ for (int j = 0; indexes[j]; ++j) {
+ printf("%s: ", list[i].tab[indexes[j]].key);
+ switch (list[i].tab[indexes[j]].flag) {
+ case 1:
+ printf("%.2lf\n", list[i].tab[indexes[j]].v.num);
+ break;
+ case 2:
+ printf("%d\n", list[i].tab[indexes[j]].v.b);
+ break;
+ case 3:
+ printf("%s\n", list[i].tab[indexes[j]].v.str);
+ break;
+ }
+ delkey(list, i, list[i].tab[indexes[j]].key);
+ }
+ free(indexes);
+ }
+
+ free(list);
+ exit(0);
+}