xref: /haiku/src/libs/zydis/Zycore/List.c (revision 1003e004e6c97eb60657a98928dd334e141c59ee)
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