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