Derive-C
Loading...
Searching...
No Matches
template.h
Go to the documentation of this file.
1
2
3#include <stdbool.h>
4#include <stddef.h>
5#include <stdint.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include <derive-c/core.h>
10#include <derive-c/panic.h>
11#include <derive-c/self.h>
12
13#ifndef T
14#error "The contained type must be defined for a vector template"
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*) {}
20#define T_DELETE derive_c_parameter_t_delete
21#endif
22
23#ifndef T_DELETE
24#define T_DELETE(value)
25#endif
26
27typedef struct {
28 size_t size;
29 size_t capacity;
32} SELF;
33
34static SELF NAME(SELF, new)() {
35 SELF temp = (SELF){
36 .size = 0,
37 .capacity = 0,
38 .data = NULL,
39 };
40 return temp;
41}
42
43static SELF NAME(SELF, new_with_capacity)(size_t capacity) {
44 DEBUG_ASSERT(capacity > 0);
45 T* data = (T*)malloc(capacity * sizeof(T));
46 ASSERT(LIKELY(data));
47 return (SELF){
48 .size = 0,
49 .capacity = capacity,
50 .data = data,
51 };
52}
53
54static SELF NAME(SELF, new_with_defaults)(size_t size, T default_value) {
55 T* data = (T*)malloc(size * sizeof(T));
56 for (size_t i = 0; i < size; i++) {
57 data[i] = default_value;
58 }
59 ASSERT(LIKELY(data));
60 return (SELF){
61 .size = size,
62 .capacity = size,
63 .data = data,
64 };
65}
66
67static SELF NAME(SELF, shallow_clone)(SELF const* self) {
68 DEBUG_ASSERT(self);
69 T* data = (T*)malloc(self->capacity * sizeof(T));
70 ASSERT(data);
71 memcpy(data, self->data, self->size * sizeof(T));
72 return (SELF){
73 .size = self->size,
74 .capacity = self->capacity,
75 .data = data,
76 };
77}
78
79static T const* NAME(SELF, try_read)(SELF const* self, size_t index) {
80 DEBUG_ASSERT(self);
81 if (LIKELY(index < self->size)) {
82 return &self->data[index];
83 } else {
84 return NULL;
85 }
86}
87
88static T const* NAME(SELF, read)(SELF const* self, size_t index) {
89 T const* value = NAME(SELF, try_read)(self, index);
90 ASSERT(value);
91 return value;
92}
93
94static T* NAME(SELF, try_write)(SELF* self, size_t index) {
95 DEBUG_ASSERT(self);
96 if (LIKELY(index < self->size)) {
97 return &self->data[index];
98 } else {
99 return NULL;
100 }
101}
102
103static T* NAME(SELF, write)(SELF* self, size_t index) {
104 T* value = NAME(SELF, try_write)(self, index);
105 ASSERT(value);
106 return value;
107}
108
109static T* NAME(SELF, push)(SELF* self, T value) {
110 DEBUG_ASSERT(self);
111 if (self->size == self->capacity) {
112 T* new_data;
113 size_t new_capacity;
114 if (self->data == NULL) {
115 DEBUG_ASSERT(self->capacity == 0);
116 // JUSTIFY: Allocating capacity of 4
117 // - Avoid repeat reallocations on growing a vector from
118 // size sero (from new)
119 // Otherwise an arbitrary choice (given we do not know the size of T)
120 new_capacity = 8;
121 new_data = (T*)malloc(new_capacity * sizeof(T));
122 } else {
123 // JUSTIFY: Growth factor of 2
124 // - Simple arithmetic (for debugging)
125 // - Same as used by GCC's std::vector implementation
126 new_capacity = self->capacity * 2;
127 new_data = (T*)realloc(self->data, new_capacity * sizeof(T));
128 }
129 ASSERT(new_data);
130 self->capacity = new_capacity;
131 self->data = new_data;
132 }
133 T* entry = &self->data[self->size];
134 *entry = value;
135 self->size++;
136 return entry;
137}
138
139static bool NAME(SELF, try_pop)(SELF* self, T* destination) {
140 DEBUG_ASSERT(self);
141 if (LIKELY(self->size > 0)) {
142 self->size--;
143 *destination = self->data[self->size];
144 return true;
145 } else {
146 return false;
147 }
148}
149
150static T NAME(SELF, pop)(SELF* self) {
151 T entry;
152 ASSERT(NAME(SELF, try_pop)(self, &entry));
153 return entry;
154}
155
156static size_t NAME(SELF, size)(SELF const* self) {
157 DEBUG_ASSERT(self);
158 return self->size;
159}
160
161static void NAME(SELF, delete)(SELF* self) {
162 DEBUG_ASSERT(self);
163 for (size_t i = 0; i < self->size; i++) {
164 T_DELETE(&self->data[i]);
165 }
166 free(self->data);
167}
168
169#define ITER NAME(SELF, iter)
170
171typedef struct {
172 SELF* vec;
173 size_t pos;
174} ITER;
175
176static T* NAME(ITER, next)(ITER* iter) {
177 DEBUG_ASSERT(iter);
178 if (iter->pos < iter->vec->size) {
179 T* item = &iter->vec->data[iter->pos];
180 iter->pos++;
181 return item;
182 } else {
183 return NULL;
184 }
185}
186
187static size_t NAME(ITER, position)(ITER const* iter) {
188 DEBUG_ASSERT(iter);
189 return iter->pos;
190}
191
192static bool NAME(ITER, empty)(ITER const* iter) {
193 DEBUG_ASSERT(iter);
194 return iter->pos >= iter->vec->size;
195}
196
197static ITER NAME(SELF, get_iter)(SELF* self) {
198 DEBUG_ASSERT(self);
199 return (ITER){
200 .vec = self,
201 .pos = 0,
202 };
203}
204#undef ITER
205
206#define ITER_CONST NAME(SELF, iter_const)
207
208typedef struct {
209 SELF const* vec;
210 size_t pos;
211} ITER_CONST;
212
213static T const* NAME(ITER_CONST, next)(ITER_CONST* iter) {
214 DEBUG_ASSERT(iter);
215 if (iter->pos < iter->vec->size) {
216 T const* item = &iter->vec->data[iter->pos];
217 iter->pos++;
218 return item;
219 } else {
220 return NULL;
221 }
222}
223
224static size_t NAME(ITER_CONST, position)(ITER_CONST const* iter) {
225 DEBUG_ASSERT(iter);
226 return iter->pos;
227}
228
229static bool NAME(ITER_CONST, empty)(ITER_CONST const* iter) {
230 DEBUG_ASSERT(iter);
231 return iter->pos >= iter->vec->size;
232}
233
234static ITER_CONST NAME(SELF, get_iter_const)(SELF const* self) {
235 DEBUG_ASSERT(self);
236 return (ITER_CONST){
237 .vec = self,
238 .pos = 0,
239 };
240}
241
242#undef ITER_CONST
243
244#undef SELF
245#undef T
246#undef T_DELETE
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
static T * push(SELF *self, T value)
Definition template.h:100
size_t capacity
Definition template.h:85
T data[INPLACE_CAPACITY]
Definition template.h:40
gdb_marker derive_c_vector
Definition template.h:31
INPLACE_TYPE size
Definition template.h:39
#define T
Definition template.h:18
static SELF new_with_capacity(size_t capacity)
Definition template.h:43
static SELF new_with_defaults(size_t size, T default_value)
Definition template.h:54