diff options
author | bpc2003 <wpesfriendnva@gmail.com> | 2025-03-10 16:31:37 -0400 |
---|---|---|
committer | bpc2003 <wpesfriendnva@gmail.com> | 2025-03-10 16:31:37 -0400 |
commit | 2011c1e008055005bf980acbff549c8f46a34f25 (patch) | |
tree | 54f6b74a190637fa2303bd6db4089bc60e419f2e /src/lib | |
parent | de52acd37ea5634712ed78c624f77566e3ac634e (diff) |
moved mdb.h and associated files int lib
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/file.c | 92 | ||||
-rw-r--r-- | src/lib/keytab.c | 113 | ||||
-rw-r--r-- | src/lib/mdb.h | 31 | ||||
-rw-r--r-- | src/lib/test.c | 39 |
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); +} |