Lazuli
list.c
Go to the documentation of this file.
1 /*
2  * SPDX-License-Identifier: GPL-3.0-only
3  * This file is part of Lazuli.
4  */
5 
14 #include <Lazuli/common.h>
15 #include <Lazuli/config.h>
16 #include <Lazuli/list.h>
17 #include <Lazuli/sys/memory.h>
18 
19 void
20 List_Append(Lz_LinkedList * const linkedList, Lz_LinkedListElement * const item)
21 {
23  if (NULL == linkedList || NULL == item) {
24  return;
25  }
26  }
27 
28  item->next = NULL;
29 
30  if (NULL == linkedList->first) {
31  item->prev = NULL;
32  linkedList->first = item;
33  linkedList->last = item;
34 
35  return;
36  }
37 
38  item->prev = linkedList->last;
39  linkedList->last->next = item;
40  linkedList->last = item;
41 }
42 
43 void
44 List_Prepend(Lz_LinkedList * const linkedList,
45  Lz_LinkedListElement * const item)
46 {
48  if (NULL == linkedList || NULL == item) {
49  return;
50  }
51  }
52 
53  item->prev = NULL;
54 
55  if (NULL == linkedList->first) {
56  item->next = NULL;
57  linkedList->first = item;
58  linkedList->last = item;
59 
60  return;
61  }
62 
63  item->next = linkedList->first;
64  linkedList->first->prev = item;
65  linkedList->first = item;
66 }
67 
68 void
69 List_AppendList(Lz_LinkedList * const linkedListDestination,
70  Lz_LinkedList * const linkedListToMove)
71 {
73  if (NULL == linkedListDestination || NULL == linkedListToMove) {
74  return;
75  }
76  }
77 
78  if (NULL == linkedListToMove->first) {
79  return;
80  }
81 
82  if (NULL == linkedListDestination->first) {
83  linkedListDestination->first = linkedListToMove->first;
84  } else {
85  linkedListDestination->last->next = linkedListToMove->first;
86  linkedListToMove->first->prev = linkedListDestination->last;
87  }
88 
89  linkedListDestination->last = linkedListToMove->last;
90 
91  linkedListToMove->first = NULL;
92  linkedListToMove->last = NULL;
93 }
94 
96 List_PickFirst(Lz_LinkedList * const linkedList)
97 {
99 
101  if (NULL == linkedList) {
102  return NULL;
103  }
104  }
105 
106  if (NULL == linkedList->first) {
107  return NULL;
108  }
109 
110  item = linkedList->first;
111 
112  linkedList->first = linkedList->first->next;
113 
114  if (NULL == linkedList->first) {
115  linkedList->last = NULL;
116  } else {
117  linkedList->first->prev = NULL;
118  }
119 
120  item->next = NULL;
121  item->prev = NULL;
122 
123  return item;
124 }
125 
127 List_PointFirst(const Lz_LinkedList * const linkedList)
128 {
130  if (NULL == linkedList) {
131  return NULL;
132  }
133  }
134 
135  return linkedList->first;
136 }
137 
138 bool
139 List_IsEmpty(const Lz_LinkedList * const linkedList)
140 {
142  if (NULL == linkedList) {
143  return true;
144  }
145  }
146 
147  return (NULL == linkedList->first && NULL == linkedList->last);
148 }
149 
150 void
151 List_InsertAfter(Lz_LinkedList * const linkedList,
152  Lz_LinkedListElement * const listItem,
153  Lz_LinkedListElement * const itemToInsert)
154 {
156  if (NULL == linkedList || NULL == listItem || NULL == itemToInsert) {
157  return;
158  }
159  }
160 
161  if (linkedList->last == listItem) {
162  linkedList->last = itemToInsert;
163  }
164 
165  itemToInsert->next = listItem->next;
166  itemToInsert->prev = listItem;
167  listItem->next = itemToInsert;
168 }
169 
170 void
171 List_InsertBefore(Lz_LinkedList * const linkedList,
172  Lz_LinkedListElement * const listItem,
173  Lz_LinkedListElement * const itemToInsert)
174 {
176  if (NULL == linkedList || NULL == listItem || NULL == itemToInsert) {
177  return;
178  }
179  }
180 
181  if (linkedList->first == listItem) {
182  linkedList->first = itemToInsert;
183  }
184 
185  itemToInsert->next = listItem;
186  itemToInsert->prev = listItem->prev;
187  listItem->prev = itemToInsert;
188 }
189 
190 /*
191  * TODO: Prove that itemToRemove belongs to linkedList.
192  * The same can be done for other functions such as List_InsertBefore...
193  */
195 List_Remove(Lz_LinkedList * const linkedList,
196  Lz_LinkedListElement * const itemToRemove)
197 {
198  Lz_LinkedListElement * previousElement;
199 
201  if (NULL == linkedList || NULL == itemToRemove) {
202  return NULL;
203  }
204  }
205 
206  previousElement = itemToRemove->prev;
207 
208  if (NULL == itemToRemove->prev) {
209  linkedList->first = itemToRemove->next;
210  } else {
211  itemToRemove->prev->next = itemToRemove->next;
212  }
213 
214  if (NULL == itemToRemove->next) {
215  linkedList->last = itemToRemove->prev;
216  } else {
217  itemToRemove->next->prev = itemToRemove->prev;
218  }
219 
220  itemToRemove->prev = NULL;
221  itemToRemove->next = NULL;
222 
223  return previousElement;
224 }
225 
227 List_PointElementAt(const Lz_LinkedList * const linkedList, const size_t index)
228 {
229  Lz_LinkedListElement *item;
230  size_t currentIndex = 0;
231 
233  if (NULL == linkedList) {
234  return NULL;
235  }
236  }
237 
238  List_UntypedForEach(linkedList, item) {
239  if (currentIndex == index) {
240  return item;
241  }
242 
243  ++currentIndex;
244  }
245 
246  return NULL;
247 }
248 
249 void
251 {
252  const Lz_LinkedList linkedListInit = LINKED_LIST_INIT;
253 
255  if (NULL == linkedList) {
256  return;
257  }
258  }
259 
260  Memory_Copy(&linkedListInit, linkedList, sizeof(linkedListInit));
261 }
262 
263 void
265 {
266  const Lz_LinkedListElement linkedListElementInit = LINKED_LIST_ELEMENT_INIT;
267 
269  if (NULL == item) {
270  return;
271  }
272  }
273 
274  Memory_Copy(&linkedListElementInit, item, sizeof(linkedListElementInit));
275 }
void List_AppendList(Lz_LinkedList *const linkedListDestination, Lz_LinkedList *const linkedListToMove)
Move the content of an Lz_LinkedList to the end of an existing Lz_LinkedList.
Definition: list.c:69
Memory management API.
#define LINKED_LIST_ELEMENT_INIT
Define the initialization value for the type Lz_LinkedListElement.
Definition: list.h:52
void List_Prepend(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const item)
Insert an Lz_LinkedListElement as the first element of an existing Lz_LinkedList. ...
Definition: list.c:44
Include appropriate config file.
Lz_LinkedListElement * List_Remove(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const itemToRemove)
Remove an element from an Lz_LinkedList.
Definition: list.c:195
#define List_UntypedForEach(LINKEDLIST, ITEM)
Run through an Lz_LinkedList like a for loop.
Definition: list.h:146
Lz_LinkedListElement * List_PointElementAt(const Lz_LinkedList *const linkedList, const size_t index)
Point to an indexed element in an Lz_LinkedList, starting at index 0.
Definition: list.c:227
struct _Lz_LinkedListElement * next
A pointer to the next element in the list.
Definition: list.h:27
Doubly linked lists interface.
void List_Append(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const item)
Insert an Lz_LinkedListElement as the last element of an existing Lz_LinkedList.
Definition: list.c:20
void Memory_Copy(const void *source, void *destination, const size_t size)
Copy bytes from one location to another in main memory.
Definition: memory.c:73
Represents the main container for doubly linked elements.
Definition: list.h:36
void List_InitLinkedList(Lz_LinkedList *const linkedList)
Initialize an Lz_LinkedList.
Definition: list.c:250
Lz_LinkedListElement * last
A pointer to the last element of the linked list.
Definition: list.h:41
#define NULL
NULL pointer.
Definition: common.h:68
Lz_LinkedListElement * first
A pointer to the first element of the linked list.
Definition: list.h:38
const bool LZ_CONFIG_CHECK_NULL_PARAMETERS_IN_LISTS
When 1, always check for NULL functions parameters in linked lists implementation.
Lz_LinkedListElement * List_PointFirst(const Lz_LinkedList *const linkedList)
Return a pointer to the first element of an existing linked list.
Definition: list.c:127
void List_InsertBefore(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const listItem, Lz_LinkedListElement *const itemToInsert)
Insert an element before another in a Lz_LinkedList.
Definition: list.c:171
Basic type definitions and useful macros.
struct _Lz_LinkedListElement * prev
A pointer to the previous element in the list.
Definition: list.h:30
Represents an element of a doubly linked list.
Definition: list.h:25
void List_InsertAfter(Lz_LinkedList *const linkedList, Lz_LinkedListElement *const listItem, Lz_LinkedListElement *const itemToInsert)
Insert an element after another in an Lz_LinkedList.
Definition: list.c:151
Lz_LinkedListElement * List_PickFirst(Lz_LinkedList *const linkedList)
Return the first element of an existing linked list.
Definition: list.c:96
#define LINKED_LIST_INIT
Define the initialization value for the type Lz_LinkedList.
Definition: list.h:47
bool List_IsEmpty(const Lz_LinkedList *const linkedList)
Test if an Lz_LinkedList is empty.
Definition: list.c:139
void List_InitLinkedListElement(Lz_LinkedListElement *const item)
Initialize an Lz_LinkedListElement.
Definition: list.c:264