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);
|
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);
|
HSlist* h_slist_remove_all(HSlist *slist, const void* item);
|
||||||
void h_slist_free(HSlist *slist);
|
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
|
#if 0
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#define arena_malloc(a, s) malloc(s)
|
#define arena_malloc(a, s) malloc(s)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue