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