16 #if !defined __clang_analyzer__
17 #error "KEY must be defined to for a hashmap template"
24 #define KEY_DELETE key_delete
26 #define KEY_CLONE key_clone
32 #if !defined __clang_analyzer__
33 #error "The hash function for K must be defined"
36 #define KEY_HASH key_hash
40 #define KEY_EQ(key_1, key_2) (*(key_1) == *(key_2))
43#if !defined KEY_DELETE
44 #define KEY_DELETE(key)
48 #define KEY_CLONE(value) (*(value))
52 #if !defined __clang_analyzer__
53 #error "VALUE must be defined to for a hashmap template"
60 #define VALUE_DELETE value_delete
62 #define VALUE_CLONE value_clone
65#if !defined VALUE_DELETE
66 #define VALUE_DELETE(value)
69#if !defined VALUE_CLONE
70 #define VALUE_CLONE(value) (*(value))
73#define KEY_ENTRY NS(SELF, key_entry)
102 .capacity = real_capacity,
127 for (
size_t i = 0; i < self->capacity; i++) {
128 if (self->keys[i].present) {
129 KEY_ENTRY const* old_entry = &self->keys[i];
140 .capacity = self->capacity,
141 .items = self->items,
144 .alloc = self->alloc,
155 if (target_capacity > self->capacity) {
157 for (
size_t index = 0; index < self->capacity; index++) {
175 uint16_t distance_from_desired = 0;
178 VALUE* placed_entry = NULL;
189 KEY switch_key = entry->
key;
191 VALUE switch_value = self->values[index];
195 self->values[index] = value;
198 distance_from_desired = switch_distance_from_desired;
199 value = switch_value;
202 placed_entry = &self->values[index];
206 distance_from_desired++;
212 self->values[index] = value;
214 placed_entry = &self->values[index];
237 return &self->values[index];
261 return &self->values[index];
287 *destination = self->values[index];
296 size_t free_index = index;
300 KEY_ENTRY* check_entry = &self->keys[check_index];
303 free_entry->
key = check_entry->
key;
305 self->values[free_index] = self->values[check_index];
307 free_index = check_index;
308 free_entry = check_entry;
311 check_entry = &self->keys[check_index];
347#define KV_PAIR NS(SELF, kv)
354#define ITER NS(SELF, iter)
364 if (iter->index < iter->map->capacity) {
365 iter->curr = (
KV_PAIR){.key = &iter->map->keys[iter->index].key,
366 .value = &iter->map->values[iter->index]};
368 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
376static bool NS(ITER,
empty)(ITER
const* iter) {
378 return iter->index >= iter->map->capacity;
383 size_t first_index = 0;
384 while (first_index < self->capacity && !self->keys[first_index].present) {
389 .index = first_index,
390 .curr = (
KV_PAIR){.key = NULL, .value = NULL},
398 for (
size_t i = 0; i < self->capacity; i++) {
399 if (self->keys[i].present) {
412#define KV_PAIR_CONST NS(SELF, kv_const)
419#define ITER_CONST NS(SELF, iter_const)
429 if (iter->index < iter->map->capacity) {
430 iter->curr = (
KV_PAIR_CONST){.key = &iter->map->keys[iter->index].key,
431 .value = &iter->map->values[iter->index]};
433 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
441static bool NS(ITER_CONST,
empty)(ITER_CONST
const* iter) {
443 return iter->index >= iter->map->capacity;
448 size_t first_index = 0;
449 while (first_index < self->capacity && !self->keys[first_index].present) {
454 .index = first_index,
static void free(SELF *self, void *ptr)
static void * malloc(SELF *self, size_t size)
static void * calloc(SELF *self, size_t count, size_t size)
static size_t const INITIAL_CAPACITY
static size_t apply_capacity_policy(size_t capacity)
static size_t modulus_power_of_2_capacity(size_t index, size_t capacity)
#define DEBUG_ASSERT(expr)
uint16_t distance_from_desired
gdb_marker derive_c_hashmap
A simple open-addressed hashmap using robin-hood hashing.
static INDEX insert(SELF *self, VALUE value)
static ITER_CONST get_iter_const(SELF const *self)
static bool empty(ITER const *iter)
static ITER get_iter(SELF *self)
static SELF new_with_capacity_for(INDEX_TYPE items, ALLOC *alloc)
static INDEX_TYPE size(SELF const *self)
static IV_PAIR const * next(ITER *iter)
static VALUE remove(SELF *self, INDEX index)
static VALUE * try_write(SELF *self, INDEX index)
static bool delete_entry(SELF *self, INDEX index)
static VALUE const * read(SELF const *self, INDEX index)
static VALUE * write(SELF *self, INDEX index)
static value_t value_clone(value_t const *self)
static void value_delete(value_t *UNUSED(self))
static bool try_remove(SELF *self, INDEX index, VALUE *destination)
static SELF clone(SELF const *self)
static VALUE const * try_read(SELF const *self, INDEX index)
static key_t key_clone(key_t const *self)
static void key_delete(key_t *UNUSED(self))
static VALUE * try_insert(SELF *self, KEY key, VALUE value)
static bool key_eq(key_t const *key_1, key_t const *key_2)
static void extend_capacity_for(SELF *self, size_t expected_items)
static size_t key_hash(key_t const *key)