1*1003e004SJérôme Duval /***************************************************************************************************
2*1003e004SJérôme Duval
3*1003e004SJérôme Duval Zyan Core Library (Zycore-C)
4*1003e004SJérôme Duval
5*1003e004SJérôme Duval Original Author : Florian Bernd
6*1003e004SJérôme Duval
7*1003e004SJérôme Duval * Permission is hereby granted, free of charge, to any person obtaining a copy
8*1003e004SJérôme Duval * of this software and associated documentation files (the "Software"), to deal
9*1003e004SJérôme Duval * in the Software without restriction, including without limitation the rights
10*1003e004SJérôme Duval * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11*1003e004SJérôme Duval * copies of the Software, and to permit persons to whom the Software is
12*1003e004SJérôme Duval * furnished to do so, subject to the following conditions:
13*1003e004SJérôme Duval *
14*1003e004SJérôme Duval * The above copyright notice and this permission notice shall be included in all
15*1003e004SJérôme Duval * copies or substantial portions of the Software.
16*1003e004SJérôme Duval *
17*1003e004SJérôme Duval * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*1003e004SJérôme Duval * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*1003e004SJérôme Duval * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*1003e004SJérôme Duval * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*1003e004SJérôme Duval * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22*1003e004SJérôme Duval * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*1003e004SJérôme Duval * SOFTWARE.
24*1003e004SJérôme Duval
25*1003e004SJérôme Duval ***************************************************************************************************/
26*1003e004SJérôme Duval
27*1003e004SJérôme Duval #include <Zycore/LibC.h>
28*1003e004SJérôme Duval #include <Zycore/List.h>
29*1003e004SJérôme Duval
30*1003e004SJérôme Duval /* ============================================================================================== */
31*1003e004SJérôme Duval /* Internal macros */
32*1003e004SJérôme Duval /* ============================================================================================== */
33*1003e004SJérôme Duval
34*1003e004SJérôme Duval /**
35*1003e004SJérôme Duval * Returns a pointer to the data of the given `node`.
36*1003e004SJérôme Duval *
37*1003e004SJérôme Duval * @param node A pointer to the `ZyanNodeData` struct.
38*1003e004SJérôme Duval *
39*1003e004SJérôme Duval * @return A pointer to the data of the given `node`.
40*1003e004SJérôme Duval */
41*1003e004SJérôme Duval #define ZYCORE_LIST_GET_NODE_DATA(node) \
42*1003e004SJérôme Duval ((void*)(node + 1))
43*1003e004SJérôme Duval
44*1003e004SJérôme Duval /* ============================================================================================== */
45*1003e004SJérôme Duval /* Internal functions */
46*1003e004SJérôme Duval /* ============================================================================================== */
47*1003e004SJérôme Duval
48*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
49*1003e004SJérôme Duval /* Helper functions */
50*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
51*1003e004SJérôme Duval
52*1003e004SJérôme Duval /**
53*1003e004SJérôme Duval * Allocates memory for a new list node.
54*1003e004SJérôme Duval *
55*1003e004SJérôme Duval * @param list A pointer to the `ZyanList` instance.
56*1003e004SJérôme Duval * @param node Receives a pointer to the new `ZyanListNode` struct.
57*1003e004SJérôme Duval *
58*1003e004SJérôme Duval * @return A zyan status code.
59*1003e004SJérôme Duval */
ZyanListAllocateNode(ZyanList * list,ZyanListNode ** node)60*1003e004SJérôme Duval static ZyanStatus ZyanListAllocateNode(ZyanList* list, ZyanListNode** node)
61*1003e004SJérôme Duval {
62*1003e004SJérôme Duval ZYAN_ASSERT(list);
63*1003e004SJérôme Duval ZYAN_ASSERT(node);
64*1003e004SJérôme Duval
65*1003e004SJérôme Duval const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
66*1003e004SJérôme Duval if (is_dynamic)
67*1003e004SJérôme Duval {
68*1003e004SJérôme Duval ZYAN_ASSERT(list->allocator->allocate);
69*1003e004SJérôme Duval ZYAN_CHECK(list->allocator->allocate(list->allocator, (void**)node,
70*1003e004SJérôme Duval sizeof(ZyanListNode) + list->element_size, 1));
71*1003e004SJérôme Duval } else
72*1003e004SJérôme Duval {
73*1003e004SJérôme Duval if (list->first_unused)
74*1003e004SJérôme Duval {
75*1003e004SJérôme Duval *node = list->first_unused;
76*1003e004SJérôme Duval list->first_unused = (*node)->next;
77*1003e004SJérôme Duval } else
78*1003e004SJérôme Duval {
79*1003e004SJérôme Duval const ZyanUSize size = list->size * (sizeof(ZyanListNode) + list->element_size);
80*1003e004SJérôme Duval if (size + (sizeof(ZyanListNode) + list->element_size) > list->capacity)
81*1003e004SJérôme Duval {
82*1003e004SJérôme Duval return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE;
83*1003e004SJérôme Duval }
84*1003e004SJérôme Duval
85*1003e004SJérôme Duval *node = (ZyanListNode*)((ZyanU8*)list->buffer + size);
86*1003e004SJérôme Duval }
87*1003e004SJérôme Duval }
88*1003e004SJérôme Duval
89*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
90*1003e004SJérôme Duval }
91*1003e004SJérôme Duval
92*1003e004SJérôme Duval /**
93*1003e004SJérôme Duval * Frees memory of a node.
94*1003e004SJérôme Duval *
95*1003e004SJérôme Duval * @param list A pointer to the `ZyanList` instance.
96*1003e004SJérôme Duval * @param node A pointer to the `ZyanListNode` struct.
97*1003e004SJérôme Duval *
98*1003e004SJérôme Duval * @return A zyan status code.
99*1003e004SJérôme Duval */
ZyanListDeallocateNode(ZyanList * list,ZyanListNode * node)100*1003e004SJérôme Duval static ZyanStatus ZyanListDeallocateNode(ZyanList* list, ZyanListNode* node)
101*1003e004SJérôme Duval {
102*1003e004SJérôme Duval ZYAN_ASSERT(list);
103*1003e004SJérôme Duval ZYAN_ASSERT(node);
104*1003e004SJérôme Duval
105*1003e004SJérôme Duval const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
106*1003e004SJérôme Duval if (is_dynamic)
107*1003e004SJérôme Duval {
108*1003e004SJérôme Duval ZYAN_ASSERT(list->allocator->deallocate);
109*1003e004SJérôme Duval ZYAN_CHECK(list->allocator->deallocate(list->allocator, (void*)node,
110*1003e004SJérôme Duval sizeof(ZyanListNode) + list->element_size, 1));
111*1003e004SJérôme Duval } else
112*1003e004SJérôme Duval {
113*1003e004SJérôme Duval node->next = list->first_unused;
114*1003e004SJérôme Duval list->first_unused = node;
115*1003e004SJérôme Duval }
116*1003e004SJérôme Duval
117*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
118*1003e004SJérôme Duval }
119*1003e004SJérôme Duval
120*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
121*1003e004SJérôme Duval
122*1003e004SJérôme Duval /* ============================================================================================== */
123*1003e004SJérôme Duval /* Exported functions */
124*1003e004SJérôme Duval /* ============================================================================================== */
125*1003e004SJérôme Duval
126*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
127*1003e004SJérôme Duval /* Constructor and destructor */
128*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
129*1003e004SJérôme Duval
130*1003e004SJérôme Duval #ifndef ZYAN_NO_LIBC
131*1003e004SJérôme Duval
ZyanListInit(ZyanList * list,ZyanUSize element_size,ZyanMemberProcedure destructor)132*1003e004SJérôme Duval ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size,
133*1003e004SJérôme Duval ZyanMemberProcedure destructor)
134*1003e004SJérôme Duval {
135*1003e004SJérôme Duval return ZyanListInitEx(list, element_size, destructor, ZyanAllocatorDefault());
136*1003e004SJérôme Duval }
137*1003e004SJérôme Duval
138*1003e004SJérôme Duval #endif // ZYAN_NO_LIBC
139*1003e004SJérôme Duval
ZyanListInitEx(ZyanList * list,ZyanUSize element_size,ZyanMemberProcedure destructor,ZyanAllocator * allocator)140*1003e004SJérôme Duval ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size, ZyanMemberProcedure destructor,
141*1003e004SJérôme Duval ZyanAllocator* allocator)
142*1003e004SJérôme Duval {
143*1003e004SJérôme Duval if (!list || !element_size || !allocator)
144*1003e004SJérôme Duval {
145*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
146*1003e004SJérôme Duval }
147*1003e004SJérôme Duval
148*1003e004SJérôme Duval list->allocator = allocator;
149*1003e004SJérôme Duval list->size = 0;
150*1003e004SJérôme Duval list->element_size = element_size;
151*1003e004SJérôme Duval list->destructor = destructor;
152*1003e004SJérôme Duval list->head = ZYAN_NULL;
153*1003e004SJérôme Duval list->tail = ZYAN_NULL;
154*1003e004SJérôme Duval list->buffer = ZYAN_NULL;
155*1003e004SJérôme Duval list->capacity = 0;
156*1003e004SJérôme Duval list->first_unused = ZYAN_NULL;
157*1003e004SJérôme Duval
158*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
159*1003e004SJérôme Duval }
160*1003e004SJérôme Duval
ZyanListInitCustomBuffer(ZyanList * list,ZyanUSize element_size,ZyanMemberProcedure destructor,void * buffer,ZyanUSize capacity)161*1003e004SJérôme Duval ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size,
162*1003e004SJérôme Duval ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity)
163*1003e004SJérôme Duval {
164*1003e004SJérôme Duval if (!list || !element_size || !buffer || !capacity)
165*1003e004SJérôme Duval {
166*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
167*1003e004SJérôme Duval }
168*1003e004SJérôme Duval
169*1003e004SJérôme Duval list->allocator = ZYAN_NULL;
170*1003e004SJérôme Duval list->size = 0;
171*1003e004SJérôme Duval list->element_size = element_size;
172*1003e004SJérôme Duval list->destructor = destructor;
173*1003e004SJérôme Duval list->head = ZYAN_NULL;
174*1003e004SJérôme Duval list->tail = ZYAN_NULL;
175*1003e004SJérôme Duval list->buffer = buffer;
176*1003e004SJérôme Duval list->capacity = capacity;
177*1003e004SJérôme Duval list->first_unused = ZYAN_NULL;
178*1003e004SJérôme Duval
179*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
180*1003e004SJérôme Duval }
181*1003e004SJérôme Duval
ZyanListDestroy(ZyanList * list)182*1003e004SJérôme Duval ZyanStatus ZyanListDestroy(ZyanList* list)
183*1003e004SJérôme Duval {
184*1003e004SJérôme Duval if (!list)
185*1003e004SJérôme Duval {
186*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
187*1003e004SJérôme Duval }
188*1003e004SJérôme Duval
189*1003e004SJérôme Duval ZYAN_ASSERT(list->element_size);
190*1003e004SJérôme Duval
191*1003e004SJérôme Duval const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
192*1003e004SJérôme Duval ZyanListNode* node = (is_dynamic || list->destructor) ? list->head : ZYAN_NULL;
193*1003e004SJérôme Duval while (node)
194*1003e004SJérôme Duval {
195*1003e004SJérôme Duval if (list->destructor)
196*1003e004SJérôme Duval {
197*1003e004SJérôme Duval list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
198*1003e004SJérôme Duval }
199*1003e004SJérôme Duval
200*1003e004SJérôme Duval ZyanListNode* const next = node->next;
201*1003e004SJérôme Duval
202*1003e004SJérôme Duval if (is_dynamic)
203*1003e004SJérôme Duval {
204*1003e004SJérôme Duval ZYAN_CHECK(list->allocator->deallocate(list->allocator, node,
205*1003e004SJérôme Duval sizeof(ZyanListNode) + list->element_size, 1));
206*1003e004SJérôme Duval }
207*1003e004SJérôme Duval
208*1003e004SJérôme Duval node = next;
209*1003e004SJérôme Duval }
210*1003e004SJérôme Duval
211*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
212*1003e004SJérôme Duval }
213*1003e004SJérôme Duval
214*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
215*1003e004SJérôme Duval /* Duplication */
216*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
217*1003e004SJérôme Duval
218*1003e004SJérôme Duval
219*1003e004SJérôme Duval
220*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
221*1003e004SJérôme Duval /* Item access */
222*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
223*1003e004SJérôme Duval
ZyanListGetHeadNode(const ZyanList * list,const ZyanListNode ** node)224*1003e004SJérôme Duval ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node)
225*1003e004SJérôme Duval {
226*1003e004SJérôme Duval if (!list)
227*1003e004SJérôme Duval {
228*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
229*1003e004SJérôme Duval }
230*1003e004SJérôme Duval
231*1003e004SJérôme Duval *node = list->head;
232*1003e004SJérôme Duval
233*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
234*1003e004SJérôme Duval }
235*1003e004SJérôme Duval
ZyanListGetTailNode(const ZyanList * list,const ZyanListNode ** node)236*1003e004SJérôme Duval ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node)
237*1003e004SJérôme Duval {
238*1003e004SJérôme Duval if (!list)
239*1003e004SJérôme Duval {
240*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
241*1003e004SJérôme Duval }
242*1003e004SJérôme Duval
243*1003e004SJérôme Duval *node = list->tail;
244*1003e004SJérôme Duval
245*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
246*1003e004SJérôme Duval }
247*1003e004SJérôme Duval
ZyanListGetPrevNode(const ZyanListNode ** node)248*1003e004SJérôme Duval ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node)
249*1003e004SJérôme Duval {
250*1003e004SJérôme Duval if (!node || !*node)
251*1003e004SJérôme Duval {
252*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
253*1003e004SJérôme Duval }
254*1003e004SJérôme Duval
255*1003e004SJérôme Duval *node = (*node)->prev;
256*1003e004SJérôme Duval
257*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
258*1003e004SJérôme Duval }
259*1003e004SJérôme Duval
ZyanListGetNextNode(const ZyanListNode ** node)260*1003e004SJérôme Duval ZyanStatus ZyanListGetNextNode(const ZyanListNode** node)
261*1003e004SJérôme Duval {
262*1003e004SJérôme Duval if (!node || !*node)
263*1003e004SJérôme Duval {
264*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
265*1003e004SJérôme Duval }
266*1003e004SJérôme Duval
267*1003e004SJérôme Duval *node = (*node)->next;
268*1003e004SJérôme Duval
269*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
270*1003e004SJérôme Duval }
271*1003e004SJérôme Duval
ZyanListGetNodeData(const ZyanListNode * node)272*1003e004SJérôme Duval const void* ZyanListGetNodeData(const ZyanListNode* node)
273*1003e004SJérôme Duval {
274*1003e004SJérôme Duval if (!node)
275*1003e004SJérôme Duval {
276*1003e004SJérôme Duval return ZYAN_NULL;
277*1003e004SJérôme Duval }
278*1003e004SJérôme Duval
279*1003e004SJérôme Duval return (const void*)ZYCORE_LIST_GET_NODE_DATA(node);
280*1003e004SJérôme Duval }
281*1003e004SJérôme Duval
ZyanListGetNodeDataEx(const ZyanListNode * node,const void ** value)282*1003e004SJérôme Duval ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value)
283*1003e004SJérôme Duval {
284*1003e004SJérôme Duval if (!node)
285*1003e004SJérôme Duval {
286*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
287*1003e004SJérôme Duval }
288*1003e004SJérôme Duval
289*1003e004SJérôme Duval *value = (const void*)ZYCORE_LIST_GET_NODE_DATA(node);
290*1003e004SJérôme Duval
291*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
292*1003e004SJérôme Duval }
293*1003e004SJérôme Duval
ZyanListGetNodeDataMutable(const ZyanListNode * node)294*1003e004SJérôme Duval void* ZyanListGetNodeDataMutable(const ZyanListNode* node)
295*1003e004SJérôme Duval {
296*1003e004SJérôme Duval if (!node)
297*1003e004SJérôme Duval {
298*1003e004SJérôme Duval return ZYAN_NULL;
299*1003e004SJérôme Duval }
300*1003e004SJérôme Duval
301*1003e004SJérôme Duval return ZYCORE_LIST_GET_NODE_DATA(node);
302*1003e004SJérôme Duval }
303*1003e004SJérôme Duval
ZyanListGetNodeDataMutableEx(const ZyanListNode * node,void ** value)304*1003e004SJérôme Duval ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value)
305*1003e004SJérôme Duval {
306*1003e004SJérôme Duval if (!node)
307*1003e004SJérôme Duval {
308*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
309*1003e004SJérôme Duval }
310*1003e004SJérôme Duval
311*1003e004SJérôme Duval *value = ZYCORE_LIST_GET_NODE_DATA(node);
312*1003e004SJérôme Duval
313*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
314*1003e004SJérôme Duval }
315*1003e004SJérôme Duval
ZyanListSetNodeData(const ZyanList * list,const ZyanListNode * node,const void * value)316*1003e004SJérôme Duval ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node, const void* value)
317*1003e004SJérôme Duval {
318*1003e004SJérôme Duval if (!list || !node || !value)
319*1003e004SJérôme Duval {
320*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
321*1003e004SJérôme Duval }
322*1003e004SJérôme Duval
323*1003e004SJérôme Duval if (list->destructor)
324*1003e004SJérôme Duval {
325*1003e004SJérôme Duval list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
326*1003e004SJérôme Duval }
327*1003e004SJérôme Duval
328*1003e004SJérôme Duval ZYAN_ASSERT(list->element_size);
329*1003e004SJérôme Duval ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), value, list->element_size);
330*1003e004SJérôme Duval
331*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
332*1003e004SJérôme Duval }
333*1003e004SJérôme Duval
334*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
335*1003e004SJérôme Duval /* Insertion */
336*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
337*1003e004SJérôme Duval
ZyanListPushBack(ZyanList * list,const void * item)338*1003e004SJérôme Duval ZyanStatus ZyanListPushBack(ZyanList* list, const void* item)
339*1003e004SJérôme Duval {
340*1003e004SJérôme Duval if (!list || !item)
341*1003e004SJérôme Duval {
342*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
343*1003e004SJérôme Duval }
344*1003e004SJérôme Duval
345*1003e004SJérôme Duval ZyanListNode* node;
346*1003e004SJérôme Duval ZYAN_CHECK(ZyanListAllocateNode(list, &node));
347*1003e004SJérôme Duval node->prev = list->tail;
348*1003e004SJérôme Duval node->next = ZYAN_NULL;
349*1003e004SJérôme Duval
350*1003e004SJérôme Duval ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), item, list->element_size);
351*1003e004SJérôme Duval
352*1003e004SJérôme Duval if (!list->head)
353*1003e004SJérôme Duval {
354*1003e004SJérôme Duval list->head = node;
355*1003e004SJérôme Duval list->tail = node;
356*1003e004SJérôme Duval } else
357*1003e004SJérôme Duval {
358*1003e004SJérôme Duval list->tail->next = node;
359*1003e004SJérôme Duval list->tail = node;
360*1003e004SJérôme Duval }
361*1003e004SJérôme Duval ++list->size;
362*1003e004SJérôme Duval
363*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
364*1003e004SJérôme Duval }
365*1003e004SJérôme Duval
ZyanListPushFront(ZyanList * list,const void * item)366*1003e004SJérôme Duval ZyanStatus ZyanListPushFront(ZyanList* list, const void* item)
367*1003e004SJérôme Duval {
368*1003e004SJérôme Duval if (!list || !item)
369*1003e004SJérôme Duval {
370*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
371*1003e004SJérôme Duval }
372*1003e004SJérôme Duval
373*1003e004SJérôme Duval ZyanListNode* node;
374*1003e004SJérôme Duval ZYAN_CHECK(ZyanListAllocateNode(list, &node));
375*1003e004SJérôme Duval node->prev = ZYAN_NULL;
376*1003e004SJérôme Duval node->next = list->head;
377*1003e004SJérôme Duval
378*1003e004SJérôme Duval ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), item, list->element_size);
379*1003e004SJérôme Duval
380*1003e004SJérôme Duval if (!list->head)
381*1003e004SJérôme Duval {
382*1003e004SJérôme Duval list->head = node;
383*1003e004SJérôme Duval list->tail = node;
384*1003e004SJérôme Duval } else
385*1003e004SJérôme Duval {
386*1003e004SJérôme Duval list->head->prev= node;
387*1003e004SJérôme Duval list->head = node;
388*1003e004SJérôme Duval }
389*1003e004SJérôme Duval ++list->size;
390*1003e004SJérôme Duval
391*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
392*1003e004SJérôme Duval }
393*1003e004SJérôme Duval
ZyanListEmplaceBack(ZyanList * list,void ** item,ZyanMemberFunction constructor)394*1003e004SJérôme Duval ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item, ZyanMemberFunction constructor)
395*1003e004SJérôme Duval {
396*1003e004SJérôme Duval if (!list || !item)
397*1003e004SJérôme Duval {
398*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
399*1003e004SJérôme Duval }
400*1003e004SJérôme Duval
401*1003e004SJérôme Duval ZyanListNode* node;
402*1003e004SJérôme Duval ZYAN_CHECK(ZyanListAllocateNode(list, &node));
403*1003e004SJérôme Duval node->prev = list->tail;
404*1003e004SJérôme Duval node->next = ZYAN_NULL;
405*1003e004SJérôme Duval
406*1003e004SJérôme Duval *item = ZYCORE_LIST_GET_NODE_DATA(node);
407*1003e004SJérôme Duval if (constructor)
408*1003e004SJérôme Duval {
409*1003e004SJérôme Duval constructor(*item);
410*1003e004SJérôme Duval }
411*1003e004SJérôme Duval
412*1003e004SJérôme Duval if (!list->head)
413*1003e004SJérôme Duval {
414*1003e004SJérôme Duval list->head = node;
415*1003e004SJérôme Duval list->tail = node;
416*1003e004SJérôme Duval } else
417*1003e004SJérôme Duval {
418*1003e004SJérôme Duval list->tail->next = node;
419*1003e004SJérôme Duval list->tail = node;
420*1003e004SJérôme Duval }
421*1003e004SJérôme Duval ++list->size;
422*1003e004SJérôme Duval
423*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
424*1003e004SJérôme Duval }
425*1003e004SJérôme Duval
ZyanListEmplaceFront(ZyanList * list,void ** item,ZyanMemberFunction constructor)426*1003e004SJérôme Duval ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item, ZyanMemberFunction constructor)
427*1003e004SJérôme Duval {
428*1003e004SJérôme Duval if (!list || !item)
429*1003e004SJérôme Duval {
430*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
431*1003e004SJérôme Duval }
432*1003e004SJérôme Duval
433*1003e004SJérôme Duval ZyanListNode* node;
434*1003e004SJérôme Duval ZYAN_CHECK(ZyanListAllocateNode(list, &node));
435*1003e004SJérôme Duval node->prev = ZYAN_NULL;
436*1003e004SJérôme Duval node->next = list->head;
437*1003e004SJérôme Duval
438*1003e004SJérôme Duval *item = ZYCORE_LIST_GET_NODE_DATA(node);
439*1003e004SJérôme Duval if (constructor)
440*1003e004SJérôme Duval {
441*1003e004SJérôme Duval constructor(*item);
442*1003e004SJérôme Duval }
443*1003e004SJérôme Duval
444*1003e004SJérôme Duval if (!list->head)
445*1003e004SJérôme Duval {
446*1003e004SJérôme Duval list->head = node;
447*1003e004SJérôme Duval list->tail = node;
448*1003e004SJérôme Duval } else
449*1003e004SJérôme Duval {
450*1003e004SJérôme Duval list->head->prev= node;
451*1003e004SJérôme Duval list->head = node;
452*1003e004SJérôme Duval }
453*1003e004SJérôme Duval ++list->size;
454*1003e004SJérôme Duval
455*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
456*1003e004SJérôme Duval }
457*1003e004SJérôme Duval
458*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
459*1003e004SJérôme Duval /* Deletion */
460*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
461*1003e004SJérôme Duval
ZyanListPopBack(ZyanList * list)462*1003e004SJérôme Duval ZyanStatus ZyanListPopBack(ZyanList* list)
463*1003e004SJérôme Duval {
464*1003e004SJérôme Duval if (!list)
465*1003e004SJérôme Duval {
466*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
467*1003e004SJérôme Duval }
468*1003e004SJérôme Duval if (!list->tail)
469*1003e004SJérôme Duval {
470*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_OPERATION;
471*1003e004SJérôme Duval }
472*1003e004SJérôme Duval
473*1003e004SJérôme Duval ZyanListNode* const node = list->tail;
474*1003e004SJérôme Duval
475*1003e004SJérôme Duval if (list->destructor)
476*1003e004SJérôme Duval {
477*1003e004SJérôme Duval list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
478*1003e004SJérôme Duval }
479*1003e004SJérôme Duval
480*1003e004SJérôme Duval list->tail = node->prev;
481*1003e004SJérôme Duval if (list->tail)
482*1003e004SJérôme Duval {
483*1003e004SJérôme Duval list->tail->next = ZYAN_NULL;
484*1003e004SJérôme Duval }
485*1003e004SJérôme Duval if (list->head == node)
486*1003e004SJérôme Duval {
487*1003e004SJérôme Duval list->head = list->tail;
488*1003e004SJérôme Duval }
489*1003e004SJérôme Duval --list->size;
490*1003e004SJérôme Duval
491*1003e004SJérôme Duval return ZyanListDeallocateNode(list, node);
492*1003e004SJérôme Duval }
493*1003e004SJérôme Duval
ZyanListPopFront(ZyanList * list)494*1003e004SJérôme Duval ZyanStatus ZyanListPopFront(ZyanList* list)
495*1003e004SJérôme Duval {
496*1003e004SJérôme Duval if (!list)
497*1003e004SJérôme Duval {
498*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
499*1003e004SJérôme Duval }
500*1003e004SJérôme Duval if (!list->head)
501*1003e004SJérôme Duval {
502*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_OPERATION;
503*1003e004SJérôme Duval }
504*1003e004SJérôme Duval
505*1003e004SJérôme Duval ZyanListNode* const node = list->head;
506*1003e004SJérôme Duval
507*1003e004SJérôme Duval if (list->destructor)
508*1003e004SJérôme Duval {
509*1003e004SJérôme Duval list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
510*1003e004SJérôme Duval }
511*1003e004SJérôme Duval
512*1003e004SJérôme Duval list->head = node->next;
513*1003e004SJérôme Duval if (list->head)
514*1003e004SJérôme Duval {
515*1003e004SJérôme Duval list->head->prev = ZYAN_NULL;
516*1003e004SJérôme Duval }
517*1003e004SJérôme Duval if (list->tail == node)
518*1003e004SJérôme Duval {
519*1003e004SJérôme Duval list->tail = list->head;
520*1003e004SJérôme Duval }
521*1003e004SJérôme Duval --list->size;
522*1003e004SJérôme Duval
523*1003e004SJérôme Duval return ZyanListDeallocateNode(list, node);
524*1003e004SJérôme Duval }
525*1003e004SJérôme Duval
ZyanListRemove(ZyanList * list,const ZyanListNode * node)526*1003e004SJérôme Duval ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node)
527*1003e004SJérôme Duval {
528*1003e004SJérôme Duval ZYAN_UNUSED(list);
529*1003e004SJérôme Duval ZYAN_UNUSED(node);
530*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
531*1003e004SJérôme Duval }
532*1003e004SJérôme Duval
ZyanListRemoveRange(ZyanList * list,const ZyanListNode * first,const ZyanListNode * last)533*1003e004SJérôme Duval ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first, const ZyanListNode* last)
534*1003e004SJérôme Duval {
535*1003e004SJérôme Duval ZYAN_UNUSED(list);
536*1003e004SJérôme Duval ZYAN_UNUSED(first);
537*1003e004SJérôme Duval ZYAN_UNUSED(last);
538*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
539*1003e004SJérôme Duval }
540*1003e004SJérôme Duval
ZyanListClear(ZyanList * list)541*1003e004SJérôme Duval ZyanStatus ZyanListClear(ZyanList* list)
542*1003e004SJérôme Duval {
543*1003e004SJérôme Duval return ZyanListResizeEx(list, 0, ZYAN_NULL);
544*1003e004SJérôme Duval }
545*1003e004SJérôme Duval
546*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
547*1003e004SJérôme Duval /* Searching */
548*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
549*1003e004SJérôme Duval
550*1003e004SJérôme Duval
551*1003e004SJérôme Duval
552*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
553*1003e004SJérôme Duval /* Memory management */
554*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
555*1003e004SJérôme Duval
ZyanListResize(ZyanList * list,ZyanUSize size)556*1003e004SJérôme Duval ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size)
557*1003e004SJérôme Duval {
558*1003e004SJérôme Duval return ZyanListResizeEx(list, size, ZYAN_NULL);
559*1003e004SJérôme Duval }
560*1003e004SJérôme Duval
ZyanListResizeEx(ZyanList * list,ZyanUSize size,const void * initializer)561*1003e004SJérôme Duval ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer)
562*1003e004SJérôme Duval {
563*1003e004SJérôme Duval if (!list)
564*1003e004SJérôme Duval {
565*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
566*1003e004SJérôme Duval }
567*1003e004SJérôme Duval if (size == list->size)
568*1003e004SJérôme Duval {
569*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
570*1003e004SJérôme Duval }
571*1003e004SJérôme Duval
572*1003e004SJérôme Duval if (size == 0)
573*1003e004SJérôme Duval {
574*1003e004SJérôme Duval const ZyanBool is_dynamic = (list->allocator != ZYAN_NULL);
575*1003e004SJérôme Duval ZyanListNode* node = (is_dynamic || list->destructor) ? list->head : ZYAN_NULL;
576*1003e004SJérôme Duval while (node)
577*1003e004SJérôme Duval {
578*1003e004SJérôme Duval if (list->destructor)
579*1003e004SJérôme Duval {
580*1003e004SJérôme Duval list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
581*1003e004SJérôme Duval }
582*1003e004SJérôme Duval
583*1003e004SJérôme Duval ZyanListNode* const next = node->next;
584*1003e004SJérôme Duval
585*1003e004SJérôme Duval if (is_dynamic)
586*1003e004SJérôme Duval {
587*1003e004SJérôme Duval ZYAN_CHECK(list->allocator->deallocate(list->allocator, node,
588*1003e004SJérôme Duval sizeof(ZyanListNode) + list->element_size, 1));
589*1003e004SJérôme Duval }
590*1003e004SJérôme Duval
591*1003e004SJérôme Duval node = next;
592*1003e004SJérôme Duval }
593*1003e004SJérôme Duval
594*1003e004SJérôme Duval list->size = 0;
595*1003e004SJérôme Duval list->head = 0;
596*1003e004SJérôme Duval list->tail = 0;
597*1003e004SJérôme Duval list->first_unused = ZYAN_NULL;
598*1003e004SJérôme Duval
599*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
600*1003e004SJérôme Duval }
601*1003e004SJérôme Duval
602*1003e004SJérôme Duval if (size > list->size)
603*1003e004SJérôme Duval {
604*1003e004SJérôme Duval ZyanListNode* node;
605*1003e004SJérôme Duval for (ZyanUSize i = list->size; i < size; ++i)
606*1003e004SJérôme Duval {
607*1003e004SJérôme Duval ZYAN_CHECK(ZyanListAllocateNode(list, &node));
608*1003e004SJérôme Duval node->prev = list->tail;
609*1003e004SJérôme Duval node->next = ZYAN_NULL;
610*1003e004SJérôme Duval
611*1003e004SJérôme Duval if (initializer)
612*1003e004SJérôme Duval {
613*1003e004SJérôme Duval ZYAN_MEMCPY(ZYCORE_LIST_GET_NODE_DATA(node), initializer, list->element_size);
614*1003e004SJérôme Duval }
615*1003e004SJérôme Duval
616*1003e004SJérôme Duval if (!list->head)
617*1003e004SJérôme Duval {
618*1003e004SJérôme Duval list->head = node;
619*1003e004SJérôme Duval list->tail = node;
620*1003e004SJérôme Duval } else
621*1003e004SJérôme Duval {
622*1003e004SJérôme Duval list->tail->next = node;
623*1003e004SJérôme Duval list->tail = node;
624*1003e004SJérôme Duval }
625*1003e004SJérôme Duval
626*1003e004SJérôme Duval // `ZyanListAllocateNode` needs the list size
627*1003e004SJérôme Duval ++list->size;
628*1003e004SJérôme Duval }
629*1003e004SJérôme Duval } else
630*1003e004SJérôme Duval {
631*1003e004SJérôme Duval for (ZyanUSize i = size; i < list->size; ++i)
632*1003e004SJérôme Duval {
633*1003e004SJérôme Duval ZyanListNode* const node = list->tail;
634*1003e004SJérôme Duval
635*1003e004SJérôme Duval if (list->destructor)
636*1003e004SJérôme Duval {
637*1003e004SJérôme Duval list->destructor(ZYCORE_LIST_GET_NODE_DATA(node));
638*1003e004SJérôme Duval }
639*1003e004SJérôme Duval
640*1003e004SJérôme Duval list->tail = node->prev;
641*1003e004SJérôme Duval if (list->tail)
642*1003e004SJérôme Duval {
643*1003e004SJérôme Duval list->tail->next = ZYAN_NULL;
644*1003e004SJérôme Duval }
645*1003e004SJérôme Duval
646*1003e004SJérôme Duval ZYAN_CHECK(ZyanListDeallocateNode(list, node));
647*1003e004SJérôme Duval }
648*1003e004SJérôme Duval
649*1003e004SJérôme Duval list->size = size;
650*1003e004SJérôme Duval }
651*1003e004SJérôme Duval
652*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
653*1003e004SJérôme Duval }
654*1003e004SJérôme Duval
655*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
656*1003e004SJérôme Duval /* Information */
657*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
658*1003e004SJérôme Duval
ZyanListGetSize(const ZyanList * list,ZyanUSize * size)659*1003e004SJérôme Duval ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size)
660*1003e004SJérôme Duval {
661*1003e004SJérôme Duval if (!list)
662*1003e004SJérôme Duval {
663*1003e004SJérôme Duval return ZYAN_STATUS_INVALID_ARGUMENT;
664*1003e004SJérôme Duval }
665*1003e004SJérôme Duval
666*1003e004SJérôme Duval *size = list->size;
667*1003e004SJérôme Duval
668*1003e004SJérôme Duval return ZYAN_STATUS_SUCCESS;
669*1003e004SJérôme Duval }
670*1003e004SJérôme Duval
671*1003e004SJérôme Duval /* ---------------------------------------------------------------------------------------------- */
672*1003e004SJérôme Duval
673*1003e004SJérôme Duval /* ============================================================================================== */
674