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 EXCLUSIVE_END_INDEX
11 #if !defined PLACEHOLDERS
12TEMPLATE_ERROR("no EXCLUSIVE_END_INDEX")
13 #endif
14 #define EXCLUSIVE_END_INDEX 32
15#endif
16
17// JUSTIFY: exclusive end + 1
18// - We want to use the smallest allowed type for indices
19// - We need to ake sure the EXCLUSIVE_END_INDEX can be represented by the type chosen.
20//
21// For example, with an EXCLUSIVE_END_INDEX of 255:
22// - Choose a uint8_t
23// For example, with an EXCLUSIVE_END_INDEX of 256:
24// - Choose a uint16_t, so we can do index < EXCLUSIVE_END_INDEX
25// - Otherwise out for(..; index < EXCLUSIVE_END_INDEX; index++) loops would hit 255, then loop
26// back to zero and never complete.
27#define INDICES_CAPACITY (EXCLUSIVE_END_INDEX + 1)
28
31
33
35
36static INDEX_TYPE NS(SELF, min_index)() { return 0; }
37
38typedef struct {
42} SELF;
43
44#define INVARIANT_CHECK(self) DC_ASSUME(self);
45
46static SELF NS(SELF, new)() {
47 return (SELF){
48 .bits = {},
49 .derive_c_bitset_static = dc_gdb_marker_new(),
50 .iterator_invalidation_tracker = mutation_tracker_new(),
51 };
52}
53
54static bool NS(SELF, try_set)(SELF* self, INDEX_TYPE index, bool value) {
55 INVARIANT_CHECK(self);
56 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
57
58 if (index >= EXCLUSIVE_END_INDEX) {
59 return false;
60 }
61
64 uint8_t mask = DC_BITSET_STATIC_OFFSET_TO_MASK(offset);
65
66 if (value) {
67 self->bits[byte] = self->bits[byte] | mask;
68 } else {
69 self->bits[byte] = self->bits[byte] & (~mask);
70 }
71 return true;
72}
73
74static void NS(SELF, set)(SELF* self, INDEX_TYPE index, bool value) {
75 INVARIANT_CHECK(self);
76 DC_ASSERT(NS(SELF, try_set)(self, index, value));
77}
78
79static bool NS(SELF, get)(SELF const* self, INDEX_TYPE index) {
80 INVARIANT_CHECK(self);
81
83
86 uint8_t mask = DC_BITSET_STATIC_OFFSET_TO_MASK(offset);
87 return (self->bits[byte] & mask) != 0;
88}
89
90static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
91 fprintf(stream, EXPAND_STRING(SELF) "@%p {\n", self);
92 fmt = dc_debug_fmt_scope_begin(fmt);
93
94 dc_debug_fmt_print(fmt, stream, "blocks: [");
95 fmt = dc_debug_fmt_scope_begin(fmt);
96 for (INDEX_TYPE index = 0; index < EXCLUSIVE_END_INDEX; index++) {
97 if (NS(SELF, get)(self, index)) {
98 dc_debug_fmt_print(fmt, stream, "(byte: %lu, offset: %lu, index: %lu)",
100 (size_t)DC_BITSET_STATIC_INDEX_TO_OFFSET(index), (size_t)index);
101 }
102 }
103 fmt = dc_debug_fmt_scope_end(fmt);
104 dc_debug_fmt_print(fmt, stream, "],\n");
105
106 fmt = dc_debug_fmt_scope_end(fmt);
107 dc_debug_fmt_print(fmt, stream, "}");
108}
109
110static SELF NS(SELF, clone)(SELF const* self) {
111 INVARIANT_CHECK(self);
112 SELF new_self = (SELF){
113 .derive_c_bitset_static = dc_gdb_marker_new(),
114 .iterator_invalidation_tracker = mutation_tracker_new(),
115 };
116 memcpy(&new_self.bits, &self->bits, sizeof(self->bits));
117 return new_self;
118}
119
120static INDEX_TYPE NS(SELF, size)(SELF const* self) {
121 INDEX_TYPE size = 0;
122
123 for (INDEX_TYPE byte = 0;
125 size += __builtin_popcount((unsigned int)self->bits[byte]);
126 }
127
128 return size;
129}
130
131static void NS(SELF, delete)(SELF* self) { INVARIANT_CHECK(self); }
132
133#define ITER_CONST NS(SELF, iter_const)
134typedef struct {
135 SELF const* bitset;
138} ITER_CONST;
140
141static bool NS(ITER_CONST, empty_item)(INDEX_TYPE const* item) {
142 return *item == EXCLUSIVE_END_INDEX;
143}
144
146 DC_ASSUME(iter);
147 mutation_version_check(&iter->version);
148
149 if (iter->next_index == EXCLUSIVE_END_INDEX) {
150 return EXCLUSIVE_END_INDEX;
151 }
152
153 INDEX_TYPE next_index = iter->next_index;
154 iter->next_index++;
155 while (iter->next_index < EXCLUSIVE_END_INDEX &&
156 !NS(SELF, get)(iter->bitset, iter->next_index)) {
157 iter->next_index++;
158 }
159 return next_index;
160}
161
162static ITER_CONST NS(SELF, get_iter_const)(SELF const* self) {
163 INVARIANT_CHECK(self);
164
165 INDEX_TYPE next_index = 0;
166 while (next_index < EXCLUSIVE_END_INDEX && !NS(SELF, get)(self, next_index)) {
167 next_index++;
168 }
169
170 return (ITER_CONST){
171 .bitset = self,
172 .next_index = next_index,
173 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
174 };
175}
176
177#undef ITER_CONST
178
179#define ITER NS(SELF, iter)
180typedef struct {
184} ITER;
185typedef INDEX_TYPE NS(ITER, item);
186
187static bool NS(ITER, empty_item)(INDEX_TYPE const* item) { return *item == EXCLUSIVE_END_INDEX; }
188
189static INDEX_TYPE NS(ITER, next)(ITER* iter) {
190 DC_ASSUME(iter);
191 mutation_version_check(&iter->version);
192
193 if (iter->next_index == EXCLUSIVE_END_INDEX) {
194 return EXCLUSIVE_END_INDEX;
195 }
196
197 INDEX_TYPE next_index = iter->next_index;
198 iter->next_index++;
199 while (iter->next_index < EXCLUSIVE_END_INDEX &&
200 !NS(SELF, get)(iter->bitset, iter->next_index)) {
201 iter->next_index++;
202 }
203 return next_index;
204}
205
206static ITER NS(SELF, get_iter)(SELF* self) {
207 INVARIANT_CHECK(self);
208
209 INDEX_TYPE next_index = 0;
210 while (next_index < EXCLUSIVE_END_INDEX && !NS(SELF, get)(self, next_index)) {
211 next_index++;
212 }
213
214 return (ITER){
215 .bitset = self,
216 .next_index = next_index,
217 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
218 };
219}
220
221#undef ITER
222
223#undef INVARIANT_CHECK
224
227
228#undef INDICES_CAPACITY
229#undef EXCLUSIVE_END_INDEX
230
232
static void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:62
#define DC_BITSET_STATIC_INDEX_TO_OFFSET(INDEX)
Definition utils.h:5
#define DC_BITSET_STATIC_CAPACITY_TO_BYTES(CAPACITY)
Definition utils.h:3
#define DC_BITSET_STATIC_INDEX_TO_BYTES(INDEX)
Definition utils.h:4
#define DC_BITSET_STATIC_OFFSET_TO_MASK(OFFSET)
Definition utils.h:6
static ITER_CONST get_iter_const(SELF const *self)
Definition template.h:449
static ITER get_iter(SELF *self)
Definition template.h:370
static IV_PAIR next(ITER *iter)
Definition template.h:352
static INDEX_TYPE size(SELF const *self)
Definition template.h:252
#define INVARIANT_CHECK(self)
Definition template.h:88
static bool empty_item(IV_PAIR const *item)
Definition template.h:344
#define ITER
Definition template.h:320
#define ITER_CONST
Definition template.h:398
static SELF clone(SELF const *self)
Definition template.h:215
IV_PAIR item
Definition template.h:283
static INDEX_TYPE min_index()
Definition template.h:36
INDEX_TYPE index_t
Definition template.h:32
static INDEX_TYPE max_index()
Definition template.h:34
static void set(SELF *self, INDEX_TYPE index, bool value)
Definition template.h:74
#define EXCLUSIVE_END_INDEX
A simple bitset for indexes [0, EXCLUSIVE_END_INDEX), statically allocated.
Definition template.h:14
static bool try_set(SELF *self, INDEX_TYPE index, bool value)
Definition template.h:54
#define DC_TRAIT_BITSET(SELF)
Definition trait.h:6
#define INDEX_TYPE
Definition template.h:74
dc_debug_fmt dc_debug_fmt_scope_end(dc_debug_fmt fmt)
Definition fmt.h:39
dc_debug_fmt dc_debug_fmt_scope_begin(dc_debug_fmt fmt)
Definition fmt.h:33
static void dc_debug_fmt_print(dc_debug_fmt fmt, FILE *stream, const char *format,...)
Definition fmt.h:22
static dc_gdb_marker dc_gdb_marker_new()
Definition gdb_marker.h:7
static mutation_tracker mutation_tracker_new()
static void mutation_version_check(mutation_version const *self)
static mutation_version mutation_tracker_get(mutation_tracker const *self)
static void mutation_tracker_mutate(mutation_tracker *self)
#define EXPAND_STRING(NAME)
Definition namespace.h:8
#define NS(pre, post)
Definition namespace.h:4
static nullalloc get()
Definition null.h:14
#define DC_ASSERT(expr,...)
Definition panic.h:36
#define DC_ASSUME(expr,...)
Definition panic.h:56
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
Definition def.h:56
#define SELF
Definition def.h:52
INDEX_TYPE next_index
Definition template.h:403
SELF const * bitset
Definition template.h:135
mutation_version version
Definition template.h:404
INDEX_TYPE next_index
Definition template.h:325
mutation_version version
Definition template.h:326
SELF * bitset
Definition template.h:181
mutation_tracker iterator_invalidation_tracker
Definition template.h:85
dc_gdb_marker derive_c_bitset_static
Definition template.h:40
uint8_t bits[DC_BITSET_STATIC_CAPACITY_TO_BYTES(EXCLUSIVE_END_INDEX)]
Definition template.h:39
Debug format helpers for debug printin data structures.
Definition fmt.h:10
tracks a specific version of a value, so that this can be compared later to check modification For ex...
static FILE * stream(SELF *self)
Opens a file for.
Definition template.h:107