diff --git a/SLS_C/include/sls/hash_table.h b/SLS_C/include/sls/hash_table.h index 5c4d1be..61be87d 100644 --- a/SLS_C/include/sls/hash_table.h +++ b/SLS_C/include/sls/hash_table.h @@ -11,27 +11,21 @@ #include "sls/string.h" typedef struct Bucket { - size_t key_hash_b; + uint32_t key_hash_b; void *item; struct Bucket *next; } Bucket; typedef struct { size_t buckets_count; - Bucket *buckets; + Bucket *buckets[]; } HashTable; -// Initializes a HashTable with buckets_count number of buckets. Returns NULL on Memory Allocation Error. -HashTable *init_hash_table(size_t buckets_count); +// Initializes a HashTable with atleast buckets_count number of buckets. Returns NULL on Memory Allocation Error. +HashTable *init_hash_table(size_t min_buckets_count); // Frees memory owned by the HashTable. void del_hash_table(HashTable *ht); -// The hash functions used by HashTable. Returns the hash of the string. -// static size_t sls_hash_a(SlsStr key); // For bucket index (in HashTable). -// static size_t sls_hash_b(SlsStr key); // For bucket key_id (in Bucket). -// Calculates the bucket index based on the number of buckets in the HashTable and the hash (a) of the string. -// static size_t bucket_index(const HashTable *ht, SlsStr key); - // Inserts an item into the HashTable based on its key. Returns FALSE on Memory Allocation Error. Boolean hash_table_put(HashTable *ht, SlsStr key, void *item); // Gets the item associated with the given key. Returns default item if not found. diff --git a/SLS_C/src/hash_table.c b/SLS_C/src/hash_table.c index 40bdb02..2debda8 100644 --- a/SLS_C/src/hash_table.c +++ b/SLS_C/src/hash_table.c @@ -3,4 +3,69 @@ // Hash Table // November 2025 +#include + #include "sls/hash_table.h" +#include "sls/string.h" + +static size_t next_power_of_two(size_t n); + +HashTable *init_hash_table(size_t min_buckets_count); + +void del_hash_table(HashTable *ht); + +static inline uint32_t sls_hash_a(SlsStr key) { + // FNV-1a + uint32_t hash = 2166136261u; + const uint8_t *p = (const uint8_t *)key.str; + for (size_t i = 0; i < key.len; i++) { + hash ^= p[i]; + hash *= 16777619u; + } + return hash; +} + +static inline uint32_t sls_hash_b(SlsStr key) { + // Murmur2A + const uint32_t m = 0x5bd1e995; + uint32_t hash = 0; + + while (key.len >= 4) { + uint32_t k = (uint32_t)key.str[0] + | (uint32_t)key.str[1] << 8 + | (uint32_t)key.str[2] << 16 + | (uint32_t)key.str[3] << 24; + k *= m; + k ^= k >> 24; + k *= m; + + hash *= m; + hash ^= k; + + key.str += 4; + key.len -= 4; + } + + switch (key.len) { + case 3: hash ^= key.str[2] << 16; + case 2: hash ^= key.str[1] << 8; + case 1: hash ^= key.str[0]; + hash *= m; + } + + hash ^= hash >> 13; + hash *= m; + hash ^= hash >> 15; + + return hash; +} + +static inline size_t bucket_index(const HashTable *ht, SlsStr key) { + return sls_hash_a(key) & (ht->buckets_count - 1); +} + +Boolean hash_table_put(HashTable *ht, SlsStr key, void *item); + +void *hash_table_get(const HashTable *ht, SlsStr key, void *default_item); + +Boolean hash_table_del(HashTable *ht, SlsStr key);