Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
2
4#if !defined(SKIP_INCLUDES)
5 #include "includes.h"
6#endif
7
9
10#if !defined CAPACITY
11 #if !defined DC_PLACEHOLDERS
12TEMPLATE_ERROR("No CAPACITY")
13 #endif
14 #define CAPACITY 32
15#endif
16
17DC_STATIC_ASSERT(CAPACITY > 0, DC_EXPAND_STRING(SELF) " CAPACITY cannot be empty");
18
19#if !defined KEY
20 #if !defined DC_PLACEHOLDERS
21TEMPLATE_ERROR("No KEY")
22 #endif
23 #define KEY map_key_t
24typedef int KEY;
25#endif
26
27#if !defined KEY_EQ
28 #define KEY_EQ DC_MEM_EQ
29#endif
30
31#if !defined KEY_DELETE
32 #define KEY_DELETE DC_NO_DELETE
33#endif
34
35#if !defined KEY_CLONE
36 #define KEY_CLONE DC_COPY_CLONE
37#endif
38
39#if !defined KEY_DEBUG
40 #define KEY_DEBUG DC_DEFAULT_DEBUG
41#endif
42
43#if !defined VALUE
44 #if !defined DC_PLACEHOLDERS
45TEMPLATE_ERROR("No VALUE")
46 #endif
47typedef struct {
48 int x;
49} value_t;
50 #define VALUE value_t
51#endif
52
53#if !defined VALUE_DELETE
54 #define VALUE_DELETE DC_NO_DELETE
55#endif
56
57#if !defined VALUE_CLONE
58 #define VALUE_CLONE DC_COPY_CLONE
59#endif
60
61#if !defined VALUE_DEBUG
62 #define VALUE_DEBUG DC_DEFAULT_DEBUG
63#endif
64
65typedef KEY NS(SELF, key_t);
66typedef VALUE NS(SELF, value_t);
67
68#define ENTRY NS(SELF, entry_t)
69typedef struct {
72} ENTRY;
73
74typedef struct {
75 size_t size;
77
80} SELF;
81
83
84#define INVARIANT_CHECK(self) \
85 DC_ASSUME(self); \
86 DC_ASSUME((self)->size <= CAPACITY);
87
88DC_PUBLIC static SELF NS(SELF, new)() {
89 return (SELF){
90 .size = 0,
91 .entries = {},
92 .derive_c_map_staticlinear = dc_gdb_marker_new(),
93 .iterator_invalidation_tracker = mutation_tracker_new(),
94 };
95}
96
97DC_PUBLIC static VALUE const* NS(SELF, try_read)(SELF const* self, KEY key) {
98 INVARIANT_CHECK(self);
99 for (size_t index = 0; index < self->size; index++) {
100 if (KEY_EQ(&self->entries[index].key, &key)) {
101 return &self->entries[index].value;
102 }
103 }
104 return NULL;
105}
106
107DC_PUBLIC static VALUE const* NS(SELF, read)(SELF const* self, KEY key) {
108 VALUE const* value = NS(SELF, try_read)(self, key);
109 DC_ASSERT(value, "Cannot read item {key=%s}", DC_DEBUG(KEY_DEBUG, &key));
110 return value;
111}
112
113DC_PUBLIC static VALUE* NS(SELF, try_write)(SELF* self, KEY key) {
114 return (VALUE*)(NS(SELF, try_read)(self, key));
115}
116
117DC_PUBLIC static VALUE* NS(SELF, write)(SELF* self, KEY key) {
118 VALUE* value = NS(SELF, try_write)(self, key);
119 DC_ASSERT(value, "Cannot write item {key=%s}", DC_DEBUG(KEY_DEBUG, &key));
120 return value;
121}
122
123DC_PUBLIC static VALUE* NS(SELF, try_insert)(SELF* self, KEY key, VALUE value) {
124 INVARIANT_CHECK(self);
125 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
126
127 if (self->size >= CAPACITY) {
128 return NULL;
129 }
130
131 VALUE const* existing_value = NS(SELF, try_read)(self, key);
132 if (existing_value) {
133 return NULL;
134 }
135
136 self->entries[self->size].key = key;
137 self->entries[self->size].value = value;
138 self->size++;
139 return &self->entries[self->size - 1].value;
140}
141
142DC_PUBLIC static VALUE* NS(SELF, insert)(SELF* self, KEY key, VALUE value) {
143 VALUE* placed = NS(SELF, try_insert)(self, key, value);
144 DC_ASSERT(placed, "Failed to insert item {key=%s, value=%s}", DC_DEBUG(KEY_DEBUG, &key),
145 DC_DEBUG(VALUE_DEBUG, &value));
146 return placed;
147}
148
149DC_PUBLIC static bool NS(SELF, try_remove)(SELF* self, KEY key, VALUE* dest) {
150 INVARIANT_CHECK(self);
151 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
152
153 for (size_t index = 0; index < self->size; index++) {
154 if (KEY_EQ(&self->entries[index].key, &key)) {
155 KEY_DELETE(&self->entries[index].key);
156 *dest = self->entries[index].value;
157 // Shift remaining entries down
158 for (size_t i = index; i < self->size - 1; i++) {
159 self->entries[i] = self->entries[i + 1];
160 }
161 self->size--;
162 return true;
163 }
164 }
165 return false;
166}
167
168DC_PUBLIC static VALUE NS(SELF, remove)(SELF* self, KEY key) {
169 VALUE dest;
170 DC_ASSERT(NS(SELF, try_remove)(self, key, &dest), "Failed to remove item {key=%s}",
171 DC_DEBUG(KEY_DEBUG, &key));
172 return dest;
173}
174
175DC_PUBLIC static void NS(SELF, delete_entry)(SELF* self, KEY key) {
176 VALUE val = NS(SELF, remove)(self, key);
177 VALUE_DELETE(&val);
178}
179
180DC_PUBLIC static size_t NS(SELF, size)(SELF const* self) { return self->size; }
181
182DC_PUBLIC static SELF NS(SELF, clone)(SELF const* self) {
183 INVARIANT_CHECK(self);
184
185 SELF new_self = (SELF){
186 .size = self->size,
187 .derive_c_map_staticlinear = dc_gdb_marker_new(),
188 .iterator_invalidation_tracker = mutation_tracker_new(),
189 };
190 for (size_t index = 0; index < self->size; index++) {
191 new_self.entries[index].key = KEY_CLONE(&self->entries[index].key);
192 new_self.entries[index].value = VALUE_CLONE(&self->entries[index].value);
193 }
194 return new_self;
195}
196
197DC_PUBLIC static void NS(SELF, delete)(SELF* self) {
198 INVARIANT_CHECK(self);
199
200 for (size_t index = 0; index < self->size; index++) {
201 KEY_DELETE(&self->entries[index].key);
202 VALUE_DELETE(&self->entries[index].value);
203 }
204}
205
206DC_PUBLIC static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
207 fprintf(stream, DC_EXPAND_STRING(SELF) "@%p {\n", (void*)self);
208 fmt = dc_debug_fmt_scope_begin(fmt);
209 dc_debug_fmt_print(fmt, stream, "capacity: %zu,\n", (size_t)CAPACITY);
210 dc_debug_fmt_print(fmt, stream, "size: %zu,\n", self->size);
211 dc_debug_fmt_print(fmt, stream, "entries: [\n");
212 fmt = dc_debug_fmt_scope_begin(fmt);
213 for (size_t index = 0; index < self->size; index++) {
214 dc_debug_fmt_print(fmt, stream, "{index: %lu, key: ", index);
215 KEY_DEBUG(&self->entries[index].key, fmt, stream);
216 fprintf(stream, ", value: ");
217 VALUE_DEBUG(&self->entries[index].value, fmt, stream);
218 fprintf(stream, "},\n");
219 }
220 fmt = dc_debug_fmt_scope_end(fmt);
221 dc_debug_fmt_print(fmt, stream, "],\n");
222
223 fmt = dc_debug_fmt_scope_end(fmt);
224 dc_debug_fmt_print(fmt, stream, "}");
225}
226
227#define ITER_CONST NS(SELF, iter_const)
228#define KV_PAIR_CONST NS(ITER_CONST, item)
229
230typedef struct {
231 SELF const* map;
234} ITER_CONST;
235
236typedef struct {
237 KEY const* key;
238 VALUE const* value;
240
242 return item->key == NULL && item->value == NULL;
243}
244
246 mutation_version_check(&iter->version);
247 size_t const next_index = iter->next_index;
248
249 if (next_index >= iter->map->size) {
250 return (KV_PAIR_CONST){.key = NULL, .value = NULL};
251 }
252
253 iter->next_index++;
254
255 return (KV_PAIR_CONST){
256 .key = &iter->map->entries[next_index].key,
257 .value = &iter->map->entries[next_index].value,
258 };
259}
260
261DC_PUBLIC static bool NS(ITER_CONST, empty)(ITER_CONST const* iter) {
262 DC_ASSUME(iter);
263 mutation_version_check(&iter->version);
264 return iter->next_index >= iter->map->size;
265}
266
268 INVARIANT_CHECK(self);
269
270 return (ITER_CONST){
271 .map = self,
272 .next_index = 0,
273 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
274 };
275}
276
277#undef KV_PAIR_CONST
278#undef ITER_CONST
279
280#define ITER NS(SELF, iter)
281#define KV_PAIR NS(ITER, item)
282
283typedef struct {
284 SELF* map;
287} ITER;
288
289typedef struct {
290 KEY const* key;
291 VALUE const* value;
292} KV_PAIR;
293
294DC_PUBLIC static bool NS(ITER, empty_item)(KV_PAIR const* item) {
295 return item->key == NULL && item->value == NULL;
296}
297
298DC_PUBLIC static KV_PAIR NS(ITER, next)(ITER* iter) {
299 mutation_version_check(&iter->version);
300 size_t const next_index = iter->next_index;
301
302 if (next_index >= iter->map->size) {
303 return (KV_PAIR){.key = NULL, .value = NULL};
304 }
305
306 iter->next_index++;
307
308 return (KV_PAIR){
309 .key = &iter->map->entries[next_index].key,
310 .value = &iter->map->entries[next_index].value,
311 };
312}
313
314DC_PUBLIC static bool NS(ITER, empty)(ITER const* iter) {
315 DC_ASSUME(iter);
316 mutation_version_check(&iter->version);
317 return iter->next_index >= iter->map->size;
318}
319
321 INVARIANT_CHECK(self);
322
323 return (ITER){
324 .map = self,
325 .next_index = 0,
326 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
327 };
328}
329
330#undef KV_PAIR
331#undef ITER
332
333#undef INVARIANT_CHECK
334#undef ENTRY
335
336#undef VALUE_DEBUG
337#undef VALUE_CLONE
338#undef VALUE_DELETE
339#undef VALUE
340
341#undef KEY_DEBUG
342#undef KEY_CLONE
343#undef KEY_DELETE
344#undef KEY_EQ
345#undef KEY
346
347#undef CAPACITY
348
350
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:212
#define CAPACITY
A hybrid of a bump allocator on a statically allocated buffer, and any other allocator.
Definition template.h:18
#define KEY
Definition template.h:32
#define VALUE
Definition template.h:35
#define KEY_DEBUG
Definition template.h:34
#define DC_STATIC_CONSTANT
Definition attributes.h:23
static DC_PUBLIC VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:180
static DC_PUBLIC VALUE * try_write(SELF *self, INDEX index)
Definition template.h:205
#define VALUE_DEBUG
Definition template.h:41
#define INVARIANT_CHECK(self)
Definition template.h:90
static DC_PUBLIC IV_PAIR next(ITER *iter)
Definition template.h:355
static DC_PUBLIC INDEX insert(SELF *self, VALUE value)
Definition template.h:126
static DC_PUBLIC bool empty(ITER const *iter)
Definition template.h:349
static DC_PUBLIC VALUE const * read(SELF const *self, INDEX index)
Definition template.h:199
static DC_PUBLIC bool try_remove(SELF *self, INDEX index, VALUE *destination)
Definition template.h:264
static DC_PUBLIC VALUE * write(SELF *self, INDEX index)
Definition template.h:209
static DC_PUBLIC bool empty_item(IV_PAIR const *item)
Definition template.h:347
static DC_PUBLIC VALUE remove(SELF *self, INDEX index)
Definition template.h:292
#define ITER
Definition template.h:322
#define VALUE_CLONE
Definition template.h:39
static DC_PUBLIC ITER get_iter(SELF *self)
Definition template.h:373
#define VALUE_DELETE
Definition template.h:37
#define ITER_CONST
Definition template.h:411
static DC_PUBLIC ITER_CONST get_iter_const(SELF const *self)
Definition template.h:464
static DC_PUBLIC size_t size(SELF const *self)
Definition template.h:252
static DC_PUBLIC SELF clone(SELF const *self)
Definition template.h:215
IV_PAIR item
Definition template.h:281
#define KV_PAIR
Definition template.h:585
#define KEY_DELETE
Definition template.h:35
#define KEY_CLONE
Definition template.h:39
DC_STATIC_CONSTANT size_t max_capacity
Definition template.h:130
static DC_PUBLIC void delete_entry(SELF *self, KEY key)
Definition template.h:504
static DC_PUBLIC VALUE * try_insert(SELF *self, KEY key, VALUE value)
Definition template.h:318
#define KEY_EQ
Definition template.h:31
#define KEY_DEBUG
Definition template.h:43
KEY key_t
Definition template.h:68
#define KV_PAIR_CONST
Definition template.h:522
#define ENTRY
Definition template.h:68
#define KEY
Definition template.h:23
#define VALUE
Definition template.h:50
#define DC_TRAIT_MAP(SELF)
Definition trait.h:5
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
Definition def.h:56
#define SELF
Definition def.h:52
#define DC_DEBUG(DEBUG_FN, DEBUG_PTR)
Definition dump.h:92
static DC_PUBLIC void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
Definition fmt.h:32
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
Definition fmt.h:57
static DC_PUBLIC dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
Definition fmt.h:50
static DC_PUBLIC dc_gdb_marker dc_gdb_marker_new()
Definition gdb_marker.h:8
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_PUBLIC
Definition namespace.h:25
#define NS(pre, post)
Definition namespace.h:14
#define DC_EXPAND_STRING(NAME)
Definition namespace.h:6
#define DC_ASSERT(expr,...)
Definition panic.h:37
#define DC_STATIC_ASSERT
Definition panic.h:22
#define DC_ASSUME(expr,...)
Definition panic.h:57
VALUE value
Definition template.h:71
KEY key
Definition template.h:70
INDEX_TYPE next_index
Definition template.h:416
mutation_version version
Definition template.h:417
INDEX_TYPE next_index
Definition template.h:327
mutation_version version
Definition template.h:328
mutation_tracker iterator_invalidation_tracker
Definition template.h:87
ENTRY entries[CAPACITY]
Definition template.h:76
size_t size
Definition template.h:75
dc_gdb_marker derive_c_map_staticlinear
Definition template.h:78
Debug format helpers for debug printin data structures.
Definition fmt.h:11
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)
Definition template.h:108