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
#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,
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)
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);
}
if (deadite != NULL)
hash->delfn(deadite);
- return true;
}
hash_entry_t* hash_get(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));
}
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);
-
// Unit Test Framework Includes
#include "atf.h"
}
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);
+ }
}