pulled in tq's hashtable

This commit is contained in:
Meredith L. Patterson 2012-10-08 19:21:56 +02:00
commit bc5e2fa754
2 changed files with 139 additions and 0 deletions

View file

@ -97,3 +97,115 @@ void h_slist_free(HSlist *slist) {
h_arena_free(slist->arena, slist);
}
HHashTable* h_hashtable_new(HArena *arena) {
HHashTable *ht = h_arena_malloc(arena, sizeof(HHashTable*));
ht->hashFunc = hashFunc;
ht->equalFunc = equalFunc;
ht->capacity = 64; // to start; should be tuned later...
ht->used = 0;
ht->contents = h_arena_malloc(arena, sizeof(HHashTableEntry) * ht->capacity);
memset(ht->contents, sizeof(HHashTableEntry) * ht->capacity);
return ht;
}
void* h_hashtable_get(HHashTable* ht, void* key) {
HHashValue hashval = ht->hashFunc(key);
#ifdef CONSISTENCY_CHECK
assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2
#endif
for (HHashTableEntry *hte = &ht->contents[hashval & (ht->capacity - 1)];
hte != NULL;
hte = hte->next) {
if (hte->hashval != hashval)
continue;
if (ht->equalFunc(key, hte->key))
return hte->value;
}
return NULL;
}
void h_hashtable_put(HHashTable* ht, void* key, void* value) {
// # Start with a rebalancing
h_hashtable_ensure_capacity(ht, ht->used + 1);
HHashValue hashval = ht->hashFunc(key);
#ifdef CONSISTENCY_CHECK
assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2
#endif
hte = &ht->contents[hashval & (ht->capacity - 1)];
if (hte->key != NULL) {
do {
if (hte->hashval == hashval && ht->equalFunc(key, hte->key))
goto insert_here;
} while (hte->next);
// Add a new link...
assert (hte->next == NULL);
hte->next = h_arena_malloc(ht->arena, sizeof(HHashTableEntry));
hte = hte->next;
hte->next = NULL;
}
insert_here:
hte->key = key;
hte->value = value;
hte->hashval = hashval;
}
int h_hashtable_present(HHashTable* ht, void* key) {
HHashValue hashval = ht->hashFunc(key);
#ifdef CONSISTENCY_CHECK
assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2
#endif
for (HHashTableEntry *hte = &ht->contents[hashval & (ht->capacity - 1)];
hte != NULL;
hte = hte->next) {
if (hte->hashval != hashval)
continue;
if (ht->equalFunc(key, hte->key))
return true;
}
return false;
}
void h_hashtable_del(HHashTable* ht, void* key) {
HHashValue hashval = ht->hashFunc(key);
#ifdef CONSISTENCY_CHECK
assert((ht->capacity & (ht->capacity - 1)) == 0); // capacity is a power of 2
#endif
for (HHashTableEntry *hte = &ht->contents[hashval & (ht->capacity - 1)];
hte != NULL;
hte = hte->next) {
if (hte->hashval != hashval)
continue;
if (ht->equalFunc(key, hte->key)) {
// FIXME: Leaks keys and values.
HHashTableEntry* hten = hte->next;
if (hten != NULL) {
*hte = *hten;
h_arena_free(ht->arena, hten);
} else {
hte->key = hte->value = NULL;
hte->hashval = 0;
}
return;
}
}
}
void h_hashtable_free(HHashTable* ht) {
for (i = 0; i < ht->capacity; i++) {
HHashTableEntry *hten, *hte = &ht->contents[i];
// FIXME: Free key and value
hte = hte->next;
while (hte != NULL) {
// FIXME: leaks keys and values.
hten = hte->next;
h_arena_free(ht->arena, hte);
hte = hten;
}
}
h_arena_free(ht->arena, ht->contents);
}

View file

@ -172,6 +172,33 @@ bool h_slist_find(HSlist *slist, const void* item);
HSlist* h_slist_remove_all(HSlist *slist, const void* item);
void h_slist_free(HSlist *slist);
typedef unsigned int HHashValue;
typedef HHashValue (*HHashFunc)(const void* key);
typedef bool (*HEqualFunc)(const void* key1, const void* key2);
typedef struct HHashTableEntry_ {
struct HHashTableEntry_ *next;
void* key;
void* value;
HHashValue hashval;
} HHashTableEntry;
typedef struct HHashTable_ {
HHashTableEntry *contents;
HHashFunc hashFunc;
HEqualFunc equalFunc;
int capacity;
int used;
} HHashTable;
HHashTable* h_hashtable_new(HArena *arena, );
void* h_hashtable_get(HHashTable* ht, void* key);
void h_hashtable_put(HHashTable* ht, void* key, void* value);
int h_hashtable_present(HHashTable* ht, void* key);
void h_hashtable_del(HHashTable* ht, void* key);
void h_hashtable_free(HHashTable* ht);
#if 0
#include <malloc.h>
#define arena_malloc(a, s) malloc(s)