diff --git a/inc/utils/hashmap.h b/inc/utils/hashmap.h new file mode 100644 index 0000000..23540ad --- /dev/null +++ b/inc/utils/hashmap.h @@ -0,0 +1,28 @@ +// This file is part of noxos and licensed under the MIT open source license + +#ifndef NOXOS_HASHMAP_H +#define NOXOS_HASHMAP_H + +#include + +typedef struct hashmap_entry_T hashmap_entry_T; +struct hashmap_entry_T { + bool in_use; + uint64_t key; + void* value; + hashmap_entry_T* prev; + hashmap_entry_T* next; +}; + +typedef struct { + uint64_t size; + hashmap_entry_T* entries; +} hashmap_T; + +hashmap_T hashmap_create (uint64_t size); +void hashmap_destruct (hashmap_T* hashmap); +void hashmap_insert (hashmap_T* hashmap, uint64_t key, void* value); +void hashmap_delete (hashmap_T* hashmap, uint64_t key); +void* hashmap_lookup (hashmap_T* hashmap, uint64_t key); + +#endif //NOXOS_HASHMAP_H diff --git a/src/utils/hashmap.c b/src/utils/hashmap.c new file mode 100644 index 0000000..3ff85e4 --- /dev/null +++ b/src/utils/hashmap.c @@ -0,0 +1,84 @@ +// This file is part of noxos and licensed under the MIT open source license + +#include +#include + +hashmap_T hashmap_create(uint64_t size) { + hashmap_T hashmap; + + hashmap.size = size; + hashmap.entries = memory_allocate(size * sizeof(hashmap_entry_T)); + memory_set(hashmap.entries, 0, size * sizeof(hashmap_entry_T)); + + return hashmap; +} + +void hashmap_destruct (hashmap_T* hashmap) { + for (uint64_t i = 0; i < hashmap->size; i++) { + hashmap_entry_T* entry = hashmap->entries[i].next; + + while (entry != NULL) { + hashmap_entry_T* next = entry->next; + memory_free(entry); + entry = next; + } + } + memory_free(hashmap->entries); +} + +void hashmap_insert(hashmap_T* hashmap, uint64_t key, void* value) { + uint64_t index = key % hashmap->size; + + if (!hashmap->entries[index].in_use) { + hashmap->entries[index].key = key; + hashmap->entries[index].value = value; + hashmap->entries[index].in_use = true; + return; + } + + hashmap_entry_T* entry = &hashmap->entries[index]; + while (entry->next != NULL) entry = entry->next; + + entry->next = memory_allocate(sizeof(hashmap_entry_T)); + entry->next->prev = entry; + entry->next->key = key; + entry->next->value = value; + entry->next->in_use = true; +} + +void hashmap_delete(hashmap_T* hashmap, uint64_t key) { + uint64_t index = key % hashmap->size; + + hashmap_entry_T* entry = &hashmap->entries[index]; + while (entry->key != key) { + if (entry->next == NULL) return; + entry = entry->next; + } + + if (entry->prev != NULL) { + entry->prev->next = entry->next; + + if (entry->next != NULL) entry->next->prev = entry->prev; + + memory_free(entry); + return; + } + + entry->key = 0; + entry->value = NULL; + entry->in_use = false; +} + +void* hashmap_lookup(hashmap_T* hashmap, uint64_t key) { + uint64_t index = key % hashmap->size; + + hashmap_entry_T* entry = &hashmap->entries[index]; + while (entry->key != key) { + if (entry->next == NULL) return NULL; + entry = entry->next; + } + + if (!entry->in_use) return NULL; + + return entry->value; +} \ No newline at end of file