7#if !defined(SKIP_INCLUDES)
15 #if !defined DC_PLACEHOLDERS
23 #if !defined DC_PLACEHOLDERS
27 #define KEY_HASH key_hash
32 #define KEY_EQ DC_MEM_EQ
35#if !defined KEY_DELETE
36 #define KEY_DELETE DC_NO_DELETE
40 #define KEY_CLONE DC_COPY_CLONE
44 #define KEY_DEBUG DC_DEFAULT_DEBUG
48 #if !defined DC_PLACEHOLDERS
57#if !defined VALUE_DELETE
58 #define VALUE_DELETE DC_NO_DELETE
61#if !defined VALUE_CLONE
62 #define VALUE_CLONE DC_COPY_CLONE
65#if !defined VALUE_DEBUG
66 #define VALUE_DEBUG DC_DEFAULT_DEBUG
73#define SLOT NS(SELF, slot_t)
94#define INVARIANT_CHECK(self) \
96 DC_ASSUME(DC_MATH_IS_POWER_OF_2((self)->capacity)); \
97 DC_ASSUME((self)->slots); \
98 DC_ASSUME((self)->ctrl); \
99 DC_ASSUME((self)->count + (self)->tombstones <= (self)->capacity);
110 for (
size_t i = 0; i < capacity; i++) {
115 ctrl[capacity + i] = ctrl[i - 1];
119 .capacity = capacity,
124 .alloc_ref = alloc_ref,
131 DC_ASSERT(for_items > 0,
"Cannot create map with capacity for 0 items {for_items=%lu}",
152 for (
size_t i = 0; i < self->capacity; i++) {
160 .capacity = self->capacity,
161 .count = self->count,
162 .tombstones = self->tombstones,
165 .alloc_ref = self->alloc_ref,
173 DC_ASSUME(self->count + self->tombstones < self->capacity);
176 const size_t mask = self->capacity - 1;
184 size_t const start = hash & mask;
187 const size_t group_start = (start + step) & mask;
200 if (
KEY_EQ(&self->slots[index].key, &key)) {
212 first_deleted = slot;
224 size_t const insert_index = has_deleted ? first_deleted : empty_idx;
230 self->slots[insert_index] = (
SLOT){
237 return &self->slots[insert_index].value;
248 DC_ASSUME(new_capacity >= self->capacity);
253 for (
size_t i = 0; i < self->capacity; i++) {
256 self->slots[i].value);
274 if (new_capacity > self->capacity) {
308 const size_t mask = self->capacity - 1;
313 const size_t start = hash & mask;
316 size_t const group_start = (start + step) & mask;
328 if (
KEY_EQ(&self->slots[i].key, &key)) {
329 return &self->slots[i].value;
359 DC_ASSERT(destination != NULL,
"Passed NULL destination pointer");
361 const size_t mask = self->capacity - 1;
365 const size_t start = hash & mask;
368 const size_t group_start = (start + step) & mask;
380 if (
KEY_EQ(&self->slots[index].key, &key)) {
381 *destination = self->slots[index].value;
423 for (
size_t i = 0; i < self->capacity; i++) {
435#define ITER_CONST NS(SELF, iter_const)
436#define KV_PAIR_CONST NS(ITER_CONST, item)
450 return item->key == NULL &&
item->value == NULL;
467 .key = &iter->map->slots[index].key,
468 .value = &iter->map->slots[index].value,
539#define ITER NS(SELF, iter)
540#define KV_PAIR NS(ITER, item)
554 return item->key == NULL &&
item->value == NULL;
571 .key = &iter->map->slots[index].key,
572 .value = &iter->map->slots[index].value,
598#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)
static DC_INTERNAL void PRIV rehash(SELF *self, size_t new_capacity)
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)
static DC_INTERNAL SELF PRIV new_with_exact_capacity(size_t capacity, ref alloc_ref)
static void PRIV next_populated_index(SELF const *self, _dc_swiss_optional_index *index)
#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()
#define DC_SWISS_INITIAL_CAPACITY
__m128i _dc_swiss_ctrl_group
#define _DC_SWISS_BITMASK_FOR_EACH(mask, idx_var)
#define DC_SWISS_VAL_EMPTY
@ DC_SWISS_DOUBLE_CAPACITY
@ DC_SWISS_CLEANUP_TOMBSONES
#define _DC_SWISS_SIMD_PROBE_SIZE
static DC_INTERNAL size_t _dc_swiss_group_index_to_slot(size_t group_start, _dc_swiss_ctrl_group_offset idx, size_t capacity)
static size_t const _dc_swiss_index_capacity
static DC_INTERNAL _dc_swiss_ctrl_group_offset _dc_swiss_ctrl_group_bitmask_lowest(_dc_swiss_ctrl_group_bitmask mask)
#define DC_SWISS_VAL_DELETED
static DC_INTERNAL size_t dc_swiss_capacity(size_t for_items)
DC_INTERNAL static DC_PURE bool _dc_swiss_is_present(_dc_swiss_ctrl ctrl)
static DC_INTERNAL void _dc_swiss_ctrl_set_at(_dc_swiss_ctrl *self, size_t capacity, size_t index, _dc_swiss_ctrl val)
uint16_t _dc_swiss_ctrl_group_bitmask
static DC_INTERNAL _dc_swiss_rehash_action _dc_swiss_heuristic_should_extend(size_t tombstones, size_t count, size_t capacity)
static DC_INTERNAL _dc_swiss_ctrl_group _dc_swiss_group_load(const _dc_swiss_ctrl *group_ptr)
static DC_INTERNAL _dc_swiss_ctrl_group_bitmask _dc_swiss_group_match(_dc_swiss_ctrl_group group, uint8_t value)
size_t _dc_swiss_optional_index
static DC_INTERNAL _dc_swiss_ctrl _dc_swiss_ctrl_from_hash(size_t hash)
#define DC_SWISS_VAL_SENTINEL
#define _DC_SWISS_NO_INDEX
#define DC_MATH_IS_POWER_OF_2(x)
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,...)
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)