19#ifndef __clang_analyzer__
20#error "Key type must be defined to for a hashmap template"
24} derive_c_parameter_key;
25#define K derive_c_parameter_key
26static void derive_c_parameter_key_delete(derive_c_parameter_key*
UNUSED(key)) {}
27#define K_DELETE derive_c_parameter_key_delete
31#ifndef __clang_analyzer__
32#error "Value type must be defined to for a hashmap template"
36} derive_c_parameter_value;
37#define V derive_c_parameter_value
38static void derive_c_parameter_value_delete(derive_c_parameter_value*
UNUSED(key)) {}
39#define V_DELETE derive_c_parameter_value_delete
43#ifndef __clang_analyzer__
44#error "The hash function for K must be defined"
46static size_t derive_c_parameter_hash(derive_c_parameter_key
const* key);
47#define HASH derive_c_parameter_hash
51#ifndef __clang_analyzer__
52#error "The equality function for K must be defined"
54static bool derive_c_parameter_eq(derive_c_parameter_key
const* key_1,
55 derive_c_parameter_key
const* key_2);
56#define EQ derive_c_parameter_eq
64#define V_DELETE(value)
67#define KEY_ENTRY NAME(SELF, key_entry)
96 .capacity = real_capacity,
122 for (
size_t i = 0; i < self->capacity; i++) {
123 if (self->keys[i].present) {
124 keys[i] = self->keys[i];
125 values[i] = self->values[i];
130 .capacity = self->capacity,
131 .items = self->items,
134 .alloc = self->alloc,
145 if (target_capacity > self->capacity) {
147 for (
size_t index = 0; index < self->capacity; index++) {
165 uint16_t distance_from_desired = 0;
166 size_t hash =
HASH(&key);
168 V* placed_entry = NULL;
174 if (
EQ(&entry->
key, &key)) {
179 K switch_key = entry->
key;
181 V switch_value = self->values[index];
185 self->values[index] = value;
188 distance_from_desired = switch_distance_from_desired;
189 value = switch_value;
192 placed_entry = &self->values[index];
196 distance_from_desired++;
202 self->values[index] = value;
204 placed_entry = &self->values[index];
220 size_t hash =
HASH(&key);
226 if (
EQ(&entry->
key, &key)) {
227 return &self->values[index];
244 size_t hash =
HASH(&key);
250 if (
EQ(&entry->
key, &key)) {
251 return &self->values[index];
268 size_t hash =
HASH(&key);
274 if (
EQ(&entry->
key, &key)) {
277 *destination = self->values[index];
286 size_t free_index = index;
290 KEY_ENTRY* check_entry = &self->keys[check_index];
293 free_entry->
key = check_entry->
key;
295 self->values[free_index] = self->values[check_index];
297 free_index = check_index;
298 free_entry = check_entry;
301 check_entry = &self->keys[check_index];
337#define KV_PAIR NAME(SELF, kv)
344#define ITER NAME(SELF, iter)
355 if (iter->index < iter->map->capacity) {
356 iter->curr = (
KV_PAIR){.key = &iter->map->keys[iter->index].key,
357 .value = &iter->map->values[iter->index]};
360 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
375 return iter->index >= iter->map->capacity;
380 size_t first_index = 0;
381 while (first_index < self->capacity && !self->keys[first_index].present) {
386 .index = first_index,
388 .curr = (
KV_PAIR){.key = NULL, .value = NULL},
396 for (
size_t i = 0; i < self->capacity; i++) {
397 if (self->keys[i].present) {
410#define KV_PAIR_CONST NAME(SELF, kv_const)
417#define ITER_CONST NAME(SELF, iter_const)
428 if (iter->index < iter->map->capacity) {
429 iter->curr = (
KV_PAIR_CONST){.key = &iter->map->keys[iter->index].key,
430 .value = &iter->map->values[iter->index]};
433 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
446static bool NAME(ITER_CONST,
empty)(ITER_CONST
const* iter) {
448 return iter->index >= iter->map->capacity;
453 size_t first_index = 0;
454 while (first_index < self->capacity && !self->keys[first_index].present) {
459 .index = first_index,
#define ALLOC
An allocator that prints to stdout when it allocates or frees memory.
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)
#define DEBUG_ASSERT(expr)
uint16_t distance_from_desired
gdb_marker derive_c_hashmap
static INDEX insert(SELF *self, V value)
static bool try_remove(SELF *self, INDEX index, V *destination)
static ITER_CONST get_iter_const(SELF const *self)
static bool empty(ITER const *iter)
static V remove(SELF *self, INDEX index)
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 V const * try_read(SELF const *self, INDEX index)
static V * write(SELF *self, INDEX index)
static bool delete_entry(SELF *self, INDEX index)
static SELF shallow_clone(SELF const *self)
static V * try_write(SELF *self, INDEX index)
static size_t position(ITER const *iter)
static V const * read(SELF const *self, INDEX index)
static void extend_capacity_for(SELF *self, size_t expected_items)
static V * try_insert(SELF *self, K key, V value)
#define ALLOC
A simple vector.
static size_t const INITIAL_CAPACITY
static size_t modulus_capacity(size_t index, size_t capacity)
static size_t apply_capacity_policy(size_t capacity)