Landtiger LPC1768 C BigLib 1
A self made, custom C library for the LandTiger board.
 
Loading...
Searching...
No Matches
cl_list.h File Reference
#include "allocator.h"
#include "cl_types.h"
#include "types.h"
#include <stdbool.h>

Go to the source code of this file.

Macros

#define CL_LIST_FOREACH(__type, __name, __list, ...)
 Macro to iterate over the elements of the list.
 
#define CL_LIST_FOREACH_PTR(__type, __name, __list, ...)
 Macro to iterate over the elements of the list with a pointer to the current element.
 

Typedefs

typedef struct __List CL_List
 

Functions

CL_ListCL_ListAlloc (MEM_Allocator *const alloc, u32 elem_sz)
 Initializes a new doubly-linked list with tail, with the allocated memory provided by the user.
 
void CL_ListFree (CL_List *const list)
 Frees the memory previously assigned to the list.
 
CL_Error CL_ListPushBack (CL_List *const list, const void *const elem)
 Adds an element at the end of the list.
 
CL_Error CL_ListPushFront (CL_List *const list, const void *const elem)
 Adds an element at the front of the list.
 
void CL_ListPopBack (CL_List *const list, void *out_elem)
 Removes the last element from the list, optionally returning it.
 
void CL_ListPopFront (CL_List *const list, void *out_elem)
 Removes the first element from the list, optionally returning it.
 
CL_Error CL_ListGet (const CL_List *const list, u32 index, void *out_elem)
 Gets an element at the specified index.
 
CL_Error CL_ListGetPtr (const CL_List *const list, u32 index, void **out_elem)
 Gets an element at the specified index as a pointer, so the user can modify it.
 
CL_Error CL_ListGetLast (const CL_List *const list, void *out_elem)
 Gets the last element from the list.
 
CL_Error CL_ListGetLastPtr (const CL_List *const list, void **out_elem)
 Gets the last element from the list as a pointer, so the user can modify it.
 
CL_Error CL_ListInsertAt (CL_List *const list, u32 index, const void *const elem)
 Inserts an element at the specified index.
 
CL_Error CL_ListRemoveAt (CL_List *const list, u32 index, void *out_elem)
 Removes an element at the specified index.
 
bool CL_ListSearch (const CL_List *const list, const void *const elem, CL_CompareFn compare_fn, u32 *out_index)
 Searches for an element in the list.
 
void CL_ListClear (CL_List *const list)
 Removes all elements from the list.
 
u32 CL_ListSize (const CL_List *const list)
 Gets the number of elements in the list.
 
bool CL_ListIsEmpty (const CL_List *const list)
 Checks if the list is empty.
 

Macro Definition Documentation

◆ CL_LIST_FOREACH

#define CL_LIST_FOREACH (   __type,
  __name,
  __list,
  ... 
)
Value:
for (u32 __i = 0; __i < CL_ListSize(__list); __i++) \
{ \
__type __name; \
CL_ListGet(__list, __i, &(__name)); \
__VA_ARGS__ \
}
u32 CL_ListSize(const CL_List *const list)
Gets the number of elements in the list.
Definition cl_list.c:334
uint32_t u32
Definition types.h:6

Macro to iterate over the elements of the list.

Parameters
__typeThe type of the elements in the list.
__nameThe name of the variable to hold the current element.
__listThe list to iterate over.
...The code to execute for each element.

Definition at line 20 of file cl_list.h.

22 { \
23 __type __name; \
24 CL_ListGet(__list, __i, &(__name)); \
25 __VA_ARGS__ \
26 }

◆ CL_LIST_FOREACH_PTR

#define CL_LIST_FOREACH_PTR (   __type,
  __name,
  __list,
  ... 
)
Value:
for (u32 __i = 0; __i < CL_ListSize(__list); __i++) \
{ \
__type *const __name; \
CL_ListGetPtr(__list, __i, (void **)&(__name)); \
__VA_ARGS__ \
}

Macro to iterate over the elements of the list with a pointer to the current element.

Parameters
__typeThe type of the elements in the list.
__nameThe name of the variable to hold the current element.
__listThe list to iterate over.
...The code to execute for each element.

Definition at line 33 of file cl_list.h.

35 { \
36 __type *const __name; \
37 CL_ListGetPtr(__list, __i, (void **)&(__name)); \
38 __VA_ARGS__ \
39 }

Typedef Documentation

◆ CL_List

typedef struct __List CL_List

Definition at line 11 of file cl_list.h.

Function Documentation

◆ CL_ListAlloc()

CL_List * CL_ListAlloc ( MEM_Allocator *const  alloc,
u32  elem_sz 
)

Initializes a new doubly-linked list with tail, with the allocated memory provided by the user.

Parameters
allocThe allocator to use for memory allocation.
elem_szThe size of each element in the list.
Returns
Pointer to the new list or NULL on error.

Definition at line 43 of file cl_list.c.

44{
45 if (!alloc || !elem_sz)
46 return NULL;
47
48 CL_List *const list = MEM_Alloc(alloc, sizeof(CL_List));
49 if (!list)
50 return NULL;
51
52 *list = (CL_List){
53 .head = NULL,
54 .tail = NULL,
55 .size = 0,
56 .elem_size = elem_sz,
57 .allocator = alloc,
58 };
59
60 return list;
61}
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
struct __List CL_List
Definition cl_list.h:11
struct __ListNode * head
Definition cl_list.c:16

◆ CL_ListClear()

void CL_ListClear ( CL_List *const  list)

Removes all elements from the list.

Parameters
listThe list to clear.

Definition at line 316 of file cl_list.c.

317{
318 if (!list || !list->size)
319 return;
320
321 struct __ListNode *current = list->head, *copy;
322 while (current)
323 {
324 copy = current;
325 current = current->next;
326 MEM_Free(list->allocator, copy->data);
327 MEM_Free(list->allocator, copy);
328 }
329
330 list->head = list->tail = NULL;
331 list->size = 0;
332}
void MEM_Free(MEM_Allocator *ma, void *ptr)
Free a previously allocated block.
Definition allocator.c:98
struct __ListNode * next
Definition cl_list.c:11
struct __ListNode * tail
Definition cl_list.c:16
u32 size
Definition cl_list.c:17
MEM_Allocator * allocator
Definition cl_list.c:18

◆ CL_ListFree()

void CL_ListFree ( CL_List *const  list)

Frees the memory previously assigned to the list.

Parameters
listThe list to release the memory of.
Note
CL_List does not take ownership of the elements, so it's the user's responsibility to free them.

Definition at line 63 of file cl_list.c.

64{
65 if (!list)
66 return;
67
68 struct __ListNode *current = list->head, *copy;
69 while (current)
70 {
71 copy = current;
72 current = current->next;
73 MEM_Free(list->allocator, copy->data);
74 MEM_Free(list->allocator, copy);
75 }
76
77 MEM_Free(list->allocator, list);
78}

◆ CL_ListGet()

CL_Error CL_ListGet ( const CL_List *const  list,
u32  index,
void *  out_elem 
)

Gets an element at the specified index.

Parameters
listThe list to get the element from.
indexThe index of the element to get.
out_elem[OUTPUT] The element at the specified index.
Returns
CL_Error The error code.
Note
This operation is not O(1) for lists. Consider using a vector if you need random access.

Definition at line 168 of file cl_list.c.

169{
170 if (!list || !out_elem)
172
173 if (index >= list->size)
175
176 u32 idx = 0;
177 struct __ListNode *current = list->head;
178 while (idx++ < index)
179 current = current->next;
180
181 // Now current is the node at the specified index.
182 memcpy(out_elem, current->data, list->elem_size);
183 return CL_ERR_OK;
184}
@ CL_ERR_OUT_OF_BOUNDS
Out of bounds.
Definition cl_types.h:32
@ CL_ERR_INVALID_PARAMS
Invalid arguments.
Definition cl_types.h:29
@ CL_ERR_OK
No error.
Definition cl_types.h:26
void * data
Definition cl_list.c:10
u32 elem_size
Definition cl_list.c:17

◆ CL_ListGetLast()

CL_Error CL_ListGetLast ( const CL_List *const  list,
void *  out_elem 
)

Gets the last element from the list.

Parameters
listThe list to get the last element from.
out_elem[OUTPUT] The last element.
Returns
CL_Error The error code.

Definition at line 204 of file cl_list.c.

205{
206 if (!list || !out_elem)
208
209 if (!list->size)
210 return CL_ERR_EMPTY;
211
212 memcpy(out_elem, list->tail->data, list->elem_size);
213 return CL_ERR_OK;
214}
@ CL_ERR_EMPTY
Empty collection.
Definition cl_types.h:41

◆ CL_ListGetLastPtr()

CL_Error CL_ListGetLastPtr ( const CL_List *const  list,
void **  out_elem 
)

Gets the last element from the list as a pointer, so the user can modify it.

Parameters
listThe list to get the last element from.
out_elem[OUTPUT] The last element, as a pointer.
Returns
CL_Error The error code.

Definition at line 216 of file cl_list.c.

217{
218 if (!list || !out_elem)
220
221 if (!list->size)
222 return CL_ERR_EMPTY;
223
224 *out_elem = list->tail->data;
225 return CL_ERR_OK;
226}

◆ CL_ListGetPtr()

CL_Error CL_ListGetPtr ( const CL_List *const  list,
u32  index,
void **  out_elem 
)

Gets an element at the specified index as a pointer, so the user can modify it.

Parameters
listThe list to get the element from.
indexThe index of the element to get.
out_elem[OUTPUT] A pointer to the element at the specified index.
Returns
CL_Error The error code.
Note
This operation is not O(1) for lists. Consider using a vector if you need random access.

Definition at line 186 of file cl_list.c.

187{
188 if (!list || !out_elem)
190
191 if (index >= list->size)
193
194 u32 idx = 0;
195 struct __ListNode *current = list->head;
196 while (idx++ < index)
197 current = current->next;
198
199 // Now current is the node at the specified index.
200 *out_elem = current->data;
201 return CL_ERR_OK;
202}

◆ CL_ListInsertAt()

CL_Error CL_ListInsertAt ( CL_List *const  list,
u32  index,
const void *const  elem 
)

Inserts an element at the specified index.

Parameters
listThe list to insert the element to.
indexThe index to insert the element at.
elemThe element to insert.
Returns
CL_Error The error code.
Note
This operation is not O(1) for lists. Consider using a vector if you need random access.

Definition at line 228 of file cl_list.c.

229{
230 if (!list || !elem)
232
233 if (index > list->size) // list->size is a valid index to insert at (insert at the back).
235
236 if (index == 0) // Insert at the front.
237 return CL_ListPushFront(list, elem);
238 else if (index == list->size) // Insert at the back.
239 return CL_ListPushBack(list, elem);
240
241 // If here, we need to insert in the middle.
242 struct __ListNode *new_node = create_node(list, elem), *current = list->head;
243 if (!new_node)
244 return CL_ERR_NO_MEMORY;
245
246 u32 idx = 0;
247 while (idx++ < index)
248 current = current->next;
249
250 // Now current is the node at the specified index.
251 new_node->prev = current->prev;
252 new_node->next = current;
253 current->prev = new_node;
254 new_node->prev->next = new_node;
255
256 list->size++;
257 return CL_ERR_OK;
258}
CL_Error CL_ListPushBack(CL_List *const list, const void *const elem)
Adds an element at the end of the list.
Definition cl_list.c:80
CL_Error CL_ListPushFront(CL_List *const list, const void *const elem)
Adds an element at the front of the list.
Definition cl_list.c:102
_PRIVATE struct __ListNode * create_node(CL_List *list, const void *const elem)
Definition cl_list.c:23
@ CL_ERR_NO_MEMORY
No memory available.
Definition cl_types.h:35
struct __ListNode * prev
Definition cl_list.c:11

◆ CL_ListIsEmpty()

bool CL_ListIsEmpty ( const CL_List *const  list)

Checks if the list is empty.

Parameters
listThe list to check.
Returns
true if the list is empty, false otherwise.

Definition at line 339 of file cl_list.c.

340{
341 return !list || !list->size;
342}

◆ CL_ListPopBack()

void CL_ListPopBack ( CL_List *const  list,
void *  out_elem 
)

Removes the last element from the list, optionally returning it.

Parameters
listThe list to remove the last element from.
out_elem[OUTPUT] The removed element, if not NULL.

Definition at line 124 of file cl_list.c.

125{
126 if (!list || !list->size)
127 return;
128
129 struct __ListNode *last = list->tail;
130 if (out_elem)
131 memcpy(out_elem, last->data, list->elem_size);
132
133 if (list->size == 1) // Only one element in the list, reset head and tail.
134 list->head = list->tail = NULL;
135 else
136 {
137 list->tail = last->prev; // Set the tail to the previous node.
138 list->tail->next = NULL; // The new tail's next is NULL.
139 }
140
141 MEM_Free(list->allocator, last->data);
142 MEM_Free(list->allocator, last);
143 list->size--;
144}

◆ CL_ListPopFront()

void CL_ListPopFront ( CL_List *const  list,
void *  out_elem 
)

Removes the first element from the list, optionally returning it.

Parameters
listThe list to remove the first element from.
out_elem[OUTPUT] The removed element, if not NULL.

Definition at line 146 of file cl_list.c.

147{
148 if (!list || !list->size)
149 return;
150
151 struct __ListNode *first = list->head;
152 if (out_elem)
153 memcpy(out_elem, first->data, list->elem_size);
154
155 if (list->size == 1) // Only one element in the list, reset head and tail.
156 list->head = list->tail = NULL;
157 else
158 {
159 list->head = first->next; // Set the head to the next node;
160 list->head->prev = NULL; // The new head's previous is NULL.
161 }
162
163 MEM_Free(list->allocator, first->data);
164 MEM_Free(list->allocator, first);
165 list->size--;
166}

◆ CL_ListPushBack()

CL_Error CL_ListPushBack ( CL_List *const  list,
const void *const  elem 
)

Adds an element at the end of the list.

Parameters
listThe list to add the element to.
elemThe element to add.
Returns
CL_Error The error code.

Definition at line 80 of file cl_list.c.

81{
82 if (!list || !elem)
84
85 struct __ListNode *new_node = create_node(list, elem);
86 if (!new_node)
87 return CL_ERR_NO_MEMORY;
88
89 if (!list->tail) // Empty list, set head and tail to the new node.
90 list->head = list->tail = new_node;
91 else
92 {
93 new_node->prev = list->tail; // Set the new node's previous to the current tail.
94 list->tail->next = new_node; // Set the current tail's next to the new node.
95 list->tail = new_node; // The new node is now the tail.
96 }
97
98 list->size++;
99 return CL_ERR_OK;
100}

◆ CL_ListPushFront()

CL_Error CL_ListPushFront ( CL_List *const  list,
const void *const  elem 
)

Adds an element at the front of the list.

Parameters
listThe list to add the element to.
elemThe element to add.
Returns
CL_Error The error code.

Definition at line 102 of file cl_list.c.

103{
104 if (!list || !elem)
106
107 struct __ListNode *new_node = create_node(list, elem);
108 if (!new_node)
109 return CL_ERR_NO_MEMORY;
110
111 if (!list->head) // Empty list, set head and tail to the new node.
112 list->head = list->tail = new_node;
113 else
114 {
115 new_node->next = list->head; // Set the new node's next to the current head.
116 list->head->prev = new_node; // Set the current head's previous to the new node.
117 list->head = new_node; // The new node is now the head.
118 }
119
120 list->size++;
121 return CL_ERR_OK;
122}

◆ CL_ListRemoveAt()

CL_Error CL_ListRemoveAt ( CL_List *const  list,
u32  index,
void *  out_elem 
)

Removes an element at the specified index.

Parameters
listThe list to remove the element from.
indexThe index of the element to remove.
out_elem[OUTPUT] The removed element, if not NULL.
Returns
CL_Error The error code.
Note
This operation is not O(1) for lists. Consider using a vector if you need random access.

Definition at line 260 of file cl_list.c.

261{
262 if (!list)
264
265 if (index >= list->size)
267
268 if (index == 0) // Remove from the front.
269 CL_ListPopFront(list, out_elem);
270 else if (index == list->size - 1) // Remove from the back.
271 CL_ListPopBack(list, out_elem);
272 else
273 {
274 // If here, we need to remove from the middle.
275 struct __ListNode *current = list->head;
276 u32 idx = 0;
277 while (idx++ < index)
278 current = current->next;
279
280 // Now current is the node at the specified index.
281 current->prev->next = current->next;
282 current->next->prev = current->prev;
283
284 if (out_elem)
285 memcpy(out_elem, current->data, list->elem_size);
286
287 MEM_Free(list->allocator, current);
288 list->size--;
289 }
290
291 return CL_ERR_OK;
292}
void CL_ListPopFront(CL_List *const list, void *out_elem)
Removes the first element from the list, optionally returning it.
Definition cl_list.c:146
void CL_ListPopBack(CL_List *const list, void *out_elem)
Removes the last element from the list, optionally returning it.
Definition cl_list.c:124

◆ CL_ListSearch()

bool CL_ListSearch ( const CL_List *const  list,
const void *const  elem,
CL_CompareFn  compare_fn,
u32 out_index 
)

Searches for an element in the list.

Parameters
listThe list to search in.
elemThe element to search for.
compare_fnThe comparison function.
out_elem[OUTPUT] The index of the element, if found and not NULL.
Returns
true if the element was found, false otherwise.

Definition at line 294 of file cl_list.c.

295{
296 if (!list || !elem || !compare_fn)
297 return false;
298
299 struct __ListNode *current = list->head;
300 u32 idx = 0;
301 while (current)
302 {
303 if (compare_fn(current->data, elem) == 0)
304 {
305 if (out_index)
306 *out_index = idx;
307 return true;
308 }
309
310 current = current->next;
311 }
312
313 return false;
314}

◆ CL_ListSize()

u32 CL_ListSize ( const CL_List *const  list)

Gets the number of elements in the list.

Parameters
listThe list to get the size of.
Returns
The number of elements in the list.

Definition at line 334 of file cl_list.c.

335{
336 return list ? list->size : 0;
337}