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/helpers.h>
#include <derive-c/core/panic.h>
#include <derive-c/core/alloc/def.h>
#include <derive-c/core/self/def.h>
#include <derive-c/core/alloc/undef.h>
#include <derive-c/core/self/undef.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  value_t
struct  INDEX
struct  SLOT
struct  SELF
 An allocator that prints to stdout when it allocates or frees memory. More...
struct  IV_PAIR
struct  IV_PAIR_CONST

Macros

#define INDEX_BITS   32
 A vector-backed arena, with support for small indices.
#define VALUE   value_t
#define VALUE_DELETE   value_delete
#define VALUE_CLONE   value_clone
#define SLOT   NS(SELF, slot)
#define CHECK_ACCESS_INDEX(self, index)
#define RESIZE_FACTOR   2
#define INDEX   NS(SELF, index)
#define IV_PAIR   NS(SELF, iv)
#define IV_PAIR_CONST   NS(SELF, iv_const)

Functions

static void value_delete (value_t *UNUSED(self))
static value_t value_clone (value_t const *self)
static SELF new_with_capacity_for (INDEX_TYPE items, ALLOC *alloc)
static INDEX insert (SELF *self, VALUE value)
static VALUEtry_write (SELF *self, INDEX index)
static VALUEwrite (SELF *self, INDEX index)
static VALUE const * try_read (SELF const *self, INDEX index)
static VALUE const * read (SELF const *self, INDEX index)
static SELF 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, VALUE *destination)
static VALUE 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 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 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

◆ CHECK_ACCESS_INDEX

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

Definition at line 69 of file template.h.

◆ INDEX

#define INDEX   NS(SELF, index)

Definition at line 76 of file template.h.

◆ INDEX_BITS

#define INDEX_BITS   32

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

Definition at line 19 of file template.h.

◆ IV_PAIR

#define IV_PAIR   NS(SELF, iv)

Definition at line 280 of file template.h.

◆ IV_PAIR_CONST

#define IV_PAIR_CONST   NS(SELF, iv_const)

Definition at line 346 of file template.h.

◆ RESIZE_FACTOR

#define RESIZE_FACTOR   2

Definition at line 73 of file template.h.

◆ SLOT

#define SLOT   NS(SELF, slot)

Definition at line 67 of file template.h.

◆ VALUE

#define VALUE   value_t

Definition at line 29 of file template.h.

◆ VALUE_CLONE

#define VALUE_CLONE   value_clone

Definition at line 33 of file template.h.

◆ VALUE_DELETE

#define VALUE_DELETE   value_delete

Definition at line 31 of file template.h.

Function Documentation

◆ clone()

SELF clone ( SELF const * self)
static

Definition at line 195 of file template.h.

195 {
196 DEBUG_ASSERT(self);
197 SLOT* slots = (SLOT*)NS(ALLOC, calloc)(self->alloc, self->capacity, sizeof(SLOT));
198 ASSERT(slots);
199
200 for (INDEX_TYPE index = 0; index < self->exclusive_end; index++) {
201 if (self->slots[index].present) {
202 slots[index].present = true;
203 slots[index].value = VALUE_CLONE(&self->slots[index].value);
204 } else {
205 slots[index].present = false;
206 slots[index].next_free = self->slots[index].next_free;
207 }
208 }
209
210 return (SELF){
211 .slots = slots,
212 .capacity = self->capacity,
213 .free_list = self->free_list,
214 .exclusive_end = self->exclusive_end,
215 .count = self->count,
216 .alloc = self->alloc,
217 };
218}
static void * calloc(SELF *self, size_t count, size_t size)
Definition template.h:34
#define ALLOC
Definition template.h:56
#define NS(pre, post)
Definition helpers.h:6
#define ASSERT(expr,...)
Definition panic.h:15
#define DEBUG_ASSERT(expr)
Definition panic.h:34
#define SELF
Definition def.h:51
VALUE value
Definition template.h:84
INDEX_TYPE next_free
Definition template.h:85
bool present
Definition template.h:92
#define SLOT
Definition template.h:67
#define VALUE_CLONE
Definition template.h:33
Here is the call graph for this function:
Here is the caller graph for this function:

◆ delete()

void delete ( SELF * self)
static

Definition at line 332 of file template.h.

332 {
333 DEBUG_ASSERT(self);
334 ITER iter = NS(SELF, get_iter)(self);
335 IV_PAIR const* entry;
336 while ((entry = NS(ITER, next)(&iter))) {
337 VALUE_DELETE(entry->value);
338 }
339
340 NS(ALLOC, free)(self->alloc, self->slots);
341}
static void free(SELF *self, void *ptr)
Definition template.h:56
VALUE * value
Definition template.h:283
SLOT * slots
Definition template.h:96
ALLOC * alloc
Definition template.h:63
static ITER get_iter(SELF *self)
Definition template.h:318
#define IV_PAIR
Definition template.h:280
static IV_PAIR const * next(ITER *iter)
Definition template.h:301
#define VALUE_DELETE
Definition template.h:31
Here is the call graph for this function:

◆ delete_entry()

bool delete_entry ( SELF * self,
INDEX index )
static

Definition at line 262 of file template.h.

262 {
263 DEBUG_ASSERT(self);
264 if (!CHECK_ACCESS_INDEX(self, index)) {
265 return false;
266 }
267
268 SLOT* entry = &self->slots[index.index];
269 if (entry->present) {
270 VALUE_DELETE(&entry->value);
271 entry->present = false;
272 entry->next_free = self->free_list;
273 self->free_list = index.index;
274 self->count--;
275 return true;
276 }
277 return false;
278}
INDEX_TYPE index
Definition template.h:79
INDEX_TYPE free_list
Definition template.h:98
size_t count
Definition template.h:108
#define CHECK_ACCESS_INDEX(self, index)
Definition template.h:69
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 293 of file template.h.

293 {
294 DEBUG_ASSERT(iter);
295 // JUSTIFY: If no entries are left, then the previous '.._next' call moved
296 // the index to the exclusive end
297 // NOTE: `index + 1 > exclusive_end` implies `index >= exclusive_end`
298 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
299}
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 364 of file template.h.

364 {
365 DEBUG_ASSERT(iter);
366 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
367}
Here is the call graph for this function:

◆ full()

bool full ( SELF const * self)
static

Definition at line 225 of file template.h.

225 {
226 DEBUG_ASSERT(self);
227 if (self->capacity == MAX_CAPACITY) {
228 if (self->free_list == INDEX_NONE) {
229 return true;
230 }
231 }
232 return false;
233}
#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 318 of file template.h.

318 {
319 DEBUG_ASSERT(self);
320 INDEX_TYPE index = 0;
321 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
322 index++;
323 }
324
325 return (ITER){
326 .arena = self,
327 .next_index = index,
328 .curr = (IV_PAIR){.index = (INDEX){.index = INDEX_NONE}, .value = NULL},
329 };
330}
#define INDEX
Definition template.h:76
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 387 of file template.h.

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

◆ insert()

INDEX insert ( SELF * self,
VALUE value )
static

Definition at line 129 of file template.h.

129 {
130 DEBUG_ASSERT(self);
131 if (self->free_list != INDEX_NONE) {
132 INDEX_TYPE free_index = self->free_list;
133 SLOT* slot = &self->slots[free_index];
134 DEBUG_ASSERT(!slot->present);
135 self->free_list = slot->next_free;
136 slot->present = true;
137 slot->value = value;
138 self->count++;
139 return (INDEX){.index = free_index};
140 }
141
142 if (self->exclusive_end == self->capacity) {
144 self->capacity *= RESIZE_FACTOR;
145 SLOT* new_alloc = (SLOT*)realloc(self->slots, self->capacity * sizeof(SLOT));
146 ASSERT(new_alloc);
147 self->slots = new_alloc;
148 }
149
150 INDEX_TYPE new_index = self->exclusive_end;
151 SLOT* slot = &self->slots[new_index];
152 slot->present = true;
153 slot->value = value;
154 self->count++;
155 self->exclusive_end++;
156 return (INDEX){.index = new_index};
157}
static void * realloc(SELF *self, void *ptr, size_t size)
Definition template.h:45
size_t capacity
Definition template.h:97
size_t exclusive_end
Definition template.h:104
#define RESIZE_FACTOR
Definition template.h:73
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 113 of file template.h.

113 {
114 DEBUG_ASSERT(items > 0);
115 size_t capacity = next_power_of_2(items);
116 ASSERT(capacity <= MAX_CAPACITY);
117 SLOT* slots = (SLOT*)NS(ALLOC, calloc)(alloc, capacity, sizeof(SLOT));
118 ASSERT(slots);
119 return (SELF){
120 .slots = slots,
121 .capacity = (INDEX_TYPE)capacity,
122 .free_list = INDEX_NONE,
123 .exclusive_end = 0,
124 .count = 0,
125 .alloc = alloc,
126 };
127}
static size_t next_power_of_2(size_t x)
Definition helpers.h:31
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 301 of file template.h.

301 {
302 DEBUG_ASSERT(iter);
303
304 if (NS(ITER, empty)(iter)) {
305 return NULL;
306 }
307 iter->curr = (IV_PAIR){.index = (INDEX){.index = iter->next_index},
308 .value = &iter->arena->slots[iter->next_index].value};
309 iter->next_index++;
310 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
311 !iter->arena->slots[iter->next_index].present) {
312 iter->next_index++;
313 }
314
315 return &iter->curr;
316}
static bool empty(ITER const *iter)
Definition template.h:293
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 369 of file template.h.

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

◆ read()

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

Definition at line 189 of file template.h.

189 {
190 VALUE const* value = NS(SELF, try_read)(self, index);
191 ASSERT(value);
192 return value;
193}
#define VALUE
Definition template.h:29
static VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:177
Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove()

VALUE remove ( SELF * self,
INDEX index )
static

Definition at line 256 of file template.h.

256 {
257 VALUE value;
258 ASSERT(NS(SELF, try_remove)(self, index, &value));
259 return value;
260}
static bool try_remove(SELF *self, INDEX index, VALUE *destination)
Definition template.h:238
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 220 of file template.h.

220 {
221 DEBUG_ASSERT(self);
222 return self->count;
223}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_read()

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

Definition at line 177 of file template.h.

177 {
178 DEBUG_ASSERT(self);
179 if (!CHECK_ACCESS_INDEX(self, index)) {
180 return NULL;
181 }
182 SLOT* slot = &self->slots[index.index];
183 if (!slot->present) {
184 return NULL;
185 }
186 return &slot->value;
187}
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,
VALUE * destination )
static

Definition at line 238 of file template.h.

238 {
239 DEBUG_ASSERT(self);
240 if (!CHECK_ACCESS_INDEX(self, index)) {
241 return false;
242 }
243
244 SLOT* entry = &self->slots[index.index];
245 if (entry->present) {
246 *destination = entry->value;
247 entry->present = false;
248 entry->next_free = self->free_list;
249 self->free_list = index.index;
250 self->count--;
251 return true;
252 }
253 return false;
254}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_write()

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

Definition at line 159 of file template.h.

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

◆ value_clone()

value_t value_clone ( value_t const * self)
static

Definition at line 32 of file template.h.

32{ return *self; }

◆ value_delete()

void value_delete ( value_t * UNUSEDself)
static

Definition at line 30 of file template.h.

30{}

◆ write()

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

Definition at line 171 of file template.h.

171 {
172 VALUE* value = NS(SELF, try_write)(self, index);
173 ASSERT(value);
174 return value;
175}
static VALUE * try_write(SELF *self, INDEX index)
Definition template.h:159
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 352 of file template.h.

352 {
353 .index = {.index = INDEX_NONE},
354 .value = NULL,
355};

◆ max_capacity

size_t max_capacity = MAX_CAPACITY
static

Definition at line 235 of file template.h.

◆ max_index

size_t max_index = MAX_INDEX
static

Definition at line 236 of file template.h.