aboutsummaryrefslogtreecommitdiff
path: root/src/db.c
diff options
context:
space:
mode:
authortlatorre <tlatorre@uchicago.edu>2018-08-14 10:08:27 -0500
committertlatorre <tlatorre@uchicago.edu>2018-08-14 10:08:27 -0500
commit24c8bcfe7f76b20124e2862ea050f815c0f768e7 (patch)
treee5bdbd638a2c7f38f1c094cc9e95cbdfe05b9481 /src/db.c
parent0b7f199c0d93074484ea580504485a32dc29f5e2 (diff)
downloadsddm-24c8bcfe7f76b20124e2862ea050f815c0f768e7.tar.gz
sddm-24c8bcfe7f76b20124e2862ea050f815c0f768e7.tar.bz2
sddm-24c8bcfe7f76b20124e2862ea050f815c0f768e7.zip
move everything to src directory
Diffstat (limited to 'src/db.c')
-rw-r--r--src/db.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/db.c b/src/db.c
new file mode 100644
index 0000000..9160cbf
--- /dev/null
+++ b/src/db.c
@@ -0,0 +1,256 @@
+#include "db.h"
+#include <stdio.h> /* for fopen(), etc. */
+#include <errno.h> /* for strerror(), etc. */
+#include <string.h> /* for strncmp(), etc. */
+#include <stdint.h> /* for uint32_t */
+#include <stdlib.h> /* for atoi() */
+#include "dict.h"
+
+char db_err[256];
+
+static uint64_t dbHash(const void *key)
+{
+ return dictGenHashFunction(key,8);
+}
+
+static int dbKeyCompare(void *privdata, const void *key1, const void *key2)
+{
+ return memcmp(key1,key2,8) == 0;
+}
+
+static void dbFree(void *privdata, void *val)
+{
+ free(val);
+}
+
+static dictType titleDB = {
+ dbHash,
+ NULL,
+ NULL,
+ dbKeyCompare,
+ dbFree,
+ dbFree
+};
+
+/* Add a bank to the database.
+ *
+ * Returns 0 on success, -1 on error. */
+int add_bank(dict *db, const char name[4], uint32_t id, dbval *data)
+{
+ uint32_t *buf = malloc(sizeof(uint32_t)*2);
+
+ memcpy(buf,name,4);
+ buf[1] = id;
+
+ if (dictAdd(db, buf, data) != DICT_OK) {
+ sprintf(db_err, "failed to add bank to database!\n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ free(buf);
+ return -1;
+}
+
+/* Get a bank from the database.
+ *
+ * Returns a pointer to the first value in the bank, or NULL if the bank
+ * doesn't exist. */
+dbval *get_bank(dict *db, const char name[4], uint32_t id)
+{
+ uint32_t buf[2];
+
+ memcpy(buf,name,4);
+ buf[1] = id;
+
+ return dictFetchValue(db, buf);
+}
+
+/* Function to iterate over the fields in a title bank text file. Works sort of
+ * like strtok(). Example:
+ *
+ * char *item = iter_field(line);
+ * while (item) {
+ * // do something with item
+ * item = iter_field(NULL);
+ * }
+ */
+static char *iter_field(char *str)
+{
+ static char *ptr;
+ static char buf[81];
+
+ if (!str) str = ptr;
+
+ ptr = buf;
+
+ while (*str != '\x0' && ptr < (buf + 81)) {
+ if (ptr == (buf + 2) && buf[0] == '#' && buf[1] == '.') {
+ ptr = buf;
+ while (*str != '\x0' && *str++ != '#');
+ continue;
+ }
+
+ if (*str == ' ' || *str == '\n') {
+ str++;
+ if (ptr == buf) continue;
+ break;
+ }
+
+ *ptr++ = *str++;
+ }
+
+ if (ptr == buf) return NULL;
+
+ *ptr = '\x0';
+ ptr = str;
+ return buf;
+}
+
+/* Create a new database. */
+dict *db_init(void)
+{
+ dict *db = dictCreate(&titleDB, NULL);
+ return db;
+}
+
+/* Free a database. */
+void db_free(dict *db)
+{
+ dictRelease(db);
+}
+
+/* Load a title bank file into the database `db`.
+ *
+ * Returns 0 on success, -1 on error. */
+int load_file(dict *db, const char *filename)
+{
+ int i, index;
+ char *item, *s;
+ char line[256];
+ char idh[4];
+ uint32_t idn;
+ int mul;
+ int64_t value;
+ double float_value;
+ dbval *buf;
+ int buf_size;
+
+ buf_size = 10;
+
+ buf = malloc(buf_size*sizeof(dbval));
+
+ if (!buf) {
+ strcpy(db_err,strerror(errno));
+ return -1;
+ }
+
+ FILE *f = fopen(filename, "r");
+
+ if (!f) {
+ sprintf(db_err, "unable to open file '%s': %s", filename, strerror(errno));
+ return -1;
+ }
+
+ index = 0;
+ while (fgets(line, sizeof(line), f)) {
+ if (!strncmp(line,"*---",4)) {
+ /* Comment. */
+ continue;
+ } else if (!strncmp(line,"*.--",4)) {
+ /* Comment. */
+ continue;
+ } else if (!strncmp(line, "*LOG",4)) {
+ /* Control line which we don't care about. */
+ continue;
+ } else if (!strncmp(line, "*PRI",4)) {
+ /* Control line which we don't care about. */
+ continue;
+ } else if (!strncmp(line, "*US",3)) {
+ /* Control line which we don't care about. */
+ continue;
+ } else if (!strncmp(line, "*KI",3)) {
+ /* Control line which we don't care about. */
+ continue;
+ } else if (!strncmp(line, "*ANYWAY",7)) {
+ /* Control line which we don't care about. */
+ continue;
+ } else if (!strncmp(line, "*FIN",4)) {
+ /* Control line which we don't care about. */
+ continue;
+ } else if (!strncmp(line, "*DO",3)) {
+ if (index > 0) {
+ /* Save previous bank. */
+ buf = realloc(buf,sizeof(dbval)*index);
+
+ if (add_bank(db, idh, idn, buf) == DICT_ERR) {
+ sprintf(db_err, "bank '%.4s' already exists in the database", idh);
+ goto err;
+ }
+
+ buf_size = 10;
+
+ buf = malloc(buf_size*sizeof(dbval));
+
+ index = 0;
+ }
+
+ item = iter_field(line);
+ item = iter_field(NULL);
+ strncpy(idh,item,4);
+ item = iter_field(NULL);
+ idn = atoi(item);
+
+ continue;
+ }
+
+ item = iter_field(line);
+ mul = 1;
+ while (item) {
+ if ((s = strchr(item,'*'))) {
+ *s = '\0';
+ mul = atoi(item);
+ item = s+1;
+ }
+
+ if (buf_size < (index+1)*sizeof(dbval)) {
+ buf_size *= 2;
+ buf = realloc(buf, buf_size*sizeof(dbval));
+ }
+
+ if (!strncmp(item,"#x",2)) {
+ /* Hexadecimal input. */
+ value = strtol(item+2,NULL,16);
+ for (i = 0; i < mul; i++) buf[index++].u32 = value;
+ } else if (strchr(item,'E') || strchr(item,'.')) {
+ /* Floating point input. */
+ float_value = strtod(item,NULL);
+ for (i = 0; i < mul; i++) buf[index++].f = float_value;
+ } else {
+ /* Assume it's an integer. */
+ value = strtol(item,NULL,10);
+ for (i = 0; i < mul; i++) buf[index++].u32 = value;
+ }
+ item = iter_field(NULL);
+ }
+ }
+
+ buf = realloc(buf,sizeof(dbval)*index);
+
+ if (add_bank(db, idh, idn, buf) == DICT_ERR) {
+ sprintf(db_err, "bank '%.4s' already exists in the database", idh);
+ goto err;
+ }
+
+ fclose(f);
+
+ return 0;
+
+err:
+
+ if (buf) free(buf);
+ fclose(f);
+ return -1;
+}