]> git.mdlowis.com Git - archive/carl.git/commitdiff
Fleshed out the hashtable implementation some more. Not tested at all yet
authorMichael D. Lowis <mike@mdlowis.com>
Thu, 1 Oct 2015 02:35:09 +0000 (22:35 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Thu, 1 Oct 2015 02:35:09 +0000 (22:35 -0400)
build.ninja
source/data/hash.c
source/data/hash.h

index 4f68f6a1b696637ae2584baaf35e29ebe6f75a0b..dc8a265a140ae3ad2c080a5b5d38eb839cce7734 100644 (file)
@@ -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
index d42475ff8b360eb1b2f2724c56f8bac34073bee7..451ea83531a088840c6997d32ff965adf983cd0c 100644 (file)
@@ -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));
 }
 
index e743769d1ec3c701c4a2b6981798ef34ddf92ff4..147c0e0346a024f17c2a659cce3a3a29cd930d9e 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdbool.h>
 
 typedef struct hash_entry_t {
+    unsigned int hash;
     struct hash_entry_t* next;
 } hash_entry_t;