4#if !defined(SKIP_INCLUDES)
12 #if !defined DC_PLACEHOLDERS
20 #if !defined DC_PLACEHOLDERS
24 #define KEY_HASH key_hash
29 #define KEY_EQ DC_MEM_EQ
32#if !defined KEY_DELETE
33 #define KEY_DELETE DC_NO_DELETE
37 #define KEY_CLONE DC_COPY_CLONE
41 #define KEY_DEBUG DC_DEFAULT_DEBUG
45 #if !defined DC_PLACEHOLDERS
54#if !defined VALUE_DELETE
55 #define VALUE_DELETE DC_NO_DELETE
58#if !defined VALUE_CLONE
59 #define VALUE_CLONE DC_COPY_CLONE
62#if !defined VALUE_DEBUG
63 #define VALUE_DEBUG DC_DEFAULT_DEBUG
70#define KEY_ENTRY NS(SELF, key_entry)
87#define INVARIANT_CHECK(self) \
89 DC_ASSUME(DC_MATH_IS_POWER_OF_2((self)->capacity)); \
90 DC_ASSUME((self)->keys); \
91 DC_ASSUME((self)->values);
96 DC_ASSERT(capacity > 0,
"Cannot create map with capacity for 0 items {capacity=%lu}", capacity);
113 sizeof(
VALUE) * real_capacity);
116 .capacity = real_capacity,
120 .alloc_ref = alloc_ref,
144 for (
size_t i = 0; i < self->capacity; i++) {
145 if (self->keys[i].present) {
146 KEY_ENTRY const* old_entry = &self->keys[i];
155 &values[i],
sizeof(
VALUE));
160 .capacity = self->capacity,
161 .items = self->items,
164 .alloc_ref = self->alloc_ref,
171 uint16_t distance_from_desired = 0;
175 VALUE* inserted_to_entry = NULL;
179 DC_ASSUME(distance_from_desired < self->capacity);
187 KEY const switch_key = entry->
key;
189 VALUE const switch_value = self->values[index];
193 self->values[index] = value;
196 distance_from_desired = switch_distance_from_desired;
197 value = switch_value;
199 if (!inserted_to_entry) {
200 inserted_to_entry = &self->values[index];
204 distance_from_desired++;
212 &self->values[index],
sizeof(
VALUE));
214 self->values[index] = value;
216 if (!inserted_to_entry) {
217 inserted_to_entry = &self->values[index];
221 return inserted_to_entry;
231 if (target_capacity > self->capacity) {
233 for (
size_t index = 0; index < self->capacity; index++) {
237 self->values[index]);
280 return &self->values[index];
304 return &self->values[index];
331 *destination = self->values[index];
340 size_t free_index = index;
345 KEY_ENTRY* check_entry = &self->keys[check_index];
348 free_entry->
key = check_entry->
key;
350 self->values[free_index] = self->values[check_index];
352 free_index = check_index;
353 free_entry = check_entry;
357 check_entry = &self->keys[check_index];
368 &self->values[free_index],
sizeof(
VALUE));
396#define KV_PAIR NS(SELF, kv)
403#define ITER NS(SELF, iter)
407 return item->key == NULL &&
item->value == NULL;
420 if (iter->index < iter->map->capacity) {
421 iter->curr = (
KV_PAIR){.key = &iter->map->keys[iter->index].key,
422 .value = &iter->map->values[iter->index]};
424 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
429 return (
KV_PAIR){.key = NULL, .value = NULL};
435 return iter->index >= iter->map->capacity;
440 size_t first_index = 0;
441 while (first_index < self->capacity && !self->keys[first_index].present) {
446 .index = first_index,
447 .curr = (
KV_PAIR){.key = NULL, .value = NULL},
455 for (
size_t i = 0; i < self->capacity; i++) {
456 if (self->keys[i].present) {
469#define KV_PAIR_CONST NS(SELF, kv_const)
476#define ITER_CONST NS(SELF, iter_const)
480 return item->key == NULL &&
item->value == NULL;
493 if (iter->index < iter->map->capacity) {
494 iter->curr = (
KV_PAIR_CONST){.key = &iter->map->keys[iter->index].key,
495 .value = &iter->map->values[iter->index]};
497 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
508 return iter->index >= iter->map->capacity;
513 size_t first_index = 0;
514 while (first_index < self->capacity && !self->keys[first_index].present) {
519 .index = first_index,
569#undef INVARIANT_CHECK
static DC_PUBLIC void deallocate(SELF *self, void *ptr, size_t size)
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
static DC_PUBLIC void * allocate_zeroed(SELF *self, size_t size)
static DC_PUBLIC void * allocate_uninit(SELF *self, size_t size)
#define DC_STATIC_CONSTANT
static DC_PUBLIC VALUE const * try_read(SELF const *self, INDEX index)
static DC_PUBLIC VALUE * try_write(SELF *self, INDEX index)
#define INVARIANT_CHECK(self)
static DC_PUBLIC IV_PAIR next(ITER *iter)
static DC_PUBLIC INDEX insert(SELF *self, VALUE value)
static DC_PUBLIC bool empty(ITER const *iter)
static DC_PUBLIC VALUE const * read(SELF const *self, INDEX index)
static DC_PUBLIC bool try_remove(SELF *self, INDEX index, VALUE *destination)
static DC_PUBLIC VALUE * write(SELF *self, INDEX index)
static DC_PUBLIC bool empty_item(IV_PAIR const *item)
static DC_PUBLIC VALUE remove(SELF *self, INDEX index)
static DC_PUBLIC ITER get_iter(SELF *self)
static DC_PUBLIC ITER_CONST get_iter_const(SELF const *self)
static DC_PUBLIC size_t size(SELF const *self)
static DC_PUBLIC SELF clone(SELF const *self)
static DC_PUBLIC SELF new_with_capacity_for(INDEX_TYPE items, ref alloc_ref)
static DC_PUBLIC void extend_capacity_for(SELF *self, size_t expected_items)
DC_STATIC_CONSTANT size_t max_capacity
static DC_INTERNAL VALUE *PRIV try_insert_no_extend_capacity(SELF *self, KEY key, VALUE value)
static DC_PUBLIC void delete_entry(SELF *self, KEY key)
static DC_PUBLIC VALUE * try_insert(SELF *self, KEY key, VALUE value)
#define KEY
A simple open-addressed hashmap using robin-hood hashing.
#define DC_TRAIT_MAP(SELF)
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
#define DC_DEBUG(DEBUG_FN, DEBUG_PTR)
static DC_PUBLIC void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
static DC_PUBLIC dc_gdb_marker dc_gdb_marker_new()
static size_t dc_apply_capacity_policy(size_t capacity)
static size_t const DC_INITIAL_CAPACITY
static DC_PUBLIC size_t DC_INLINE DC_CONST dc_math_modulus_power_of_2_capacity(size_t index, size_t capacity)
static DC_PUBLIC void dc_memory_tracker_set(dc_memory_tracker_level level, dc_memory_tracker_capability cap, const volatile void *addr, size_t size)
@ DC_MEMORY_TRACKER_LVL_CONTAINER
@ DC_MEMORY_TRACKER_CAP_WRITE
@ DC_MEMORY_TRACKER_CAP_NONE
static DC_PUBLIC void mutation_tracker_mutate(mutation_tracker *self)
static DC_PUBLIC void mutation_version_check(mutation_version const *self)
static DC_PUBLIC mutation_tracker mutation_tracker_new()
static DC_PUBLIC mutation_version mutation_tracker_get(mutation_tracker const *self)
#define DC_EXPAND_STRING(NAME)
#define DC_ASSERT(expr,...)
#define DC_ASSUME(expr,...)
uint16_t distance_from_desired
mutation_tracker iterator_invalidation_tracker
dc_gdb_marker derive_c_hashmap
Debug format helpers for debug printin data structures.
tracks a specific version of a value, so that this can be compared later to check modification For ex...
static DC_PUBLIC FILE * stream(SELF *self)