#include "hash_map.h" #include "string.h" HashMap hash_map_from_sizes(size_t key, size_t value, HashFunc hasher) { HashMap self = { .hasher = hasher, .key_size = key, .value_size = value }; for(size_t i = 0; i < CUTES_HASH_MAP_BUCKETS; ++i) self.buckets[i] = list_init(sizeof(uintptr_t) + key + value); return self; } void hash_map_empty(HashMap *self) { for(size_t i = 0; i < CUTES_HASH_MAP_BUCKETS; ++i) { list_empty(self->buckets + i); } } void *hash_map_get_raw(HashMap *self, void *key) { uintptr_t hash = self->hasher(key); // hash the key first List bucket = self->buckets[hash % CUTES_HASH_MAP_BUCKETS]; // get the bucket to search // linear search through the bucket to find the element for(size_t i = 0; i < bucket.len; ++i) { uintptr_t *key_at = list_at(&bucket, i); if(hash == *key_at) return ((char*)key_at) + sizeof(uintptr_t) + self->key_size; } return NULL; } void hash_map_insert(HashMap *self, void *key, void *value) { uintptr_t hash = self->hasher(key); // stage key-value-pair data char data[self->buckets[0].element_size]; memcpy(data, &hash, sizeof(uintptr_t)); // copy key hash into start of data memcpy(data + sizeof(uintptr_t), key, self->key_size); // copy key after hash memcpy(data + sizeof(uintptr_t) + self->key_size, value, self->value_size); // copy value into end of data // insert staged data into list list_add(self->buckets + (hash % CUTES_HASH_MAP_BUCKETS), data); } List hash_map_keys(HashMap *self) { List keys = list_from_type(void*); for(size_t bucket_index = 0; bucket_index < CUTES_HASH_MAP_BUCKETS; ++bucket_index) { for(size_t key_index = 0; key_index < self->buckets[bucket_index].len; ++key_index) { void *key = list_at(self->buckets + bucket_index, key_index) + sizeof(uintptr_t); list_add(&keys, &key); } } return keys; } List hash_map_values(HashMap *self) { List values = list_from_type(void*); for(size_t bucket_index = 0; bucket_index < CUTES_HASH_MAP_BUCKETS; ++bucket_index) { for(size_t value_index = 0; value_index < self->buckets[bucket_index].len; ++value_index) { void *value = ((char*)list_at(self->buckets + bucket_index, value_index)) + (sizeof(uintptr_t) + self->key_size); list_add(&values, &value); } } return values; }