]> git.mdlowis.com Git - archive/carl.git/commitdiff
Added tests for delete and tweaked the API a bit
authorMike D. Lowis <mike.lowis@gentex.com>
Thu, 1 Oct 2015 16:41:20 +0000 (12:41 -0400)
committerMike D. Lowis <mike.lowis@gentex.com>
Thu, 1 Oct 2015 16:41:20 +0000 (12:41 -0400)
build.ninja
source/data/hash.c
source/data/hash.h
tests/data/hash.c

index 306242d4c8cf95d0a4610dd05546ee7050faa2ac..9a98d49523fd92d8a9b0ec6730076484304f5c3c 100644 (file)
@@ -1,9 +1,9 @@
 CC = gcc
 DEPSUFFIX = .d
 CPPFLAGS = -Isource/ -Imodules/atf/source
-CFLAGS = -g -O3 -Wall -Wextra --std=c99 --pedantic --coverage
+CFLAGS = -g -O3 -Wall -Wextra --std=c99 --pedantic
 LD = gcc
-LDFLAGS = --coverage
+LDFLAGS =
 AR = ar
 ARFLAGS = rcs
 
index 7d613fb22c272a2ac76c7bb05979bad463b03e02..7fadd122a7c0ec3116a6a5173a82fd590d8dd29e 100644 (file)
@@ -7,7 +7,7 @@
 #include <data/hash.h>
 #include <stdlib.h>
 
-#define NUM_PRIMES (sizeof(primes)/sizeof(unsigned int))
+#define NUM_PRIMES (sizeof(Primes)/sizeof(unsigned int))
 
 static unsigned int Primes[] = {
     5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
@@ -33,22 +33,24 @@ static void find_entry(hash_t* hash, hash_entry_t** parent, hash_entry_t** curre
 
 static void rehash(hash_t* hash)
 {
-    unsigned int oldcount = hash->bkt_count++;
-    hash_entry_t** oldbuckets = hash->buckets;
-    hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count));
-    hash->size = 0;
-    /* 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);
+    if ((hash->bkt_count+1) < NUM_PRIMES) {
+        unsigned int oldcount = hash->bkt_count++;
+        hash_entry_t** oldbuckets = hash->buckets;
+        hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count));
+        hash->size = 0;
+        /* 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);
     }
-    /* 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)
@@ -72,7 +74,7 @@ size_t hash_size(hash_t* hash)
     return hash->size;
 }
 
-bool hash_set(hash_t* hash, hash_entry_t* entry)
+void hash_set(hash_t* hash, hash_entry_t* entry)
 {
     if (hash->size >= num_buckets(hash->bkt_count))
         rehash(hash);
@@ -101,7 +103,6 @@ bool hash_set(hash_t* hash, hash_entry_t* entry)
     }
     if (deadite != NULL)
         hash->delfn(deadite);
-    return true;
 }
 
 hash_entry_t* hash_get(hash_t* hash, hash_entry_t* entry)
@@ -132,24 +133,22 @@ bool hash_del(hash_t* hash, hash_entry_t* entry)
             hash->buckets[index] = node;
         hash->delfn(deadite);
         ret = true;
+        hash->size--;
     }
     return ret;
 }
 
 void hash_clr(hash_t* hash)
 {
-    /* Delete all the entries  in the hash */
+    /* Delete all the entries in the hash */
     for (unsigned int i = 0; i < num_buckets(hash->bkt_count); i++) {
         hash_entry_t* node = hash->buckets[i];
+        hash->buckets[i] = NULL;
         while (node != NULL) {
             hash_entry_t* deadite = node;
             node = node->next;
             hash->delfn(deadite);
         }
     }
-    /* Shrink the buckets array */
-    free(hash->buckets);
-    hash->bkt_count = 0;
-    hash->buckets   = (hash_entry_t**)calloc(sizeof(hash_entry_t*), num_buckets(hash->bkt_count));
 }
 
index 3a22bab92de27fcb5ce29c41b5ffeb1d786b8843..0c9f54f3852815e338a071004c6ae35cf97d6cd4 100644 (file)
@@ -34,7 +34,7 @@ void hash_deinit(hash_t* hash);
 
 size_t hash_size(hash_t* hash);
 
-bool hash_set(hash_t* hash, hash_entry_t* entry);
+void hash_set(hash_t* hash, hash_entry_t* entry);
 
 hash_entry_t* hash_get(hash_t* hash, hash_entry_t* entry);
 
index fb0883e074087ef2fab07e0307aad80168ff6e6c..e77a43fdbbd0649670b7f96f640837db17fbcc51 100644 (file)
@@ -1,4 +1,3 @@
-
 // Unit Test Framework Includes
 #include "atf.h"
 
@@ -106,4 +105,74 @@ TEST_SUITE(Hash) {
         }
         hash_deinit(&hash);
     }
+
+    TEST(Verify sequential inserts and deletions)
+    {
+        uint maxval = 1000000;
+        hash_t hash;
+        hash_init(&hash, hash_func, compare_func, delete_func);
+        for (uint i = 0; i < maxval; i++)
+        {
+            int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t));
+            entry->val = i;
+            hash_set(&hash, &(entry->link));
+            CHECK(i+1 == hash_size(&hash));
+            CHECK(&(entry->link) == hash_get(&hash, &(entry->link)));
+        }
+        for (uint i = 0; i < maxval; i++)
+        {
+            int_node_t search = { .val = i };
+            CHECK(hash_del(&hash, &(search.link)));
+            CHECK((maxval - (i+1)) == hash_size(&hash));
+        }
+        hash_deinit(&hash);
+    }
+
+    TEST(Verify reverse inserts and deletions)
+    {
+        uint maxval = 1000000;
+        hash_t hash;
+        hash_init(&hash, hash_func, compare_func, delete_func);
+        for (uint i = 0; i < maxval; i++)
+        {
+            int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t));
+            entry->val = maxval - i;
+            hash_set(&hash, &(entry->link));
+            CHECK(i+1 == hash_size(&hash));
+            CHECK(&(entry->link) == hash_get(&hash, &(entry->link)));
+        }
+        for (uint i = 0; i < maxval; i++)
+        {
+            int_node_t search = { .val = i+1 };
+            CHECK(hash_del(&hash, &(search.link)));
+            CHECK((maxval - (i+1)) == hash_size(&hash));
+        }
+        hash_deinit(&hash);
+    }
+
+    TEST(Verify ping pong hash inserts and deletions)
+    {
+        uint maxval = 1000000;
+        hash_t hash;
+        hash_init(&hash, hash_func, compare_func, delete_func);
+        for (uint i = 0; i < (maxval/2); i++) {
+            /* Insert the lower number */
+            int_node_t* entry = (int_node_t*)malloc(sizeof(int_node_t));
+            entry->val = i;
+            hash_set(&hash, &(entry->link));
+            CHECK(&(entry->link) == hash_get(&hash, &(entry->link)));
+            /* Insert the higher number */
+            entry = (int_node_t*)malloc(sizeof(int_node_t));
+            entry->val = maxval - i;
+            hash_set(&hash, &(entry->link));
+            CHECK(&(entry->link) == hash_get(&hash, &(entry->link)));
+        }
+        for (uint i = 0; i < maxval; i++)
+        {
+            int_node_t search = { .val = i };
+            if (hash_get(&hash, &(search.link)))
+                CHECK(hash_del(&hash, &(search.link)));
+        }
+        hash_deinit(&hash);
+    }
 }