GCC Code Coverage Report


Directory: src/gate/
File: src/gate/arrays.c
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 720 854 84.3%
Functions: 81 84 96.4%
Branches: 303 492 61.6%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/arrays.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32 #include "gate/atomics.h"
33
34 struct gate_arraylist_class
35 {
36 char* data_ptr; /* pointer to first item in array */
37 gate_size_t item_size; /* size of one item in bytes */
38 gate_size_t item_offset; /* offset in data_ptr where first item is located */
39 gate_size_t item_count; /* amount of valid items in array */
40 gate_size_t item_capacity; /* amount of possible items in allocated array space */
41 gate_atomic_int_t ref_counter; /* usage reference count of arraylist */
42 gate_mem_copyctor_t construct_item; /* copy-constructor function of a single item */
43 gate_mem_dtor_t destruct_item; /* destructor function of a single item */
44 };
45
46 402 gate_array_t* gate_array_create_static(gate_array_t* arr, void const* data_ptr, gate_size_t item_size, gate_size_t item_count)
47 {
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402 times.
402 GATE_DEBUG_ASSERT(arr != NULL);
49
50 402 arr->data_ptr = data_ptr;
51 402 arr->item_size = item_size;
52 402 arr->item_count = item_count;
53 402 arr->array_list = NULL;
54 402 return arr;
55 }
56 815 gate_array_t* gate_array_create_empty(gate_array_t* arr)
57 {
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 815 times.
815 GATE_DEBUG_ASSERT(arr != NULL);
59
60 815 arr->data_ptr = NULL;
61 815 arr->item_size = 0;
62 815 arr->item_count = 0;
63 815 arr->array_list = NULL;
64 815 return arr;
65 }
66 468 gate_array_t* gate_array_create(gate_array_t* arr, gate_arraylist_t arraylist)
67 {
68 gate_arraylist_t tmp_array_list;
69
70
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 GATE_DEBUG_ASSERT(arr != NULL);
71
72
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 460 times.
468 if (arraylist == NULL)
73 {
74 8 gate_array_create_empty(arr);
75 }
76 else
77 {
78
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 460 times.
460 if (gate_atomic_int_dec(&arraylist->ref_counter) != 0)
79 {
80 /* array data MUST NOT be used by multiple instances
81 and MUST NOT be shared between threads */
82 arr = NULL;
83 }
84 else
85 {
86 460 tmp_array_list = gate_mem_alloc(sizeof(struct gate_arraylist_class));
87
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 460 times.
460 if (tmp_array_list == NULL)
88 {
89 arr = NULL;
90 }
91 else
92 {
93 /* transferring all arraylist-members into array */
94 460 gate_atomic_int_init(&tmp_array_list->ref_counter, 1);
95 460 tmp_array_list->data_ptr = arraylist->data_ptr;
96 460 tmp_array_list->item_offset = arraylist->item_offset;
97 460 tmp_array_list->item_size = arraylist->item_size;
98 460 tmp_array_list->item_count = arraylist->item_count;
99 460 tmp_array_list->item_capacity = arraylist->item_capacity;
100 460 tmp_array_list->construct_item = arraylist->construct_item;
101 460 tmp_array_list->destruct_item = arraylist->destruct_item;
102
103 460 arr->array_list = tmp_array_list;
104
105 /* cleaning up original arraylist */
106 460 arraylist->data_ptr = NULL;
107 460 arraylist->item_size = 0;
108 460 arraylist->item_offset = 0;
109 460 arraylist->item_count = 0;
110 460 arraylist->item_capacity = 0;
111
112
2/2
✓ Branch 0 taken 204 times.
✓ Branch 1 taken 256 times.
460 if (arr->array_list->data_ptr == NULL)
113 {
114 /* pointer arithmetic on NULL-ptrs is UB */
115 204 arr->data_ptr = NULL;
116 }
117 else
118 {
119 256 arr->data_ptr = arr->array_list->data_ptr + (arr->array_list->item_size * arr->array_list->item_offset);
120 }
121 460 arr->item_size = arr->array_list->item_size;
122 460 arr->item_count = arr->array_list->item_count;
123 }
124 }
125 460 gate_atomic_int_inc(&arraylist->ref_counter);
126 }
127 468 return arr;
128 }
129
130 1 gate_array_t* gate_array_copy(gate_array_t* arr, gate_array_t const* src)
131 {
132 1 gate_array_t* ret = NULL;
133 1 gate_arraylist_t copylist = NULL;
134
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(arr != NULL);
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(src != NULL);
137
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src->array_list == NULL)
139 {
140 copylist = gate_arraylist_create(src->item_size, src->data_ptr, src->item_count, NULL, NULL);
141 }
142 else
143 {
144 2 copylist = gate_arraylist_create(src->item_size, src->data_ptr, src->item_count,
145 1 src->array_list->construct_item, src->array_list->destruct_item);
146 }
147
148
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (copylist == NULL)
149 {
150 return NULL;
151 }
152
153 1 ret = gate_array_create(arr, copylist);
154 1 gate_arraylist_release(copylist);
155 1 return ret;
156 }
157
158 1900 gate_array_t* gate_array_duplicate(gate_array_t* dest, gate_array_t const* src)
159 {
160
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1900 times.
1900 GATE_DEBUG_ASSERT(dest != NULL);
161
162
2/2
✓ Branch 0 taken 1490 times.
✓ Branch 1 taken 410 times.
1900 if (src != NULL)
163 {
164
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 1232 times.
1490 if (src->array_list != NULL)
165 {
166 258 gate_arraylist_retain(src->array_list);
167 }
168 1490 dest->array_list = src->array_list;
169 1490 dest->item_size = src->item_size;
170 1490 dest->item_count = src->item_count;
171 1490 dest->data_ptr = src->data_ptr;
172 }
173 else
174 {
175 410 gate_array_create_empty(dest);
176 }
177 1900 return dest;
178 }
179 1 gate_array_t* gate_array_subset(gate_array_t* dest, gate_array_t const* arr, gate_size_t offset, gate_size_t count)
180 {
181 char const* ptr;
182
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(dest != NULL);
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (arr == NULL)
185 {
186 gate_array_create_empty(dest);
187 }
188 else
189 {
190
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (arr->array_list != NULL)
191 {
192 1 gate_arraylist_retain(arr->array_list);
193 }
194 1 dest->array_list = arr->array_list;
195 1 ptr = (char const*)arr->data_ptr;
196
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if ((ptr != NULL) && (offset < arr->item_count))
197 {
198 1 ptr += arr->item_size * offset;
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (count > arr->item_count - offset)
200 {
201 count = arr->item_count - offset;
202 }
203 }
204 else
205 {
206 ptr = NULL;
207 count = 0;
208 }
209 1 dest->item_size = arr->item_size;
210 1 dest->item_count = count;
211 1 dest->data_ptr = ptr;
212
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 if ((count == 0) && (arr->array_list != NULL))
213 {
214 gate_arraylist_release(arr->array_list);
215 }
216 }
217 1 return dest;
218 }
219
220 4736 void gate_array_release(gate_array_t* arr)
221 {
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4736 times.
4736 if (arr == NULL)
223 {
224 return;
225 }
226
227
2/2
✓ Branch 0 taken 717 times.
✓ Branch 1 taken 4019 times.
4736 if (arr->array_list != NULL)
228 {
229 717 gate_arraylist_release(arr->array_list);
230 }
231 4736 arr->data_ptr = NULL;
232 4736 arr->item_count = 0;
233 4736 arr->item_size = 0;
234 4736 arr->array_list = NULL;
235 }
236 733 gate_size_t gate_array_length(gate_array_t const* arr)
237 {
238 gate_size_t ret;
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 733 times.
733 if (arr == NULL)
240 {
241 ret = 0;
242 }
243 else
244 {
245 733 ret = arr->item_count;
246 }
247 733 return ret;
248 }
249 1689 void const* gate_array_get(gate_array_t const* arr, gate_size_t index)
250 {
251 1689 void const* ret = NULL;
252
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1689 times.
1689 GATE_DEBUG_ASSERT(arr != NULL);
254
255
3/4
✓ Branch 0 taken 1687 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1687 times.
✗ Branch 3 not taken.
1689 if ((index < arr->item_count) && (arr->data_ptr != NULL))
256 {
257 1687 char const* ptr = (char const*)arr->data_ptr;
258 1687 ptr += (arr->item_size * index);
259 1687 ret = (void const*)ptr;
260 }
261 1689 return ret;
262 }
263
264 1113 static gate_bool_t gate_array_enumerate_is_valid(gate_enumerator_t const* enumerator)
265 {
266
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1113 times.
1113 GATE_DEBUG_ASSERT(enumerator != NULL);
267 1113 return enumerator->current_position < enumerator->end_position;
268 }
269 1101 static gate_bool_t gate_array_enumerate_next(gate_enumerator_t* enumerator)
270 {
271 gate_array_t* arr;
272
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1101 times.
1101 GATE_DEBUG_ASSERT(enumerator != NULL);
274 1101 arr = (gate_array_t*)enumerator->ptr_origin;
275
276
1/2
✓ Branch 0 taken 1101 times.
✗ Branch 1 not taken.
1101 if (enumerator->current_position != NULL)
277 {
278 1101 enumerator->current_position = (void*)((char*)enumerator->current_position + arr->item_size);
279 }
280 1101 return enumerator->current_position < enumerator->end_position;
281 }
282 1218 static void const* gate_array_enumerate_get(gate_enumerator_t const* enumerator)
283 {
284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1218 times.
1218 GATE_DEBUG_ASSERT(enumerator != NULL);
285 1218 return (void const*)enumerator->current_position;
286 }
287
288 12 gate_enumerator_t* gate_array_enumerate(gate_array_t const* arr, gate_enumerator_t* enumerator)
289 {
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 GATE_DEBUG_ASSERT(arr != NULL);
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 GATE_DEBUG_ASSERT(enumerator != NULL);
292
293 12 enumerator->is_valid = &gate_array_enumerate_is_valid;
294 12 enumerator->next = &gate_array_enumerate_next;
295 12 enumerator->get = &gate_array_enumerate_get;
296 12 enumerator->ptr_origin = arr;
297 12 enumerator->current_position = (void*)arr->data_ptr;
298
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if (enumerator->current_position != NULL)
299 {
300 11 enumerator->end_position = (void*)((char*)enumerator->current_position + (arr->item_size * arr->item_count));
301 }
302 else
303 {
304 1 enumerator->end_position = NULL;
305 }
306 12 return enumerator;
307 }
308
309 1 gate_result_t gate_array_copy_constructor(void* dst, void const* src)
310 {
311 1 gate_array_t const* srcarray = (gate_array_t const*)src;
312 1 gate_array_t* dstarray = (gate_array_t*)dst;
313
314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(dst != NULL);
315
316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_array_duplicate(dstarray, srcarray))
317 {
318 return GATE_RESULT_OUTOFMEMORY;
319 }
320 1 return GATE_RESULT_OK;
321 }
322 1 void gate_array_destructor(void* dst)
323 {
324 1 gate_array_t* dstarray = (gate_array_t*)dst;
325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(dst != NULL);
326 1 gate_array_release(dstarray);
327 1 }
328
329 1 void* gate_array_sort(void* items, gate_size_t item_size, gate_size_t items_count, gate_comparer_t comparer,
330 gate_mem_copyctor_t copy_constructor, gate_mem_dtor_t destructor)
331 {
332 1 char* ptr1 = (char*)items;
333 char* ptr2;
334 char* ptr_end;
335 char* ptr_end1;
336 gate_intptr_t cmp;
337
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(ptr1 != NULL);
339
340 1 ptr_end = ptr1 + items_count * item_size;
341 1 ptr_end1 = ptr_end - item_size;
342
343
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 for (; ptr1 != ptr_end1; ptr1 += item_size)
344 {
345
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 7 times.
35 for (ptr2 = ptr1 + item_size; ptr2 != ptr_end; ptr2 += item_size)
346 {
347 28 cmp = gate_compare_types(ptr1, ptr2, item_size, comparer);
348
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (cmp > 0)
349 {
350
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (!gate_mem_swap(ptr1, ptr2, item_size, copy_constructor, destructor))
351 {
352 return NULL;
353 }
354 }
355 }
356 }
357 1 return items;
358 }
359
360 1 void* gate_array_sort_descending(void* items, gate_size_t item_size, gate_size_t items_count, gate_comparer_t comparer,
361 gate_mem_copyctor_t copy_constructor, gate_mem_dtor_t destructor)
362 {
363 1 char* ptr1 = (char*)items;
364 char* ptr2;
365 char* ptr_end;
366 char* ptr_end1;
367
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(ptr1 != NULL);
369
370 1 ptr_end = ptr1 + items_count * item_size;
371 1 ptr_end1 = ptr_end - item_size;
372
373
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 for (; ptr1 != ptr_end1; ptr1 += item_size)
374 {
375
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 7 times.
35 for (ptr2 = ptr1 + item_size; ptr2 != ptr_end; ptr2 += item_size)
376 {
377
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (comparer(ptr1, ptr2) < 0)
378 {
379
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (!gate_mem_swap(ptr1, ptr2, item_size, copy_constructor, destructor))
380 {
381 return NULL;
382 }
383 }
384 }
385 }
386
387 1 return items;
388 }
389
390 1 gate_size_t gate_array_remove_if(void* items, gate_size_t item_size, gate_size_t item_count,
391 gate_check_condition_t condition_callback, void* param,
392 gate_mem_copyctor_t copy_constructor, gate_mem_dtor_t destructor)
393 {
394 1 gate_size_t new_item_count = 0;
395 1 char* ptr = (char*)items;
396 1 char* ptrend = ptr;
397
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 while (item_count != 0)
398 {
399
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
8 if (condition_callback(ptr, param))
400 {
401 /* to be deleted */
402 4 gate_mem_destruct(ptr, destructor);
403 }
404 else
405 {
406 /* to be preserved -> move it to (new) end */
407
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (ptr != ptrend)
408 {
409 3 gate_mem_swap(ptr, ptrend, item_size, copy_constructor, destructor);
410 3 gate_mem_destruct(ptr, destructor);
411 }
412 4 ptrend += item_size;
413 4 ++new_item_count;
414 }
415
416 8 ptr += item_size;
417 8 --item_count;
418 }
419 1 return new_item_count;
420 }
421
422 /*******************************
423 * arraylist implementation **
424 *******************************/
425
426 215 static char* gate_arraylist_copy_items(char* dstptr, char const* srcptr, gate_size_t count, gate_size_t itemsize, gate_mem_copyctor_t ctor, gate_mem_dtor_t dtor)
427 {
428 gate_size_t constructed;
429 gate_result_t result;
430
431
2/4
✓ Branch 0 taken 215 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 215 times.
215 if (!dstptr || !srcptr)
432 {
433 GATE_DEBUG_TRACE("Invalid input");
434 }
435
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 212 times.
215 else if (ctor == NULL)
436 {
437 3 gate_mem_copy(dstptr, srcptr, count * itemsize);
438 }
439 else
440 {
441
2/2
✓ Branch 0 taken 4476 times.
✓ Branch 1 taken 212 times.
4688 for (constructed = 0; constructed != count; ++constructed)
442 {
443 4476 result = ctor(dstptr, srcptr);
444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4476 times.
4476 if (GATE_FAILED(result))
445 {
446 /* construction failed */
447 if (dtor != NULL)
448 {
449 while (constructed-- != 0)
450 {
451 dstptr -= itemsize;
452 dtor(dstptr);
453 }
454 dstptr = NULL;
455 break;
456 }
457 }
458 4476 srcptr += itemsize;
459 4476 dstptr += itemsize;
460 }
461 }
462 215 return dstptr;
463 }
464
465 static void gate_arraylist_defrag(gate_arraylist_t arr)
466 {
467 GATE_DEBUG_ASSERT(arr != NULL);
468
469 if ((arr->data_ptr != NULL) && (arr->item_offset > 0))
470 {
471 char* src = arr->data_ptr + (arr->item_offset * arr->item_size);
472 char* dst = arr->data_ptr;
473 if (arr->construct_item || arr->destruct_item)
474 {
475 gate_size_t count = arr->item_count;
476 while (count-- > 0)
477 {
478 if (arr->construct_item)
479 {
480 arr->construct_item(dst, src);
481 }
482 else
483 {
484 gate_mem_copy(dst, src, arr->item_size);
485 }
486 if (arr->destruct_item)
487 {
488 arr->destruct_item(src);
489 }
490 src += arr->item_size;
491 dst += arr->item_size;
492 }
493 }
494 else
495 {
496 gate_mem_move(dst, src, (arr->item_size * arr->item_count));
497 }
498 arr->item_offset = 0;
499 }
500 }
501
502 395 static gate_arraylist_t gate_arraylist_reserve(gate_arraylist_t arr, gate_size_t capacity)
503 {
504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 GATE_DEBUG_ASSERT(arr != NULL);
505
506
1/2
✓ Branch 0 taken 395 times.
✗ Branch 1 not taken.
395 if (capacity > arr->item_capacity)
507 {
508 395 gate_size_t newbuffersize = arr->item_size * capacity;
509 395 char* newbuffer = gate_mem_alloc(newbuffersize);
510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 395 times.
395 if (newbuffer == NULL)
511 {
512 return NULL;
513 }
514
3/4
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 196 times.
✓ Branch 2 taken 199 times.
✗ Branch 3 not taken.
395 if ((arr->item_count != 0) && (arr->data_ptr != NULL))
515 {
516 199 char* const srcptr = arr->data_ptr + (arr->item_offset * arr->item_size);
517
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 147 times.
199 if (arr->construct_item == NULL)
518 {
519 52 gate_size_t oldbuffersize = arr->item_size * arr->item_count;
520 52 gate_mem_copy(newbuffer, srcptr, oldbuffersize);
521 }
522 else
523 {
524
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 147 times.
147 if (gate_arraylist_copy_items(newbuffer, srcptr, arr->item_count, arr->item_size, arr->construct_item, arr->destruct_item) == NULL)
525 {
526 /*failed:*/
527 gate_mem_dealloc(newbuffer);
528 return NULL;
529 }
530 }
531
532
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 52 times.
199 if (arr->destruct_item != NULL)
533 {
534 147 char* dstptr = arr->data_ptr + (arr->item_offset * arr->item_size);
535 gate_size_t constructed;
536
2/2
✓ Branch 0 taken 2730 times.
✓ Branch 1 taken 147 times.
2877 for (constructed = 0; constructed != arr->item_count; ++constructed)
537 {
538 2730 arr->destruct_item(dstptr);
539 2730 dstptr += arr->item_size;
540 }
541 }
542 }
543
2/2
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 196 times.
395 if (arr->data_ptr)
544 {
545 199 gate_mem_dealloc(arr->data_ptr);
546 }
547
548 395 arr->data_ptr = newbuffer;
549 395 arr->item_capacity = capacity;
550 395 arr->item_offset = 0;
551 }
552 else
553 {
554 gate_arraylist_defrag(arr);
555 }
556 395 return arr;
557 }
558
559 676 gate_arraylist_t gate_arraylist_create(gate_size_t itemsize, void const* source, gate_size_t length, gate_mem_copyctor_t ctor, gate_mem_dtor_t dtor)
560 {
561 676 gate_arraylist_t ret = NULL;
562
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 676 times.
676 if (itemsize == 0)
564 {
565 return NULL;
566 }
567
568 676 ret = (gate_arraylist_t)gate_mem_alloc(sizeof(struct gate_arraylist_class));
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 676 times.
676 if (ret == NULL)
570 {
571 return NULL;
572 }
573 676 gate_atomic_int_init(&ret->ref_counter, 1);
574 676 ret->item_size = itemsize;
575 676 ret->item_capacity = length;
576 676 ret->item_offset = 0;
577 676 ret->construct_item = ctor;
578 676 ret->destruct_item = dtor;
579
2/2
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 210 times.
676 if (length == 0)
580 {
581 466 ret->item_count = 0;
582 466 ret->data_ptr = NULL;
583 }
584 else
585 {
586 210 ret->data_ptr = gate_mem_alloc(itemsize * length);
587
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 210 times.
210 if (ret->data_ptr == NULL)
588 {
589 gate_mem_dealloc(ret);
590 return NULL;
591 }
592
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 68 times.
210 if (source == NULL)
593 {
594 142 ret->item_count = 0;
595 }
596 else
597 {
598
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 68 times.
68 if (gate_arraylist_copy_items((char*)ret->data_ptr, (char const*)source, length, itemsize, ctor, dtor) == NULL)
599 {
600 gate_mem_dealloc(ret->data_ptr);
601 gate_mem_dealloc(ret);
602 return NULL;
603 }
604 68 ret->item_count = length;
605 }
606 }
607 676 return ret;
608 }
609
610 265 gate_arraylist_t gate_arraylist_retain(gate_arraylist_t arr)
611 {
612
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 265 times.
265 GATE_DEBUG_ASSERT(arr != NULL);
613
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 265 times.
265 if (gate_atomic_int_inc(&arr->ref_counter) < 2)
614 {
615 /* error! reference count MUST be greater than 2,
616 otherwise array is in currently in destruction process
617 */
618 arr = NULL;
619 }
620 265 return arr;
621 }
622
623 2464 void gate_arraylist_release(gate_arraylist_t arr)
624 {
625
2/2
✓ Branch 0 taken 1396 times.
✓ Branch 1 taken 1068 times.
2464 if (arr != NULL)
626 {
627
2/2
✓ Branch 1 taken 1131 times.
✓ Branch 2 taken 265 times.
1396 if (gate_atomic_int_dec(&arr->ref_counter) == 0)
628 {
629
2/2
✓ Branch 0 taken 401 times.
✓ Branch 1 taken 730 times.
1131 if (arr->data_ptr != NULL)
630 {
631
4/4
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 295 times.
✓ Branch 3 taken 53 times.
401 if ((arr->item_count != 0) && (arr->destruct_item != NULL))
632 {
633 295 char* dstptr = arr->data_ptr + (arr->item_offset * arr->item_size);
634
2/2
✓ Branch 0 taken 2565 times.
✓ Branch 1 taken 295 times.
2860 while (arr->item_count-- != 0)
635 {
636 2565 arr->destruct_item(dstptr);
637 2565 dstptr += arr->item_size;
638 }
639 }
640 401 gate_mem_dealloc(arr->data_ptr);
641 }
642 1131 gate_mem_dealloc(arr);
643 }
644 }
645 2464 }
646
647 54 gate_arraylist_t gate_arraylist_copy(gate_arraylist_t src_arr)
648 {
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 GATE_DEBUG_ASSERT(src_arr != NULL);
650 162 return gate_arraylist_create(src_arr->item_size,
651 54 src_arr->data_ptr + (src_arr->item_offset * src_arr->item_size), src_arr->item_count,
652 src_arr->construct_item, src_arr->destruct_item);
653 }
654
655 3656 gate_size_t gate_arraylist_length(gate_arraylist_t arr)
656 {
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3656 times.
3656 GATE_DEBUG_ASSERT(arr != NULL);
658 3656 return arr->item_count;
659 }
660
661 13 gate_size_t gate_arraylist_itemsize(gate_arraylist_t arr)
662 {
663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_DEBUG_ASSERT(arr != NULL);
664 13 return arr->item_size;
665 }
666
667 2644 void* gate_arraylist_get(gate_arraylist_t arr, gate_size_t index)
668 {
669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2644 times.
2644 GATE_DEBUG_ASSERT(arr != NULL);
670
2/2
✓ Branch 0 taken 2639 times.
✓ Branch 1 taken 5 times.
2644 if (arr->data_ptr != NULL)
671 {
672 2639 char* dstptr = (char*)arr->data_ptr;
673 2639 dstptr += (arr->item_size * (arr->item_offset + index));
674 2639 return (void*)dstptr;
675 }
676 5 return NULL;
677 }
678
679 174 void* gate_arraylist_insert(gate_arraylist_t arr, gate_size_t index, void const* item, gate_size_t itemcount)
680 {
681 char* movesrc;
682 char* movedst;
683 gate_size_t movecount;
684 char const* srcptr;
685 gate_result_t result;
686
687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 174 times.
174 GATE_DEBUG_ASSERT(arr != NULL);
688
689
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 137 times.
174 if ((arr->item_offset + arr->item_count + itemcount) > arr->item_capacity)
690 {
691
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if ((arr->item_count + itemcount) > arr->item_capacity)
692 {
693 37 arr = gate_arraylist_reserve(arr, arr->item_count + itemcount + (arr->item_capacity / 2));
694 }
695 else
696 {
697 gate_arraylist_defrag(arr);
698 }
699 }
700
701
2/2
✓ Branch 0 taken 172 times.
✓ Branch 1 taken 2 times.
174 if (index >= arr->item_count)
702 {
703 /* append */
704 172 index = arr->item_count;
705 172 movedst = arr->data_ptr + ((arr->item_offset + arr->item_count) * arr->item_size);
706
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 167 times.
172 if (arr->construct_item != NULL)
707 {
708 5 srcptr = (char const*)item;
709
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 while (itemcount-- != 0)
710 {
711 5 result = arr->construct_item(movedst, srcptr);
712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (GATE_FAILED(result))
713 {
714 /* construction error */
715 return NULL;
716 }
717 5 movedst += arr->item_size;
718 5 srcptr += arr->item_size;
719 5 ++arr->item_count;
720 }
721 }
722 else
723 {
724 167 gate_mem_copy(movedst, item, itemcount * arr->item_size);
725 167 arr->item_count += itemcount;
726 }
727 }
728 else
729 {
730 2 movecount = arr->item_count - index;
731
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (arr->construct_item != NULL)
732 {
733 2 movesrc = arr->data_ptr + ((arr->item_offset + arr->item_count - 1) * arr->item_size);
734 2 movedst = movesrc + (itemcount * arr->item_size);
735
736
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 while (movecount-- != 0)
737 {
738 3 result = arr->construct_item(movedst, movesrc);
739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (GATE_FAILED(result))
740 {
741 /* construction error */
742 /* TODO */
743 return NULL;
744 }
745
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (arr->destruct_item != NULL)
746 {
747 3 arr->destruct_item(movesrc);
748 }
749 3 movesrc -= arr->item_size;
750 3 movedst -= arr->item_size;
751 }
752
753 2 srcptr = (char const*)item;
754 2 movedst = ((char*)arr->data_ptr) + ((arr->item_offset + index) * arr->item_size);
755
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 while (itemcount-- != 0)
756 {
757 2 result = arr->construct_item(movedst, srcptr);
758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(result))
759 {
760 /* construction error*/
761 /* TODO */
762 return NULL;
763 }
764 2 srcptr += arr->item_size;
765 2 movedst += arr->item_size;
766 2 ++arr->item_count;
767 }
768 }
769 else
770 {
771 movesrc = arr->data_ptr + ((arr->item_offset + index) * arr->item_size);
772 movedst = movesrc + (itemcount * arr->item_size);
773
774 gate_mem_move(movedst, movesrc, movecount * arr->item_size);
775
776 movedst = (char*)arr->data_ptr + ((arr->item_offset + index) * arr->item_size);
777 gate_mem_copy(movedst, item, itemcount * arr->item_size);
778
779 arr->item_count += itemcount;
780 }
781 }
782 174 return arr->data_ptr + ((arr->item_offset + index) * arr->item_size);
783 }
784
785 2009 void* gate_arraylist_add(gate_arraylist_t arr, void const* item)
786 {
787 char* dstptr;
788 gate_result_t result;
789
790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2009 times.
2009 GATE_DEBUG_ASSERT(arr != NULL);
791
792
2/2
✓ Branch 0 taken 358 times.
✓ Branch 1 taken 1651 times.
2009 if (arr->item_capacity == (arr->item_offset + arr->item_count))
793 {
794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 358 times.
358 if (arr->item_offset > 0)
795 {
796 gate_arraylist_defrag(arr);
797 }
798 else
799 {
800
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 358 times.
358 if (gate_arraylist_reserve(arr, arr->item_capacity + (arr->item_capacity / 2) + 2) == NULL)
801 {
802 return NULL;
803 }
804 }
805 }
806 2009 dstptr = arr->data_ptr + ((arr->item_offset + arr->item_count) * arr->item_size);
807 2009 result = gate_mem_copy_construct(dstptr, item, arr->item_size, arr->construct_item);
808
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2009 times.
2009 if (GATE_FAILED(result))
809 {
810 return NULL;
811 }
812 2009 ++arr->item_count;
813
814 2009 return ((char*)arr->data_ptr) + ((arr->item_offset + arr->item_count - 1) * arr->item_size);
815 }
816
817 3 void* gate_arraylist_add_n(gate_arraylist_t arr, void const* item, gate_size_t repeat_count)
818 {
819 3 void* ret = NULL;
820 char* dstptr;
821 gate_result_t result;
822
823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(arr != NULL);
824
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if ((arr->item_offset + arr->item_count + repeat_count) > arr->item_capacity)
826 {
827 if ((arr->item_count + repeat_count) > arr->item_capacity)
828 {
829 if (gate_arraylist_reserve(arr, arr->item_capacity + repeat_count + (arr->item_capacity / 2) + 2) == NULL)
830 {
831 return NULL;
832 }
833 }
834 else
835 {
836 gate_arraylist_defrag(arr);
837 }
838 }
839 3 dstptr = (char*)arr->data_ptr + ((arr->item_offset + arr->item_count) * arr->item_size);
840 3 ret = dstptr;
841
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 while (repeat_count-- != 0)
842 {
843 7 result = gate_mem_copy_construct(dstptr, item, arr->item_size, arr->construct_item);
844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (GATE_FAILED(result))
845 {
846 break;
847 }
848 7 dstptr += arr->item_size;
849 7 ++arr->item_count;
850 }
851
852 3 return ret;
853 }
854
855 1028 gate_result_t gate_arraylist_remove(gate_arraylist_t arr, gate_size_t index, gate_size_t count)
856 {
857 char* srcptr;
858
859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1028 times.
1028 GATE_DEBUG_ASSERT(arr != NULL);
860
861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1028 times.
1028 if (index >= arr->item_count)
862 {
863 return GATE_RESULT_OUTOFBOUNDS;
864 }
865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1028 times.
1028 if (index + count > arr->item_count)
866 {
867 count = arr->item_count - index;
868 }
869
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1028 times.
1028 if (count == 0)
870 {
871 return GATE_RESULT_OK;
872 }
873
874 1028 srcptr = arr->data_ptr + ((arr->item_offset + index) * arr->item_size);
875
2/2
✓ Branch 0 taken 1017 times.
✓ Branch 1 taken 11 times.
1028 if (index == 0)
876 {
877 /* optimization */
878 1017 arr->item_offset += count;
879 1017 arr->item_count -= count;
880
2/2
✓ Branch 0 taken 1017 times.
✓ Branch 1 taken 1017 times.
2034 while (count-- != 0)
881 {
882
2/2
✓ Branch 0 taken 1009 times.
✓ Branch 1 taken 8 times.
1017 if (arr->destruct_item)
883 {
884 1009 arr->destruct_item(srcptr);
885 }
886 1017 srcptr += arr->item_size;
887 }
888
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1007 times.
1017 if (arr->item_count == 0)
889 {
890 10 arr->item_offset = 0;
891 }
892 }
893 else
894 {
895 11 char* dstptr = srcptr;
896 11 gate_size_t movecount = arr->item_count - index - count;
897
898
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8 times.
11 if (arr->destruct_item != NULL)
899 {
900
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 while (count-- != 0)
901 {
902 3 arr->destruct_item(srcptr);
903 3 srcptr += arr->item_size;
904 3 --arr->item_count;
905 }
906 }
907 else
908 {
909 8 srcptr += count * arr->item_size;
910 8 arr->item_count -= count;
911 }
912
913
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 if (movecount != 0)
914 {
915
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (arr->construct_item != NULL)
916 {
917
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 while (movecount-- != 0)
918 {
919 2 arr->construct_item(dstptr, srcptr);
920
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (arr->destruct_item != NULL)
921 {
922 2 arr->destruct_item(srcptr);
923 }
924 2 srcptr += arr->item_size;
925 2 dstptr += arr->item_size;
926 }
927 }
928 else
929 {
930 1 gate_mem_move(dstptr, srcptr, movecount * arr->item_size);
931 }
932 }
933 }
934 1028 return GATE_RESULT_OK;
935 }
936
937 55 gate_result_t gate_arraylist_remove_if(gate_arraylist_t arr, gate_check_condition_t condition, void* param)
938 {
939 55 gate_result_t ret = GATE_RESULT_OK;
940 char* srcptr;
941 char* dstptr;
942 gate_size_t ndx;
943 55 gate_size_t new_size = 0;
944
945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
55 GATE_DEBUG_ASSERT(arr != NULL);
946
947 55 srcptr = arr->data_ptr + (arr->item_offset * arr->item_size);
948 55 dstptr = srcptr;
949
950
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 55 times.
134 for (ndx = 0; ndx != arr->item_count; ++ndx)
951 {
952
2/2
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 66 times.
79 if (condition(srcptr, param))
953 {
954 /*remove item*/
955 13 gate_mem_destruct(srcptr, arr->destruct_item);
956 }
957 else
958 {
959 66 ret = gate_mem_move_construct(dstptr, srcptr, arr->item_size, arr->construct_item, arr->destruct_item);
960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (GATE_FAILED(ret))
961 {
962 /* critical error, now we have a gap in the array */
963 while (ndx != arr->item_count)
964 {
965 gate_mem_destruct(srcptr, arr->destruct_item);
966 srcptr += arr->item_size;
967 ++ndx;
968 }
969 break;
970 }
971 66 dstptr += arr->item_size;
972 66 ++new_size;
973 }
974 79 srcptr += arr->item_size;
975 }
976 55 arr->item_count = new_size;
977 55 return ret;
978 }
979
980 13 void gate_arraylist_clear(gate_arraylist_t arr)
981 {
982
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_DEBUG_ASSERT(arr != NULL);
983
984
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (arr->destruct_item != NULL)
985 {
986 gate_size_t ndx;
987 1 char* ptr = arr->data_ptr + (arr->item_offset * arr->item_size);
988
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (ndx = 0; ndx != arr->item_count; ++ndx)
989 {
990 2 arr->destruct_item(ptr);
991 2 ptr += arr->item_size;
992 }
993 }
994 13 arr->item_count = 0;
995 13 arr->item_offset = 0;
996 13 }
997
998 3 gate_size_t gate_arraylist_get_value(gate_arraylist_t arr, gate_size_t index, void* dest_buffer, gate_size_t dest_buffer_size)
999 {
1000 char* itemptr;
1001 gate_result_t result;
1002
1003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(arr != NULL);
1004
1005
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if ((dest_buffer_size < arr->item_size) || (index >= arr->item_count))
1006 {
1007 /* invalid arg or index out of bounds */
1008 return 0;
1009 }
1010
1011 3 itemptr = arr->data_ptr + ((arr->item_offset + index) * arr->item_size);
1012
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (arr->construct_item)
1013 {
1014 3 result = arr->construct_item(dest_buffer, itemptr);
1015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (GATE_FAILED(result))
1016 {
1017 /* copy construction failed */
1018 return 0;
1019 }
1020 }
1021 else
1022 {
1023 gate_mem_copy(dest_buffer, itemptr, arr->item_size);
1024 }
1025 3 return arr->item_size;
1026 }
1027
1028 1 gate_size_t gate_arraylist_create_item(gate_arraylist_t arr, void* dest_buffer, gate_size_t dest_buffer_size)
1029 {
1030 1 gate_size_t ret = 0;
1031 gate_result_t result;
1032
1033
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(arr != NULL);
1034
1035
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (dest_buffer_size >= arr->item_size)
1036 {
1037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (arr->construct_item == NULL)
1038 {
1039 gate_mem_clear(dest_buffer, arr->item_size);
1040 ret = arr->item_size;
1041 }
1042 else
1043 {
1044 1 result = arr->construct_item(dest_buffer, NULL);
1045
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(result))
1046 {
1047 1 ret = arr->item_size;
1048 }
1049 }
1050 }
1051 1 return ret;
1052 }
1053
1054 void gate_arraylist_destroy_item(gate_arraylist_t arr, void* dest_buffer)
1055 {
1056 GATE_DEBUG_ASSERT(arr != NULL);
1057
1058 if (arr->destruct_item != NULL)
1059 {
1060 arr->destruct_item(dest_buffer);
1061 }
1062 }
1063
1064 1023 static gate_bool_t gate_arraylist_enumerate_is_valid(gate_enumerator_t const* enumerator)
1065 {
1066 1023 return enumerator->current_position < enumerator->end_position;
1067 }
1068 1021 static gate_bool_t gate_arraylist_enumerate_next(gate_enumerator_t* enumerator)
1069 {
1070 1021 gate_arraylist_t arr = (gate_arraylist_t)enumerator->ptr_origin;
1071
2/2
✓ Branch 0 taken 1020 times.
✓ Branch 1 taken 1 times.
1021 if (enumerator->current_position)
1072 {
1073 1020 enumerator->current_position = (void*)((char*)enumerator->current_position + arr->item_size);
1074 1020 return enumerator->current_position < enumerator->end_position;
1075 }
1076 else
1077 {
1078 1 return false;
1079 }
1080 }
1081 1020 static void const* gate_arraylist_enumerate_get(gate_enumerator_t const* enumerator)
1082 {
1083 1020 return (void const*)enumerator->current_position;
1084 }
1085
1086 3 gate_enumerator_t* gate_arraylist_enumerate(gate_arraylist_t arr, gate_enumerator_t* enumerator)
1087 {
1088 3 enumerator->is_valid = &gate_arraylist_enumerate_is_valid;
1089 3 enumerator->next = &gate_arraylist_enumerate_next;
1090 3 enumerator->get = &gate_arraylist_enumerate_get;
1091 3 enumerator->ptr_origin = arr;
1092
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (arr->data_ptr)
1093 {
1094 2 enumerator->current_position = arr->data_ptr + (arr->item_offset * arr->item_size);
1095 2 enumerator->end_position = (char*)enumerator->current_position + ((arr->item_offset + arr->item_count) * arr->item_size);
1096 }
1097 else
1098 {
1099 1 enumerator->current_position = NULL;
1100 1 enumerator->end_position = NULL;
1101 }
1102 3 return enumerator;
1103 }
1104
1105 1 gate_result_t gate_arraylist_copy_constructor(void* dst, void const* src)
1106 {
1107 1 gate_arraylist_t* dstlist = (gate_arraylist_t*)dst;
1108 1 gate_arraylist_t const* srclist = (gate_arraylist_t const*)src;
1109 1 *dstlist = *srclist;
1110
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (*dstlist != NULL)
1111 {
1112 1 *dstlist = gate_arraylist_copy(*srclist);
1113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (*dstlist == NULL)
1114 {
1115 /* error: copying failed*/
1116 return GATE_RESULT_FAILED;
1117 }
1118 }
1119 1 return GATE_RESULT_OK;
1120 }
1121 1 void gate_arraylist_destructor(void* dst)
1122 {
1123 1 gate_arraylist_t* dstlist = (gate_arraylist_t*)dst;
1124 1 gate_arraylist_release(*dstlist);
1125 1 *dstlist = NULL;
1126 1 }
1127
1128 /*****************************
1129 * *
1130 * SlotList implementation *
1131 * *
1132 *****************************/
1133
1134 52 gate_slotlist_t* gate_slotlist_create(gate_slotlist_t* sl, gate_size_t itemsize, gate_mem_copyctor_t ctor, gate_mem_dtor_t dtor)
1135 {
1136 52 sl->data_ptr = NULL;
1137 52 sl->item_size = itemsize;
1138 52 sl->item_count = 0;
1139 52 sl->item_capacity = 0;
1140 52 sl->construct_item = ctor;
1141 52 sl->destruct_item = dtor;
1142 52 return sl;
1143 }
1144 22 static gate_slotlist_t* gate_slotlist_resize_to(gate_slotlist_t* sl, gate_size_t newcapacity)
1145 {
1146 gate_size_t ndx;
1147 gate_size_t newdatasize;
1148 void** newbuffer;
1149
1150
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 21 times.
22 if (newcapacity <= sl->item_capacity)
1151 {
1152 1 newcapacity = sl->item_capacity + (sl->item_capacity / 2) + 16;
1153 }
1154 22 newdatasize = newcapacity * sizeof(void*);
1155 22 newbuffer = (void**)gate_mem_realloc(sl->data_ptr, newdatasize);
1156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (newbuffer == NULL)
1157 {
1158 return NULL;
1159 }
1160
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 22 times.
122 for (ndx = sl->item_capacity; ndx < newcapacity; ++ndx)
1161 {
1162 100 newbuffer[ndx] = NULL;
1163 }
1164 22 sl->data_ptr = newbuffer;
1165 22 sl->item_capacity = newcapacity;
1166 22 return sl;
1167 }
1168
1169 3 gate_slotlist_t* gate_slotlist_create_copy(gate_slotlist_t* sl, gate_slotlist_t const* src)
1170 {
1171 3 gate_slotlist_t* ret = NULL;
1172 3 gate_slotlist_create(sl, src->item_size, src->construct_item, src->destruct_item);
1173
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if (NULL != gate_slotlist_resize_to(sl, src->item_count))
1174 {
1175 3 void** ptr = src->data_ptr;
1176 3 ret = sl;
1177
1178
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (ptr)
1179 {
1180 gate_size_t ndx;
1181
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 for (ndx = 0; ndx != src->item_capacity; ++ndx)
1182 {
1183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ptr[ndx] == NULL)
1184 {
1185 continue;
1186 }
1187
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (NULL == gate_slotlist_add(sl, ptr[ndx]))
1188 {
1189 gate_slotlist_destroy(sl);
1190 ret = NULL;
1191 break;
1192 }
1193 }
1194 }
1195 }
1196 3 return ret;
1197 }
1198
1199 52 void gate_slotlist_destroy(gate_slotlist_t* sl)
1200 {
1201 52 void** ptr = sl->data_ptr;
1202
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 30 times.
52 if (ptr)
1203 {
1204 22 void** ptrend = ptr + sl->item_capacity;
1205
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 22 times.
122 for (; ptr != ptrend; ++ptr)
1206 {
1207
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 72 times.
100 if (*ptr != NULL)
1208 {
1209
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (sl->destruct_item != NULL)
1210 {
1211 28 sl->destruct_item(*ptr);
1212 }
1213 28 gate_mem_dealloc(*ptr);
1214 28 *ptr = NULL;
1215 }
1216 }
1217 22 gate_mem_dealloc(sl->data_ptr);
1218 }
1219 52 gate_mem_clear(sl, sizeof(gate_slotlist_t));
1220 52 }
1221
1222 31 static void** gate_slotlist_next_free_slot(gate_slotlist_t* sl)
1223 {
1224 31 void** ptr = sl->data_ptr;
1225
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 void** ptrend = ptr ? (ptr + sl->item_capacity) : NULL;
1226
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 for (; ptr != ptrend; ++ptr)
1227 {
1228
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 18 times.
49 if (*ptr == NULL)
1229 {
1230 31 return ptr;
1231 }
1232 }
1233 return NULL;
1234 }
1235
1236 31 void* gate_slotlist_add(gate_slotlist_t* sl, void const* item)
1237 {
1238 gate_result_t result;
1239 31 void* ret = NULL;
1240 31 void* new_ptr = gate_mem_alloc(sl->item_size);
1241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (NULL == new_ptr)
1242 {
1243 return NULL;
1244 }
1245 31 result = gate_mem_copy_construct(new_ptr, item, sl->item_size, sl->construct_item);
1246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (GATE_FAILED(result))
1247 {
1248 gate_mem_dealloc(new_ptr);
1249 return NULL;
1250 }
1251 31 ret = gate_slotlist_import(sl, new_ptr);
1252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (NULL == ret)
1253 {
1254 gate_mem_destruct(new_ptr, sl->destruct_item);
1255 gate_mem_dealloc(new_ptr);
1256 }
1257 31 return ret;
1258 }
1259 27 void* gate_slotlist_first(gate_slotlist_t const* sl, gate_slotlist_iterator_t* iterator)
1260 {
1261 27 void* ret = NULL;
1262 27 void** ptr = sl->data_ptr;
1263
1264
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 2 times.
27 if (ptr != NULL)
1265 {
1266 gate_size_t ndx;
1267 25 void** ptrend = ptr + sl->item_capacity;
1268
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 for (ndx = 0; ptr != ptrend; ++ptr, ++ndx)
1269 {
1270
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
28 if (*ptr != NULL)
1271 {
1272 25 *iterator = ndx;
1273 25 ret = *ptr;
1274 25 break;
1275 }
1276 }
1277 }
1278 27 return ret;
1279 }
1280 26 void* gate_slotlist_next(gate_slotlist_t const* sl, gate_slotlist_iterator_t* iterator)
1281 {
1282 26 void* ret = NULL;
1283 26 void** ptr = sl->data_ptr;
1284
1285
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 GATE_DEBUG_ASSERT(iterator != NULL);
1286
1287
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (ptr)
1288 {
1289 26 void** ptrend = ptr + sl->item_capacity;
1290 26 gate_size_t ndx = *iterator;
1291
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 if (ndx < sl->item_capacity)
1292 {
1293 26 ++ndx;
1294
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 20 times.
80 for (ptr += ndx; ptr < ptrend; ++ptr, ++ndx)
1295 {
1296
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 54 times.
60 if (*ptr != NULL)
1297 {
1298 6 *iterator = ndx;
1299 6 ret = *ptr;
1300 6 break;
1301 }
1302 }
1303 }
1304 }
1305 26 return ret;
1306 }
1307 16 void* gate_slotlist_at(gate_slotlist_t const* sl, gate_size_t index)
1308 {
1309
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 if ((index < sl->item_capacity) && (sl->data_ptr != NULL))
1310 {
1311 16 return sl->data_ptr[index];
1312 }
1313 return NULL;
1314 }
1315
1316 1 void* gate_slotlist_get(gate_slotlist_t const* sl, gate_slotlist_iterator_t const* iterator)
1317 {
1318
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!sl || !iterator)
1319 {
1320 return NULL;
1321 }
1322 1 return gate_slotlist_at(sl, *iterator);
1323 }
1324
1325 1 void* gate_slotlist_insert_at(gate_slotlist_t* sl, gate_size_t index, void const* item)
1326 {
1327 gate_result_t result;
1328 1 void* ret = NULL;
1329 1 void* new_ptr = gate_mem_alloc(sl->item_size);
1330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == new_ptr)
1331 {
1332 return NULL;
1333 }
1334 1 result = gate_mem_copy_construct(new_ptr, item, sl->item_size, sl->construct_item);
1335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
1336 {
1337 gate_mem_dealloc(new_ptr);
1338 return NULL;
1339 }
1340 1 ret = gate_slotlist_import_at(sl, index, new_ptr);
1341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == ret)
1342 {
1343 gate_mem_destruct(new_ptr, sl->destruct_item);
1344 gate_mem_dealloc(new_ptr);
1345 }
1346 1 return ret;
1347 }
1348
1349 4 gate_bool_t gate_slotlist_remove(gate_slotlist_t* sl, gate_slotlist_iterator_t const* iterator)
1350 {
1351 4 const gate_size_t ndx = *iterator;
1352 4 return gate_slotlist_remove_at(sl, ndx);
1353 }
1354
1355 4 gate_bool_t gate_slotlist_remove_at(gate_slotlist_t* sl, gate_size_t index)
1356 {
1357 4 void* ptr_data = gate_slotlist_export_at(sl, index);
1358
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ptr_data != NULL)
1359 {
1360 4 gate_mem_destruct(ptr_data, sl->destruct_item);
1361 4 gate_mem_dealloc(ptr_data);
1362 4 return true;
1363 }
1364 return false;
1365 }
1366
1367 2 void gate_slotlist_optimize(gate_slotlist_t* sl)
1368 {
1369 2 void** ptr_in = sl->data_ptr;
1370 2 void** ptr_out = ptr_in;
1371 2 void** ptr_end = ptr_in + sl->item_capacity;
1372
1373
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 while (ptr_in != ptr_end)
1374 {
1375
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
8 if (*ptr_in != NULL)
1376 {
1377
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
7 if (ptr_in != ptr_out)
1378 {
1379 2 *ptr_out = *ptr_in;
1380 }
1381 7 ++ptr_out;
1382 }
1383 8 ++ptr_in;
1384 }
1385
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 while (ptr_out != ptr_end)
1386 {
1387 1 *ptr_out = NULL;
1388 1 ++ptr_out;
1389 }
1390 2 }
1391
1392 1 void gate_slotlist_clear(gate_slotlist_t* sl)
1393 {
1394 1 gate_size_t itemsize = sl->item_size;
1395 1 gate_mem_copyctor_t ctor = sl->construct_item;
1396 1 gate_mem_dtor_t dtor = sl->destruct_item;
1397 1 gate_slotlist_destroy(sl);
1398 1 gate_slotlist_create(sl, itemsize, ctor, dtor);
1399 1 }
1400 6 gate_size_t gate_slotlist_length(gate_slotlist_t const* sl)
1401 {
1402 6 return sl->item_count;
1403 }
1404 33 gate_size_t gate_slotlist_capacity(gate_slotlist_t const* sl)
1405 {
1406 33 return sl->item_capacity;
1407 }
1408
1409 31 void* gate_slotlist_import(gate_slotlist_t* sl, void* item)
1410 {
1411 void** ptr;
1412
1413
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12 times.
31 if (sl->item_count >= sl->item_capacity)
1414 {
1415
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19 times.
19 if (NULL == gate_slotlist_resize_to(sl, sl->item_count + 4 + sl->item_capacity / 2))
1416 {
1417 /* out of memory */
1418 return NULL;
1419 }
1420 }
1421 31 ptr = gate_slotlist_next_free_slot(sl);
1422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ptr == NULL)
1423 {
1424 return NULL;
1425 }
1426 31 *ptr = item;
1427
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (item != NULL)
1428 {
1429 31 ++sl->item_count;
1430 }
1431 31 return *ptr;
1432 }
1433 1 void* gate_slotlist_import_at(gate_slotlist_t* sl, gate_size_t index, void* item)
1434 {
1435 gate_size_t move_count;
1436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (index >= sl->item_capacity)
1437 {
1438 if (NULL == gate_slotlist_resize_to(sl, index + 4))
1439 {
1440 /* out of memory */
1441 return NULL;
1442 }
1443 }
1444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 else if (sl->data_ptr[index] != NULL)
1445 {
1446 if (NULL == gate_slotlist_resize_to(sl, sl->item_capacity + 4))
1447 {
1448 /* out of memory */
1449 return NULL;
1450 }
1451 }
1452
1453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (sl->data_ptr[index] != NULL)
1454 {
1455 move_count = sl->item_capacity - index - 1;
1456 if (move_count > 0)
1457 {
1458 gate_mem_move(&sl->data_ptr[index + 1], &sl->data_ptr[index], move_count * sizeof(void*));
1459 }
1460 }
1461 1 sl->data_ptr[index] = item;
1462
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (item != NULL)
1463 {
1464 1 ++sl->item_count;
1465 }
1466 1 return item;
1467 }
1468 void* gate_slotlist_export(gate_slotlist_t* sl, gate_slotlist_iterator_t* iterator)
1469 {
1470 return gate_slotlist_export_at(sl, *iterator);
1471 }
1472 4 void* gate_slotlist_export_at(gate_slotlist_t* sl, gate_size_t index)
1473 {
1474 void* ret;
1475
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if (index >= sl->item_capacity || (sl->data_ptr == NULL))
1476 {
1477 return NULL;
1478 }
1479 4 ret = sl->data_ptr[index];
1480 4 sl->data_ptr[index] = NULL;
1481
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (ret != NULL)
1482 {
1483 4 --sl->item_count;
1484 }
1485 4 return ret;
1486 }
1487
1488 5 static gate_bool_t slotlist_enum_is_valid(gate_enumerator_t const* enumerator)
1489 {
1490 5 return enumerator->current_position != NULL;
1491 }
1492
1493 4 static gate_bool_t slotlist_enum_next(gate_enumerator_t* enumerator)
1494 {
1495 4 gate_slotlist_t const* ptr_sl = (gate_slotlist_t const*)enumerator->ptr_origin;
1496 4 gate_slotlist_iterator_t* ptr_iter = (gate_slotlist_iterator_t*)&enumerator->handles[0];
1497 4 enumerator->current_position = gate_slotlist_next(ptr_sl, ptr_iter);
1498 4 return NULL != enumerator->current_position;
1499 }
1500 4 static void const* slotlist_enum_get(gate_enumerator_t const* enumerator)
1501 {
1502 4 return enumerator->current_position;
1503 }
1504
1505 1 gate_enumerator_t* gate_slotlist_enumerate(gate_slotlist_t const* sl, gate_enumerator_t* enumerator)
1506 {
1507 gate_slotlist_iterator_t* ptr_iter;
1508
1509 1 gate_mem_clear(enumerator, sizeof(gate_enumerator_t));
1510 1 ptr_iter = (gate_slotlist_iterator_t*)&enumerator->handles[0];
1511 1 enumerator->ptr_origin = sl;
1512 1 enumerator->is_valid = &slotlist_enum_is_valid;
1513 1 enumerator->next = &slotlist_enum_next;
1514 1 enumerator->get = &slotlist_enum_get;
1515 1 enumerator->current_position = gate_slotlist_first(sl, ptr_iter);
1516
1517 1 return enumerator;
1518 }
1519
1520 /*******************************
1521 * *
1522 * LinkedList implementation *
1523 * *
1524 *******************************/
1525
1526 23 gate_result_t gate_linkedlist_create(gate_linkedlist_t* list, gate_size_t itemsize, gate_mem_copyctor_t copyctor, gate_mem_dtor_t dtor)
1527 {
1528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 GATE_DEBUG_ASSERT(list != NULL);
1529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 GATE_DEBUG_ASSERT(itemsize > 0);
1530 23 list->item_size = itemsize;
1531 23 list->construct_item = copyctor;
1532 23 list->destruct_item = dtor;
1533 23 list->first = NULL;
1534 23 list->last = NULL;
1535 23 return GATE_RESULT_OK;
1536 }
1537 23 void gate_linkedlist_destroy(gate_linkedlist_t* list)
1538 {
1539 gate_linkedentry_t* ptr;
1540 gate_linkedentry_t* next;
1541
1542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 GATE_DEBUG_ASSERT(list != NULL);
1543
1544 23 ptr = list->first;
1545
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 19 times.
23 if (list->destruct_item != NULL)
1546 {
1547 4 gate_mem_dtor_t const dtor = list->destruct_item;
1548
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 while (ptr != NULL)
1549 {
1550 6 dtor(ptr->data);
1551 6 next = ptr->next;
1552 6 gate_mem_dealloc(ptr);
1553 6 ptr = next;
1554 }
1555 }
1556 else
1557 {
1558
2/2
✓ Branch 0 taken 132208 times.
✓ Branch 1 taken 19 times.
132227 while (ptr != NULL)
1559 {
1560 132208 next = ptr->next;
1561 132208 gate_mem_dealloc(ptr);
1562 132208 ptr = next;
1563 }
1564 }
1565 23 gate_mem_clear(list, sizeof(gate_linkedlist_t));
1566 23 }
1567
1568 132218 static gate_linkedentry_t* gate_linkedentry_create(gate_linkedlist_t* list, void const* item)
1569 {
1570 gate_linkedentry_t* ret;
1571 gate_size_t entry_size;
1572
1573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132218 times.
132218 GATE_DEBUG_ASSERT(list != NULL);
1574
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132218 times.
132218 GATE_DEBUG_ASSERT(item != NULL);
1575
1576 132218 entry_size = sizeof(gate_linkedentry_t) + list->item_size;
1577 132218 ret = (gate_linkedentry_t*)gate_mem_alloc(entry_size);
1578
1/2
✓ Branch 0 taken 132218 times.
✗ Branch 1 not taken.
132218 if (ret != NULL)
1579 {
1580 do
1581 {
1582 132218 gate_mem_clear(ret, entry_size);
1583
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 132208 times.
132218 if (list->construct_item)
1584 {
1585 10 gate_result_t result = list->construct_item(&ret->attachment.content[0], item);
1586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (GATE_FAILED(result))
1587 {
1588 gate_mem_dealloc(ret);
1589 break;
1590 }
1591 }
1592 else
1593 {
1594
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 132208 times.
132208 if (NULL == gate_mem_copy(&ret->attachment.content[0], item, list->item_size))
1595 {
1596 gate_mem_dealloc(ret);
1597 break;
1598 }
1599 }
1600 132218 ret->data = &ret->attachment.content[0];
1601 132218 ret->previous = NULL;
1602 132218 ret->next = NULL;
1603 } while (0);
1604 }
1605
1606 132218 return ret;
1607 }
1608 4 static void gate_linkedentry_destroy(gate_linkedlist_t* list, gate_linkedentry_t* entry)
1609 {
1610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(list != NULL);
1611
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(entry != NULL);
1612
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (list->destruct_item)
1613 {
1614 4 list->destruct_item(entry->data);
1615 }
1616 4 gate_mem_dealloc(entry);
1617 4 }
1618
1619 132217 gate_linkedentry_t* gate_linkedlist_add(gate_linkedlist_t* list, void const* item)
1620 {
1621 132217 gate_linkedentry_t* ret = gate_linkedentry_create(list, item);
1622
1/2
✓ Branch 0 taken 132217 times.
✗ Branch 1 not taken.
132217 if (ret)
1623 {
1624 132217 ret->previous = list->last;
1625
2/2
✓ Branch 0 taken 132195 times.
✓ Branch 1 taken 22 times.
132217 if (list->last)
1626 {
1627 132195 list->last->next = ret;
1628 }
1629 else
1630 {
1631 22 list->first = ret;
1632 }
1633 132217 list->last = ret;
1634 }
1635 132217 return ret;
1636 }
1637 1 gate_linkedentry_t* gate_linkedlist_insert(gate_linkedlist_t* list, gate_linkedentry_t* entry, void const* item)
1638 {
1639 gate_linkedentry_t* ret;
1640
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (entry == NULL)
1641 {
1642 ret = gate_linkedlist_add(list, item);
1643 }
1644 else
1645 {
1646 1 ret = gate_linkedentry_create(list, item);
1647
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ret)
1648 {
1649 1 ret->next = entry;
1650 1 ret->previous = entry->previous;
1651 1 entry->previous = ret;
1652
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ret->previous == NULL)
1653 {
1654 1 list->first = ret;
1655 }
1656 }
1657 }
1658 1 return ret;
1659 }
1660 4 gate_result_t gate_linkedlist_remove(gate_linkedlist_t* list, gate_linkedentry_t* entry)
1661 {
1662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(list != NULL);
1663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_DEBUG_ASSERT(entry != NULL);
1664
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
4 if ((entry->previous == NULL) && (entry->next == NULL))
1665 {
1666 1 list->first = NULL;
1667 1 list->last = NULL;
1668 }
1669 else
1670 {
1671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (entry->previous == NULL)
1672 {
1673 list->first = entry->next;
1674 entry->next->previous = NULL;
1675 }
1676
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 else if (entry->next == NULL)
1677 {
1678 3 list->last = entry->previous;
1679 3 entry->previous->next = NULL;
1680 }
1681 else
1682 {
1683 entry->previous->next = entry->next;
1684 entry->next->previous = entry->previous;
1685 }
1686 }
1687 4 gate_linkedentry_destroy(list, entry);
1688 4 return GATE_RESULT_OK;
1689 }
1690 45 gate_linkedentry_t* gate_linkedlist_first(gate_linkedlist_t const* list)
1691 {
1692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
45 GATE_DEBUG_ASSERT(list != NULL);
1693 45 return list->first;
1694 }
1695 6 gate_linkedentry_t* gate_linkedlist_last(gate_linkedlist_t const* list)
1696 {
1697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_DEBUG_ASSERT(list != NULL);
1698 6 return list->last;
1699 }
1700 5 gate_linkedentry_t* gate_linkedlist_previous(gate_linkedentry_t const* entry)
1701 {
1702
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (entry)
1703 {
1704 5 return entry->previous;
1705 }
1706 return NULL;
1707 }
1708 264430 gate_linkedentry_t* gate_linkedlist_next(gate_linkedentry_t const* entry)
1709 {
1710
1/2
✓ Branch 0 taken 264430 times.
✗ Branch 1 not taken.
264430 if (entry)
1711 {
1712 264430 return entry->next;
1713 }
1714 return NULL;
1715 }
1716
1717 5 gate_bool_t gate_linkedlist_empty(gate_linkedlist_t const* list)
1718 {
1719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_DEBUG_ASSERT(list != NULL);
1720 5 return list->first == NULL;
1721 }
1722
1723 8 static gate_bool_t gate_linkedlist_enum_is_valid(gate_enumerator_t const* enumerator)
1724 {
1725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_DEBUG_ASSERT(enumerator != NULL);
1726 8 return NULL != enumerator->current_position;
1727 }
1728 3 static gate_bool_t gate_linkedlist_enum_next(gate_enumerator_t* enumerator)
1729 {
1730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_DEBUG_ASSERT(enumerator != NULL);
1731
1732
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (enumerator->current_position != NULL)
1733 {
1734 3 gate_linkedentry_t* const entry = (gate_linkedentry_t*)enumerator->current_position;
1735 3 enumerator->current_position = entry->next;
1736 3 return (enumerator->current_position == NULL) ? false : true;
1737 }
1738 return false;
1739 }
1740 9 static void const* gate_linkedlist_enum_get(gate_enumerator_t const* enumerator)
1741 {
1742
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 GATE_DEBUG_ASSERT(enumerator != NULL);
1743
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (enumerator->current_position != NULL)
1744 {
1745 9 gate_linkedentry_t* const entry = (gate_linkedentry_t*)enumerator->current_position;
1746 9 return entry->data;
1747 }
1748 return NULL;
1749 }
1750
1751 1 gate_enumerator_t* gate_linkedlist_enumerate(gate_linkedlist_t const* list, gate_enumerator_t* enumerator)
1752 {
1753
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!list || !enumerator)
1754 {
1755 return NULL;
1756 }
1757 else
1758 {
1759 1 gate_mem_clear(enumerator, sizeof(gate_enumerator_t));
1760 1 enumerator->is_valid = &gate_linkedlist_enum_is_valid;
1761 1 enumerator->next = &gate_linkedlist_enum_next;
1762 1 enumerator->get = &gate_linkedlist_enum_get;
1763
1764 1 enumerator->ptr_origin = list;
1765 1 enumerator->current_position = list->first;
1766 1 return enumerator;
1767 }
1768 }
1769