diff --git a/hashtable.c b/hashtable.c index ba4356d..fc42eca 100644 --- a/hashtable.c +++ b/hashtable.c @@ -16,10 +16,16 @@ bool hashtable_expand(hashtable* table) { temptable.filled = 0; temptable.items = newitems; for (size_t i = 0; i < oldcapacity; i++) { - if (olditems[i].name == NULL) + if (olditems[i].name == NULL || olditems[i].name == (void*)1) continue; - size_t index = hashtable_insert(&temptable, olditems[i].name); - newitems[index].data = olditems[i].data; + size_t_optional index = hashtable_insert(&temptable, olditems[i].name); + if (!index.exists) { + hashtable_item* array = temptable.items; + for (size_t i = 0; i < temptable.capacity; i++) + free(array[i].name); + return false; + } + newitems[index.sizet].data = olditems[i].data; } table->capacity = newcapacity; table->filled = temptable.filled; @@ -29,6 +35,8 @@ bool hashtable_expand(hashtable* table) { hashtable* hashtable_create(void) { hashtable* table = malloc(sizeof(hashtable)); + if (table == NULL) + return NULL; table->capacity = 16; table->items = calloc(16, sizeof(hashtable_item)); return table; @@ -40,29 +48,29 @@ size_t_optional hashtable_key(hashtable* table, char* name) { 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); + if (array[index].name != (void*)(1)) + if (!strcmp(name, array[index].name)) + return (size_t_optional) { true, index }; + index = (index + 1) & (table->capacity - 1); } } -size_t hashtable_insert(hashtable* table, char* name) { +size_t_optional 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) { + if (array[index].name == NULL || array[index].name == (void*)1) { array[index].name = malloc(strlen(name) + sizeof(name)); strcpy(array[index].name, name); table->filled++; - return index; + return (size_t_optional) {true, index}; } else if (!strcmp(array[index].name, name)) - return index; + return (size_t_optional) {true, index}; else index = (index + 1) & (table->capacity - 1); } @@ -83,6 +91,22 @@ void* hashtable_get(hashtable* table, char* name) { } void hashtable_set(hashtable* table, char* name, void* data) { - size_t index = hashtable_insert(table, name); - table->items[index].data = data; + size_t_optional index = hashtable_insert(table, name); + if (index.exists) + table->items[index.sizet].data = data; +} + +void hashtable_delete(hashtable* table, char* name) { + size_t_optional index = hashtable_key(table, name); + if (index.exists) { + table->items[index.sizet].name = (void*)1; + table->filled--; + } +} + +void hashtable_forall(hashtable* table, void (*callback)(char*, void*)) { + size_t capacity = table->capacity; + hashtable_item* items = table->items; + for (size_t i = 0; i < capacity; i++) + callback(items[i].name, items[i].data); } diff --git a/hashtable.h b/hashtable.h index 0c4c575..5497be2 100644 --- a/hashtable.h +++ b/hashtable.h @@ -23,8 +23,12 @@ void hashtable_destroy(hashtable*); size_t_optional hashtable_key(hashtable*, char*); -size_t hashtable_insert(hashtable*, char*); +size_t_optional hashtable_insert(hashtable*, char*); void* hashtable_get(hashtable* table, char* name); void hashtable_set(hashtable* table, char* name, void* data); + +void hashtable_delete(hashtable*, char*); + +void hashtable_forall(hashtable*, void (*)(char*, void*));