cutes/hash_map.c

67 lines
2.5 KiB
C

#include "hash_map.h"
#include "string.h"
#include "debug.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) {
char *key_at = ((char*)bucket.data) + (bucket.element_size * i);
if(memcmp(&hash, key_at, sizeof(uintptr_t)) == 0) {
return 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;
}