From: Michael D. Lowis Date: Thu, 1 Oct 2015 02:35:09 +0000 (-0400) Subject: Fleshed out the hashtable implementation some more. Not tested at all yet X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=33ff2d087b9c778cc3c85f871f5864bbc74a68db;p=archive%2Fcarl.git Fleshed out the hashtable implementation some more. Not tested at all yet --- diff --git a/build.ninja b/build.ninja index 4f68f6a..dc8a265 100644 --- a/build.ninja +++ b/build.ninja @@ -3,7 +3,7 @@ DEPSUFFIX = .d CPPFLAGS = -Isource/ -Imodules/atf/source CFLAGS = -g -O3 -Wall -Wextra --std=c99 --pedantic LD = gcc -LDFLAGS = +LDFLAGS = AR = ar ARFLAGS = rcs @@ -57,5 +57,5 @@ build tests/data/slist.o: cc tests/data/slist.c build tests/main.o: cc tests/main.c build modules/atf/source/atf.o: cc modules/atf/source/atf.c build test_libc: ld tests/refcount.o tests/utf/test_unicodedata.o tests/data/bstree.o tests/data/slist.o tests/main.o modules/atf/source/atf.o libcarl.a -build Tests: command test_libc +build Unit$ Tests: command test_libc CMD = ./test_libc diff --git a/source/data/hash.c b/source/data/hash.c index d42475f..451ea83 100644 --- a/source/data/hash.c +++ b/source/data/hash.c @@ -16,8 +16,38 @@ static unsigned int Primes[] = { 805306457, 1610612741 }; -static inline unsigned int num_buckets(hash_t* hash) { - return Primes[hash->bkt_count]; +static inline unsigned int num_buckets(unsigned int idx) { + return Primes[idx]; +} + +static void find_entry(hash_t* hash, hash_entry_t** parent, hash_entry_t** current, hash_entry_t* entry) +{ + while(*current != NULL) { + if (((*current)->hash == entry->hash) && + (0 == hash->cmpfn(*current, entry))) + break; + *parent = *current; + *current = (*current)->next; + } +} + +static void rehash(hash_t* hash) +{ + unsigned int oldcount = hash->bkt_count++; + hash_entry_t** oldbuckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count)); + hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count)); + /* Iterate over all of the old buckets */ + for (unsigned int i = 0; i < num_buckets(oldcount); i++) { + hash_entry_t* node = oldbuckets[i]; + /* re-insert all entries in the bucket into the new bucket table */ + while (node != NULL) { + hash_entry_t* entry = node; + node = entry->next; + hash_set(hash, entry); + } + } + /* Free the old bucket table */ + free(oldbuckets); } void hash_init(hash_t* hash, hash_hashfn_t hashfn, hash_cmpfn_t cmpfn, hash_freefn_t delfn) @@ -27,59 +57,77 @@ void hash_init(hash_t* hash, hash_hashfn_t hashfn, hash_cmpfn_t cmpfn, hash_free hash->hashfn = hashfn; hash->cmpfn = cmpfn; hash->delfn = delfn; - hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash)); + hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count)); } void hash_deinit(hash_t* hash) { - (void)hash; + hash_clr(hash); + free(hash->buckets); } bool hash_set(hash_t* hash, hash_entry_t* entry) { - //if (hash->size >= num_buckets(hash)) - // rehash(hash); - unsigned int hashval = hash->hashfn(entry); - unsigned int index = (hashval % num_buckets(hash)); + if (hash->size >= num_buckets(hash->bkt_count)) + rehash(hash); + entry->hash = hash->hashfn(entry); + unsigned int index = (entry->hash % num_buckets(hash->bkt_count)); hash_entry_t* parent = NULL; hash_entry_t* node = hash->buckets[index]; - //find_entry(&parent, &node, hash); - + find_entry(hash, &parent, &node, entry); if (node != NULL) { - if (parent == NULL) { - hash_entry_t* deadite = node; - node = node->next; - hash->delfn(deadite); - } - + hash_entry_t* deadite = node; + node = node->next; + entry->next = node; + if (parent != NULL) + parent->next = entry; + else + hash->buckets[index] = entry; + hash->delfn(deadite); } else { - + hash->buckets[index] = entry; + entry->next = NULL; } return true; } hash_entry_t* hash_get(hash_t* hash, hash_entry_t* entry) { - unsigned int hashval = hash->hashfn(entry); - unsigned int index = (hashval % num_buckets(hash)); - //hash_entry_t* parent = NULL; + entry->hash = hash->hashfn(entry); + unsigned int index = (entry->hash % num_buckets(hash->bkt_count)); + hash_entry_t* parent = NULL; hash_entry_t* node = hash->buckets[index]; - //find_entry(&parent, &node, hashval, entry); + find_entry(hash, &parent, &node, entry); + (void)parent; return node; } bool hash_del(hash_t* hash, hash_entry_t* entry) { - (void)hash; - (void)entry; - return false; + bool ret = false; + entry->hash = hash->hashfn(entry); + unsigned int index = (entry->hash % num_buckets(hash->bkt_count)); + hash_entry_t* parent = NULL; + hash_entry_t* node = hash->buckets[index]; + find_entry(hash, &parent, &node, entry); + if (node != NULL) { + hash_entry_t* deadite = node; + node = node->next; + if (parent != NULL) + parent->next = node; + else + hash->buckets[index] = node; + hash->delfn(deadite); + ret = true; + } + return ret; } void hash_clr(hash_t* hash) { /* Delete all the entries in the hash */ - for (unsigned int i = 0; i < num_buckets(hash); i++) { - hash_entry_t* node = hash->buckets[0]; + for (unsigned int i = 0; i < num_buckets(hash->bkt_count); i++) { + hash_entry_t* node = hash->buckets[i]; while (node != NULL) { hash_entry_t* deadite = node; node = node->next; @@ -89,6 +137,6 @@ void hash_clr(hash_t* hash) /* Shrink the buckets array */ free(hash->buckets); hash->bkt_count = 0; - hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash)); + hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count)); } diff --git a/source/data/hash.h b/source/data/hash.h index e743769..147c0e0 100644 --- a/source/data/hash.h +++ b/source/data/hash.h @@ -9,6 +9,7 @@ #include typedef struct hash_entry_t { + unsigned int hash; struct hash_entry_t* next; } hash_entry_t;