pulled in tq's hashtable
This commit is contained in:
commit
bc5e2fa754
2 changed files with 139 additions and 0 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue