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 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 INDEX_BITS   32
 A vector-backed arena, with support for small indices.
 
#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)
 
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 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 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 iv_empty
 
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 57 of file template.h.

◆ INDEX

#define INDEX   NAME(SELF, index)

Definition at line 64 of file template.h.

◆ INDEX_BITS

#define INDEX_BITS   32

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

Definition at line 15 of file template.h.

◆ IV_PAIR

#define IV_PAIR   NAME(SELF, iv)

Definition at line 255 of file template.h.

◆ IV_PAIR_CONST

#define IV_PAIR_CONST   NAME(SELF, iv_const)

Definition at line 335 of file template.h.

◆ RESIZE_FACTOR

#define RESIZE_FACTOR   2

Definition at line 61 of file template.h.

◆ SLOT

#define SLOT   NAME(SELF, SLOT)

Definition at line 55 of file template.h.

◆ V

#define V   derive_c_parameter_value

Definition at line 23 of file template.h.

◆ V_DELETE

#define V_DELETE   derive_c_parameter_value_delete

Definition at line 25 of file template.h.

Function Documentation

◆ delete()

static void delete ( SELF * self)
static

Definition at line 319 of file template.h.

319 {
320 DEBUG_ASSERT(self);
321 ITER iter = NAME(SELF, get_iter)(self);
322 while (!NAME(ITER, empty)(&iter)) {
323 IV_PAIR pair = NAME(ITER, next)(&iter);
324 if (pair.value) {
325 V_DELETE(pair.value);
326 }
327 }
328
329 free(self->slots);
330}
static bool empty(ITER const *iter)
Definition template.h:273
static ITER get_iter(SELF *self)
Definition template.h:305
static IV_PAIR next(ITER *iter)
Definition template.h:281
#define IV_PAIR
Definition template.h:255
#define V_DELETE
Definition template.h:25
#define NAME(pre, post)
Definition core.h:5
#define DEBUG_ASSERT(expr)
Definition panic.h:24
#define SELF
Definition self.h:4
V * value
Definition template.h:258
SLOT * slots
Definition template.h:84
Here is the call graph for this function:

◆ delete_entry()

static bool delete_entry ( SELF * self,
INDEX index )
static

Definition at line 237 of file template.h.

237 {
238 DEBUG_ASSERT(self);
239 if (!CHECK_ACCESS_INDEX(self, index)) {
240 return false;
241 }
242
243 SLOT* entry = &self->slots[index.index];
244 if (entry->present) {
245 V_DELETE(&entry->value);
246 entry->present = false;
247 entry->next_free = self->free_list;
248 self->free_list = index.index;
249 self->count--;
250 return true;
251 }
252 return false;
253}
#define SLOT
Definition template.h:55
#define CHECK_ACCESS_INDEX(self, index)
Definition template.h:57
INDEX_TYPE index
Definition template.h:67
INDEX_TYPE free_list
Definition template.h:86
size_t count
Definition template.h:96
INDEX_TYPE next_free
Definition template.h:73
V value
Definition template.h:72
bool present
Definition template.h:80
Here is the call graph for this function:
Here is the caller graph for this function:

◆ empty() [1/2]

static bool empty ( ITER const * iter)
static

Definition at line 273 of file template.h.

273 {
274 DEBUG_ASSERT(iter);
275 // JUSTIFY: If no entries are left, then the previous '.._next' call moved
276 // the index to the exclusive end
277 // NOTE: `index + 1 > exclusive_end` implies `index >= exclusive_end`
278 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
279}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ empty() [2/2]

static bool empty ( ITER_CONST const * iter)
static

Definition at line 353 of file template.h.

353 {
354 DEBUG_ASSERT(iter);
355 return iter->next_index == INDEX_NONE || iter->next_index >= iter->arena->exclusive_end;
356}
Here is the call graph for this function:

◆ full()

static bool full ( SELF const * self)
static

Definition at line 199 of file template.h.

199 {
200 DEBUG_ASSERT(self);
201 if (self->capacity == MAX_CAPACITY) {
202 if (self->free_list == INDEX_NONE) {
203 return true;
204 }
205 }
206 return false;
207}
#define MAX_CAPACITY
Definition staticvec.c:10
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_iter()

static ITER get_iter ( SELF * self)
static

Definition at line 305 of file template.h.

305 {
306 DEBUG_ASSERT(self);
307 INDEX_TYPE index = 0;
308 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
309 index++;
310 }
311
312 return (ITER){
313 .arena = self,
314 .next_index = index,
315 .pos = 0,
316 };
317}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_iter_const()

static ITER_CONST get_iter_const ( SELF const * self)
static

Definition at line 382 of file template.h.

382 {
383 DEBUG_ASSERT(self);
384 INDEX_TYPE index = 0;
385 while (index < INDEX_NONE && index < self->exclusive_end && !self->slots[index].present) {
386 index++;
387 }
388
389 return (ITER_CONST){
390 .arena = self,
391 .next_index = index,
392 .pos = 0,
393 };
394}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ insert()

static INDEX insert ( SELF * self,
V value )
static

Definition at line 114 of file template.h.

114 {
115 DEBUG_ASSERT(self);
116 if (self->free_list != INDEX_NONE) {
117 INDEX_TYPE free_index = self->free_list;
118 SLOT* slot = &self->slots[free_index];
119 DEBUG_ASSERT(!SLOT->present);
120 self->free_list = slot->next_free;
121 slot->present = true;
122 slot->value = value;
123 self->count++;
124 return (INDEX){.index = free_index};
125 }
126
127 if (self->exclusive_end == self->capacity) {
129 self->capacity *= RESIZE_FACTOR;
130 SLOT* new_alloc = (SLOT*)realloc(self->slots, self->capacity * sizeof(SLOT));
131 ASSERT(new_alloc);
132 self->slots = new_alloc;
133 }
134
135 INDEX_TYPE new_index = self->exclusive_end;
136 SLOT* slot = &self->slots[new_index];
137 slot->present = true;
138 slot->value = value;
139 self->count++;
140 self->exclusive_end++;
141 return (INDEX){.index = new_index};
142}
#define RESIZE_FACTOR
Definition template.h:61
#define INDEX
Definition template.h:64
#define ASSERT(expr,...)
Definition panic.h:15
size_t capacity
Definition template.h:85
size_t exclusive_end
Definition template.h:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ new_with_capacity_for()

static SELF new_with_capacity_for ( INDEX_TYPE items)
static

Definition at line 99 of file template.h.

99 {
100 DEBUG_ASSERT(items > 0);
101 size_t capacity = next_power_of_2(items);
102 ASSERT(capacity <= MAX_CAPACITY);
103 SLOT* slots = (SLOT*)calloc(capacity, sizeof(SLOT));
104 ASSERT(slots);
105 return (SELF){
106 .slots = slots,
107 .capacity = (INDEX_TYPE)capacity,
108 .free_list = INDEX_NONE,
109 .exclusive_end = 0,
110 .count = 0,
111 };
112}
static size_t next_power_of_2(size_t x)
Definition core.h:24
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next() [1/2]

static IV_PAIR next ( ITER * iter)
static

Definition at line 281 of file template.h.

281 {
282 DEBUG_ASSERT(iter);
283
284 if (NAME(ITER, empty)(iter)) {
285 return (IV_PAIR){.index = (INDEX){.index = INDEX_NONE}, .value = NULL};
286 } else {
287 IV_PAIR out = (IV_PAIR){.index = (INDEX){.index = iter->next_index},
288 .value = &iter->arena->slots[iter->next_index].value};
289 iter->next_index++;
290 while (iter->next_index < INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
291 !iter->arena->slots[iter->next_index].present) {
292 iter->next_index++;
293 }
294
295 iter->pos++;
296 return out;
297 }
298}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next() [2/2]

static IV_PAIR_CONST next ( ITER_CONST * iter)
static

Definition at line 358 of file template.h.

358 {
359 DEBUG_ASSERT(iter);
360
361 if (NAME(ITER_CONST, empty)(iter)) {
362 return (IV_PAIR_CONST){.index = (INDEX){.index = INDEX_NONE}, .value = NULL};
363 } else {
364 IV_PAIR_CONST out = (IV_PAIR_CONST){.index = (INDEX){.index = iter->next_index},
365 .value = &iter->arena->slots[iter->next_index].value};
366 iter->next_index++;
367 while (iter->next_index != INDEX_NONE && iter->next_index < iter->arena->exclusive_end &&
368 !iter->arena->slots[iter->next_index].present) {
369 iter->next_index++;
370 }
371
372 iter->pos++;
373 return out;
374 }
375}
#define IV_PAIR_CONST
Definition template.h:335
Here is the call graph for this function:

◆ position() [1/2]

static size_t position ( ITER const * iter)
static

Definition at line 300 of file template.h.

300 {
301 DEBUG_ASSERT(iter);
302 return iter->pos;
303}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ position() [2/2]

static size_t position ( ITER_CONST const * iter)
static

Definition at line 377 of file template.h.

377 {
378 DEBUG_ASSERT(iter);
379 return iter->pos;
380}
Here is the call graph for this function:

◆ read()

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

Definition at line 174 of file template.h.

174 {
175 V const* value = NAME(SELF, try_read)(self, index);
176 ASSERT(value);
177 return value;
178}
static V const * try_read(SELF const *self, INDEX index)
Definition template.h:162
#define V
Definition template.h:23
Here is the call graph for this function:
Here is the caller graph for this function:

◆ remove()

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

Definition at line 231 of file template.h.

231 {
232 V value;
233 ASSERT(NAME(SELF, try_remove)(self, index, &value));
234 return value;
235}
static bool try_remove(SELF *self, INDEX index, V *destination)
Definition template.h:212
Here is the call graph for this function:
Here is the caller graph for this function:

◆ shallow_clone()

static SELF shallow_clone ( SELF const * self)
static

Definition at line 180 of file template.h.

180 {
181 DEBUG_ASSERT(self);
182 SLOT* slots = (SLOT*)malloc(self->capacity * sizeof(SLOT));
183 ASSERT(slots);
184 memcpy(slots, self->slots, self->exclusive_end * sizeof(SLOT));
185 return (SELF){
186 .slots = slots,
187 .capacity = self->capacity,
188 .free_list = self->free_list,
189 .exclusive_end = self->exclusive_end,
190 .count = self->count,
191 };
192}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ size()

static INDEX_TYPE size ( SELF const * self)
static

Definition at line 194 of file template.h.

194 {
195 DEBUG_ASSERT(self);
196 return self->count;
197}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_read()

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

Definition at line 162 of file template.h.

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

◆ try_remove()

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

Definition at line 212 of file template.h.

212 {
213 DEBUG_ASSERT(self);
214 if (!CHECK_ACCESS_INDEX(self, index)) {
215 return false;
216 }
217
218 SLOT* entry = &self->slots[index.index];
219 if (entry->present) {
220 *destination = entry->value;
221 entry->present = false;
222 entry->next_free = self->free_list;
223 self->free_list = index.index;
224 self->count--;
225 return true;
226 } else {
227 return false;
228 }
229}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_write()

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

Definition at line 144 of file template.h.

144 {
145 DEBUG_ASSERT(self);
146 if (!CHECK_ACCESS_INDEX(self, index)) {
147 return NULL;
148 }
149 SLOT* slot = &self->slots[index.index];
150 if (!slot->present) {
151 return NULL;
152 }
153 return &slot->value;
154}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write()

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

Definition at line 156 of file template.h.

156 {
157 V* value = NAME(SELF, try_write)(self, index);
158 ASSERT(value);
159 return value;
160}
static V * try_write(SELF *self, INDEX index)
Definition template.h:144
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 341 of file template.h.

341 {
342 .index = {.index = INDEX_NONE},
343 .value = NULL,
344};

◆ iv_empty

IV_PAIR iv_empty
static
Initial value:
= {
.index = {.index = INDEX_NONE},
.value = NULL,
}

Definition at line 261 of file template.h.

261 {
262 .index = {.index = INDEX_NONE},
263 .value = NULL,
264};

◆ max_capacity

size_t max_capacity = MAX_CAPACITY
static

Definition at line 209 of file template.h.

◆ max_index

size_t max_index = MAX_INDEX
static

Definition at line 210 of file template.h.