GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/inifiles.c
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 292 357 81.8%
Functions: 22 22 100.0%
Branches: 98 163 60.1%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/encode/inifiles.h"
30 #include "gate/comparers.h"
31 #include "gate/results.h"
32 #include "gate/debugging.h"
33
34 95 static gate_flatmap_iterator_t gate_inifile_store_use_section(gate_inifile_store_t* store, gate_string_t const* section)
35 {
36 95 gate_flatmap_iterator_t iter = gate_flatmap_get(&store->sections, section);
37
38
2/2
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 55 times.
95 if (!gate_flatmap_iterator_valid(&store->sections, iter))
39 {
40 40 gate_flatmap_t content = GATE_INIT_EMPTY;
41
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 if (NULL != gate_flatmap_create(&content, &gate_compare_string,
42 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor,
43 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor))
44 {
45 40 iter = gate_flatmap_add(&store->sections, section, &content);
46
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (!iter)
47 {
48 gate_flatmap_destroy(&content);
49 }
50 }
51 }
52 95 return iter;
53 }
54
55 18 gate_result_t gate_inifile_store_create(gate_inifile_store_t* store)
56 {
57 18 gate_result_t ret = GATE_RESULT_FAILED;
58 gate_flatmap_iterator_t global_section_entry;
59 static gate_string_t const empty_string = GATE_STRING_INIT_EMPTY;
60
61 do
62 {
63 18 gate_mem_clear(store, sizeof(gate_inifile_store_t));
64
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if (NULL == gate_flatmap_create(&store->sections, &gate_compare_string,
65 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor,
66 sizeof(gate_flatmap_t), &gate_flatmap_copy_constructor, &gate_flatmap_destructor))
67 {
68 ret = GATE_RESULT_OUTOFMEMORY;
69 break;
70 }
71
72 18 global_section_entry = gate_inifile_store_use_section(store, &empty_string);
73
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (NULL == global_section_entry)
74 {
75 gate_flatmap_destroy(&store->sections);
76 ret = GATE_RESULT_OUTOFMEMORY;
77 break;
78 }
79
80 18 ret = GATE_RESULT_OK;
81 } while (0);
82
83 18 return ret;
84 }
85 2 gate_result_t gate_inifile_store_copy(gate_inifile_store_t* store, gate_inifile_store_t const* source)
86 {
87
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_flatmap_copy(&store->sections, &source->sections))
88 {
89 return GATE_RESULT_OUTOFMEMORY;
90 }
91 2 return GATE_RESULT_OK;
92 }
93
94
95 20 gate_result_t gate_inifile_store_destroy(gate_inifile_store_t* store)
96 {
97 20 gate_result_t ret = GATE_RESULT_FAILED;
98
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (store)
99 {
100 20 gate_flatmap_destroy(&store->sections);
101 20 ret = GATE_RESULT_OK;
102 }
103 20 return ret;
104 }
105
106
107 17 gate_result_t gate_inifile_store_add_section(gate_inifile_store_t* store, gate_string_t const* section)
108 {
109 17 gate_flatmap_iterator_t section_entry = gate_inifile_store_use_section(store, section);
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if (section_entry == NULL)
111 {
112 return GATE_RESULT_OUTOFMEMORY;
113 }
114 else
115 {
116 17 return GATE_RESULT_OK;
117 }
118 }
119 3 gate_result_t gate_inifile_store_remove_section(gate_inifile_store_t* store, gate_string_t const* section)
120 {
121
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 if (gate_flatmap_remove(&store->sections, section))
122 {
123 2 return GATE_RESULT_OK;
124 }
125 else
126 {
127 1 return GATE_RESULT_OK_UNCHANGED;
128 }
129 }
130 3 gate_result_t gate_inifile_store_list_sections(gate_inifile_store_t const* inistore, gate_array_t* sections)
131 {
132 3 gate_flatmap_iterator_t it = gate_flatmap_first(&inistore->sections);
133 3 gate_flatmap_iterator_t it_end = gate_flatmap_end(&inistore->sections);
134 3 gate_arraylist_t arr = gate_arraylist_create(sizeof(gate_string_t), NULL, 0, &gate_string_copy_constructor, &gate_string_destructor);
135 3 gate_array_t* ret = NULL;
136
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (arr == NULL)
138 {
139 return GATE_RESULT_OUTOFMEMORY;
140 }
141
142
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 3 times.
12 while (!gate_flatmap_iterator_equals(it, it_end))
143 {
144 9 gate_string_t const* const key = (gate_string_t const*)gate_flatmap_iterator_key(it);
145 9 gate_flatmap_t const* const value = (gate_flatmap_t const*)gate_flatmap_iterator_value(it);
146
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
9 if (gate_flatmap_count(value) > 0)
147 {
148 6 gate_arraylist_add(arr, key);
149 }
150 9 it = gate_flatmap_iterator_next(it);
151 }
152
153 3 ret = gate_array_create(sections, arr);
154 3 gate_arraylist_release(arr);
155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret == NULL)
156 {
157 return GATE_RESULT_OUTOFMEMORY;
158 }
159 3 return GATE_RESULT_OK;
160 }
161
162 5 gate_result_t gate_inifile_store_list_section_keys(gate_inifile_store_t const* inistore, gate_string_t const* section, gate_array_t* keys)
163 {
164 gate_result_t ret;
165 5 gate_arraylist_t arr = NULL;
166
167 do
168 {
169 gate_flatmap_iterator_t it, itend;
170 5 gate_flatmap_t const* const kv_map = (gate_flatmap_t const*)gate_flatmap_get_value(&inistore->sections, section);
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (kv_map == NULL)
172 {
173 ret = GATE_RESULT_NOMATCH;
174 break;
175 }
176
177 5 arr = gate_arraylist_create(sizeof(gate_string_t), NULL, 0, &gate_string_copy_constructor, &gate_string_destructor);
178
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (arr == NULL)
179 {
180 ret = GATE_RESULT_OUTOFMEMORY;
181 break;
182 }
183
184 5 it = gate_flatmap_first(kv_map);
185 5 itend = gate_flatmap_end(kv_map);
186
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 5 times.
15 while(!gate_flatmap_iterator_equals(it, itend))
187 {
188 10 gate_string_t const* const key = (gate_string_t const*)gate_flatmap_iterator_key(it);
189 10 gate_arraylist_add(arr, key);
190 10 it = gate_flatmap_iterator_next(it);
191 }
192
193
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 ret = (gate_array_create(keys, arr)) == NULL ? GATE_RESULT_OUTOFMEMORY : GATE_RESULT_OK;
194 } while (0);
195
196
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (arr != NULL)
197 {
198 5 gate_arraylist_release(arr);
199 }
200
201 5 return ret;
202 }
203
204
205 60 gate_result_t gate_inifile_store_set(gate_inifile_store_t* store, gate_string_t const* section,
206 gate_string_t const* key, gate_string_t const* value)
207 {
208 60 gate_result_t ret = GATE_RESULT_OK;
209
210 do
211 {
212 gate_flatmap_iterator_t section_entry;
213 gate_flatmap_t* entry_map;
214
215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (gate_string_is_empty(key))
216 {
217 /* a key MUST NOT be empty */
218 ret = GATE_RESULT_INVALIDARG;
219 break;
220 }
221 60 section_entry = gate_inifile_store_use_section(store, section);
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (NULL == section_entry)
223 {
224 /* failed to access or create section */
225 ret = GATE_RESULT_OUTOFMEMORY;
226 break;
227 }
228 60 entry_map = (gate_flatmap_t*)gate_flatmap_iterator_value(section_entry);
229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (NULL == entry_map)
230 {
231 /* section entry is invalid */
232 ret = GATE_RESULT_INVALIDCONTENT;
233 break;
234 }
235
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (NULL == gate_flatmap_add(entry_map, key, value))
236 {
237 /* failed to add */
238 ret = GATE_RESULT_OUTOFMEMORY;
239 break;
240 }
241 /* new value successfully attached */
242 60 ret = GATE_RESULT_OK;
243 } while (0);
244
245 60 return ret;
246 }
247 16 gate_result_t gate_inifile_store_get(gate_inifile_store_t const* store, gate_string_t const* section,
248 gate_string_t const* key, gate_string_t* return_value)
249 {
250 16 gate_result_t ret = GATE_RESULT_OK;
251
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 GATE_DEBUG_ASSERT(store != NULL);
252
253 do
254 {
255 16 gate_flatmap_iterator_t section_entry = gate_flatmap_get(&store->sections, section);
256 gate_flatmap_t* entry_map;
257 gate_flatmap_iterator_t entry_iter;
258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (NULL == section_entry)
259 {
260 /* failed to access or create section */
261 ret = GATE_RESULT_OUTOFMEMORY;
262 break;
263 }
264 16 entry_map = (gate_flatmap_t*)gate_flatmap_iterator_value(section_entry);
265
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (NULL == entry_map)
266 {
267 /* section entry is invalid */
268 ret = GATE_RESULT_INVALIDCONTENT;
269 break;
270 }
271 16 entry_iter = gate_flatmap_get(entry_map, key);
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (NULL == entry_iter)
273 {
274 /* key does not exist in section */
275 ret = GATE_RESULT_NOMATCH;
276 break;
277 }
278
279
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (NULL != return_value)
280 {
281
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (NULL == gate_string_duplicate(return_value, (gate_string_t const*)gate_flatmap_iterator_value(entry_iter)))
282 {
283 ret = GATE_RESULT_OUTOFMEMORY;
284 break;
285 }
286 }
287 /* value successfully retrieved */
288 16 ret = GATE_RESULT_OK;
289 } while (0);
290
291 16 return ret;
292 }
293
294 9 gate_result_t gate_inifile_store_remove(gate_inifile_store_t* store, gate_string_t const* section, gate_string_t const* key)
295 {
296 9 gate_result_t ret = GATE_RESULT_FAILED;
297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 GATE_DEBUG_ASSERT(store != NULL);
298
299 do
300 {
301 9 gate_flatmap_iterator_t section_entry = gate_flatmap_get(&store->sections, section);
302 gate_flatmap_t* entry_map;
303
304
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (NULL == section_entry)
305 {
306 /* failed to access or create section */
307 1 ret = GATE_RESULT_NOMATCH;
308 1 break;
309 }
310 8 entry_map = (gate_flatmap_t*)gate_flatmap_iterator_value(section_entry);
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (NULL == entry_map)
312 {
313 /* section entry is invalid */
314 ret = GATE_RESULT_INVALIDCONTENT;
315 break;
316 }
317
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_flatmap_remove(entry_map, key))
318 {
319 /* entry key does not exist */
320 ret = GATE_RESULT_NOMATCH;
321 break;
322 }
323
324 /* entry successfully removed */
325 8 ret = GATE_RESULT_OK;
326 } while (0);
327
328 9 return ret;
329 }
330
331
332
333
334
335 15 gate_result_t gate_inifile_store_load(gate_inifile_store_t* inistore, gate_stream_t* input)
336 {
337 15 gate_result_t ret = GATE_RESULT_FAILED;
338 15 gate_string_t current_section = GATE_STRING_INIT_EMPTY;
339 char buffer[8192];
340 15 gate_uint64_t comment_counter = 0;
341 15 char comment_id[128] = ";;;;;;;;;;;;;;;;";
342 gate_size_t linelen;
343 15 gate_string_t comment_key = GATE_STRING_INIT_EMPTY;
344 15 gate_string_t current_line = GATE_STRING_INIT_EMPTY;
345 15 gate_string_t current_key = GATE_STRING_INIT_EMPTY;
346 15 gate_string_t current_value = GATE_STRING_INIT_EMPTY;
347 gate_size_t pos;
348 gate_char8_t chr;
349 gate_char8_t chr_last;
350
351 do
352 {
353 15 ret = GATE_RESULT_OK;
354
1/2
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
98 while (GATE_SUCCEEDED(ret))
355 {
356 98 ret = gate_stream_read_line(input, buffer, sizeof(buffer), &linelen);
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 GATE_BREAK_IF_FAILED(ret);
358
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 83 times.
98 if (linelen == 0)
359 {
360 /* end of stream reached */
361 15 break;
362 }
363
364 83 gate_string_create_static_len(&current_line, buffer, linelen);
365 83 gate_string_rtrim(&current_line, &current_line);
366 83 gate_string_ltrim(&current_line, &current_line);
367
368
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 59 times.
83 if (gate_string_is_empty(&current_line))
369 {
370 24 continue;
371 }
372
373 59 chr = gate_string_char_at(&current_line, 0);
374
2/3
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
59 switch (chr)
375 {
376 15 case '[':
377 {
378 /* new section */
379 15 chr_last = gate_string_char_at(&current_line, gate_string_length(&current_line) - 1);
380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (chr_last != ']')
381 {
382 ret = GATE_RESULT_INVALIDINPUT;
383 break;
384 }
385 15 gate_string_release(&current_section);
386
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 15 times.
15 if (NULL == gate_string_create(&current_section, gate_string_ptr(&current_line, 1), gate_string_length(&current_line) - 2))
387 {
388 ret = GATE_RESULT_OUTOFMEMORY;
389 break;
390 }
391 15 ret = gate_inifile_store_add_section(inistore, &current_section);
392 15 break;
393 }
394 case '#':
395 case ';':
396 {
397 /* comment line */
398 gate_str_print_uint64(&comment_id[1], sizeof(comment_id) - 1, ++comment_counter);
399 gate_string_create_static(&comment_key, comment_id);
400 gate_inifile_store_set(inistore, &current_section, &comment_key, &current_line);
401 gate_string_release(&comment_key);
402 break;
403 }
404 44 default:
405 {
406 /* key-value entry */
407 44 pos = gate_string_char_pos(&current_line, '=', 0);
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (pos == GATE_STR_NPOS)
409 {
410 gate_string_duplicate(&current_key, &current_line);
411 gate_string_create_empty(&current_value);
412 }
413 else
414 {
415 44 gate_string_substr(&current_key, &current_line, 0, pos);
416 44 gate_string_rtrim(&current_key, &current_key);
417 44 gate_string_substr(&current_value, &current_line, pos + 1, GATE_STR_NPOS);
418 44 gate_string_ltrim(&current_value, &current_value);
419 }
420 44 ret = gate_inifile_store_set(inistore, &current_section, &current_key, &current_value);
421 44 gate_string_release(&current_value);
422 44 gate_string_release(&current_key);
423 44 break;
424 }
425 }
426 59 gate_string_release(&current_line);
427 }
428
429 } while (0);
430
431 15 gate_string_release(&current_section);
432
433 15 return ret;
434 }
435
436 11 gate_result_t gate_inifile_store_save(gate_inifile_store_t const* inistore, gate_stream_t* output)
437 {
438 11 gate_result_t ret = GATE_RESULT_FAILED;
439 gate_flatmap_iterator_t section_iter;
440 gate_flatmap_iterator_t entry_iter;
441 gate_string_t const* ptr_section_name;
442 gate_flatmap_t const* ptr_section_content;
443 gate_string_t const* ptr_key;
444 gate_string_t const* ptr_value;
445 gate_size_t entry_count;
446
447 do
448 {
449 11 section_iter = gate_flatmap_first(&inistore->sections);
450
2/2
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 11 times.
34 while (gate_flatmap_iterator_valid(&inistore->sections, section_iter))
451 {
452 23 ptr_section_name = (gate_string_t const*)gate_flatmap_iterator_key(section_iter);
453 23 ptr_section_content = (gate_flatmap_t const*)gate_flatmap_iterator_value(section_iter);
454
2/4
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
23 if (ptr_section_name && ptr_section_content)
455 {
456
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 11 times.
23 if (!gate_string_is_empty(ptr_section_name))
457 {
458 12 gate_stream_print(output,
459 GATE_PRINT_CHAR, '[',
460 GATE_PRINT_STRING, ptr_section_name,
461 GATE_PRINT_CHAR, ']',
462 GATE_PRINT_NEWLINE,
463 GATE_PRINT_END);
464 }
465 23 entry_count = gate_flatmap_count(ptr_section_content);
466
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 7 times.
23 if (entry_count > 0)
467 {
468 16 entry_iter = gate_flatmap_first(ptr_section_content);
469
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 16 times.
44 while (gate_flatmap_iterator_valid(ptr_section_content, entry_iter))
470 {
471 28 ptr_key = (gate_string_t const*)gate_flatmap_iterator_key(entry_iter);
472 28 ptr_value = (gate_string_t const*)gate_flatmap_iterator_value(entry_iter);
473
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (gate_string_starts_with_char(ptr_key, ';'))
474 {
475 gate_stream_print(output,
476 GATE_PRINT_STRING, ptr_value,
477 GATE_PRINT_NEWLINE,
478 GATE_PRINT_END);
479 }
480 else
481 {
482 28 gate_stream_print(output,
483 GATE_PRINT_STRING, ptr_key,
484 GATE_PRINT_CSTR, " = ",
485 GATE_PRINT_STRING, ptr_value,
486 GATE_PRINT_NEWLINE,
487 GATE_PRINT_END);
488 }
489 28 entry_iter = gate_flatmap_iterator_next(entry_iter);
490 }
491 16 gate_stream_print(output,
492 GATE_PRINT_NEWLINE,
493 GATE_PRINT_END);
494 }
495 }
496 23 section_iter = gate_flatmap_iterator_next(section_iter);
497 }
498 11 ret = GATE_RESULT_OK;
499 } while (0);
500
501 11 return ret;
502 }
503
504 6 static gate_result_t gate_inifile_store_import_tree(gate_inifile_store_t* inistore, gate_property_t const* property_tree, gate_string_t const* section)
505 {
506 6 gate_result_t ret = GATE_RESULT_FAILED;
507 gate_size_t count, ndx;
508 6 gate_array_t names = GATE_INIT_EMPTY;
509 gate_string_t const* ptr_name;
510 gate_property_t const* ptr_prop;
511 gate_property_typeid_t prop_type;
512 gate_string_t prop_value;
513 gate_strbuilder_t builder;
514 gate_string_t sub_section;
515
516 do
517 {
518
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (NULL == gate_property_member_names(property_tree, &names))
519 {
520 ret = GATE_RESULT_OUTOFMEMORY;
521 break;
522 }
523 6 count = gate_array_length(&names);
524 6 ret = GATE_RESULT_OK;
525
3/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 6 times.
18 for (ndx = 0; GATE_SUCCEEDED(ret) && (ndx != count); ++ndx)
526 {
527 12 ptr_name = (gate_string_t const*)gate_array_get(&names, ndx);
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!ptr_name)
529 {
530 continue;
531 }
532 12 ptr_prop = gate_property_member_get(property_tree, ptr_name);
533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!ptr_prop)
534 {
535 continue;
536 }
537 12 prop_type = gate_property_get_type(ptr_prop);
538
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
12 switch (prop_type)
539 {
540 8 case GATE_PROPERTY_TYPE_BOOL:
541 case GATE_PROPERTY_TYPE_INT:
542 case GATE_PROPERTY_TYPE_REAL:
543 case GATE_PROPERTY_TYPE_STRING:
544 {
545 8 ret = gate_property_get_string(ptr_prop, &prop_value);
546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
547 8 ret = gate_inifile_store_set(inistore, section, ptr_name, &prop_value);
548 8 gate_string_release(&prop_value);
549 8 break;
550 }
551 case GATE_PROPERTY_TYPE_ARRAY:
552 {
553 break;
554 }
555 4 case GATE_PROPERTY_TYPE_OBJECT:
556 {
557 4 gate_strbuilder_create(&builder, 0);
558 4 gate_strbuilder_append_string(&builder, section);
559
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (gate_strbuilder_length(&builder) != 0)
560 {
561 gate_strbuilder_append_cstr(&builder, "/");
562 }
563 4 gate_strbuilder_append_string(&builder, ptr_name);
564
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (NULL == gate_strbuilder_to_string(&builder, &sub_section))
565 {
566 ret = GATE_RESULT_OUTOFMEMORY;
567 }
568 4 gate_strbuilder_release(&builder);
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
570 4 ret = gate_inifile_store_import_tree(inistore, ptr_prop, &sub_section);
571 4 gate_string_release(&sub_section);
572 4 break;
573 }
574 }
575 12 }
576
577 } while (0);
578
579 6 gate_array_release(&names);
580
581 6 return ret;
582 }
583
584 2 gate_result_t gate_inifile_store_import(gate_inifile_store_t* inistore, gate_property_t const* property_tree)
585 {
586 2 gate_string_t section = GATE_STRING_INIT_EMPTY;
587
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_property_get_type(property_tree) != GATE_PROPERTY_TYPE_OBJECT)
588 {
589 return GATE_RESULT_INVALIDINPUT;
590 }
591 else
592 {
593 2 return gate_inifile_store_import_tree(inistore, property_tree, &section);
594 }
595 }
596
597 4 static gate_property_t* select_sub_property(gate_property_t* root, gate_string_t const* path)
598 {
599 4 gate_property_t* cur_prop = root;
600 gate_string_t cur_path;
601 4 gate_bool_t continue_loop = true;
602
603 /* path = "item1/item2/item3" */
604
605
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (NULL == gate_string_duplicate(&cur_path, path))
606 {
607 return NULL;
608 }
609
610
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 while(continue_loop)
611 {
612 gate_string_t parent_name;
613 gate_string_t subtree_path;
614 gate_property_t* child_prop;
615
616 4 gate_size_t pos = gate_string_char_pos(&cur_path, '/', 0);
617
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (pos == GATE_STR_NPOS)
618 {
619 4 continue_loop = false;
620
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (gate_string_is_empty(&cur_path))
621 {
622 break;
623 }
624 }
625
626 4 gate_string_substr(&parent_name, &cur_path, 0, pos);
627 4 gate_string_substr(&subtree_path, &cur_path, pos + 1, GATE_STR_NPOS);
628 4 child_prop = (gate_property_t*)gate_property_member_get(cur_prop, &parent_name);
629
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (child_prop == NULL)
630 {
631 gate_property_t obj;
632 4 gate_property_create_object(&obj);
633 4 child_prop = gate_property_member_add(cur_prop, &parent_name, &obj);
634 4 gate_property_destroy(&obj);
635 }
636 4 cur_prop = child_prop;
637 4 gate_string_release(&parent_name);
638 4 gate_string_release(&cur_path);
639 4 gate_mem_copy(&cur_path, &subtree_path, sizeof(cur_path));
640 }
641
642 4 gate_string_release(&cur_path);
643 4 return cur_prop;
644 }
645
646 4 static gate_result_t generate_property_entries(gate_inifile_store_t const* inistore, gate_string_t const* section, gate_property_t* property_tree)
647 {
648 gate_result_t ret;
649 4 gate_array_t keys = GATE_INIT_EMPTY;
650 do
651 {
652 4 gate_property_t* target_prop = NULL;
653 4 ret = gate_inifile_store_list_section_keys(inistore, section, &keys);
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
655
656 4 target_prop = select_sub_property(property_tree, section);
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(NULL == target_prop)
658 {
659 ret = GATE_RESULT_FAILED;
660 break;
661 }
662 else
663 {
664 gate_size_t ndx;
665 4 gate_size_t const cnt = gate_array_length(&keys);
666
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for(ndx = 0; ndx != cnt; ++ndx)
667 {
668 8 gate_string_t const* key = (gate_string_t const*)gate_array_get(&keys, ndx);
669 8 gate_string_t value = GATE_STRING_INIT_EMPTY;
670 gate_property_t prop;
671 8 ret = gate_inifile_store_get(inistore, section, key, &value);
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (GATE_FAILED(ret))
673 {
674 continue;
675 }
676
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if(NULL != gate_property_create_string(&prop, &value))
677 {
678 8 gate_property_member_add(target_prop, key, &prop);
679 8 gate_property_destroy(&prop);
680 }
681 8 gate_string_release(&value);
682 }
683 }
684
685 } while (0);
686
687 4 gate_array_release(&keys);
688 4 return ret;
689 }
690
691 2 gate_result_t gate_inifile_store_export(gate_inifile_store_t const* inistore, gate_property_t* property_tree)
692 {
693 gate_result_t ret;
694 2 gate_array_t sections = GATE_INIT_EMPTY;
695
696
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(inistore != NULL);
697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(property_tree != NULL);
698
699 2 gate_property_create_empty(property_tree);
700 do
701 {
702 gate_size_t ndx, cnt;
703 2 ret = gate_inifile_store_list_sections(inistore, &sections);
704
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
705
706
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if(NULL == gate_property_create_object(property_tree))
707 {
708 ret = GATE_RESULT_OUTOFMEMORY;
709 break;
710 }
711
712 2 ret = GATE_RESULT_OK;
713 2 cnt = gate_array_length(&sections);
714
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (ndx = 0; ndx != cnt; ++ndx)
715 {
716 4 gate_string_t const* section = (gate_string_t const*)gate_array_get(&sections, ndx);
717 4 ret = generate_property_entries(inistore, section, property_tree);
718
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
719 }
720
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(GATE_FAILED(ret))
721 {
722 gate_property_destroy(property_tree);
723 }
724 } while (0);
725
726 2 gate_array_release(&sections);
727 2 return ret;
728 }
729
730 1 gate_result_t gate_inifile_parse_string(gate_string_t const* source, gate_property_t* property_tree)
731 {
732 1 gate_memstream_impl_t mem_stream = GATE_INIT_EMPTY;
733 1 char const* ptr_src = gate_string_ptr(source, 0);
734 1 gate_size_t len_src = gate_string_length(source);
735 1 gate_memstream_create_static_unmanaged_readonly(&mem_stream, ptr_src, len_src, len_src);
736 1 return gate_inifile_parse((gate_stream_t*)&mem_stream, property_tree);
737 }
738
739 1 gate_result_t gate_inifile_build_string(gate_property_t const* property_tree, gate_strbuilder_t* dest_builder)
740 {
741 gate_result_t ret;
742 1 gate_stringstream_t* stream = gate_stringstream_create_builder(dest_builder);
743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == stream)
744 {
745 ret = GATE_RESULT_OUTOFMEMORY;
746 }
747 else
748 {
749 1 ret = gate_inifile_build(property_tree, (gate_stream_t*)stream);
750 1 gate_object_release(stream);
751 }
752 1 return ret;
753 }
754
755 2 gate_result_t gate_inifile_parse(gate_stream_t* source, gate_property_t* property_tree)
756 {
757 2 gate_result_t ret = GATE_RESULT_FAILED;
758 2 gate_inifile_store_t store = GATE_INIT_EMPTY;
759 do
760 {
761 2 ret = gate_inifile_store_create(&store);
762
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
763
764 2 ret = gate_inifile_store_load(&store, source);
765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
766
767 2 ret = gate_inifile_store_export(&store, property_tree);
768 } while (0);
769
770 2 gate_inifile_store_destroy(&store);
771
772 2 return ret;
773 }
774 2 gate_result_t gate_inifile_build(gate_property_t const* property_tree, gate_stream_t* output)
775 {
776 2 gate_result_t ret = GATE_RESULT_FAILED;
777 2 gate_inifile_store_t store = GATE_INIT_EMPTY;
778 do
779 {
780 2 ret = gate_inifile_store_create(&store);
781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
782
783 2 ret = gate_inifile_store_import(&store, property_tree);
784
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
785
786 2 ret = gate_inifile_store_save(&store, output);
787 } while (0);
788
789 2 gate_inifile_store_destroy(&store);
790
791 2 return ret;
792 }
793