GCC Code Coverage Report


Directory: src/gate/
File: src/gate/arrays.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 720 854 84.3%
Functions: 81 84 96.4%
Branches: 302 492 61.4%

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