parent
90d4e52169
commit
967a9ace62
81
src/map.c
81
src/map.c
|
@ -1,81 +0,0 @@
|
|||
#include "map.h"
|
||||
#include "memory.h"
|
||||
#include "math.h"
|
||||
#include "debug.h"
|
||||
|
||||
HashMap hash_map_from_sizes(size_t ksize, size_t vsize, HashFn hasher) {
|
||||
return (HashMap) {
|
||||
.data = list_init(ksize + vsize + sizeof(uintptr_t)),
|
||||
.hasher = hasher,
|
||||
.key_size = ksize,
|
||||
.value_size = vsize,
|
||||
};
|
||||
}
|
||||
|
||||
void hash_map_empty(HashMap* self) {
|
||||
list_empty(&self->data);
|
||||
}
|
||||
|
||||
static inline
|
||||
uintptr_t _internal_get_hash(HashMap* self, size_t at) {
|
||||
return *list_at_as(uintptr_t, &self->data, at);
|
||||
}
|
||||
|
||||
static inline
|
||||
void* _internal_get_key(HashMap* self, size_t at) {
|
||||
return (void*)(list_at_as(uint8_t, &self->data, at) + sizeof(uintptr_t) + self->value_size);
|
||||
}
|
||||
|
||||
static inline
|
||||
void* _internal_get_value(HashMap* self, size_t at) {
|
||||
return (void*)(list_at_as(uint8_t, &self->data, at) + sizeof(uintptr_t));
|
||||
}
|
||||
|
||||
static inline
|
||||
size_t _internal_search(HashMap* self, uintptr_t hash) {
|
||||
int left = 0;
|
||||
int right = self->data.len - 1;
|
||||
int m;
|
||||
|
||||
while(left <= right) {
|
||||
m = floor((float)(left + right) / 2.0);
|
||||
if(*list_at_as(uintptr_t, &self->data, m) < hash) {
|
||||
left = m + 1;
|
||||
} else if(*list_at_as(uintptr_t, &self->data, m) > hash) {
|
||||
right = m - 1;
|
||||
} else {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
||||
return self->data.len;
|
||||
}
|
||||
|
||||
void hash_map_insert(HashMap* self, void* key, void* value) {
|
||||
const uintptr_t hash = self->hasher(key);
|
||||
const size_t target_index = _internal_search(self, hash);
|
||||
|
||||
list_reserve(&self->data, self->data.len + 1);
|
||||
self->data.len += 1;
|
||||
|
||||
uint8_t* target_address = list_at(&self->data, target_index);
|
||||
|
||||
uintptr_t* target_hash = (uintptr_t*)target_address;
|
||||
uint8_t* target_value = target_address + sizeof(uintptr_t);
|
||||
uint8_t* target_key = target_value + self->value_size;
|
||||
|
||||
*target_hash = hash;
|
||||
memcpy(target_value, value, self->value_size);
|
||||
memcpy(target_key, key, self->key_size);
|
||||
}
|
||||
|
||||
void hash_map_erase(HashMap* self, void* key) {
|
||||
const size_t target_index = _internal_search(self, self->hasher(key));
|
||||
ASSERT_RETURN(target_index < self->data.len,, "Attempted to erase a hashmap by a key that is not in the hashmap");
|
||||
list_erase(&self->data, target_index);
|
||||
}
|
||||
|
||||
void* hash_map_at(HashMap* self, void* key) {
|
||||
const size_t target_index = _internal_search(self, self->hasher(key));
|
||||
return list_at(&self->data, target_index);
|
||||
}
|
28
src/map.h
28
src/map.h
|
@ -1,28 +0,0 @@
|
|||
#ifndef _fencer_hashmap_h
|
||||
#define _fencer_hashmap_h
|
||||
|
||||
#include "stdint.h"
|
||||
#include "list.h"
|
||||
|
||||
typedef uintptr_t (*HashFn)(void*);
|
||||
|
||||
typedef struct HashMap {
|
||||
HashFn hasher;
|
||||
List data;
|
||||
size_t key_size;
|
||||
size_t value_size;
|
||||
} HashMap;
|
||||
|
||||
extern HashMap hash_map_from_sizes(size_t key_size, size_t value_size, HashFn hasher);
|
||||
extern void hash_map_empty(HashMap* self);
|
||||
extern void hash_map_insert(HashMap* self, void* key, void* value);
|
||||
extern void hash_map_erase(HashMap* self, void* key);
|
||||
extern void* hash_map_at(HashMap* self, void* key);
|
||||
|
||||
#define hash_map_at_as(__Type, __Map, __Key)\
|
||||
((__Type*)hash_map_at(__Map, __Key))
|
||||
|
||||
#define hash_map_from_types(__KType, __VType, __Hasher)\
|
||||
(hash_map_from_sizes(sizeof(__KType), sizeof(_VType), __Hasher))
|
||||
|
||||
#endif // !_fencer_hashmap_h
|
Loading…
Reference in a new issue