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
7#include <derive-c/core.h>
8#include <derive-c/panic.h>
9#include <derive-c/self.h>
10
11#ifndef T
12#ifndef __clang_analyzer__
13#error "The contained type must be defined for a vector template"
14#endif
15typedef struct {
16 int x;
17} derive_c_parameter_t;
18#define T derive_c_parameter_t // Allows independent debugging
19static void derive_c_parameter_t_delete(derive_c_parameter_t* UNUSED(self)) {}
20#define T_DELETE derive_c_parameter_t_delete
21#endif
22
23#ifndef T_DELETE
24#define T_DELETE(value)
25#endif
26
27#ifndef INPLACE_CAPACITY
28#ifndef __clang_analyzer__
29#error "The number of elements to store in-place must be defined"
30#endif
31#define INPLACE_CAPACITY 8
32#endif
33
34#if INPLACE_CAPACITY <= 255
35#define INPLACE_TYPE uint8_t
36#elif INPLACE_CAPACITY <= 65535
37#define INPLACE_TYPE uint16_t
38#else
39#error "INPLACE_CAPACITY must be less than or equal to 65535"
40#define INPLACE_TYPE size_t
41#endif
42
43typedef struct {
47} SELF;
48
49static SELF NAME(SELF, new)() { return (SELF){.size = 0}; }
50
51static SELF NAME(SELF, shallow_clone)(SELF const* self) {
52 SELF new_self = NAME(SELF, new)();
53 new_self.size = self->size;
54 // TODO(oliverkillane): premature optimization, only copy the data needed.
55 // If this is already a very small vector, may be better to just
56 // `return *self` and copy the entire buffer
57 for (INPLACE_TYPE i = 0; i < self->size; i++) {
58 new_self.data[i] = self->data[i];
59 }
60 return new_self;
61}
62
63static T const* NAME(SELF, try_read)(SELF const* self, INPLACE_TYPE index) {
64 DEBUG_ASSERT(self);
65 if (LIKELY(index < self->size)) {
66 return &self->data[index];
67 }
68 return NULL;
69}
70
71static T const* NAME(SELF, read)(SELF const* self, INPLACE_TYPE index) {
72 T const* value = NAME(SELF, try_read)(self, index);
73 ASSERT(value);
74 return value;
75}
76
77static T* NAME(SELF, try_write)(SELF* self, INPLACE_TYPE index) {
78 DEBUG_ASSERT(self);
79 if (LIKELY(index < self->size)) {
80 return &self->data[index];
81 }
82 return NULL;
83}
84
85static T* NAME(SELF, write)(SELF* self, INPLACE_TYPE index) {
86 T* value = NAME(SELF, try_write)(self, index);
87 ASSERT(value);
88 return value;
89}
90
91static T* NAME(SELF, try_push)(SELF* self, T value) {
92 DEBUG_ASSERT(self);
93 if (self->size < INPLACE_CAPACITY) {
94 T* slot = &self->data[self->size];
95 *slot = value;
96 self->size++;
97 return slot;
98 }
99 return NULL;
100}
101
102static T* NAME(SELF, push)(SELF* self, T value) {
103 T* slot = NAME(SELF, try_push)(self, value);
104 ASSERT(slot);
105 return slot;
106}
107
108static bool NAME(SELF, try_pop)(SELF* self, T* destination) {
109 DEBUG_ASSERT(self);
110 if (LIKELY(self->size > 0)) {
111 self->size--;
112 *destination = self->data[self->size];
113 return true;
114 }
115 return false;
116}
117
118static T NAME(SELF, pop)(SELF* self) {
119 T entry;
120 ASSERT(NAME(SELF, try_pop)(self, &entry));
121 return entry;
122}
123
124static size_t NAME(SELF, size)(SELF const* self) {
125 DEBUG_ASSERT(self);
126 return self->size;
127}
128
129static void NAME(SELF, delete)(SELF* self) {
130 DEBUG_ASSERT(self);
131 for (INPLACE_TYPE i = 0; i < self->size; i++) {
132 T_DELETE(&self->data[i]);
133 }
134}
135
136#define ITER NAME(SELF, iter)
137
138typedef struct {
139 SELF* vec;
140 size_t pos;
141} ITER;
142
143static T* NAME(ITER, next)(ITER* iter) {
144 DEBUG_ASSERT(iter);
145 if (iter->pos < iter->vec->size) {
146 T* item = &iter->vec->data[iter->pos];
147 iter->pos++;
148 return item;
149 }
150 return NULL;
151}
152
153static size_t NAME(ITER, position)(ITER const* iter) {
154 DEBUG_ASSERT(iter);
155 return iter->pos;
156}
157
158static bool NAME(ITER, empty)(ITER const* iter) {
159 DEBUG_ASSERT(iter);
160 return iter->pos >= iter->vec->size;
161}
162
163static ITER NAME(SELF, get_iter)(SELF* self) {
164 DEBUG_ASSERT(self);
165 return (ITER){
166 .vec = self,
167 .pos = 0,
168 };
169}
170
171#undef ITER
172
173#define ITER_CONST NAME(SELF, iter_const)
174
175typedef struct {
176 SELF const* vec;
177 size_t pos;
178} ITER_CONST;
179
180static T const* NAME(ITER_CONST, next)(ITER_CONST* iter) {
181 DEBUG_ASSERT(iter);
182 if (iter->pos < iter->vec->size) {
183 T const* item = &iter->vec->data[iter->pos];
184 iter->pos++;
185 return item;
186 }
187 return NULL;
188}
189
190static size_t NAME(ITER_CONST, position)(ITER_CONST const* iter) {
191 DEBUG_ASSERT(iter);
192 return iter->pos;
193}
194
195static bool NAME(ITER_CONST, empty)(ITER_CONST const* iter) {
196 DEBUG_ASSERT(iter);
197 return iter->pos >= iter->vec->size;
198}
199
200static ITER_CONST NAME(SELF, get_iter_const)(SELF const* self) {
201 DEBUG_ASSERT(self);
202 return (ITER_CONST){
203 .vec = self,
204 .pos = 0,
205 };
206}
207
208#undef ITER_CONST
209#undef INPLACE_TYPE
210
211#undef SELF
212#undef T
213#undef T_DELETE
214#undef INPLACE_CAPACITY
#define T
Definition template.h:68
#define SELF
Definition template.h:70
#define UNUSED(ident)
Definition core.h:13
#define NAME(pre, post)
Definition core.h:5
#define LIKELY(x)
Definition core.h:15
#define ASSERT(expr,...)
Definition panic.h:16
#define DEBUG_ASSERT(expr)
Definition panic.h:23
gdb_marker derive_c_staticvec
Definition template.h:46
T data[INPLACE_CAPACITY]
Definition template.h:45
INPLACE_TYPE size
Definition template.h:44
static ITER_CONST get_iter_const(SELF const *self)
Definition template.h:389
static bool empty(ITER const *iter)
Definition template.h:281
static ITER get_iter(SELF *self)
Definition template.h:312
static INDEX_TYPE size(SELF const *self)
Definition template.h:207
static IV_PAIR const * next(ITER *iter)
Definition template.h:289
static V const * try_read(SELF const *self, INDEX index)
Definition template.h:174
static V * write(SELF *self, INDEX index)
Definition template.h:168
static SELF shallow_clone(SELF const *self)
Definition template.h:192
static V * try_write(SELF *self, INDEX index)
Definition template.h:156
static size_t position(ITER const *iter)
Definition template.h:307
static V const * read(SELF const *self, INDEX index)
Definition template.h:186
#define T_DELETE
Definition template.h:20
static T pop(SELF *self)
Definition template.h:118
static bool try_pop(SELF *self, T *destination)
Definition template.h:108
#define INPLACE_TYPE
Definition template.h:35
#define INPLACE_CAPACITY
Definition template.h:31
static T * push(SELF *self, T value)
Definition template.h:102
static T * try_push(SELF *self, T value)
Definition template.h:91
#define T
Definition template.h:25