feat: added HashMap type
parent
172d1ee10e
commit
c4ec92fa82
|
@ -0,0 +1,58 @@
|
||||||
|
#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 ++key_at;
|
||||||
|
}
|
||||||
|
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[sizeof(uintptr_t) + self->key_size + self->value_size];
|
||||||
|
memcpy(data, &hash, sizeof(uintptr_t)); // copy key hash into start of data
|
||||||
|
memcpy(data + sizeof(uintptr_t), key, self->key_size);
|
||||||
|
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_init(self->key_size);
|
||||||
|
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)
|
||||||
|
list_add(&keys, list_at(self->buckets + bucket_index, key_index));
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
List hash_map_values(HashMap *self) {
|
||||||
|
List values = list_init(self->value_size);
|
||||||
|
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)
|
||||||
|
list_add(&values, ((char*)list_at(self->buckets + bucket_index, value_index)) + (sizeof(uintptr_t) + self->key_size));
|
||||||
|
return values;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef CUTES_HASH_MAP_H
|
||||||
|
#define CUTES_HASH_MAP_H
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "typeclass_helpers.h"
|
||||||
|
|
||||||
|
#define CUTES_HASH_MAP_BUCKETS 24
|
||||||
|
|
||||||
|
typedef uintptr_t (*HashFunc)(void *data);
|
||||||
|
|
||||||
|
typedef struct HashMap {
|
||||||
|
List buckets[CUTES_HASH_MAP_BUCKETS];
|
||||||
|
HashFunc hasher;
|
||||||
|
size_t key_size;
|
||||||
|
size_t value_size;
|
||||||
|
} HashMap;
|
||||||
|
|
||||||
|
HashMap hash_map_from_sizes(size_t key_size, size_t value_size, HashFunc hasher);
|
||||||
|
void hash_map_empty(HashMap *self);
|
||||||
|
void *hash_map_get_raw(HashMap *self, void *key);
|
||||||
|
void hash_map_insert(HashMap *self, void *key, void *value);
|
||||||
|
List hash_map_keys(HashMap *self);
|
||||||
|
List hash_map_values(HashMap *self);
|
||||||
|
|
||||||
|
#define hash_map_from_types(TKey, TValue, KeyHasher) (hash_map_from_sizes(sizeof(TKey), sizeof(TValue), (HashFunc)KeyHasher)); TC_FN_TYPECHECK(uintptr_t, KeyHasher, TKey*)
|
||||||
|
#define hash_map_get_as(TValue, Self, Key) ((TValue*)hash_map_get_raw(Self, Key))
|
||||||
|
|
||||||
|
#endif // !CUTES_HASH_MAP_H
|
Loading…
Reference in New Issue