Cthulhu  0.2.10
Cthulhu compiler collection
vector.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "std/vector.h"
4 #include "arena/arena.h"
5 #include "base/panic.h"
6 #include "base/util.h"
7 
15 typedef struct vector_t
16 {
18 
19  size_t size;
20  size_t used;
21  STA_FIELD_SIZE(size) void *data[];
22 } vector_t;
23 
24 vector_t gEmptyVector = { NULL, 0, 0 };
25 const vector_t kEmptyVector = { NULL, 0, 0 };
26 
27 // get the size of the vector struct given a number of elements
28 static size_t vector_typesize(size_t size)
29 {
30  return sizeof(vector_t) + (size * sizeof(void *));
31 }
32 
33 #define CHECK_VECTOR(vector) \
34  CTASSERT((vector) != NULL); \
35  CTASSERT(*(vector) != NULL);
36 
37 #define VEC (*vector)
38 
39 static void vector_ensure(vector_t **vector, size_t size)
40 {
41  if (size >= VEC->size)
42  {
43  size_t resize = (size + 1) * 2;
44  VEC = arena_realloc(VEC, vector_typesize(resize), vector_typesize(size), VEC->arena);
45  VEC->size = resize;
46  }
47 }
48 
49 static vector_t *vector_init_inner(size_t size, size_t used, arena_t *arena)
50 {
51  vector_t *vector = ARENA_MALLOC(vector_typesize(size), "vector", NULL, arena);
52 
53  vector->arena = arena;
54  vector->size = size;
55  vector->used = used;
56 
57  return vector;
58 }
59 
60 // vector public api
61 
63 vector_t *vector_new(size_t size, arena_t *arena)
64 {
65  CTASSERT(arena != NULL);
66 
67  return vector_init_inner(size, 0, arena);
68 }
69 
71 vector_t *vector_of(size_t len, arena_t *arena)
72 {
73  CTASSERT(arena != NULL);
74 
75  return vector_init_inner(len, len, arena);
76 }
77 
79 vector_t *vector_init(void *value, arena_t *arena)
80 {
81  CTASSERT(arena != NULL);
82 
83  vector_t *vector = vector_of(1, arena);
84  vector_set(vector, 0, value);
85  return vector;
86 }
87 
90 {
91  CTASSERT(vector != NULL);
92 
93  size_t len = vector_len(vector);
94  vector_t *clone = vector_of(len, vector->arena);
95  ctu_memcpy(clone->data, vector->data, len * sizeof(void *));
96  return clone;
97 }
98 
100 void vector_delete(vector_t *vector)
101 {
102  CTASSERT(vector != NULL);
103 
104  arena_free(vector, vector_typesize(vector->size), vector->arena);
105 }
106 
107 STA_DECL
108 void vector_push(vector_t **vector, void *value)
109 {
110  CHECK_VECTOR(vector);
111 
112  vector_ensure(vector, VEC->used + 1);
113  VEC->data[VEC->used++] = value;
114 }
115 
116 STA_DECL
117 void vector_drop(vector_t *vector)
118 {
119  CTASSERT(vector != NULL);
120  CTASSERT(vector_len(vector) > 0);
121  vector->used -= 1;
122 }
123 
124 STA_DECL
125 void vector_set(vector_t *vector, size_t index, void *value)
126 {
127  CTASSERT(vector != NULL);
128  CTASSERT(vector_len(vector) > index);
129 
130  vector->data[index] = value;
131 }
132 
133 STA_DECL
134 void *vector_get(const vector_t *vector, size_t index)
135 {
136  CTASSERT(vector != NULL);
137  CTASSERT(vector_len(vector) > index);
138 
139  return vector->data[index];
140 }
141 
142 STA_DECL
143 void *vector_tail(const vector_t *vector)
144 {
145  CTASSERT(vector != NULL);
146  CTASSERT(vector_len(vector) > 0);
147 
148  return vector->data[vector->used - 1];
149 }
150 
151 STA_DECL
152 size_t vector_len(const vector_t *vector)
153 {
154  CTASSERT(vector != NULL);
155 
156  return vector->used;
157 }
158 
159 STA_DECL
160 size_t vector_find(vector_t *vector, const void *element)
161 {
162  CTASSERT(vector != NULL);
163 
164  for (size_t i = 0; i < vector_len(vector); i++)
165  {
166  if (vector_get(vector, i) == element)
167  {
168  return i;
169  }
170  }
171 
172  return SIZE_MAX;
173 }
174 
175 STA_DECL
176 void vector_append(vector_t **vector, const vector_t *other)
177 {
178  CHECK_VECTOR(vector);
179 
180  size_t len = vector_len(other);
181 
182  vector_ensure(vector, VEC->used + len);
183  ctu_memcpy(VEC->data + VEC->used, other->data, len * sizeof(void *));
184  VEC->used += len;
185 }
186 
187 STA_DECL
189 {
190  CTASSERT(vec != NULL);
191 
192  vec->used = 0;
193 }
194 
195 STA_DECL
196 void **vector_data(vector_t *vec)
197 {
198  CTASSERT(vec != NULL);
199 
200  return vec->data;
201 }
CT_NODISCARD size_t size
Definition: scan.h:128
#define STA_FIELD_SIZE(of)
annotate a field as being an array of of elements
#define STA_DECL
sal2 annotation on function implementations to copy annotations from the declaration
CT_NOALIAS CT_BASE_API void * ctu_memcpy(STA_WRITES(size) void *CT_RESTRICT dst, STA_READS(size) const void *CT_RESTRICT src, size_t size)
copy memory from one location to another equivalent to memcpy but with safety checks
CT_NODISCARD CT_ARENA_API void * arena_realloc(STA_RELEASE void *ptr, size_t new_size, size_t old_size, arena_t *arena)
resize a memory allocation from a custom allocator
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
Definition: arena.h:392
CT_ARENA_API void arena_free(STA_RELEASE void *ptr, size_t size, arena_t *arena)
release memory from a custom allocator
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
STA_DECL void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
Definition: vector.c:134
STA_DECL vector_t * vector_new(size_t size, arena_t *arena)
create a new vector with an initial capacity
Definition: vector.c:63
STA_DECL vector_t * vector_of(size_t len, arena_t *arena)
create a new vector with a specified length
Definition: vector.c:71
const vector_t kEmptyVector
a global empty vector used to avoid allocating alot of empty vectors
Definition: vector.c:25
STA_DECL void vector_push(vector_t **vector, void *value)
push a value onto the end of a vector
Definition: vector.c:108
STA_DECL void vector_drop(vector_t *vector)
pop a value from the end of a vector
Definition: vector.c:117
STA_DECL void * vector_tail(const vector_t *vector)
get the last element of a vector
Definition: vector.c:143
STA_DECL void vector_set(vector_t *vector, size_t index, void *value)
set a value in a vector
Definition: vector.c:125
vector_t gEmptyVector
a global empty vector used to avoid allocating alot of empty vectors
Definition: vector.c:24
STA_DECL vector_t * vector_init(void *value, arena_t *arena)
create a new vector with a single initial value
Definition: vector.c:79
STA_DECL vector_t * vector_clone(vector_t *vector)
clone a vector
Definition: vector.c:89
STA_DECL size_t vector_find(vector_t *vector, const void *element)
find an element in a vector searches via pointer equality
Definition: vector.c:160
STA_DECL void vector_reset(vector_t *vec)
reset the contents of a vector
Definition: vector.c:188
STA_DECL void ** vector_data(vector_t *vec)
get the data of a vector
Definition: vector.c:196
STA_DECL size_t vector_len(const vector_t *vector)
get the length of a vector
Definition: vector.c:152
STA_DECL void vector_append(vector_t **vector, const vector_t *other)
append the contents of one vector to another this copies the contents of other into vector
Definition: vector.c:176
an allocator object
Definition: arena.h:86
a generic vector of pointers
Definition: vector.c:16
size_t size
the total number of allocated elements
Definition: vector.c:19
size_t used
the number of elements in use
Definition: vector.c:20
arena_t * arena
Definition: vector.c:17
#define CHECK_VECTOR(vector)
Definition: vector.c:33
STA_DECL void vector_delete(vector_t *vector)
Definition: vector.c:100
#define VEC
Definition: vector.c:37