Derive-C
Loading...
Searching...
No Matches
template.h File Reference
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <derive-c/core.h>
#include <derive-c/panic.h>
#include <derive-c/self.h>
#include <derive-c/allocs/std.h>
Include dependency graph for template.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  INDEX
struct  SLOT
struct  SELF
struct  IV_PAIR
struct  IV_PAIR_CONST

Macros

#define ALLOC   stdalloc
 A vector-backed arena, with support for small indices.
#define INDEX_BITS   32
#define V   derive_c_parameter_value
#define V_DELETE   derive_c_parameter_value_delete
#define SLOT   NAME(SELF, SLOT)
#define CHECK_ACCESS_INDEX(self, index)
#define RESIZE_FACTOR   2
#define INDEX   NAME(SELF, index)
#define IV_PAIR   NAME(SELF, iv)
#define IV_PAIR_CONST   NAME(SELF, iv_const)

Functions

static SELF new_with_capacity_for (INDEX_TYPE items, ALLOC *alloc)
static INDEX insert (SELF *self, V value)
static Vtry_write (SELF *self, INDEX index)
static Vwrite (SELF *self, INDEX index)
static V const * try_read (SELF const *self, INDEX index)
static V const * read (SELF const *self, INDEX index)
static SELF shallow_clone (SELF const *self)
static INDEX_TYPE size (SELF const *self)
static bool full (SELF const *self)
static bool try_remove (SELF *self, INDEX index, V *destination)
static V remove (SELF *self, INDEX index)
static bool delete_entry (SELF *self, INDEX index)
static bool empty (ITER const *iter)
static IV_PAIR const * next (ITER *iter)
static size_t position (ITER const *iter)
static ITER get_iter (SELF *self)
static void delete (SELF *self)
static bool empty (ITER_CONST const *iter)
static IV_PAIR_CONST const * next (ITER_CONST *iter)
static size_t position (ITER_CONST const *iter)
static ITER_CONST get_iter_const (SELF const *self)

Variables

static size_t max_capacity = MAX_CAPACITY
static size_t max_index = MAX_INDEX
static IV_PAIR_CONST iv_const_empty

Macro Definition Documentation

◆ ALLOC

#define ALLOC   stdalloc

A vector-backed arena, with support for small indices.

Definition at line 15 of file template.h.

◆ CHECK_ACCESS_INDEX

#define CHECK_ACCESS_INDEX ( self,
index )
Value:
((index).index < (self)->exclusive_end)

Definition at line 66 of file template.h.

◆ INDEX

#define INDEX   NAME(SELF, index)

Definition at line 73 of file template.h.

◆ INDEX_BITS

#define INDEX_BITS   32

Definition at line 22 of file template.h.

◆ IV_PAIR

#define IV_PAIR   NAME(SELF, iv)

Definition at line 267 of file template.h.

◆ IV_PAIR_CONST

#define IV_PAIR_CONST   NAME(SELF, iv_const)

Definition at line 341 of file template.h.

◆ RESIZE_FACTOR

#define RESIZE_FACTOR   2

Definition at line 70 of file template.h.

◆ SLOT

#define SLOT   NAME(SELF, SLOT)

Definition at line 64 of file template.h.

◆ V

#define V   derive_c_parameter_value

Definition at line 32 of file template.h.

◆ V_DELETE

#define V_DELETE   derive_c_parameter_value_delete

Definition at line 34 of file template.h.

Function Documentation

◆ delete()

void delete ( SELF * self)
static

Definition at line 327 of file template.h.

327 {
328 DEBUG_ASSERT(self);
329 ITER iter = NAME(SELF, get_iter)(self);
330 IV_PAIR const* entry;
331 while ((entry = NAME(ITER, next)(&iter))) {
332 V_DELETE(entry->value);
333 }
334
335 NAME(ALLOC, free)(self->alloc, self->slots);
336}
#define ALLOC
An allocator that prints to stdout when it allocates or frees memory.
Definition template.h:17
static void free(SELF *self, void *ptr)
Definition template.h:62
#define SELF
Definition template.h:70
#define NAME(pre, post)
Definition core.h:5
#define DEBUG_ASSERT(expr)
Definition panic.h:23
V * value
Definition template.h:270
SLOT * slots
Definition template.h:93
ALLOC * alloc
Definition template.h:76
static ITER get_iter(SELF *self)
Definition template.h:312
#define IV_PAIR
Definition template.h:267
static IV_PAIR const * next(ITER *iter)
Definition template.h:289
#define V_DELETE
Definition template.h:34
Here is the call graph for this function:

◆ delete_entry()

bool delete_entry ( SELF * self,
INDEX index )
static

Definition at line 249 of file template.h.

249 {
250 DEBUG_ASSERT(self);
251 if (!CHECK_ACCESS_INDEX(self, index)) {
252 return false;
253 }
254
255 SLOT* entry = &self->slots[index.index];
256 if (entry->present) {
257 V_DELETE(&entry->value);
258 entry->present = false;
259 entry->next_free = self->free_list;
260 self->free_list = index.index;
261 self->count--;
262 return true;
263 }
264 return false;
265}
INDEX_TYPE index
Definition template.h:76
INDEX_TYPE free_list
Definition template.h:95
size_t count
Definition template.h:105
INDEX_TYPE next_free
Definition template.h:82
V value
Definition template.h:81
bool present
Definition template.h:89
#define SLOT
Definition template.h:64
#define CHECK_ACCESS_INDEX(self, index)
Definition template.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ empty() [1/2]

bool empty ( ITER const * iter)
static

Definition at line 281 of file template.h.

281 {
282 DEBUG_ASSERT(iter);
283 // JUSTIFY: If no entries are left, then the previous '.._next' call moved
284 // the index to the exclusive end
285 // NOTE: `index + 1 > exclusive_end` implies `index >= exclusive_end`
286 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
287}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ empty() [2/2]

bool empty ( ITER_CONST const * iter)
static

Definition at line 360 of file template.h.

360 {
361 DEBUG_ASSERT(iter);
362 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
363}
Here is the call graph for this function:

◆ full()

bool full ( SELF const * self)
static

Definition at line 212 of file template.h.

212 {
213 DEBUG_ASSERT(self);
214 if (self->capacity == MAX_CAPACITY) {
215 if (self->free_list == INDEX_NONE) {
216 return true;
217 }
218 }
219 return false;
220}
#define MAX_CAPACITY
Definition staticvec.c:9
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_iter()

ITER get_iter ( SELF * self)
static

Definition at line 312 of file template.h.

312 {
313 DEBUG_ASSERT(self);
314 INDEX_TYPE index = 0;
315 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
316 index++;
317 }
318
319 return (ITER){
320 .arena = self,
321 .next_index = index,
322 .pos = 0,
323 .curr = (IV_PAIR){.index = (INDEX){.index = INDEX_NONE}, .value = NULL},
324 };
325}
#define INDEX
Definition template.h:73
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_iter_const()

ITER_CONST get_iter_const ( SELF const * self)
static

Definition at line 389 of file template.h.

389 {
390 DEBUG_ASSERT(self);
391 INDEX_TYPE index = 0;
392 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
393 index++;
394 }
395
396 return (ITER_CONST){
397 .arena = self,
398 .next_index = index,
399 .pos = 0,
400 .curr = (IV_PAIR_CONST){.index = (INDEX){.index = INDEX_NONE}, .value = NULL},
401 };
402}
#define IV_PAIR_CONST
Definition template.h:341
Here is the call graph for this function:
Here is the caller graph for this function:

◆ insert()

INDEX insert ( SELF * self,
V value )
static

Definition at line 126 of file template.h.

126 {
127 DEBUG_ASSERT(self);
128 if (self->free_list != INDEX_NONE) {
129 INDEX_TYPE free_index = self->free_list;
130 SLOT* slot = &self->slots[free_index];
131 DEBUG_ASSERT(!slot->present);
132 self->free_list = slot->next_free;
133 slot->present = true;
134 slot->value = value;
135 self->count++;
136 return (INDEX){.index = free_index};
137 }
138
139 if (self->exclusive_end == self->capacity) {
141 self->capacity *= RESIZE_FACTOR;
142 SLOT* new_alloc = (SLOT*)realloc(self->slots, self->capacity * sizeof(SLOT));
143 ASSERT(new_alloc);
144 self->slots = new_alloc;
145 }
146
147 INDEX_TYPE new_index = self->exclusive_end;
148 SLOT* slot = &self->slots[new_index];
149 slot->present = true;
150 slot->value = value;
151 self->count++;
152 self->exclusive_end++;
153 return (INDEX){.index = new_index};
154}
static void * realloc(SELF *self, void *ptr, size_t size)
Definition template.h:51
#define ASSERT(expr,...)
Definition panic.h:16
size_t capacity
Definition template.h:94
size_t exclusive_end
Definition template.h:101
#define RESIZE_FACTOR
Definition template.h:70
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_with_capacity_for()

SELF new_with_capacity_for ( INDEX_TYPE items,
ALLOC * alloc )
static

Definition at line 110 of file template.h.

110 {
111 DEBUG_ASSERT(items > 0);
112 size_t capacity = next_power_of_2(items);
113 ASSERT(capacity <= MAX_CAPACITY);
114 SLOT* slots = (SLOT*)NAME(ALLOC, calloc)(alloc, capacity, sizeof(SLOT));
115 ASSERT(slots);
116 return (SELF){
117 .slots = slots,
118 .capacity = (INDEX_TYPE)capacity,
119 .free_list = INDEX_NONE,
120 .exclusive_end = 0,
121 .count = 0,
122 .alloc = alloc,
123 };
124}
static void * calloc(SELF *self, size_t count, size_t size)
Definition template.h:40
static size_t next_power_of_2(size_t x)
Definition core.h:28
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next() [1/2]

IV_PAIR const * next ( ITER * iter)
static

Definition at line 289 of file template.h.

289 {
290 DEBUG_ASSERT(iter);
291
292 if (NAME(ITER, empty)(iter)) {
293 return NULL;
294 }
295 iter->curr = (IV_PAIR){.index = (INDEX){.index = iter->next_index},
296 .value = &iter->arena->slots[iter->next_index].value};
297 iter->next_index++;
298 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
299 !iter->arena->slots[iter->next_index].present) {
300 iter->next_index++;
301 }
302
303 iter->pos++;
304 return &iter->curr;
305}
static bool empty(ITER const *iter)
Definition template.h:281
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next() [2/2]

IV_PAIR_CONST const * next ( ITER_CONST * iter)
static

Definition at line 365 of file template.h.

365 {
366 DEBUG_ASSERT(iter);
367
368 if (NAME(ITER_CONST, empty)(iter)) {
369 return NULL;
370 }
371
372 iter->curr = (IV_PAIR_CONST){.index = (INDEX){.index = iter->next_index},
373 .value = &iter->arena->slots[iter->next_index].value};
374 iter->next_index++;
375 while (iter->next_index != INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
376 !iter->arena->slots[iter->next_index].present) {
377 iter->next_index++;
378 }
379
380 iter->pos++;
381 return &iter->curr;
382}
Here is the call graph for this function:

◆ position() [1/2]

size_t position ( ITER const * iter)
static

Definition at line 307 of file template.h.

307 {
308 DEBUG_ASSERT(iter);
309 return iter->pos;
310}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ position() [2/2]

size_t position ( ITER_CONST const * iter)
static

Definition at line 384 of file template.h.

384 {
385 DEBUG_ASSERT(iter);
386 return iter->pos;
387}
Here is the call graph for this function:

◆ read()

V const * read ( SELF const * self,
INDEX index )
static

Definition at line 186 of file template.h.

186 {
187 V const* value = NAME(SELF, try_read)(self, index);
188 ASSERT(value);
189 return value;
190}
static V const * try_read(SELF const *self, INDEX index)
Definition template.h:174
#define V
Definition template.h:32
Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove()

V remove ( SELF * self,
INDEX index )
static

Definition at line 243 of file template.h.

243 {
244 V value;
245 ASSERT(NAME(SELF, try_remove)(self, index, &value));
246 return value;
247}
static bool try_remove(SELF *self, INDEX index, V *destination)
Definition template.h:225
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shallow_clone()

SELF shallow_clone ( SELF const * self)
static

Definition at line 192 of file template.h.

192 {
193 DEBUG_ASSERT(self);
194 SLOT* slots = (SLOT*)NAME(ALLOC, calloc)(self->alloc, self->capacity, sizeof(SLOT));
195 ASSERT(slots);
196 memcpy(slots, self->slots, self->exclusive_end * sizeof(SLOT));
197 return (SELF){
198 .slots = slots,
199 .capacity = self->capacity,
200 .free_list = self->free_list,
201 .exclusive_end = self->exclusive_end,
202 .count = self->count,
203 .alloc = self->alloc,
204 };
205}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ size()

INDEX_TYPE size ( SELF const * self)
static
Examples
complex/prime_sieve.c.

Definition at line 207 of file template.h.

207 {
208 DEBUG_ASSERT(self);
209 return self->count;
210}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_read()

V const * try_read ( SELF const * self,
INDEX index )
static

Definition at line 174 of file template.h.

174 {
175 DEBUG_ASSERT(self);
176 if (!CHECK_ACCESS_INDEX(self, index)) {
177 return NULL;
178 }
179 SLOT* slot = &self->slots[index.index];
180 if (!slot->present) {
181 return NULL;
182 }
183 return &slot->value;
184}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_remove()

bool try_remove ( SELF * self,
INDEX index,
V * destination )
static

Definition at line 225 of file template.h.

225 {
226 DEBUG_ASSERT(self);
227 if (!CHECK_ACCESS_INDEX(self, index)) {
228 return false;
229 }
230
231 SLOT* entry = &self->slots[index.index];
232 if (entry->present) {
233 *destination = entry->value;
234 entry->present = false;
235 entry->next_free = self->free_list;
236 self->free_list = index.index;
237 self->count--;
238 return true;
239 }
240 return false;
241}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_write()

V * try_write ( SELF * self,
INDEX index )
static

Definition at line 156 of file template.h.

156 {
157 DEBUG_ASSERT(self);
158 if (!CHECK_ACCESS_INDEX(self, index)) {
159 return NULL;
160 }
161 SLOT* slot = &self->slots[index.index];
162 if (!slot->present) {
163 return NULL;
164 }
165 return &slot->value;
166}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write()

V * write ( SELF * self,
INDEX index )
static

Definition at line 168 of file template.h.

168 {
169 V* value = NAME(SELF, try_write)(self, index);
170 ASSERT(value);
171 return value;
172}
static V * try_write(SELF *self, INDEX index)
Definition template.h:156
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ iv_const_empty

IV_PAIR_CONST iv_const_empty
static
Initial value:
= {
.index = {.index = INDEX_NONE},
.value = NULL,
}

Definition at line 347 of file template.h.

347 {
348 .index = {.index = INDEX_NONE},
349 .value = NULL,
350};

◆ max_capacity

size_t max_capacity = MAX_CAPACITY
static

Definition at line 222 of file template.h.

◆ max_index

size_t max_index = MAX_INDEX
static

Definition at line 223 of file template.h.