#include "hash_map.h" #include #include #include #include #include #include /* ** Hash the key using FNV-1a 32 bits hash algorithm. */ static size_t hash(const char *key) { if (key == NULL) return 0; uint32_t hash = 2166136261; // FNV offset basis uint32_t prime = 16777619; // FNV prime while (*key != 0) { hash ^= *key; hash *= prime; key++; } return hash; } struct hash_map *hash_map_init(size_t size) { struct hash_map *p = malloc(sizeof(struct hash_map)); if (p != NULL) { p->data = calloc(size, sizeof(struct pair_list *)); if (p->data == NULL) { free(p); return NULL; } p->size = size; } return p; } bool hash_map_insert(struct hash_map *hash_map, const char *key, void *value, bool *updated) { if (hash_map == NULL || hash_map->size == 0 || key == NULL) return false; size_t h = hash(key); struct pair_list **l = hash_map->data; size_t i = h % hash_map->size; if (l[i] != NULL) { // check if key is in linked list struct pair_list *iter = l[i]; while (iter) { if (strcmp(iter->key, key) == 0) { // update iter->value = value; if (updated) *updated = true; return true; } iter = iter->next; } // if not found => collision } struct pair_list *p = malloc(sizeof(struct pair_list)); if (p == NULL) return false; if (updated) *updated = false; p->key = key; p->value = value; p->next = l[i]; l[i] = p; l[i] = p; return true; } void hash_map_free(struct hash_map *hash_map) { struct pair_list *l; struct pair_list *prev; if (hash_map) { for (size_t i = 0; i < hash_map->size; i++) { l = hash_map->data[i]; while (l != NULL) { prev = l; l = l->next; free(prev); } } free(hash_map->data); free(hash_map); } } void hash_map_foreach(struct hash_map *hash_map, void (*fn)(const char *, const void *)) { if (hash_map == NULL) return; struct pair_list *iter; for (size_t i = 0; i < hash_map->size; i++) { iter = hash_map->data[i]; while (iter != NULL) { fn(iter->key, iter->value); iter = iter->next; } } } const void *hash_map_get(const struct hash_map *hash_map, const char *key) { if (hash_map == NULL || hash_map->size == 0) return NULL; size_t h = hash(key); size_t i = h % hash_map->size; struct pair_list *l = hash_map->data[i]; while (l != NULL) { if (strcmp(l->key, key) == 0) return l->value; l = l->next; } return NULL; } bool hash_map_remove(struct hash_map *hash_map, const char *key) { if (hash_map == NULL || hash_map->size == 0) return false; size_t h = hash(key); size_t i = h % hash_map->size; struct pair_list *l = hash_map->data[i]; struct pair_list *p = NULL; while (l != NULL) { if (strcmp(l->key, key) == 0) { if (p != NULL) p->next = l->next; else hash_map->data[i] = l->next; free(l); return true; } p = l; l = l->next; } return false; }