Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
3
4#include <stddef.h>
5#include <stdint.h>
6#include <string.h>
7
10
12
13#if !defined ITEM
14 #if !defined __clang_analyzer__
15 #error "ITEM must be defined"
16 #endif
17typedef struct {
18 int x;
19} item_t;
20 #define ITEM item_t
21static void item_delete(item_t* UNUSED(self)) {}
22 #define ITEM_DELETE item_delete
23static item_t item_clone(item_t const* self) { return *self; }
24 #define ITEM_CLONE item_clone
25#endif
26
27#if !defined ITEM_DELETE
28 #define ITEM_DELETE(value)
29#endif
30
31#if !defined ITEM_CLONE
32 #define ITEM_CLONE(value) (*(value))
33#endif
34
35#if !defined INPLACE_CAPACITY
36 #if !defined __clang_analyzer__
37 #error "The number of elements to store in-place must be defined"
38 #endif
39 #define INPLACE_CAPACITY 8
40#endif
41
42#if INPLACE_CAPACITY <= 255
43 #define INPLACE_TYPE uint8_t
44#elif INPLACE_CAPACITY <= 65535
45 #define INPLACE_TYPE uint16_t
46#else
47 #error "INPLACE_CAPACITY must be less than or equal to 65535"
48 #define INPLACE_TYPE size_t
49#endif
50
51typedef struct {
55} SELF;
56
57static SELF NS(SELF, new)() { return (SELF){.size = 0}; }
58
60
61static SELF NS(SELF, clone)(SELF const* self) {
62 SELF new_self = NS(SELF, new)();
63 new_self.size = self->size;
64 for (INPLACE_TYPE i = 0; i < self->size; i++) {
65 new_self.data[i] = ITEM_CLONE(&self->data[i]);
66 }
67 return new_self;
68}
69
70static ITEM const* NS(SELF, try_read)(SELF const* self, INPLACE_TYPE index) {
71 DEBUG_ASSERT(self);
72 if (LIKELY(index < self->size)) {
73 return &self->data[index];
74 }
75 return NULL;
76}
77
78static ITEM const* NS(SELF, read)(SELF const* self, INPLACE_TYPE index) {
79 ITEM const* value = NS(SELF, try_read)(self, index);
80 ASSERT(value);
81 return value;
82}
83
84static ITEM* NS(SELF, try_write)(SELF* self, INPLACE_TYPE index) {
85 DEBUG_ASSERT(self);
86 if (LIKELY(index < self->size)) {
87 return &self->data[index];
88 }
89 return NULL;
90}
91
92static ITEM* NS(SELF, write)(SELF* self, INPLACE_TYPE index) {
93 ITEM* value = NS(SELF, try_write)(self, index);
94 ASSERT(value);
95 return value;
96}
97
98static ITEM* NS(SELF, try_push)(SELF* self, ITEM item) {
99 DEBUG_ASSERT(self);
100 if (self->size < INPLACE_CAPACITY) {
101 ITEM* slot = &self->data[self->size];
102 *slot = item;
103 self->size++;
104 return slot;
105 }
106 return NULL;
107}
108
109static bool NS(SELF, try_insert_at)(SELF* self, size_t at, ITEM const* items, size_t count) {
110 DEBUG_ASSERT(self);
111 DEBUG_ASSERT(items);
112 ASSERT(at <= self->size);
113
114 if (self->size + count > INPLACE_CAPACITY) {
115 return false;
116 }
117
118 memmove(&self->data[at + count], &self->data[at], (self->size - at) * sizeof(ITEM));
119 memcpy(&self->data[at], items, count * sizeof(ITEM));
120 self->size += count;
121 return true;
122}
123
124static void NS(SELF, remove_at)(SELF* self, size_t at, size_t count) {
125 DEBUG_ASSERT(self);
126 ASSERT(at + count <= self->size);
127
128 if (count == 0) {
129 return;
130 }
131
132 for (size_t i = at; i < at + count; i++) {
133 ITEM_DELETE(&self->data[i]);
134 }
135
136 memmove(&self->data[at], &self->data[at + count], (self->size - (at + count)) * sizeof(ITEM));
137 self->size -= count;
138}
139
140static ITEM* NS(SELF, push)(SELF* self, ITEM item) {
141 ITEM* slot = NS(SELF, try_push)(self, item);
142 ASSERT(slot);
143 return slot;
144}
145
146static bool NS(SELF, try_pop)(SELF* self, ITEM* destination) {
147 DEBUG_ASSERT(self);
148 if (LIKELY(self->size > 0)) {
149 self->size--;
150 *destination = self->data[self->size];
151 return true;
152 }
153 return false;
154}
155
156static ITEM NS(SELF, pop)(SELF* self) {
157 ITEM entry;
158 ASSERT(NS(SELF, try_pop)(self, &entry));
159 return entry;
160}
161
162static size_t NS(SELF, size)(SELF const* self) {
163 DEBUG_ASSERT(self);
164 return self->size;
165}
166
167static void NS(SELF, delete)(SELF* self) {
168 DEBUG_ASSERT(self);
169 for (INPLACE_TYPE i = 0; i < self->size; i++) {
170 ITEM_DELETE(&self->data[i]);
171 }
172}
173
174#define ITER NS(SELF, iter)
175
176typedef struct {
177 SELF* vec;
178 size_t pos;
179} ITER;
180
181static ITEM* NS(ITER, next)(ITER* iter) {
182 DEBUG_ASSERT(iter);
183 if (iter->pos < iter->vec->size) {
184 ITEM* item = &iter->vec->data[iter->pos];
185 iter->pos++;
186 return item;
187 }
188 return NULL;
189}
190
191static size_t NS(ITER, position)(ITER const* iter) {
192 DEBUG_ASSERT(iter);
193 return iter->pos;
194}
195
196static bool NS(ITER, empty)(ITER const* iter) {
197 DEBUG_ASSERT(iter);
198 return iter->pos >= iter->vec->size;
199}
200
201static ITER NS(SELF, get_iter)(SELF* self) {
202 DEBUG_ASSERT(self);
203 return (ITER){
204 .vec = self,
205 .pos = 0,
206 };
207}
208
209#undef ITER
210
211#define ITER_CONST NS(SELF, iter_const)
212
213typedef struct {
214 SELF const* vec;
215 size_t pos;
216} ITER_CONST;
217
218static ITEM const* NS(ITER_CONST, next)(ITER_CONST* iter) {
219 DEBUG_ASSERT(iter);
220 if (iter->pos < iter->vec->size) {
221 ITEM const* item = &iter->vec->data[iter->pos];
222 iter->pos++;
223 return item;
224 }
225 return NULL;
226}
227
228static size_t NS(ITER_CONST, position)(ITER_CONST const* iter) {
229 DEBUG_ASSERT(iter);
230 return iter->pos;
231}
232
233static bool NS(ITER_CONST, empty)(ITER_CONST const* iter) {
234 DEBUG_ASSERT(iter);
235 return iter->pos >= iter->vec->size;
236}
237
238static ITER_CONST NS(SELF, get_iter_const)(SELF const* self) {
239 DEBUG_ASSERT(self);
240 return (ITER_CONST){
241 .vec = self,
242 .pos = 0,
243 };
244}
245
246#undef ITER_CONST
247
248#undef INPLACE_TYPE
249#undef INPLACE_CAPACITY
250
251#undef ITEM
252#undef ITEM_DELETE
253#undef ITEM_CLONE
254
#define ITEM
Definition template.h:55
#define UNUSED(ident)
Definition helpers.h:16
#define NS(pre, post)
Definition helpers.h:6
#define LIKELY(x)
Definition helpers.h:18
#define ASSERT(expr,...)
Definition panic.h:15
#define DEBUG_ASSERT(expr)
Definition panic.h:34
#define SELF
Definition def.h:51
gdb_marker derive_c_staticvec
Definition template.h:54
ITEM * data
Definition template.h:38
INPLACE_TYPE size
Definition template.h:52
A queue comprised of an extendable circular buffer.
Definition template.h:19
static ITER_CONST get_iter_const(SELF const *self)
Definition template.h:387
static bool empty(ITER const *iter)
Definition template.h:293
static ITER get_iter(SELF *self)
Definition template.h:318
static INDEX_TYPE size(SELF const *self)
Definition template.h:220
static IV_PAIR const * next(ITER *iter)
Definition template.h:301
static VALUE * try_write(SELF *self, INDEX index)
Definition template.h:159
static VALUE const * read(SELF const *self, INDEX index)
Definition template.h:189
static VALUE * write(SELF *self, INDEX index)
Definition template.h:171
static SELF clone(SELF const *self)
Definition template.h:195
static VALUE const * try_read(SELF const *self, INDEX index)
Definition template.h:177
#define ITEM_DELETE
Definition template.h:24
static void item_delete(item_t *UNUSED(self))
Definition template.h:23
#define ITEM_CLONE
Definition template.h:26
static item_t item_clone(item_t const *self)
Definition template.h:25
static void remove_at(SELF *self, size_t at, size_t count)
Definition template.h:124
static ITEM * push(SELF *self, ITEM item)
Definition template.h:140
static bool try_pop(SELF *self, ITEM *destination)
Definition template.h:146
static ITEM pop(SELF *self)
Definition template.h:156
static ITEM * try_push(SELF *self, ITEM item)
Definition template.h:98
#define INPLACE_TYPE
Definition template.h:43
static size_t position(ITER const *iter)
Definition template.h:191
#define INPLACE_CAPACITY
Definition template.h:39
static bool try_insert_at(SELF *self, size_t at, ITEM const *items, size_t count)
Definition template.h:109
static const INPLACE_TYPE max_size
Definition template.h:59
#define ITEM
Definition template.h:22