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/typed/vector.h"
4 
5 #include "base/util.h"
6 #include "core/macros.h"
7 
8 #include "arena/arena.h"
9 #include "base/panic.h"
10 
11 #include <stdlib.h>
12 
13 const typevec_t kEmptyTypevec = { 0 };
14 
15 // seperate from typevec_offset because we want to be able to get offsets
16 // outside of the vector
17 static void *get_element_offset(const typevec_t *vec, size_t index)
18 {
19  CTASSERT(vec != NULL);
20 
21  return ((char*)vec->data) + (index * vec->width);
22 }
23 
24 static void copy_elements(const typevec_t *vec, void *dst, const void *src, size_t count)
25 {
26  CTASSERT(vec != NULL);
27 
28  ctu_memcpy(dst, src, vec->width * count);
29 }
30 
31 static void typevec_ensure(typevec_t *vec, size_t extra)
32 {
33  CTASSERT(vec != NULL);
34 
35  if (vec->used + extra > vec->size)
36  {
37  size_t new_size = CT_MAX(vec->size * 2, vec->used + extra);
38 
39  vec->data = arena_realloc(vec->data, new_size * vec->width, vec->size * vec->width, vec->arena);
40 
41  vec->size = new_size;
42  }
43 }
44 
45 static typevec_t *typevec_create(size_t width, size_t len, arena_t *arena)
46 {
47  typevec_t *vec = ARENA_MALLOC(sizeof(typevec_t), "typevec", NULL, arena);
48  typevec_init(vec, width, len, arena);
49  return vec;
50 }
51 
53 void typevec_init(typevec_t *vec, size_t width, size_t len, arena_t *arena)
54 {
55  CTASSERT(vec != NULL);
56  CTASSERT(arena != NULL);
57  CTASSERT(width > 0);
58 
59  size_t size = CT_MAX(len, 1);
60 
61  vec->arena = arena;
62  vec->size = size;
63  vec->used = 0;
64  vec->width = width;
65  vec->data = ARENA_MALLOC(width * (size + 1), "data", vec, arena);
66 }
67 
69 typevec_t typevec_make(size_t width, size_t len, arena_t *arena)
70 {
71  typevec_t vec = { 0 };
72  typevec_init(&vec, width, len, arena);
73  return vec;
74 }
75 
77 typevec_t *typevec_new(size_t width, size_t len, arena_t *arena)
78 {
79  return typevec_create(width, len, arena);
80 }
81 
83 typevec_t *typevec_of(size_t width, size_t len, arena_t *arena)
84 {
85  typevec_t *self = typevec_create(width, len, arena);
86  self->used = len;
87  return self;
88 }
89 
91 typevec_t *typevec_of_array(size_t width, const void *src, size_t count, arena_t *arena)
92 {
93  CTASSERT(src != NULL);
94 
95  typevec_t *self = typevec_create(width, count, arena);
96  self->used = count;
97 
98  copy_elements(self, self->data, src, count);
99 
100  return self;
101 }
102 
103 STA_DECL
104 typevec_t *typevec_slice(const typevec_t *vec, size_t start, size_t end)
105 {
106  CTASSERT(vec != NULL);
107  CTASSERTF(start <= end, "start %zu > end %zu", start, end);
108  CTASSERTF(end <= typevec_len(vec), "end %zu out of bounds %zu", end, typevec_len(vec));
109 
110  size_t len = end - start;
111  typevec_t *self = typevec_create(vec->width, len, vec->arena);
112  self->used = len;
113 
114  copy_elements(self, self->data, typevec_offset(vec, start), len);
115 
116  return self;
117 }
118 
119 STA_DECL
120 size_t typevec_len(const typevec_t *vec)
121 {
122  CTASSERT(vec != NULL);
123 
124  return vec->used;
125 }
126 
127 STA_DECL
128 void typevec_set(typevec_t *vec, size_t index, const void *src)
129 {
130  CTASSERT(vec != NULL);
131  CTASSERT(src != NULL);
132 
133  void *dst = typevec_offset(vec, index);
134  copy_elements(vec, dst, src, 1);
135 }
136 
137 STA_DECL
138 void typevec_get(const typevec_t *vec, size_t index, void *dst)
139 {
140  CTASSERT(vec != NULL);
141  CTASSERT(dst != NULL);
142 
143  void *src = typevec_offset(vec, index);
144  copy_elements(vec, dst, src, 1);
145 }
146 
147 STA_DECL
148 void typevec_tail(const typevec_t *vec, void *dst)
149 {
150  CTASSERT(typevec_len(vec) > 0);
151 
152  typevec_get(vec, vec->used - 1, dst);
153 }
154 
155 STA_DECL
156 void *typevec_push(typevec_t *vec, const void *src)
157 {
158  CTASSERT(vec != NULL);
159 
160  typevec_ensure(vec, 1);
161 
162  void *dst = get_element_offset(vec, vec->used++);
163  copy_elements(vec, dst, src, 1);
164 
165  return dst;
166 }
167 
168 STA_DECL
169 void typevec_append(typevec_t *vec, const void *src, size_t len)
170 {
171  CTASSERT(vec != NULL);
172  CTASSERT(src != NULL);
173 
174  typevec_ensure(vec, len);
175 
176  void *dst = get_element_offset(vec, vec->used);
177  ctu_memcpy(dst, src, vec->width * len);
178  vec->used += len;
179 }
180 
181 STA_DECL
182 void typevec_pop(typevec_t *vec, void *dst)
183 {
184  CTASSERT(typevec_len(vec) > 0);
185 
186  void *src = typevec_offset(vec, --vec->used);
187  copy_elements(vec, dst, src, 1);
188 }
189 
190 STA_DECL
191 void *typevec_offset(const typevec_t *vec, size_t index)
192 {
193  CTASSERTF(index < typevec_len(vec), "index %zu out of bounds %zu", index, typevec_len(vec));
194 
195  return ((char*)vec->data) + (index * vec->width);
196 }
197 
198 STA_DECL
199 void *typevec_data(const typevec_t *vec)
200 {
201  CTASSERT(vec != NULL);
202 
203  return vec->data;
204 }
205 
206 void typevec_sort(IN_NOTNULL typevec_t *vec, int (*cmp)(const void *, const void *))
207 {
208  CTASSERT(vec != NULL);
209  CTASSERT(cmp != NULL);
210 
211  // TODO: we cant do this, some platforms dont have qsort
212 
213  qsort(vec->data, vec->used, vec->width, cmp);
214 }
215 
216 STA_DECL
217 void typevec_reset(typevec_t *vec)
218 {
219  CTASSERT(vec != NULL);
220 
221  vec->used = 0;
222 }
CT_NODISCARD size_t size
Definition: scan.h:128
#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
#define CT_MAX(L, R)
Definition: macros.h:34
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
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:116
STA_DECL typevec_t * typevec_of(size_t width, size_t len, arena_t *arena)
create a new typed vector with an initial size and length
Definition: vector.c:83
STA_DECL typevec_t typevec_make(size_t width, size_t len, arena_t *arena)
create a new typed vector on the stack
Definition: vector.c:69
STA_DECL void typevec_init(typevec_t *vec, size_t width, size_t len, arena_t *arena)
initialize a typed vector
Definition: vector.c:53
const typevec_t kEmptyTypevec
Definition: vector.c:13
STA_DECL typevec_t * typevec_slice(const typevec_t *vec, size_t start, size_t end)
create a new typevec from an existing typevec
Definition: vector.c:104
STA_DECL typevec_t * typevec_new(size_t width, size_t len, arena_t *arena)
create a new typed vector on the heap
Definition: vector.c:77
an allocator object
Definition: arena.h:86
A vector with a fixed type size.
Definition: vector.h:24
size_t used
The number of elements used.
Definition: vector.h:31
size_t width
The size of each element.
Definition: vector.h:34
arena_t * arena
Definition: vector.h:25
size_t size
The number of elements allocated.
Definition: vector.h:28
STA_DECL typevec_t * typevec_of_array(size_t width, const void *src, size_t count, arena_t *arena)
Definition: vector.c:91