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 DC_PLACEHOLDERS
12TEMPLATE_ERROR("no EXCLUSIVE_END_INDEX")
13 #endif
14 #define EXCLUSIVE_END_INDEX 32
15#endif
16
19 DC_EXPAND_STRING(SELF) " EXCLUSIVE_END_INDEX must be larger than 0 for nonempty bitset");
20
21#define INDICES_CAPACITY EXCLUSIVE_END_INDEX
22
25
26typedef INDEX_TYPE NS(SELF, index_t);
27
30
31typedef struct {
35} SELF;
36
37#define INVARIANT_CHECK(self) DC_ASSUME(self);
38
39DC_PUBLIC static SELF NS(SELF, new)() {
40 return (SELF){
41 .bits = {},
42 .derive_c_bitset_static = dc_gdb_marker_new(),
43 .iterator_invalidation_tracker = mutation_tracker_new(),
44 };
45}
46
47DC_PUBLIC static bool NS(SELF, try_set)(SELF* self, INDEX_TYPE index, bool value) {
48 INVARIANT_CHECK(self);
49 mutation_tracker_mutate(&self->iterator_invalidation_tracker);
50
51 // JUSTIFY: Only checking if the end index could be smaller than max
52 // - If exclusive end is 1 larger than the max index, this check does not work.
53 // e.g. exclusive end is 256. So index is uint8_t, which means we can never represent an
54 // incorrect index, so no check.
55#if EXCLUSIVE_END_INDEX <= MAX_INDEX
56 if (index >= EXCLUSIVE_END_INDEX) {
57 return false;
58 }
59#endif
60
61 INDEX_TYPE byte = DC_BITSET_STATIC_INDEX_TO_BYTES(index);
62 INDEX_TYPE offset = DC_BITSET_STATIC_INDEX_TO_OFFSET(index);
63 uint8_t mask = DC_BITSET_STATIC_OFFSET_TO_MASK(offset);
64
65 if (value) {
66 self->bits[byte] = self->bits[byte] | mask;
67 } else {
68 self->bits[byte] = self->bits[byte] & (~mask);
69 }
70 return true;
71}
72
73DC_PUBLIC static void NS(SELF, set)(SELF* self, INDEX_TYPE index, bool value) {
74 INVARIANT_CHECK(self);
75 DC_ASSERT(NS(SELF, try_set)(self, index, value),
76 "Failed to set index {index=%lu, value=%d, exclusive_end_index=%d}", (size_t)index,
77 value, EXCLUSIVE_END_INDEX);
78}
79
80DC_PUBLIC static bool NS(SELF, get)(SELF const* self, INDEX_TYPE index) {
81 INVARIANT_CHECK(self);
82
83#if EXCLUSIVE_END_INDEX <= MAX_INDEX
85 "Index out of bounds {index=%lu, exclusive_end_index=%d}", (size_t)index,
87#endif
88
89 INDEX_TYPE byte = DC_BITSET_STATIC_INDEX_TO_BYTES(index);
90 INDEX_TYPE offset = DC_BITSET_STATIC_INDEX_TO_OFFSET(index);
91 uint8_t mask = DC_BITSET_STATIC_OFFSET_TO_MASK(offset);
92 return (self->bits[byte] & mask) != 0;
93}
94
95DC_PUBLIC static void NS(SELF, debug)(SELF const* self, dc_debug_fmt fmt, FILE* stream) {
96 fprintf(stream, DC_EXPAND_STRING(SELF) "@%p {\n", (void*)self);
97 fmt = dc_debug_fmt_scope_begin(fmt);
98
99 dc_debug_fmt_print(fmt, stream, "blocks: [\n");
100 fmt = dc_debug_fmt_scope_begin(fmt);
101 for (size_t index = 0; index < EXCLUSIVE_END_INDEX; index++) {
102 if (NS(SELF, get)(self, (INDEX_TYPE)index)) {
103 dc_debug_fmt_print(fmt, stream, "{ byte: %lu, offset: %lu, index: %lu},\n",
106 }
107 }
108 fmt = dc_debug_fmt_scope_end(fmt);
109 dc_debug_fmt_print(fmt, stream, "],\n");
110
111 fmt = dc_debug_fmt_scope_end(fmt);
112 dc_debug_fmt_print(fmt, stream, "}");
113}
114
115DC_PUBLIC static SELF NS(SELF, clone)(SELF const* self) {
116 INVARIANT_CHECK(self);
117 SELF new_self = (SELF){
118 .derive_c_bitset_static = dc_gdb_marker_new(),
119 .iterator_invalidation_tracker = mutation_tracker_new(),
120 };
121 memcpy(&new_self.bits, &self->bits, sizeof(self->bits));
122 return new_self;
123}
124
125DC_PUBLIC static size_t NS(SELF, size)(SELF const* self) {
126 size_t size = 0;
127
128 for (INDEX_TYPE byte = 0;
129 byte < (INDEX_TYPE)DC_BITSET_STATIC_CAPACITY_TO_BYTES(EXCLUSIVE_END_INDEX); byte++) {
130 size += (uint32_t)__builtin_popcount((unsigned int)self->bits[byte]);
131 }
132
133 return size;
134}
135
136DC_PUBLIC static void NS(SELF, delete)(SELF* self) { INVARIANT_CHECK(self); }
137
138// JUSTIFY: Larger iter index type if the exclusive end is larger than the max representable index.
139// - We need to represent the none index.
140// - We need the smallest type that can represent the exclusive end index.
141#if EXCLUSIVE_END_INDEX < MAX_INDEX
142 #define ITER_INDEX_TYPE INDEX_TYPE
143#else
144 #define ITER_INDEX_TYPE INDEX_LARGER_TYPE
145#endif
146
147#define ITER_CONST NS(SELF, iter_const)
148typedef struct {
149 SELF const* bitset;
152} ITER_CONST;
154
156 return *item == EXCLUSIVE_END_INDEX;
157}
158
160 DC_ASSUME(iter);
161 mutation_version_check(&iter->version);
162
163 if (iter->next_index == EXCLUSIVE_END_INDEX) {
164 return EXCLUSIVE_END_INDEX;
165 }
166
167 ITER_INDEX_TYPE next_index = iter->next_index;
168 iter->next_index++;
169 while (iter->next_index < EXCLUSIVE_END_INDEX &&
170 !NS(SELF, get)(iter->bitset, (INDEX_TYPE)iter->next_index)) {
171 iter->next_index++;
172 }
173 return next_index;
174}
175
176DC_PUBLIC static bool NS(ITER_CONST, empty)(ITER_CONST const* iter) {
177 DC_ASSUME(iter);
178 mutation_version_check(&iter->version);
179 return iter->next_index >= EXCLUSIVE_END_INDEX;
180}
181
183 INVARIANT_CHECK(self);
184
185 ITER_INDEX_TYPE next_index = 0;
186 while (next_index < EXCLUSIVE_END_INDEX && !NS(SELF, get)(self, (INDEX_TYPE)next_index)) {
187 next_index++;
188 }
189
190 return (ITER_CONST){
191 .bitset = self,
192 .next_index = next_index,
193 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
194 };
195}
196
197#undef ITER_CONST
198
199#define ITER NS(SELF, iter)
200typedef struct {
204} ITER;
205typedef ITER_INDEX_TYPE NS(ITER, item);
206
207DC_PUBLIC static bool NS(ITER, empty_item)(ITER_INDEX_TYPE const* item) {
208 return *item == EXCLUSIVE_END_INDEX;
209}
210
212 DC_ASSUME(iter);
213 mutation_version_check(&iter->version);
214
215 if (iter->next_index == EXCLUSIVE_END_INDEX) {
216 return EXCLUSIVE_END_INDEX;
217 }
218
219 ITER_INDEX_TYPE next_index = iter->next_index;
220 iter->next_index++;
221 while (iter->next_index < EXCLUSIVE_END_INDEX &&
222 !NS(SELF, get)(iter->bitset, (INDEX_TYPE)iter->next_index)) {
223 iter->next_index++;
224 }
225 return next_index;
226}
227
228DC_PUBLIC static bool NS(ITER, empty)(ITER const* iter) {
229 DC_ASSUME(iter);
230 mutation_version_check(&iter->version);
231 return iter->next_index >= EXCLUSIVE_END_INDEX;
232}
233
235 INVARIANT_CHECK(self);
236
237 ITER_INDEX_TYPE next_index = 0;
238 while (next_index < EXCLUSIVE_END_INDEX && !NS(SELF, get)(self, (INDEX_TYPE)next_index)) {
239 next_index++;
240 }
241
242 return (ITER){
243 .bitset = self,
244 .next_index = next_index,
245 .version = mutation_tracker_get(&self->iterator_invalidation_tracker),
246 };
247}
248
249#undef ITER
250#undef ITER_INDEX_TYPE
251#undef INVARIANT_CHECK
252
255
256#undef INDICES_CAPACITY
257#undef EXCLUSIVE_END_INDEX
258
260
static DC_PUBLIC void debug(SELF const *self, dc_debug_fmt fmt, FILE *stream)
Definition template.h:212
#define DC_STATIC_CONSTANT
Definition attributes.h:23
#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
#define INVARIANT_CHECK(self)
Definition template.h:90
static DC_PUBLIC IV_PAIR next(ITER *iter)
Definition template.h:355
static DC_PUBLIC bool empty(ITER const *iter)
Definition template.h:349
static DC_PUBLIC bool empty_item(IV_PAIR const *item)
Definition template.h:347
#define ITER
Definition template.h:322
static DC_PUBLIC ITER get_iter(SELF *self)
Definition template.h:373
#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
static DC_PUBLIC bool try_set(SELF *self, INDEX_TYPE index, bool value)
Definition template.h:47
static DC_PUBLIC bool get(SELF const *self, INDEX_TYPE index)
Definition template.h:80
INDEX_TYPE index_t
Definition template.h:26
static DC_PUBLIC void set(SELF *self, INDEX_TYPE index, bool value)
Definition template.h:73
#define ITER_INDEX_TYPE
Definition template.h:144
DC_STATIC_CONSTANT INDEX_TYPE max_index
Definition template.h:28
#define EXCLUSIVE_END_INDEX
A simple bitset for indexes [0, EXCLUSIVE_END_INDEX), statically allocated.
Definition template.h:14
DC_STATIC_CONSTANT INDEX_TYPE min_index
Definition template.h:29
#define DC_TRAIT_BITSET(SELF)
Definition trait.h:6
#define TEMPLATE_ERROR(...)
With the user provided name, even in nested templates.
Definition def.h:56
#define SELF
Definition def.h:52
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
INDEX_TYPE next_index
Definition template.h:416
SELF const * bitset
Definition template.h:149
mutation_version version
Definition template.h:417
INDEX_TYPE next_index
Definition template.h:327
mutation_version version
Definition template.h:328
SELF * bitset
Definition template.h:201
mutation_tracker iterator_invalidation_tracker
Definition template.h:87
dc_gdb_marker derive_c_bitset_static
Definition template.h:33
uint8_t bits[DC_BITSET_STATIC_CAPACITY_TO_BYTES(EXCLUSIVE_END_INDEX)]
Definition template.h:32
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