GCC Code Coverage Report


Directory: src/gate/
File: src/gate/utilities.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 380 476 79.8%
Functions: 39 40 97.5%
Branches: 116 219 53.0%

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/utilities.h"
30 #include "gate/comparers.h"
31 #include "gate/results.h"
32 #include "gate/structs.h"
33 #include "gate/properties.h"
34 #include "gate/times.h"
35 #include "gate/guids.h"
36 #include "gate/blobs.h"
37 #include "gate/synchronization.h"
38 #include "gate/platforms.h"
39
40 4 gate_map_t* gate_util_stringmap_create(gate_map_t* m)
41 {
42
43 4 return gate_map_create(m, &gate_compare_string,
44 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor,
45 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor
46 );
47 }
48 20 gate_map_t* gate_util_stringmap_create_ex(gate_map_t* m, gate_bool_t duplicate_ctor, gate_bool_t ignore_case)
49 {
50
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 gate_comparer_t comp = ignore_case ? &gate_compare_string_ic : &gate_compare_string;
51
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 gate_mem_copyctor_t cctor = duplicate_ctor ? &gate_string_duplicate_constructor : &gate_string_copy_constructor;
52 20 return gate_map_create(m, comp,
53 sizeof(gate_string_t), cctor, &gate_string_destructor,
54 sizeof(gate_string_t), cctor, &gate_string_destructor
55 );
56 }
57
58 1 gate_string_t const* gate_util_stringmap_get(gate_map_t* m, char const* key)
59 {
60 gate_string_t k;
61
62 1 gate_string_create_static(&k, key);
63 1 return gate_util_stringmap_get_string(m, &k);
64 }
65 3 gate_string_t const* gate_util_stringmap_get_string(gate_map_t* m, gate_string_t const* key)
66 {
67 3 gate_string_t const* ret = NULL;
68
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if ((m->key_size == sizeof(gate_string_t)) && (m->value_size == sizeof(gate_string_t)))
69 {
70 3 ret = (gate_string_t const*)gate_map_get_value(m, key);
71 }
72 3 return ret;
73 }
74 2 gate_map_iterator_t gate_util_stringmap_add(gate_map_t* m, char const* key, char const* value)
75 {
76 2 gate_map_iterator_t ret = NULL;
77 2 gate_string_t k = GATE_STRING_INIT_EMPTY;
78 2 gate_string_t v = GATE_STRING_INIT_EMPTY;
79
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (NULL != gate_string_create(&k, key, gate_str_length(key)))
80 {
81
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (NULL != gate_string_create(&v, value, gate_str_length(value)))
82 {
83 2 ret = gate_util_stringmap_add_string(m, &k, &v);
84 2 gate_string_release(&v);
85 }
86 2 gate_string_release(&k);
87 }
88 2 return ret;
89 }
90 13 gate_map_iterator_t gate_util_stringmap_add_string(gate_map_t* m, gate_string_t const* key, gate_string_t const* value)
91 {
92 13 gate_map_iterator_t ret = NULL;
93 13 gate_string_t key_clone = GATE_STRING_INIT_EMPTY;
94 13 gate_string_t value_clone = GATE_STRING_INIT_EMPTY;
95
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 if (gate_string_clone(&key_clone, key))
96 {
97
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 if (gate_string_clone(&value_clone, value))
98 {
99 13 ret = gate_map_add(m, &key_clone, &value_clone);
100 13 gate_string_release(&value_clone);
101 }
102 13 gate_string_release(&key_clone);
103 }
104 13 return ret;
105 }
106
107
108 /*************************
109 * stringset utilities *
110 *************************/
111
112 16 gate_set_t* gate_util_stringset_create(gate_set_t* s)
113 {
114 16 return gate_set_create(s, &gate_compare_string, sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor);
115 }
116 2 gate_bool_t gate_util_stringset_contains_string(gate_set_t* s, gate_string_t const* key)
117 {
118 2 return gate_set_iterator_valid(gate_set_get(s, key));
119 }
120 1 gate_bool_t gate_util_stringset_contains(gate_set_t* s, char const* key)
121 {
122 1 gate_bool_t ret = false;
123 gate_string_t str;
124
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_create_static(&str, key))
125 {
126 1 ret = gate_util_stringset_contains_string(s, &str);
127 1 gate_string_release(&str);
128 }
129 1 return ret;
130 }
131 2 gate_bool_t gate_util_stringset_add_string(gate_set_t* s, gate_string_t const* key)
132 {
133 2 gate_bool_t ret = false;
134 gate_string_t key_clone;
135
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (gate_string_clone(&key_clone, key))
136 {
137 2 ret = gate_set_iterator_valid(gate_set_add(s, &key_clone));
138 2 gate_string_release(&key_clone);
139 }
140 2 return ret;
141 }
142 1 gate_bool_t gate_util_stringset_add(gate_set_t* s, char const* key)
143 {
144 1 gate_bool_t ret = false;
145 gate_string_t str;
146
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (gate_string_create(&str, key, gate_str_length(key)))
147 {
148 1 ret = gate_util_stringset_add_string(s, &str);
149 1 gate_string_release(&str);
150 }
151 1 return ret;
152 }
153 2 gate_bool_t gate_util_stringset_remove_string(gate_set_t* s, gate_string_t const* key)
154 {
155 2 return gate_set_remove(s, key);
156 }
157 1 gate_bool_t gate_util_stringset_remove(gate_set_t* s, char const* key)
158 {
159 1 gate_bool_t ret = false;
160 gate_string_t str;
161
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_create_static(&str, key))
162 {
163 1 ret = gate_util_stringset_remove_string(s, &str);
164 1 gate_string_release(&str);
165 }
166 1 return ret;
167 }
168
169
170 gate_arraylist_t gate_util_blobarray_create()
171 {
172 return gate_arraylist_create(sizeof(gate_blob_t), NULL, 0, &gate_blob_copy_constructor, &gate_blob_destructor);
173 }
174
175
176
177 8 gate_arraylist_t gate_util_stringarray_create()
178 {
179 8 return gate_arraylist_create(sizeof(gate_string_t), NULL, 0, &gate_string_copy_constructor, &gate_string_destructor);
180 }
181 1 gate_arraylist_t gate_util_stringarray_create_duplicate(gate_size_t prealloc)
182 {
183 1 return gate_arraylist_create(sizeof(gate_string_t), NULL, prealloc, &gate_string_duplicate_constructor, &gate_string_destructor);
184 }
185
186
187 3 gate_string_t const* gate_util_stringarray_add(gate_arraylist_t lst, gate_string_t const* new_entry)
188 {
189 3 return (gate_string_t const*)gate_arraylist_add(lst, new_entry);
190 }
191 1 gate_string_t const* gate_util_stringarray_add_str(gate_arraylist_t lst, char const* new_entry)
192 {
193 1 gate_string_t const* ret = NULL;
194 gate_string_t str;
195
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (NULL != gate_string_create(&str, new_entry, gate_str_length(new_entry)))
196 {
197 1 ret = gate_util_stringarray_add(lst, &str);
198 1 gate_string_release(&str);
199 }
200 1 return ret;
201 }
202
203
204 3 gate_bool_t gate_util_string_eval_bool(gate_string_t const* str)
205 {
206 static gate_string_t const false_token = GATE_STRING_INIT_STATIC("false");
207 static gate_string_t const zero_token = GATE_STRING_INIT_STATIC("0");
208
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (gate_string_is_empty(str))
209 {
210 1 return false;
211 }
212
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_string_equals_ic(str, &false_token)
213
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 || gate_string_equals(str, &zero_token))
214 {
215 1 return false;
216 }
217 1 return true;
218 }
219
220 3 gate_arraylist_t gate_util_string_split(gate_string_t const* str, gate_string_t const* separator, gate_size_t max_count)
221 {
222 3 gate_string_t txt = GATE_STRING_INIT_EMPTY;
223 3 gate_string_t head = GATE_STRING_INIT_EMPTY;
224 3 gate_string_t tail = GATE_STRING_INIT_EMPTY;
225 3 gate_arraylist_t ret = gate_util_stringarray_create();
226 gate_size_t parsed;
227 3 gate_size_t items_count = 0;
228
229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!ret)
230 {
231 return ret;
232 }
233 3 gate_string_duplicate(&txt, str);
234
235
3/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 1 times.
10 while (!gate_string_is_empty(&txt) && (items_count < max_count))
236 {
237 9 parsed = gate_string_parse(&txt, separator, 0, &head, &tail, false);
238
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 7 times.
9 if (!parsed)
239 {
240 2 gate_arraylist_add(ret, &txt);
241 2 break;
242 }
243 7 gate_arraylist_add(ret, &head);
244 7 gate_string_release(&head);
245 7 gate_string_release(&txt);
246 7 gate_mem_copy(&txt, &tail, sizeof(tail));
247 7 gate_mem_clear(&tail, sizeof(tail));
248 7 ++items_count;
249 }
250
251 3 gate_string_release(&txt);
252 3 return ret;
253 }
254
255
256
257
258 1 gate_arraylist_t gate_util_map_export_keys(gate_map_t* m)
259 {
260 1 gate_arraylist_t ret = NULL;
261
262 1 ret = gate_arraylist_create(m->key_size, NULL, 0, m->key_constructor, m->key_destructor);
263
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ret)
264 {
265 1 gate_map_iterator_t iter = gate_map_first(m);
266
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 while (gate_map_iterator_valid(iter))
267 {
268 2 void const* key = gate_map_iterator_key(iter);
269
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (key)
270 {
271
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!gate_arraylist_add(ret, key))
272 {
273 /* allocation error */
274 gate_arraylist_release(ret);
275 ret = NULL;
276 break;
277 }
278 }
279 2 iter = gate_map_iterator_next(iter);
280 }
281 }
282 1 return ret;
283 }
284
285 1 gate_arraylist_t gate_util_map_export_values(gate_map_t* m)
286 {
287 1 gate_arraylist_t ret = NULL;
288
289 1 ret = gate_arraylist_create(m->value_size, NULL, 0, m->value_constructor, m->value_destructor);
290
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ret)
291 {
292 1 gate_map_iterator_t iter = gate_map_first(m);
293
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 while (gate_map_iterator_valid(iter))
294 {
295 2 void const* value = gate_map_iterator_value(iter);
296
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (value)
297 {
298
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!gate_arraylist_add(ret, value))
299 {
300 /* allocation error */
301 gate_arraylist_release(ret);
302 ret = NULL;
303 break;
304 }
305 }
306 2 iter = gate_map_iterator_next(iter);
307 }
308 }
309 1 return ret;
310 }
311
312
313
314
315
316
317 3 gate_result_t gate_util_buffer_load(char const** ptrbuffer, gate_size_t* ptrbuffersize, gate_stream_t* srcstream, gate_memstream_t** membuffer)
318 {
319 3 gate_result_t ret = GATE_RESULT_OK;
320 3 gate_memstream_t* memstream = NULL;
321
322 do
323 {
324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (srcstream == NULL)
325 {
326 *ptrbuffer = NULL;
327 *ptrbuffersize = 0;
328 }
329 else
330 {
331 3 char const* srcstreamtype = gate_object_get_interface_name(srcstream);
332
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (0 == gate_str_comp(GATE_INTERFACE_NAME_MEMSTREAM, srcstreamtype))
333 {
334 /* the source stream is already a memory stream, we can directly access its data */
335 1 memstream = (gate_memstream_t*)srcstream;
336 1 gate_object_retain(memstream);
337 1 *ptrbuffer = gate_memstream_get_data(memstream);
338 1 *ptrbuffersize = gate_memstream_size(memstream);
339 }
340
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 else if (0 == gate_str_comp(GATE_INTERFACE_NAME_STRINGSTREAM, srcstreamtype))
341 {
342 1 gate_stringstream_t* stringstrm = (gate_stringstream_t*)srcstream;
343 1 *ptrbuffer = gate_stringstream_get_data(stringstrm);
344 1 *ptrbuffersize = gate_stringstream_size(stringstrm);
345 }
346 else
347 {
348
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (*membuffer == NULL)
349 {
350 1 memstream = gate_memstream_create(GATE_MAX_COPYBUFFER_LENGTH);
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (memstream == NULL)
352 {
353 ret = GATE_RESULT_OUTOFMEMORY;
354 break;
355 }
356 1 *membuffer = memstream;
357 }
358 else
359 {
360 memstream = *membuffer;
361 }
362 1 gate_object_retain(memstream);
363 1 ret = gate_stream_transfer(srcstream, (gate_stream_t*)memstream);
364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
365 {
366 break;
367 }
368 1 *ptrbuffer = gate_memstream_get_data(memstream);
369 1 *ptrbuffersize = gate_memstream_size(memstream);
370 }
371 }
372
373 } while (0);
374
375
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (memstream != NULL)
376 {
377 2 gate_object_release(memstream);
378 }
379
380 3 return ret;
381 }
382
383
384 12 gate_size_t gate_util_print_byte_size(gate_uint64_t bytes, gate_char8_t* dest_buffer, gate_size_t dest_size)
385 {
386 gate_size_t ret;
387
388
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if (bytes < 1024)
389 {
390 2 ret = gate_str_print_uint64(dest_buffer, dest_size, bytes);
391 2 ret += gate_str_print_text(&dest_buffer[ret], dest_size - ret, " Bytes", 6);
392 }
393
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6 times.
10 else if (bytes < 1048576)
394 {
395 4 ret = gate_str_print_real(dest_buffer, dest_size, (gate_real64_t)(gate_int64_t)bytes / 1024.0, 0, 1, 3);
396 4 ret += gate_str_print_text(&dest_buffer[ret], dest_size - ret, " KB", 3);
397 }
398
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 else if (bytes < 1073741824)
399 {
400 4 ret = gate_str_print_real(dest_buffer, dest_size, (gate_real64_t)(gate_int64_t)bytes / 1048576.0, 0, 2, 3);
401 4 ret += gate_str_print_text(&dest_buffer[ret], dest_size - ret, " MB", 3);
402 }
403 else
404 {
405 2 ret = gate_str_print_real(dest_buffer, dest_size, (gate_real64_t)(gate_int64_t)bytes / 1073741824.0, 0, 2, 3);
406 2 ret += gate_str_print_text(&dest_buffer[ret], dest_size - ret, " GB", 3);
407 }
408
409 12 return ret;
410 }
411
412 6 gate_size_t gate_util_print_duration(gate_uint64_t seconds, gate_char8_t* dest_buffer, gate_size_t dest_size, gate_bool_t shortFormat)
413 {
414 6 gate_size_t ret = 0;
415 6 gate_bool_t print_days = true;
416 6 gate_bool_t print_hours = true;
417 6 gate_bool_t print_minutes = true;
418
419 6 gate_uint64_t days = 0;
420 6 gate_uint64_t hours = 0;
421 6 gate_uint64_t minutes = 0;
422 gate_size_t lenused;
423
424 6 days = seconds / 86400;
425 6 seconds %= 86400;
426
427 6 hours = seconds / 3600;
428 6 seconds %= 3600;
429
430 6 minutes = seconds / 60;
431 6 seconds %= 60;
432 do
433 {
434
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (days == 0)
435 {
436 3 print_days = false;
437 }
438 else
439 {
440 3 break;
441 }
442
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (hours == 0)
443 {
444 2 print_hours = false;
445 }
446 else
447 {
448 1 break;
449 }
450
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (minutes == 0)
451 {
452 1 print_minutes = 0;
453 }
454 } while (0);
455
456
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (print_days)
457 {
458 3 lenused = gate_str_print_uint(dest_buffer, dest_size, days, 0);
459 3 dest_buffer += lenused;
460 3 dest_size -= lenused;
461 3 ret += lenused;
462
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (shortFormat)
463 {
464 2 lenused = gate_str_print_text(dest_buffer, dest_size, "d ", 2);
465 }
466 else
467 {
468 1 lenused = gate_str_print_text(dest_buffer, dest_size, " days ", 6);
469 }
470 3 dest_buffer += lenused;
471 3 dest_size -= lenused;
472 3 ret += lenused;
473 }
474
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if (print_hours)
475 {
476 4 lenused = gate_str_print_uint(dest_buffer, dest_size, hours, 0);
477 4 dest_buffer += lenused;
478 4 dest_size -= lenused;
479 4 ret += lenused;
480
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 if (shortFormat)
481 {
482 3 lenused = gate_str_print_text(dest_buffer, dest_size, "h ", 2);
483 }
484 else
485 {
486 1 lenused = gate_str_print_text(dest_buffer, dest_size, " hours ", 7);
487 }
488 4 dest_buffer += lenused;
489 4 dest_size -= lenused;
490 4 ret += lenused;
491 }
492
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (print_minutes)
493 {
494 5 lenused = gate_str_print_uint(dest_buffer, dest_size, minutes, 0);
495 5 dest_buffer += lenused;
496 5 dest_size -= lenused;
497 5 ret += lenused;
498
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (shortFormat)
499 {
500 4 lenused = gate_str_print_text(dest_buffer, dest_size, "m ", 2);
501 }
502 else
503 {
504 1 lenused = gate_str_print_text(dest_buffer, dest_size, " minutes ", 9);
505 }
506 5 dest_buffer += lenused;
507 5 dest_size -= lenused;
508 5 ret += lenused;
509 }
510
511 {
512 6 lenused = gate_str_print_uint(dest_buffer, dest_size, seconds, 0);
513 6 dest_buffer += lenused;
514 6 dest_size -= lenused;
515 6 ret += lenused;
516
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 if (shortFormat)
517 {
518 5 lenused = gate_str_print_text(dest_buffer, dest_size, "s", 1);
519 }
520 else
521 {
522 1 lenused = gate_str_print_text(dest_buffer, dest_size, "seconds", 7);
523 }
524 /*
525 dest_buffer += lenused;
526 dest_size -= lenused;
527 */
528 6 ret += lenused;
529 }
530 6 return ret;
531 }
532
533 2 gate_string_t* gate_util_int_to_string(gate_string_t* output, gate_int64_t input)
534 {
535 char buffer[256];
536 2 gate_size_t used = gate_str_print_int64(buffer, sizeof(buffer), input);
537 2 return gate_string_create(output, buffer, used);
538 }
539 1 gate_string_t* gate_util_uint_to_string(gate_string_t* output, gate_uint64_t input)
540 {
541 char buffer[256];
542 1 gate_size_t used = gate_str_print_uint64(buffer, sizeof(buffer), input);
543 1 return gate_string_create(output, buffer, used);
544 }
545 1 gate_string_t* gate_util_real_to_string(gate_string_t* output, gate_real64_t input, unsigned int_len, unsigned decimal_len, unsigned group_len)
546 {
547 char buffer[256];
548 1 gate_size_t used = gate_str_print_real(buffer, sizeof(buffer), input, int_len, decimal_len, group_len);
549 1 return gate_string_create(output, buffer, used);
550 }
551 1 gate_int64_t gate_util_string_to_int(gate_string_t const* input)
552 {
553 1 gate_int64_t ret = 0;
554
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (input)
555 {
556 1 gate_str_parse_int64(input->str, input->length, &ret);
557 }
558 1 return ret;
559 }
560 1 gate_uint64_t gate_util_string_to_uint(gate_string_t const* input)
561 {
562 1 gate_uint64_t ret = 0;
563
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (input)
564 {
565 1 gate_str_parse_uint64(input->str, input->length, &ret);
566 }
567 1 return ret;
568 }
569 1 gate_real64_t gate_util_string_to_real(gate_string_t const* input)
570 {
571 1 gate_real64_t ret = 0.0;
572
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (input)
573 {
574 1 gate_str_parse_real(input->str, input->length, &ret);
575 }
576 1 return ret;
577 }
578
579
580 30 gate_result_t gate_util_dump_type(gate_stream_t* target, gate_type_id_t type, void const* data)
581 {
582 30 gate_result_t ret = GATE_RESULT_FAILED;
583 30 char buffer[1024] = GATE_INIT_EMPTY;
584 30 gate_size_t buffer_size = sizeof(buffer);
585 30 gate_datetime_t dt = GATE_INIT_EMPTY;
586
587
15/26
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 2 times.
✓ Branch 17 taken 2 times.
✓ Branch 18 taken 2 times.
✓ Branch 19 taken 2 times.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
30 switch (type)
588 {
589 2 case GATE_TYPE_BOOL:
590 2 case GATE_TYPE_I8: ret = gate_stream_print_int(target, *((gate_int8_t const*)data)); break;
591 2 case GATE_TYPE_I16: ret = gate_stream_print_int(target, *((gate_int16_t const*)data)); break;
592 2 case GATE_TYPE_I32: ret = gate_stream_print_int(target, *((gate_int32_t const*)data)); break;
593 2 case GATE_TYPE_I64: ret = gate_stream_print_int64(target, *((gate_int64_t const*)data)); break;
594 case GATE_TYPE_UI8: ret = gate_stream_print_uint(target, *((gate_uint8_t const*)data)); break;
595 2 case GATE_TYPE_UI16: ret = gate_stream_print_uint(target, *((gate_uint16_t const*)data)); break;
596 2 case GATE_TYPE_UI32: ret = gate_stream_print_uint(target, *((gate_uint32_t const*)data)); break;
597 2 case GATE_TYPE_UI64: ret = gate_stream_print_uint64(target, *((gate_uint64_t const*)data)); break;
598 2 case GATE_TYPE_R32: ret = gate_stream_print_real(target, *((gate_real32_t const*)data), 0, 0, 0); break;
599 2 case GATE_TYPE_R64: ret = gate_stream_print_real(target, *((gate_real64_t const*)data), 0, 0, 0); break;
600 case GATE_TYPE_ADDRESS: ret = gate_stream_print_uint64(target, *((gate_uintptr_t const*)data)); break;
601
602 case GATE_TYPE_DATAPTR: ret = gate_stream_print_uint64(target, (gate_uintptr_t)(*((gate_dataptr_t const*)data))); break;
603 case GATE_TYPE_FUNCPTR: ret = gate_stream_print_uint64(target, (gate_uintptr_t)(*((gate_funcptr_t const*)data))); break;
604 case GATE_TYPE_CSTR: ret = gate_stream_print_cstr(target, (gate_cstr_t)data); break;
605 case GATE_TYPE_WSTR: ret = gate_stream_print_wstr(target, (gate_wstr_t)data, gate_wstr_length((gate_wstr_t)data)); break;
606 2 case GATE_TYPE_GUID:
607 2 ret = gate_guid_to_string((gate_guid_t const*)data, buffer);
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
609 2 ret = gate_stream_print_cstr(target, buffer);
610 2 break;
611 2 case GATE_TYPE_DATE:
612 2 gate_mem_copy(&dt.date, data, sizeof(gate_date_t));
613 2 ret = gate_date_to_string((gate_datetime_t const*)data, 0, "{YYYY}-{MM}-{DD}", buffer, &buffer_size);
614
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
615 2 ret = gate_stream_print_cstr(target, buffer);
616 2 break;
617 2 case GATE_TYPE_DAYTIME:
618 2 gate_mem_copy(&dt.time, data, sizeof(gate_daytime_t));
619 2 ret = gate_date_to_string((gate_datetime_t const*)data, 0, "{hh}:{mm}:{ss}.{SSS}", buffer, &buffer_size);
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
621 2 ret = gate_stream_print_cstr(target, buffer);
622 2 break;
623 2 case GATE_TYPE_DATETIME:
624 2 ret = gate_date_to_string((gate_datetime_t const*)data, 0, NULL, buffer, &buffer_size);
625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
626 2 ret = gate_stream_print_cstr(target, buffer);
627 2 break;
628 2 case GATE_TYPE_TIME:
629 2 ret = gate_time_to_string((gate_time_t const*)data, NULL, buffer, &buffer_size);
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
631 2 ret = gate_stream_print_cstr(target, buffer);
632 2 break;
633 2 case GATE_TYPE_STRING:
634 2 ret = gate_stream_print_string(target, (gate_string_t const*)data);
635 2 break;
636 case GATE_TYPE_ARRAY:
637 ret = gate_stream_print_cstr(target, "{gate_array_t}");
638 break;
639
640 case GATE_TYPE_STRUCT:
641 ret = gate_stream_print_cstr(target, "{gate_struct_t}");
642 break;
643 case GATE_TYPE_OBJECT:
644 ret = gate_stream_print_cstr(target, "{gate_object_t}");
645 break;
646 case GATE_TYPE_PROPERTY:
647 ret = gate_stream_print_cstr(target, "{gate_property_t}");
648 break;
649 default:
650 {
651 if ((type & GATE_TYPE_ARRAYLIST) == GATE_TYPE_ARRAYLIST)
652 {
653 ret = gate_stream_print_cstr(target, "{gate_arraylist_t}");
654 }
655 else
656 {
657 ret = GATE_RESULT_NOTSUPPORTED;
658 }
659 break;
660 }
661 }
662 30 return ret;
663 }
664
665 15 static gate_result_t gate_util_print_indent(gate_stream_t* target, gate_size_t indent)
666 {
667 char buffer[4096];
668 15 gate_strbuilder_t builder = GATE_INIT_EMPTY;
669 gate_size_t lenused;
670 15 gate_size_t written = 0;
671
672 15 gate_strbuilder_create_static(&builder, buffer, sizeof(buffer), 0);
673 15 lenused = gate_strbuilder_append_chars(&builder, indent, '\t');
674 15 return gate_stream_write_block(target, buffer, lenused, &written);
675 }
676
677 1 static gate_result_t gate_util_struct_dump_to(gate_stream_t* target, void const* ptr_input_struct, gate_size_t indent)
678 {
679 1 gate_result_t ret = GATE_RESULT_OK;
680 1 gate_size_t const count = gate_struct_get_member_count(ptr_input_struct);
681 gate_size_t index;
682 gate_size_t arr_length;
683 gate_size_t arr_index;
684 gate_type_id_t arr_type;
685 void const* arr_item;
686
687
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
16 for (index = 0; index != count; ++index)
688 {
689 15 char const* name = gate_struct_get_member_name(ptr_input_struct, index);
690 15 gate_type_id_t type = gate_struct_get_member_type(ptr_input_struct, index);
691 15 void const* value = gate_struct_get_member(ptr_input_struct, index);
692
693 15 gate_util_print_indent(target, indent);
694 15 gate_stream_print_cstr(target, name);
695 15 gate_stream_print_cstr(target, " = ");
696
697
1/7
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
15 switch (type)
698 {
699 15 case GATE_TYPE_UI8:
700 case GATE_TYPE_UI16:
701 case GATE_TYPE_UI32:
702 case GATE_TYPE_UI64:
703 case GATE_TYPE_I8:
704 case GATE_TYPE_I16:
705 case GATE_TYPE_I32:
706 case GATE_TYPE_I64:
707 case GATE_TYPE_R32:
708 case GATE_TYPE_R64:
709 case GATE_TYPE_ADDRESS:
710 case GATE_TYPE_DATAPTR:
711 case GATE_TYPE_FUNCPTR:
712 case GATE_TYPE_CSTR:
713 case GATE_TYPE_WSTR:
714 case GATE_TYPE_GUID:
715 case GATE_TYPE_DATE:
716 case GATE_TYPE_DAYTIME:
717 case GATE_TYPE_DATETIME:
718 case GATE_TYPE_TIME:
719 case GATE_TYPE_STRING:
720 {
721 15 ret = gate_util_dump_type(target, type, value);
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 GATE_BREAK_IF_FAILED(ret);
723 15 ret = gate_stream_println_cstr(target, NULL);
724 15 break;
725 }
726 case GATE_TYPE_ARRAY:
727 {
728 ret = gate_stream_println_cstr(target, "{gate_array_t}");
729 break;
730 }
731 case GATE_TYPE_STRUCT:
732 {
733 ret = gate_stream_println_cstr(target, "{gate_struct_t}");
734 GATE_BREAK_IF_FAILED(ret);
735 ret = gate_util_struct_dump_to(target, value, indent + 1);
736 break;
737 }
738 case GATE_TYPE_OBJECT:
739 {
740 ret = gate_stream_println_cstr(target, "{gate_object_t}");
741 break;
742 }
743 case GATE_TYPE_PROPERTY:
744 {
745 ret = gate_stream_println_cstr(target, "{gate_property_t}");
746 break;
747 }
748 case GATE_TYPE_ARRAYLIST_STRUCT:
749 {
750 arr_length = gate_arraylist_length(*(gate_arraylist_t const*)value);
751 ret = gate_stream_println_cstr(target, "{gate_arraylist_t[gate_struct_t]}");
752 GATE_BREAK_IF_FAILED(ret);
753 for (arr_index = 0; arr_index != arr_length; ++arr_index)
754 {
755 arr_item = gate_arraylist_get(*(gate_arraylist_t const*)value, arr_index);
756 if (arr_item)
757 {
758 ret = gate_util_struct_dump_to(target, arr_item, indent + 1);
759 GATE_BREAK_IF_FAILED(ret);
760 }
761 }
762 break;
763 }
764 default:
765 {
766 if ((type & GATE_TYPE_ARRAYLIST) == GATE_TYPE_ARRAYLIST)
767 {
768 arr_type = (type & (~GATE_TYPE_ARRAYLIST));
769 arr_length = gate_arraylist_length(*(gate_arraylist_t const*)value);
770 ret = gate_stream_print_cstr(target, "{gate_arraylist_t[");
771 GATE_BREAK_IF_FAILED(ret);
772 ret = gate_stream_print_uint(target, arr_type);
773 GATE_BREAK_IF_FAILED(ret);
774 ret = gate_stream_println_cstr(target, "]}");
775 for (arr_index = 0; arr_index != arr_length; ++arr_index)
776 {
777 arr_item = gate_arraylist_get(*(gate_arraylist_t const*)value, arr_index);
778 if (arr_item)
779 {
780 ret = gate_util_print_indent(target, indent + 1);
781 GATE_BREAK_IF_FAILED(ret);
782 ret = gate_util_dump_type(target, arr_type, arr_item);
783 GATE_BREAK_IF_FAILED(ret);
784 ret = gate_stream_println_cstr(target, NULL);
785 GATE_BREAK_IF_FAILED(ret);
786 }
787 }
788 }
789 else
790 {
791 ret = gate_stream_print_cstr(target, "{unsupported_type_");
792 GATE_BREAK_IF_FAILED(ret);
793 ret = gate_stream_print_uint(target, type);
794 GATE_BREAK_IF_FAILED(ret);
795 ret = gate_stream_println_cstr(target, "}");
796 }
797 break;
798 }
799 } /* switch */
800 } /* for */
801 1 return ret;
802 }
803
804 1 gate_result_t gate_util_dump_struct(gate_stream_t* target, void const* ptr_input_struct)
805 {
806 1 return gate_util_struct_dump_to(target, ptr_input_struct, 0);
807 }
808
809
810 static gate_atomic_int_t global_state_init = 0;
811 static gate_mutex_t global_state_mutex;
812 static gate_synccondition_t global_state_signal;
813
814 2 static void close_state_objects_atexit(void)
815 {
816 2 gate_synccondition_destroy(&global_state_signal);
817 2 gate_mutex_destroy(&global_state_mutex);
818 2 gate_atomic_int_set(&global_state_init, 0);
819 2 }
820
821 10 static gate_result_t gate_util_state_init()
822 {
823 gate_result_t result;
824 gate_int32_t v;
825
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
10 if (2 == gate_atomic_int_get(&global_state_init))
826 {
827 8 return GATE_RESULT_OK;
828 }
829
830
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 while (2 != (v = gate_atomic_int_xchg_if(&global_state_init, 0, 1)))
831 {
832
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (v == 0)
833 {
834 2 result = gate_mutex_create(&global_state_mutex);
835
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(result))
836 {
837 gate_atomic_int_set(&global_state_init, 0);
838 return GATE_RESULT_OUTOFRESOURCES;
839 }
840 2 result = gate_synccondition_create(&global_state_signal);
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(result))
842 {
843 gate_mutex_destroy(&global_state_mutex);
844 gate_atomic_int_set(&global_state_init, 0);
845 return GATE_RESULT_OUTOFRESOURCES;
846 }
847 /* init succeeded */
848 2 gate_atomic_int_set(&global_state_init, 2);
849 2 gate_platform_atexit(&close_state_objects_atexit);
850 2 break;
851 }
852 else
853 {
854 /* spin until succeeded or fail-reset */
855 }
856 }
857 2 return GATE_RESULT_OK;
858 }
859
860 1 gate_result_t gate_util_state_set(gate_atomic_int_t* ptr_state, gate_int32_t value)
861 {
862 1 gate_result_t ret = gate_util_state_init();
863 do
864 {
865
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
866 1 ret = gate_mutex_acquire(&global_state_mutex);
867
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
868 1 gate_atomic_int_set(ptr_state, value);
869 1 ret = gate_synccondition_signal_all(&global_state_signal);
870 1 gate_mutex_release(&global_state_mutex);
871
872 } while (0);
873 1 return ret;
874 }
875 1 gate_result_t gate_util_state_update(gate_atomic_int_t* ptr_state, gate_int32_t from_value, gate_int32_t to_value)
876 {
877 gate_int32_t prev_value;
878 1 gate_result_t ret = gate_util_state_init();
879 do
880 {
881
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
882 1 ret = gate_mutex_acquire(&global_state_mutex);
883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
884 1 prev_value = gate_atomic_int_xchg_if(ptr_state, from_value, to_value);
885 1 ret = gate_synccondition_signal_all(&global_state_signal);
886
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
887 {
888
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (prev_value != from_value)
889 {
890 ret = GATE_RESULT_INVALIDSTATE;
891 }
892 }
893 1 gate_mutex_release(&global_state_mutex);
894
895 } while (0);
896 1 return ret;
897 }
898 8 gate_result_t gate_util_state_await(gate_atomic_int_t* ptr_state, gate_int32_t await_value, gate_uint32_t timeout_ms)
899 {
900 gate_timecounter_t now;
901 gate_timecounter_t timeout_time;
902 gate_int64_t diff;
903 8 gate_result_t ret = gate_util_state_init();
904 do
905 {
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
907 8 ret = gate_timecounter_now(&now);
908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
909 8 timeout_time = gate_timecounter_add(now, ((gate_int64_t)timeout_ms) * 1000);
910
911 8 ret = gate_mutex_acquire(&global_state_mutex);
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
913
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
8 while (gate_atomic_int_get(ptr_state) != await_value)
914 {
915 2 ret = gate_timecounter_now(&now);
916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
917
918 2 diff = gate_timecounter_diff(timeout_time, now);
919
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (diff <= 0)
920 {
921 2 ret = GATE_RESULT_TIMEOUT;
922 2 break;
923 }
924
925 ret = gate_synccondition_timed_wait(&global_state_signal, &global_state_mutex, timeout_ms);
926 if (ret == GATE_RESULT_TIMEOUT)
927 {
928 ret = GATE_RESULT_OK;
929 }
930 GATE_BREAK_IF_FAILED(ret);
931 }
932 8 gate_mutex_release(&global_state_mutex);
933 } while (0);
934 8 return ret;
935 }
936