GCC Code Coverage Report


Directory: src/gate/
File: src/gate/arrays.c
Date: 2026-10-19 17:06:30
Exec Total Coverage
Lines: 775 890 87.1%
Functions: 85 87 97.7%
Branches: 324 502 64.5%

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