89 lines
2.3 KiB
C
89 lines
2.3 KiB
C
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include "sdbm.h"
|
||
|
#include "hashtable.h"
|
||
|
|
||
|
bool hashtable_expand(hashtable* table) {
|
||
|
size_t oldcapacity = table->capacity;
|
||
|
size_t newcapacity = oldcapacity << 1;
|
||
|
hashtable_item* olditems = table->items;
|
||
|
hashtable_item* newitems = calloc(newcapacity, sizeof(hashtable_item));
|
||
|
if (newitems == NULL)
|
||
|
return false;
|
||
|
hashtable temptable;
|
||
|
temptable.capacity = newcapacity;
|
||
|
temptable.filled = 0;
|
||
|
temptable.items = newitems;
|
||
|
for (size_t i = 0; i < oldcapacity; i++) {
|
||
|
if (olditems[i].name == NULL)
|
||
|
continue;
|
||
|
size_t index = hashtable_insert(&temptable, olditems[i].name);
|
||
|
newitems[index].data = olditems[i].data;
|
||
|
}
|
||
|
table->capacity = newcapacity;
|
||
|
table->filled = temptable.filled;
|
||
|
table->items = newitems;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
hashtable* hashtable_create(void) {
|
||
|
hashtable* table = malloc(sizeof(hashtable));
|
||
|
table->capacity = 16;
|
||
|
table->items = calloc(16, sizeof(hashtable_item));
|
||
|
return table;
|
||
|
}
|
||
|
|
||
|
size_t_optional hashtable_key(hashtable* table, char* name) {
|
||
|
size_t index = sdbm(name) & (table->capacity - 1);
|
||
|
hashtable_item* array = table->items;
|
||
|
while (1) {
|
||
|
if (array[index].name == NULL)
|
||
|
return (size_t_optional) { false, 0 };
|
||
|
if (!strcmp(name, array[index].name))
|
||
|
return (size_t_optional) { true, index };
|
||
|
else
|
||
|
index = (index + 1) & (table->capacity - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
size_t hashtable_insert(hashtable* table, char* name) {
|
||
|
size_t index = sdbm(name) & (table->capacity - 1);
|
||
|
hashtable_item* array = table->items;
|
||
|
if ((table->capacity >> 2) * 3 < table->filled) {
|
||
|
hashtable_expand(table);
|
||
|
}
|
||
|
while (1) {
|
||
|
if (array[index].name == NULL) {
|
||
|
array[index].name = malloc(strlen(name) + sizeof(name));
|
||
|
strcpy(array[index].name, name);
|
||
|
table->filled++;
|
||
|
return index;
|
||
|
}
|
||
|
else
|
||
|
if (!strcmp(array[index].name, name))
|
||
|
return index;
|
||
|
else
|
||
|
index = (index + 1) & (table->capacity - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void hashtable_destroy(hashtable* table) {
|
||
|
hashtable_item* array = table->items;
|
||
|
for (size_t i = 0; i < table->capacity; i++)
|
||
|
free(array[i].name);
|
||
|
free(table);
|
||
|
}
|
||
|
|
||
|
void* hashtable_get(hashtable* table, char* name) {
|
||
|
size_t_optional index = hashtable_key(table, name);
|
||
|
if (!index.exists)
|
||
|
return NULL;
|
||
|
return table->items[index.sizet].data;
|
||
|
}
|
||
|
|
||
|
void hashtable_set(hashtable* table, char* name, void* data) {
|
||
|
size_t index = hashtable_insert(table, name);
|
||
|
table->items[index].data = data;
|
||
|
}
|