Landtiger LPC1768 C BigLib 1
A self made, custom C library for the LandTiger board.
 
Loading...
Searching...
No Matches
cl_vector.c
Go to the documentation of this file.
1#include "cl_vector.h"
2
3#include <stdlib.h>
4#include <string.h>
5
6// TYPE DEFINITION
7
14
15#define RESZ_FACTOR 2
16#define BASE_CAPACITY 10
17
18// PRIVATE FUNCTIONS
19
20_PRIVATE inline void *realloc_data(CL_Vector *const arr, u32 new_capacity)
21{
22 void *new_data = MEM_Realloc(arr->allocator, arr->data, new_capacity * arr->elem_size);
23 if (!new_data)
24 return NULL;
25
26 arr->data = new_data;
27 arr->capacity = new_capacity;
28 return new_data;
29}
30
31// PUBLIC FUNCTIONS
32
33CL_Vector *CL_VectorAllocWithCapacity(MEM_Allocator *const alloc, u32 capacity, u32 elem_sz)
34{
35 if (!alloc || !capacity || !elem_sz)
36 return NULL;
37
38 CL_Vector *const arr = MEM_Alloc(alloc, sizeof(CL_Vector));
39 if (!arr)
40 return NULL;
41
42 *arr = (CL_Vector){
43 .data = MEM_Alloc(alloc, capacity * elem_sz),
44 .size = 0,
45 .capacity = capacity,
46 .elem_size = elem_sz,
47 .allocator = alloc,
48 };
49
50 if (!arr->data)
51 {
52 MEM_Free(alloc, arr);
53 return NULL;
54 }
55
56 return arr;
57}
58
60{
61 return CL_VectorAllocWithCapacity(alloc, BASE_CAPACITY, elem_sz);
62}
63
65{
66 if (!arr)
67 return;
68
69 MEM_Free(arr->allocator, arr->data);
70 MEM_Free(arr->allocator, arr);
71}
72
73CL_Error CL_VectorPushBack(CL_Vector *const arr, const void *const elem, u32 *out_index)
74{
75 if (!arr || !elem)
77
78 // Checking if the array can hold the element
79 if (arr->size >= arr->capacity)
80 {
81 const u32 new_cap = arr->capacity * RESZ_FACTOR;
82 if (!realloc_data(arr, new_cap))
83 return CL_ERR_NO_MEMORY;
84 }
85
86 const u32 offset = arr->size * arr->elem_size;
87 memcpy((u8 *)(arr->data) + offset, elem, arr->elem_size);
88 arr->size++;
89
90 if (out_index)
91 *out_index = arr->size - 1;
92
93 return CL_ERR_OK;
94}
95
96CL_Error CL_VectorPushFront(CL_Vector *const arr, const void *const elem)
97{
98 // Inserting at the front is equivalent to inserting at index 0
99 return CL_VectorInsert(arr, elem, 0);
100}
101
102void CL_VectorPopBack(CL_Vector *const arr, void *out_elem)
103{
104 if (!arr || !arr->size)
105 return;
106
107 const u32 offset = (arr->size - 1) * arr->elem_size;
108 if (out_elem)
109 memcpy(out_elem, (u8 *)(arr->data) + offset, arr->elem_size);
110
111 // memset((u8 *)(arr->data) + offset, 0, arr->elem_size); // Not necessary
112 arr->size--;
113}
114
115void CL_VectorPopFront(CL_Vector *const arr, void *out_elem)
116{
117 if (!arr || !arr->size)
118 return;
119
120 if (out_elem)
121 CL_VectorGet(arr, 0, out_elem);
122
123 CL_VectorRemove(arr, 0);
124}
125
126CL_Error CL_VectorGet(const CL_Vector *const arr, u32 index, void *out_elem)
127{
128 if (!arr || !out_elem)
130
131 if (index >= arr->size || index < 0)
133
134 if (arr->size == 0)
135 return CL_ERR_EMPTY;
136
137 const u32 offset = index * arr->elem_size;
138 memcpy(out_elem, (u8 *)(arr->data) + offset, arr->elem_size);
139 return CL_ERR_OK;
140}
141
142CL_Error CL_VectorGetPtr(const CL_Vector *const arr, u32 index, void **out_elem)
143{
144 if (!arr || !out_elem)
146
147 if (index >= arr->size || index < 0)
149
150 if (arr->size == 0)
151 return CL_ERR_EMPTY;
152
153 const u32 offset = index * arr->elem_size;
154 *out_elem = (u8 *)(arr->data) + offset;
155 return CL_ERR_OK;
156}
157
158CL_Error CL_VectorGetLast(const CL_Vector *const arr, void *out_elem)
159{
160 if (arr->size == 0)
161 return CL_ERR_EMPTY;
162
163 return CL_VectorGet(arr, arr->size - 1, out_elem);
164}
165
166CL_Error CL_VectorGetLastPtr(const CL_Vector *const arr, void **out_elem)
167{
168 if (arr->size == 0)
169 return CL_ERR_EMPTY;
170
171 return CL_VectorGetPtr(arr, arr->size - 1, out_elem);
172}
173
174CL_Error CL_VectorInsert(CL_Vector *const arr, const void *const elem, u32 index)
175{
176 if (!arr || !elem)
178
179 if (index > arr->size || index < 0)
181
182 if (arr->size >= arr->capacity)
183 {
184 const u32 new_cap = arr->capacity * RESZ_FACTOR;
185 if (!realloc_data(arr, new_cap))
186 return CL_ERR_NO_MEMORY;
187 }
188
189 const u32 where_offset = index * arr->elem_size;
190 const u32 next_offset = where_offset + arr->elem_size;
191
192 // Shift the elements to the right, in order to make space for the new element
193 memmove((u8 *)arr->data + next_offset, (u8 *)arr->data + where_offset, (arr->size - index) * arr->elem_size);
194 memcpy((u8 *)arr->data + where_offset, elem, arr->elem_size);
195 arr->size++;
196 return CL_ERR_OK;
197}
198
200{
201 if (!arr)
203
204 if (index >= arr->size || index < 0)
206
207 if (arr->size == 0)
208 return CL_ERR_EMPTY;
209
210 const u32 where_offset = index * arr->elem_size;
211 const u32 next_offset = where_offset + arr->elem_size;
212
213 // Shift the elements to the left, in order to remove the element
214 memmove((u8 *)arr->data + where_offset, (u8 *)arr->data + next_offset, (arr->size - index - 1) * arr->elem_size);
215 arr->size--;
216 return CL_ERR_OK;
217}
218
219void CL_VectorClear(CL_Vector *const arr)
220{
221 if (!arr || !arr->size)
222 return;
223
224 // memset(arr->data, 0, arr->size * arr->elem_size); // Not necessary
225 arr->size = 0;
226}
227
228bool CL_VectorIsEmpty(const CL_Vector *const arr)
229{
230 return arr ? arr->size == 0 : true;
231}
232
233u32 CL_VectorSize(const CL_Vector *const arr)
234{
235 return arr ? arr->size : 0;
236}
237
239{
240 return arr ? arr->capacity : 0;
241}
242
244{
245 if (!arr || !cmp || arr->size < 2)
246 return;
247
248 qsort(arr->data, arr->size, arr->elem_size, cmp);
249}
250
251bool CL_VectorSearch(const CL_Vector *const arr, const void *elem, CL_CompareFn compare_fn, u32 *out_index)
252{
253 if (!arr || !elem || !compare_fn)
254 return false;
255
256 u32 offset;
257 for (u32 i = 0; i < arr->size; i++)
258 {
259 offset = i * arr->elem_size;
260 if (!compare_fn(elem, (u8 *)(arr->data) + offset))
261 {
262 if (out_index)
263 *out_index = i;
264
265 return true;
266 }
267 }
268
269 return false;
270}
void MEM_Free(MEM_Allocator *ma, void *ptr)
Free a previously allocated block.
Definition allocator.c:98
void * MEM_Alloc(MEM_Allocator *ma, u32 size)
Allocate a block of memory from the pool with at least 'size' bytes.
Definition allocator.c:52
void * MEM_Realloc(MEM_Allocator *ma, void *ptr, u32 new_size)
Reallocate a previously allocated block to a new size.
Definition allocator.c:131
int(* CL_CompareFn)(const void *, const void *)
A function pointer type for comparing two elements.
Definition cl_types.h:7
CL_Error
Specify this in the size parameter of the collections initialization to tell the library that the num...
Definition cl_types.h:24
@ CL_ERR_EMPTY
Empty collection.
Definition cl_types.h:41
@ CL_ERR_OUT_OF_BOUNDS
Out of bounds.
Definition cl_types.h:32
@ CL_ERR_NO_MEMORY
No memory available.
Definition cl_types.h:35
@ CL_ERR_INVALID_PARAMS
Invalid arguments.
Definition cl_types.h:29
@ CL_ERR_OK
No error.
Definition cl_types.h:26
CL_Error CL_VectorGet(const CL_Vector *const arr, u32 index, void *out_elem)
Gets an element at the specified index.
Definition cl_vector.c:126
void CL_VectorSort(CL_Vector *const arr, CL_CompareFn cmp)
Sorts the vector.
Definition cl_vector.c:243
void CL_VectorFree(CL_Vector *arr)
Frees the memory previously assigned to the vector.
Definition cl_vector.c:64
u32 CL_VectorCapacity(const CL_Vector *const arr)
Gets the capacity of the vector.
Definition cl_vector.c:238
bool CL_VectorSearch(const CL_Vector *const arr, const void *elem, CL_CompareFn compare_fn, u32 *out_index)
Searches for an element in the vector.
Definition cl_vector.c:251
void CL_VectorPopBack(CL_Vector *const arr, void *out_elem)
Removes the last element from the vector, optionally returning it.
Definition cl_vector.c:102
u32 CL_VectorSize(const CL_Vector *const arr)
Gets the size of the vector.
Definition cl_vector.c:233
#define BASE_CAPACITY
Definition cl_vector.c:16
CL_Error CL_VectorGetPtr(const CL_Vector *const arr, u32 index, void **out_elem)
Gets a pointer to an element at the specified index.
Definition cl_vector.c:142
CL_Error CL_VectorGetLast(const CL_Vector *const arr, void *out_elem)
Gets the last element from the vector.
Definition cl_vector.c:158
bool CL_VectorIsEmpty(const CL_Vector *const arr)
Checks if the vector is empty.
Definition cl_vector.c:228
CL_Vector * CL_VectorAllocWithCapacity(MEM_Allocator *const alloc, u32 capacity, u32 elem_sz)
Initializes the vector with allocated memory provided by the user.
Definition cl_vector.c:33
CL_Error CL_VectorPushFront(CL_Vector *const arr, const void *const elem)
Adds an element at the front of the vector.
Definition cl_vector.c:96
void CL_VectorPopFront(CL_Vector *const arr, void *out_elem)
Removes the first element from the vector, optionally returning it.
Definition cl_vector.c:115
CL_Error CL_VectorInsert(CL_Vector *const arr, const void *const elem, u32 index)
Inserts an element at the specified index.
Definition cl_vector.c:174
CL_Error CL_VectorRemove(CL_Vector *const arr, u32 index)
Removes an element at the specified index.
Definition cl_vector.c:199
#define RESZ_FACTOR
Definition cl_vector.c:15
void CL_VectorClear(CL_Vector *const arr)
Clears the vector.
Definition cl_vector.c:219
CL_Error CL_VectorGetLastPtr(const CL_Vector *const arr, void **out_elem)
Gets a pointer to the last element from the vector.
Definition cl_vector.c:166
CL_Error CL_VectorPushBack(CL_Vector *const arr, const void *const elem, u32 *out_index)
Adds an element at the end of the vector.
Definition cl_vector.c:73
_PRIVATE void * realloc_data(CL_Vector *const arr, u32 new_capacity)
Definition cl_vector.c:20
CL_Vector * CL_VectorAlloc(MEM_Allocator *const alloc, u32 elem_sz)
Initializes the vector with a default capacity.
Definition cl_vector.c:59
struct __Vector CL_Vector
Definition cl_vector.h:11
u32 elem_size
Definition cl_vector.c:11
u32 capacity
Definition cl_vector.c:11
void * data
Definition cl_vector.c:10
MEM_Allocator * allocator
Definition cl_vector.c:12
u32 size
Definition cl_vector.c:11
uint8_t u8
Definition types.h:8
#define _PRIVATE
Definition types.h:37
uint32_t u32
Definition types.h:6