#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <derive-c/core.h>
#include <derive-c/panic.h>
#include <derive-c/self.h>
#include <derive-c/structures/hashmap/utils.h>
#include <derive-c/allocs/std.h>
Go to the source code of this file.
|
static SELF | new_with_capacity_for (size_t capacity, ALLOC *alloc) |
static SELF | new (ALLOC *alloc) |
static SELF | shallow_clone (SELF const *self) |
static void | delete (SELF *self) |
static V * | insert (SELF *self, K key, V value) |
static void | extend_capacity_for (SELF *self, size_t expected_items) |
static V * | try_insert (SELF *self, K key, V value) |
static V * | try_write (SELF *self, K key) |
static V * | write (SELF *self, K key) |
static V const * | try_read (SELF const *self, K key) |
static V const * | read (SELF const *self, K key) |
static bool | try_remove (SELF *self, K key, V *destination) |
static V | remove (SELF *self, K key) |
static void | delete_entry (SELF *self, K key) |
static size_t | size (SELF const *self) |
static KV_PAIR const * | next (ITER *iter) |
static size_t | position (ITER const *iter) |
static bool | empty (ITER const *iter) |
static ITER | get_iter (SELF *self) |
static KV_PAIR_CONST const * | next (ITER_CONST *iter) |
static size_t | position (ITER_CONST const *iter) |
static bool | empty (ITER_CONST const *iter) |
static ITER_CONST | get_iter_const (SELF const *self) |
◆ ALLOC
A simple open-addressed hashmap using robin-hood hashing.
Definition at line 15 of file template.h.
◆ EQ
#define EQ derive_c_parameter_eq |
◆ HASH
#define HASH derive_c_parameter_hash |
#define K derive_c_parameter_key |
◆ K_DELETE
#define K_DELETE derive_c_parameter_key_delete |
◆ KEY_ENTRY
◆ KV_PAIR
◆ KV_PAIR_CONST
#define KV_PAIR_CONST NAME(SELF, kv_const) |
#define V derive_c_parameter_value |
◆ V_DELETE
#define V_DELETE derive_c_parameter_value_delete |
◆ delete()
void delete |
( |
SELF * | self | ) |
|
|
static |
Definition at line 392 of file template.h.
392 {
395
396 for (
size_t i = 0; i < self->
capacity; i++) {
400 }
401 }
402
405}
#define ALLOC
An allocator that prints to stdout when it allocates or frees memory.
static void free(SELF *self, void *ptr)
#define DEBUG_ASSERT(expr)
static ITER get_iter(SELF *self)
◆ delete_entry()
void delete_entry |
( |
SELF * | self, |
|
|
K | key ) |
|
static |
Definition at line 327 of file template.h.
327 {
330}
static V remove(SELF *self, INDEX index)
◆ empty() [1/2]
bool empty |
( |
ITER const * | iter | ) |
|
|
static |
Definition at line 373 of file template.h.
373 {
375 return iter->index >= iter->map->capacity;
376}
◆ empty() [2/2]
bool empty |
( |
ITER_CONST const * | iter | ) |
|
|
static |
Definition at line 446 of file template.h.
446 {
448 return iter->index >= iter->map->capacity;
449}
◆ extend_capacity_for()
void extend_capacity_for |
( |
SELF * | self, |
|
|
size_t | expected_items ) |
|
static |
Definition at line 142 of file template.h.
142 {
145 if (target_capacity > self->
capacity) {
147 for (
size_t index = 0; index < self->
capacity; index++) {
151 }
152 }
155 *self = new_map;
156 }
157}
static INDEX insert(SELF *self, V value)
static SELF new_with_capacity_for(INDEX_TYPE items, ALLOC *alloc)
static size_t apply_capacity_policy(size_t capacity)
◆ get_iter()
ITER get_iter |
( |
SELF * | self | ) |
|
|
static |
Definition at line 378 of file template.h.
378 {
380 size_t first_index = 0;
381 while (first_index < self->capacity && !self->
keys[first_index].
present) {
382 first_index++;
383 }
384 return (ITER){
385 .map = self,
386 .index = first_index,
387 .pos = 0,
388 .curr = (
KV_PAIR){.key = NULL, .value = NULL},
389 };
390}
◆ get_iter_const()
ITER_CONST get_iter_const |
( |
SELF const * | self | ) |
|
|
static |
Definition at line 451 of file template.h.
451 {
453 size_t first_index = 0;
454 while (first_index < self->capacity && !self->keys[first_index].present) {
455 first_index++;
456 }
457 return (ITER_CONST){
458 .map = self,
459 .index = first_index,
460 .pos = 0,
462 };
463}
◆ insert()
V * insert |
( |
SELF * | self, |
|
|
K | key, |
|
|
V | value ) |
|
static |
Definition at line 212 of file template.h.
212 {
215 return value_ptr;
216}
static V * try_insert(SELF *self, K key, V value)
◆ new()
Definition at line 104 of file template.h.
104 {
106}
static size_t const INITIAL_CAPACITY
◆ new_with_capacity_for()
SELF new_with_capacity_for |
( |
size_t | capacity, |
|
|
ALLOC * | alloc ) |
|
static |
Definition at line 85 of file template.h.
85 {
89
90
91
96 .capacity = real_capacity,
97 .items = 0,
98 .keys = keys,
99 .values = values,
100 .alloc = alloc,
101 };
102}
static void * malloc(SELF *self, size_t size)
static void * calloc(SELF *self, size_t count, size_t size)
◆ next() [1/2]
KV_PAIR const * next |
( |
ITER * | iter | ) |
|
|
static |
Definition at line 353 of file template.h.
353 {
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]};
358 iter->pos++;
359 iter->index++;
360 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
361 iter->index++;
362 }
363 return &iter->curr;
364 }
365 return NULL;
366}
◆ next() [2/2]
Definition at line 426 of file template.h.
426 {
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]};
431 iter->pos++;
432 iter->index++;
433 while (iter->index < iter->map->capacity && !iter->map->keys[iter->index].present) {
434 iter->index++;
435 }
436 return &iter->curr;
437 }
438 return NULL;
439}
◆ position() [1/2]
size_t position |
( |
ITER const * | iter | ) |
|
|
static |
Definition at line 368 of file template.h.
368 {
370 return iter->pos;
371}
◆ position() [2/2]
size_t position |
( |
ITER_CONST const * | iter | ) |
|
|
static |
Definition at line 441 of file template.h.
441 {
443 return iter->pos;
444}
◆ read()
V const * read |
( |
SELF const * | self, |
|
|
K | key ) |
|
static |
Definition at line 260 of file template.h.
260 {
263 return value;
264}
static V const * try_read(SELF const *self, INDEX index)
◆ remove()
V remove |
( |
SELF * | self, |
|
|
K | key ) |
|
static |
Definition at line 321 of file template.h.
321 {
324 return value;
325}
static bool try_remove(SELF *self, INDEX index, V *destination)
◆ shallow_clone()
Definition at line 108 of file template.h.
108 {
110
111
112
113
114
115
116
121
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];
126 }
127 }
128
130 .capacity = self->capacity,
131 .items = self->items,
132 .keys = keys,
133 .values = values,
134 .alloc = self->alloc,
135 };
136}
◆ size()
size_t size |
( |
SELF const * | self | ) |
|
|
static |
Definition at line 332 of file template.h.
332 {
334 return self->items;
335}
◆ try_insert()
V * try_insert |
( |
SELF * | self, |
|
|
K | key, |
|
|
V | value ) |
|
static |
Definition at line 159 of file template.h.
159 {
163 }
164
165 uint16_t distance_from_desired = 0;
166 size_t hash =
HASH(&key);
168 V* placed_entry = NULL;
169 for (;;) {
172
174 if (
EQ(&entry->
key, &key)) {
175 return NULL;
176 }
177
179 K switch_key = entry->
key;
181 V switch_value = self->
values[index];
182
185 self->
values[index] = value;
186
187 key = switch_key;
188 distance_from_desired = switch_distance_from_desired;
189 value = switch_value;
190
191 if (!placed_entry) {
192 placed_entry = &self->
values[index];
193 }
194 }
195
196 distance_from_desired++;
198 } else {
202 self->
values[index] = value;
203 if (!placed_entry) {
204 placed_entry = &self->
values[index];
205 }
207 return placed_entry;
208 }
209 }
210}
uint16_t distance_from_desired
static void extend_capacity_for(SELF *self, size_t expected_items)
static size_t modulus_capacity(size_t index, size_t capacity)
◆ try_read()
V const * try_read |
( |
SELF const * | self, |
|
|
K | key ) |
|
static |
Definition at line 242 of file template.h.
242 {
244 size_t hash =
HASH(&key);
246
247 for (;;) {
250 if (
EQ(&entry->
key, &key)) {
251 return &self->values[index];
252 }
254 } else {
255 return NULL;
256 }
257 }
258}
◆ try_remove()
bool try_remove |
( |
SELF * | self, |
|
|
K | key, |
|
|
V * | destination ) |
|
static |
Definition at line 266 of file template.h.
266 {
268 size_t hash =
HASH(&key);
270
271 for (;;) {
274 if (
EQ(&entry->
key, &key)) {
276
277 *destination = self->
values[index];
279
280
281
282
283
284
285
286 size_t free_index = index;
288
291
293 free_entry->
key = check_entry->
key;
296
297 free_index = check_index;
298 free_entry = check_entry;
299
301 check_entry = &self->
keys[check_index];
302 }
303
304
305
306
307
308
309
311
312 return true;
313 }
315 } else {
316 return false;
317 }
318 }
319}
◆ try_write()
V * try_write |
( |
SELF * | self, |
|
|
K | key ) |
|
static |
Definition at line 218 of file template.h.
218 {
220 size_t hash =
HASH(&key);
222
223 for (;;) {
226 if (
EQ(&entry->
key, &key)) {
227 return &self->
values[index];
228 }
230 } else {
231 return NULL;
232 }
233 }
234}
◆ write()
V * write |
( |
SELF * | self, |
|
|
K | key ) |
|
static |
Definition at line 236 of file template.h.
236 {
239 return value;
240}
static V * try_write(SELF *self, INDEX index)