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