From 3ff13e35b12d3087478c0b42ffa957c6a2fcc562 Mon Sep 17 00:00:00 2001 From: Aaron Blakely Date: Tue, 5 Mar 2024 22:53:00 -0600 Subject: [PATCH] db.c supports multiple types now --- lib/db.h | 21 +++++++++++++++--- src/db.c | 62 ++++++++++++++++++++++++++++++++++++++++++++---------- test_db.c | 29 +++++++++---------------- testdb | Bin 21928 -> 22944 bytes xbot.db | Bin 133 -> 151 bytes 5 files changed, 79 insertions(+), 33 deletions(-) mode change 100755 => 100644 xbot.db diff --git a/lib/db.h b/lib/db.h index 56fb2bd..3aecbf1 100755 --- a/lib/db.h +++ b/lib/db.h @@ -4,12 +4,20 @@ #define DB_MAGIC 0xdeadbeef #define DB_VER 0x10 +enum db_type +{ + DB_TYPE_CHAR, + DB_TYPE_INT +}; + struct db_hash { int key_len; int value_len; + int type; + char *key; - char *value; + void *value; }; struct db_table @@ -23,8 +31,15 @@ struct db_table int write_db(struct db_table *db, char *fname); struct db_table *read_db(char *fname); -int db_add_hash(struct db_table *db, char *key, char *value); + +int db_add_hash(struct db_table *db, char *key, void *value); +int db_add_hash_char(struct db_table *db, char *key, char *value); +int db_add_hash_int(struct db_table *db, char *key, int value); + int db_del_hash(struct db_table *db, char *key); -char *get_hash(struct db_table *db, char *key); + +void *get_hash(struct db_table *db, char *key); +char *get_hash_char(struct db_table *db, char *key); +int get_hash_int(struct db_table *db, char *key); #endif diff --git a/src/db.c b/src/db.c index 43048d2..0c3eeaf 100755 --- a/src/db.c +++ b/src/db.c @@ -89,7 +89,7 @@ struct db_table *read_db(char *fname) return db; } -int db_add_hash(struct db_table *db, char *key, char *value) +int db_add_hash(struct db_table *db, char *key, void *value) { int i; @@ -101,27 +101,52 @@ int db_add_hash(struct db_table *db, char *key, char *value) } } + db->hashes[db->count].key_len = strlen(key) + 1; + db->hashes[db->count].key = (char *)malloc(sizeof(char) * db->hashes[db->count].key_len); + + memset(db->hashes[db->count].key, 0, sizeof(char) * db->hashes[db->count].key_len); + + strlcpy(db->hashes[db->count].key, key, sizeof(char) * db->hashes[db->count].key_len); + + db->hashes[db->count].value = value; + + db->count++; + + return 0; +} + +int db_add_hash_char(struct db_table *db, char *key, char *value) +{ db->hashes = (struct db_hash *)realloc(db->hashes, sizeof(struct db_hash) * (db->count + 1)); // zero out reallocated memory memset(&db->hashes[db->count], 0, sizeof(struct db_hash)); - db->hashes[db->count].key_len = strlen(key) + 1; + db->hashes[db->count].type = DB_TYPE_CHAR; db->hashes[db->count].value_len = strlen(value) + 1; - - printf("key_len: %d, value_len: %d\n", sizeof(char) * db->hashes[db->count].key_len, sizeof(char) * db->hashes[db->count].value_len); - - db->hashes[db->count].key = (char *)malloc(sizeof(char) * db->hashes[db->count].key_len); db->hashes[db->count].value = (char *)malloc(sizeof(char) * db->hashes[db->count].value_len); - memset(db->hashes[db->count].key, 0, sizeof(char) * db->hashes[db->count].key_len); memset(db->hashes[db->count].value, 0, sizeof(char) * db->hashes[db->count].value_len); - strlcpy(db->hashes[db->count].key, key, sizeof(char) * db->hashes[db->count].key_len); strlcpy(db->hashes[db->count].value, value, sizeof(char) * db->hashes[db->count].value_len); - db->count++; - return 0; + return db_add_hash(db, key, db->hashes[db->count].value); +} + +int db_add_hash_int(struct db_table *db, char *key, int value) +{ + db->hashes = (struct db_hash *)realloc(db->hashes, sizeof(struct db_hash) * (db->count + 1)); + + // zero out reallocated memory + memset(&db->hashes[db->count], 0, sizeof(struct db_hash)); + + db->hashes[db->count].type = DB_TYPE_INT; + db->hashes[db->count].value_len = sizeof(int); + db->hashes[db->count].value = (int *)malloc(sizeof(int)); + + memcpy(db->hashes[db->count].value, &value, sizeof(int)); + + return db_add_hash(db, key, db->hashes[db->count].value); } int db_del_hash(struct db_table *db, char *key) @@ -144,7 +169,7 @@ int db_del_hash(struct db_table *db, char *key) return -1; } -char *get_hash(struct db_table *db, char *key) +void *get_hash(struct db_table *db, char *key) { int i; @@ -158,3 +183,18 @@ char *get_hash(struct db_table *db, char *key) return NULL; } + +char *get_hash_char(struct db_table *db, char *key) +{ + return (char *)get_hash(db, key); +} + +int get_hash_int(struct db_table *db, char *key) +{ + int value; + + memcpy(&value, get_hash(db, key), sizeof(int)); + + return value; +} + diff --git a/test_db.c b/test_db.c index 4fbde56..df2d54a 100755 --- a/test_db.c +++ b/test_db.c @@ -11,22 +11,6 @@ int main() struct db_table *db; int i; - /* - db = (struct db_table *)malloc(sizeof(struct db_table)); - db->count = 0; - db->hashes = NULL; - - db_add_hash(db, "lua.scripts", "hello.lua,test.lua,youtube.lua"); - db_add_hash(db, "lua.scriptcount", "2"); - - if (write_db(db, FNAME) == -1) - { - printf("Error writing db\n"); - } - - free(db); - */ - if (access(FNAME, F_OK) == -1) { printf("Creating db\n"); @@ -43,8 +27,8 @@ int main() // write some data if db is empty if (db->count == 0) { - db_add_hash(db, "lua.scripts", "hello.lua,test.lua,youtube.lua"); - db_add_hash(db, "lua.scriptcount", "2"); + db_add_hash_char(db, "lua.scripts", "hello.lua,test.lua,youtube.lua"); + db_add_hash_int(db, "lua.scriptcount", 2); write_db(db, FNAME); return 0; @@ -52,7 +36,14 @@ int main() for (i = 0; i < db->count; i++) { - printf("Key: %s, Value: %s\n", db->hashes[i].key, db->hashes[i].value); + if (db->hashes[i].type == DB_TYPE_INT) + { + printf("Key: %s, Value: %d\n", db->hashes[i].key, get_hash_int(db, db->hashes[i].key)); + } + else + { + printf("Key: %s, Value: %s\n", db->hashes[i].key, get_hash_char(db, db->hashes[i].key)); + } } free(db); diff --git a/testdb b/testdb index 6aa938808ec61d27353943ff9229645a67f3bb41..5a58f5a5dc35d6d19908108730f0b13558fe3f23 100755 GIT binary patch literal 22944 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 KXmKbwQ1PG9^{#pV literal 21928 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 delta 76 zcmbQv*vjbme&5=A0t^fcOh60*4%0({fPsMr$d(7<57Qug0jM}k?FFcK!^A)*CL;y_ DmB