Added hashtable implementation

This commit is contained in:
Dan Hirsch 2012-10-08 19:20:36 +02:00
parent 69ba191783
commit 12035d66a1
2 changed files with 141 additions and 0 deletions

View file

@ -63,3 +63,117 @@ void h_slist_free(HSlist *slist) {
h_slist_pop(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);
}