GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/inifiles.c
Date: 2026-10-19 17:06:30
Exec Total Coverage
Lines: 291 356 81.7%
Functions: 22 22 100.0%
Branches: 97 161 60.2%

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 1 not taken.
✓ Branch 2 taken 3 times.
3 if (gate_arraylist_is_null(arr))
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 = GATE_INIT_EMPTY;
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 1 not taken.
✓ Branch 2 taken 5 times.
5 if (gate_arraylist_is_null(arr))
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 5 gate_arraylist_release(&arr);
197 5 return ret;
198 }
199
200
201 60 gate_result_t gate_inifile_store_set(gate_inifile_store_t* store, gate_string_t const* section,
202 gate_string_t const* key, gate_string_t const* value)
203 {
204 60 gate_result_t ret = GATE_RESULT_OK;
205
206 do
207 {
208 gate_flatmap_iterator_t section_entry;
209 gate_flatmap_t* entry_map;
210
211
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (gate_string_is_empty(key))
212 {
213 /* a key MUST NOT be empty */
214 ✗ ret = GATE_RESULT_INVALIDARG;
215 ✗ break;
216 }
217 60 section_entry = gate_inifile_store_use_section(store, section);
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (NULL == section_entry)
219 {
220 /* failed to access or create section */
221 ✗ ret = GATE_RESULT_OUTOFMEMORY;
222 ✗ break;
223 }
224 60 entry_map = (gate_flatmap_t*)gate_flatmap_iterator_value(section_entry);
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (NULL == entry_map)
226 {
227 /* section entry is invalid */
228 ✗ ret = GATE_RESULT_INVALIDCONTENT;
229 ✗ break;
230 }
231
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
60 if (NULL == gate_flatmap_add(entry_map, key, value))
232 {
233 /* failed to add */
234 ✗ ret = GATE_RESULT_OUTOFMEMORY;
235 ✗ break;
236 }
237 /* new value successfully attached */
238 60 ret = GATE_RESULT_OK;
239 } while (0);
240
241 60 return ret;
242 }
243 16 gate_result_t gate_inifile_store_get(gate_inifile_store_t const* store, gate_string_t const* section,
244 gate_string_t const* key, gate_string_t* return_value)
245 {
246 16 gate_result_t ret = GATE_RESULT_OK;
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 GATE_DEBUG_ASSERT(store != NULL);
248
249 do
250 {
251 16 gate_flatmap_iterator_t section_entry = gate_flatmap_get(&store->sections, section);
252 gate_flatmap_t* entry_map;
253 gate_flatmap_iterator_t entry_iter;
254
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (!gate_flatmap_iterator_valid(&store->sections, section_entry))
255 {
256 /* failed to access or create section */
257 ✗ ret = GATE_RESULT_OUTOFMEMORY;
258 ✗ break;
259 }
260 16 entry_map = (gate_flatmap_t*)gate_flatmap_iterator_value(section_entry);
261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (NULL == entry_map)
262 {
263 /* section entry is invalid */
264 ✗ ret = GATE_RESULT_INVALIDCONTENT;
265 ✗ break;
266 }
267 16 entry_iter = gate_flatmap_get(entry_map, key);
268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (!gate_flatmap_iterator_valid(entry_map, entry_iter))
269 {
270 /* key does not exist in section */
271 ✗ ret = GATE_RESULT_NOMATCH;
272 ✗ break;
273 }
274
275
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (NULL != return_value)
276 {
277
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)))
278 {
279 ✗ ret = GATE_RESULT_OUTOFMEMORY;
280 ✗ break;
281 }
282 }
283 /* value successfully retrieved */
284 16 ret = GATE_RESULT_OK;
285 } while (0);
286
287 16 return ret;
288 }
289
290 9 gate_result_t gate_inifile_store_remove(gate_inifile_store_t* store, gate_string_t const* section, gate_string_t const* key)
291 {
292 9 gate_result_t ret = GATE_RESULT_FAILED;
293
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 GATE_DEBUG_ASSERT(store != NULL);
294
295 do
296 {
297 gate_flatmap_t* entry_map;
298 9 gate_flatmap_iterator_t section_entry = gate_flatmap_get(&store->sections, section);
299
300
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8 times.
9 if (!gate_flatmap_iterator_valid(&store->sections, section_entry))
301 {
302 /* failed to access or create section */
303 1 ret = GATE_RESULT_NOMATCH;
304 1 break;
305 }
306 8 entry_map = (gate_flatmap_t*)gate_flatmap_iterator_value(section_entry);
307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (NULL == entry_map)
308 {
309 /* section entry is invalid */
310 ✗ ret = GATE_RESULT_INVALIDCONTENT;
311 ✗ break;
312 }
313
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_flatmap_remove(entry_map, key))
314 {
315 /* entry key does not exist */
316 ✗ ret = GATE_RESULT_NOMATCH;
317 ✗ break;
318 }
319
320 /* entry successfully removed */
321 8 ret = GATE_RESULT_OK;
322 } while (0);
323
324 9 return ret;
325 }
326
327
328
329
330
331 15 gate_result_t gate_inifile_store_load(gate_inifile_store_t* inistore, gate_stream_t* input)
332 {
333 15 gate_result_t ret = GATE_RESULT_FAILED;
334 15 gate_string_t current_section = GATE_STRING_INIT_EMPTY;
335 char buffer[8192];
336 15 gate_uint64_t comment_counter = 0;
337 15 char comment_id[128] = ";;;;;;;;;;;;;;;;";
338 gate_size_t linelen;
339 15 gate_string_t comment_key = GATE_STRING_INIT_EMPTY;
340 15 gate_string_t current_line = GATE_STRING_INIT_EMPTY;
341 15 gate_string_t current_key = GATE_STRING_INIT_EMPTY;
342 15 gate_string_t current_value = GATE_STRING_INIT_EMPTY;
343 gate_size_t pos;
344 gate_char8_t chr;
345 gate_char8_t chr_last;
346
347 do
348 {
349 15 ret = GATE_RESULT_OK;
350
1/2
✓ Branch 0 taken 98 times.
✗ Branch 1 not taken.
98 while (GATE_SUCCEEDED(ret))
351 {
352 98 ret = gate_stream_read_line(input, buffer, sizeof(buffer), &linelen);
353
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 GATE_BREAK_IF_FAILED(ret);
354
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 83 times.
98 if (linelen == 0)
355 {
356 /* end of stream reached */
357 15 break;
358 }
359
360 83 gate_string_create_static_len(&current_line, buffer, linelen);
361 83 gate_string_rtrim(&current_line, &current_line);
362 83 gate_string_ltrim(&current_line, &current_line);
363
364
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 59 times.
83 if (gate_string_is_empty(&current_line))
365 {
366 24 continue;
367 }
368
369 59 chr = gate_string_char_at(&current_line, 0);
370
2/3
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
59 switch (chr)
371 {
372 15 case '[':
373 {
374 /* new section */
375 15 chr_last = gate_string_char_at(&current_line, gate_string_length(&current_line) - 1);
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 if (chr_last != ']')
377 {
378 ✗ ret = GATE_RESULT_INVALIDINPUT;
379 ✗ break;
380 }
381 15 gate_string_release(&current_section);
382
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))
383 {
384 ✗ ret = GATE_RESULT_OUTOFMEMORY;
385 ✗ break;
386 }
387 15 ret = gate_inifile_store_add_section(inistore, &current_section);
388 15 break;
389 }
390 ✗ case '#':
391 case ';':
392 {
393 /* comment line */
394 ✗ gate_str_print_uint64(&comment_id[1], sizeof(comment_id) - 1, ++comment_counter);
395 ✗ gate_string_create_static(&comment_key, comment_id);
396 ✗ gate_inifile_store_set(inistore, &current_section, &comment_key, &current_line);
397 ✗ gate_string_release(&comment_key);
398 ✗ break;
399 }
400 44 default:
401 {
402 /* key-value entry */
403 44 pos = gate_string_char_pos(&current_line, '=', 0);
404
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (pos == GATE_STR_NPOS)
405 {
406 ✗ gate_string_duplicate(&current_key, &current_line);
407 ✗ gate_string_create_empty(&current_value);
408 }
409 else
410 {
411 44 gate_string_substr(&current_key, &current_line, 0, pos);
412 44 gate_string_rtrim(&current_key, &current_key);
413 44 gate_string_substr(&current_value, &current_line, pos + 1, GATE_STR_NPOS);
414 44 gate_string_ltrim(&current_value, &current_value);
415 }
416 44 ret = gate_inifile_store_set(inistore, &current_section, &current_key, &current_value);
417 44 gate_string_release(&current_value);
418 44 gate_string_release(&current_key);
419 44 break;
420 }
421 }
422 59 gate_string_release(&current_line);
423 }
424
425 } while (0);
426
427 15 gate_string_release(&current_section);
428
429 15 return ret;
430 }
431
432 11 gate_result_t gate_inifile_store_save(gate_inifile_store_t const* inistore, gate_stream_t* output)
433 {
434 11 gate_result_t ret = GATE_RESULT_FAILED;
435 gate_flatmap_iterator_t section_iter;
436 gate_flatmap_iterator_t entry_iter;
437 gate_string_t const* ptr_section_name;
438 gate_flatmap_t const* ptr_section_content;
439 gate_string_t const* ptr_key;
440 gate_string_t const* ptr_value;
441 gate_size_t entry_count;
442
443 do
444 {
445 11 section_iter = gate_flatmap_first(&inistore->sections);
446
2/2
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 11 times.
34 while (gate_flatmap_iterator_valid(&inistore->sections, section_iter))
447 {
448 23 ptr_section_name = (gate_string_t const*)gate_flatmap_iterator_key(section_iter);
449 23 ptr_section_content = (gate_flatmap_t const*)gate_flatmap_iterator_value(section_iter);
450
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)
451 {
452
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 11 times.
23 if (!gate_string_is_empty(ptr_section_name))
453 {
454 12 gate_stream_print(output,
455 GATE_PRINT_CHAR, '[',
456 GATE_PRINT_STRING, ptr_section_name,
457 GATE_PRINT_CHAR, ']',
458 GATE_PRINT_NEWLINE,
459 GATE_PRINT_END);
460 }
461 23 entry_count = gate_flatmap_count(ptr_section_content);
462
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 7 times.
23 if (entry_count > 0)
463 {
464 16 entry_iter = gate_flatmap_first(ptr_section_content);
465
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 16 times.
44 while (gate_flatmap_iterator_valid(ptr_section_content, entry_iter))
466 {
467 28 ptr_key = (gate_string_t const*)gate_flatmap_iterator_key(entry_iter);
468 28 ptr_value = (gate_string_t const*)gate_flatmap_iterator_value(entry_iter);
469
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (gate_string_starts_with_char(ptr_key, ';'))
470 {
471 ✗ gate_stream_print(output,
472 GATE_PRINT_STRING, ptr_value,
473 GATE_PRINT_NEWLINE,
474 GATE_PRINT_END);
475 }
476 else
477 {
478 28 gate_stream_print(output,
479 GATE_PRINT_STRING, ptr_key,
480 GATE_PRINT_CSTR, " = ",
481 GATE_PRINT_STRING, ptr_value,
482 GATE_PRINT_NEWLINE,
483 GATE_PRINT_END);
484 }
485 28 entry_iter = gate_flatmap_iterator_next(entry_iter);
486 }
487 16 gate_stream_print(output,
488 GATE_PRINT_NEWLINE,
489 GATE_PRINT_END);
490 }
491 }
492 23 section_iter = gate_flatmap_iterator_next(section_iter);
493 }
494 11 ret = GATE_RESULT_OK;
495 } while (0);
496
497 11 return ret;
498 }
499
500 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)
501 {
502 6 gate_result_t ret = GATE_RESULT_FAILED;
503 gate_size_t count, ndx;
504 6 gate_array_t names = GATE_INIT_EMPTY;
505 gate_string_t const* ptr_name;
506 gate_property_t const* ptr_prop;
507 gate_property_typeid_t prop_type;
508 gate_string_t prop_value;
509 gate_strbuilder_t builder;
510 gate_string_t sub_section;
511
512 do
513 {
514
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (NULL == gate_property_member_names(property_tree, &names))
515 {
516 ✗ ret = GATE_RESULT_OUTOFMEMORY;
517 ✗ break;
518 }
519 6 count = gate_array_length(&names);
520 6 ret = GATE_RESULT_OK;
521
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)
522 {
523 12 ptr_name = (gate_string_t const*)gate_array_get(&names, ndx);
524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!ptr_name)
525 {
526 ✗ continue;
527 }
528 12 ptr_prop = gate_property_member_get(property_tree, ptr_name);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (!ptr_prop)
530 {
531 ✗ continue;
532 }
533 12 prop_type = gate_property_get_type(ptr_prop);
534
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
12 switch (prop_type)
535 {
536 8 case GATE_PROPERTY_TYPE_BOOL:
537 case GATE_PROPERTY_TYPE_INT:
538 case GATE_PROPERTY_TYPE_REAL:
539 case GATE_PROPERTY_TYPE_STRING:
540 {
541 8 ret = gate_property_get_string(ptr_prop, &prop_value);
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
543 8 ret = gate_inifile_store_set(inistore, section, ptr_name, &prop_value);
544 8 gate_string_release(&prop_value);
545 8 break;
546 }
547 ✗ case GATE_PROPERTY_TYPE_ARRAY:
548 {
549 ✗ break;
550 }
551 4 case GATE_PROPERTY_TYPE_OBJECT:
552 {
553 4 gate_strbuilder_create(&builder, 0);
554 4 gate_strbuilder_append_string(&builder, section);
555
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (gate_strbuilder_length(&builder) != 0)
556 {
557 ✗ gate_strbuilder_append_cstr(&builder, "/");
558 }
559 4 gate_strbuilder_append_string(&builder, ptr_name);
560
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (NULL == gate_strbuilder_to_string(&builder, &sub_section))
561 {
562 ✗ ret = GATE_RESULT_OUTOFMEMORY;
563 }
564 4 gate_strbuilder_release(&builder);
565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
566 4 ret = gate_inifile_store_import_tree(inistore, ptr_prop, &sub_section);
567 4 gate_string_release(&sub_section);
568 4 break;
569 }
570 }
571 12 }
572
573 } while (0);
574
575 6 gate_array_release(&names);
576
577 6 return ret;
578 }
579
580 2 gate_result_t gate_inifile_store_import(gate_inifile_store_t* inistore, gate_property_t const* property_tree)
581 {
582 2 gate_string_t section = GATE_STRING_INIT_EMPTY;
583
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_property_get_type(property_tree) != GATE_PROPERTY_TYPE_OBJECT)
584 {
585 ✗ return GATE_RESULT_INVALIDINPUT;
586 }
587 else
588 {
589 2 return gate_inifile_store_import_tree(inistore, property_tree, &section);
590 }
591 }
592
593 4 static gate_property_t* select_sub_property(gate_property_t* root, gate_string_t const* path)
594 {
595 4 gate_property_t* cur_prop = root;
596 gate_string_t cur_path;
597 4 gate_bool_t continue_loop = true;
598
599 /* path = "item1/item2/item3" */
600
601
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (NULL == gate_string_duplicate(&cur_path, path))
602 {
603 ✗ return NULL;
604 }
605
606
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 while(continue_loop)
607 {
608 gate_string_t parent_name;
609 gate_string_t subtree_path;
610 gate_property_t* child_prop;
611
612 4 gate_size_t pos = gate_string_char_pos(&cur_path, '/', 0);
613
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (pos == GATE_STR_NPOS)
614 {
615 4 continue_loop = false;
616
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (gate_string_is_empty(&cur_path))
617 {
618 ✗ break;
619 }
620 }
621
622 4 gate_string_substr(&parent_name, &cur_path, 0, pos);
623 4 gate_string_substr(&subtree_path, &cur_path, pos + 1, GATE_STR_NPOS);
624 4 child_prop = (gate_property_t*)gate_property_member_get(cur_prop, &parent_name);
625
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (child_prop == NULL)
626 {
627 gate_property_t obj;
628 4 gate_property_create_object(&obj);
629 4 child_prop = gate_property_member_add(cur_prop, &parent_name, &obj);
630 4 gate_property_destroy(&obj);
631 }
632 4 cur_prop = child_prop;
633 4 gate_string_release(&parent_name);
634 4 gate_string_release(&cur_path);
635 4 gate_mem_copy(&cur_path, &subtree_path, sizeof(cur_path));
636 }
637
638 4 gate_string_release(&cur_path);
639 4 return cur_prop;
640 }
641
642 4 static gate_result_t generate_property_entries(gate_inifile_store_t const* inistore, gate_string_t const* section, gate_property_t* property_tree)
643 {
644 gate_result_t ret;
645 4 gate_array_t keys = GATE_INIT_EMPTY;
646 do
647 {
648 4 gate_property_t* target_prop = NULL;
649 4 ret = gate_inifile_store_list_section_keys(inistore, section, &keys);
650
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
651
652 4 target_prop = select_sub_property(property_tree, section);
653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(NULL == target_prop)
654 {
655 ✗ ret = GATE_RESULT_FAILED;
656 ✗ break;
657 }
658 else
659 {
660 gate_size_t ndx;
661 4 gate_size_t const cnt = gate_array_length(&keys);
662
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 for(ndx = 0; ndx != cnt; ++ndx)
663 {
664 8 gate_string_t const* key = (gate_string_t const*)gate_array_get(&keys, ndx);
665 8 gate_string_t value = GATE_STRING_INIT_EMPTY;
666 gate_property_t prop;
667 8 ret = gate_inifile_store_get(inistore, section, key, &value);
668
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (GATE_FAILED(ret))
669 {
670 ✗ continue;
671 }
672
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if(NULL != gate_property_create_string(&prop, &value))
673 {
674 8 gate_property_member_add(target_prop, key, &prop);
675 8 gate_property_destroy(&prop);
676 }
677 8 gate_string_release(&value);
678 }
679 }
680
681 } while (0);
682
683 4 gate_array_release(&keys);
684 4 return ret;
685 }
686
687 2 gate_result_t gate_inifile_store_export(gate_inifile_store_t const* inistore, gate_property_t* property_tree)
688 {
689 gate_result_t ret;
690 2 gate_array_t sections = GATE_INIT_EMPTY;
691
692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(inistore != NULL);
693
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_DEBUG_ASSERT(property_tree != NULL);
694
695 2 gate_property_create_empty(property_tree);
696 do
697 {
698 gate_size_t ndx, cnt;
699 2 ret = gate_inifile_store_list_sections(inistore, &sections);
700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
701
702
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if(NULL == gate_property_create_object(property_tree))
703 {
704 ✗ ret = GATE_RESULT_OUTOFMEMORY;
705 ✗ break;
706 }
707
708 2 ret = GATE_RESULT_OK;
709 2 cnt = gate_array_length(&sections);
710
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 for (ndx = 0; ndx != cnt; ++ndx)
711 {
712 4 gate_string_t const* section = (gate_string_t const*)gate_array_get(&sections, ndx);
713 4 ret = generate_property_entries(inistore, section, property_tree);
714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
715 }
716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(GATE_FAILED(ret))
717 {
718 ✗ gate_property_destroy(property_tree);
719 }
720 } while (0);
721
722 2 gate_array_release(&sections);
723 2 return ret;
724 }
725
726 1 gate_result_t gate_inifile_parse_string(gate_string_t const* source, gate_property_t* property_tree)
727 {
728 1 gate_memstream_impl_t mem_stream = GATE_INIT_EMPTY;
729 1 char const* ptr_src = gate_string_ptr(source, 0);
730 1 gate_size_t len_src = gate_string_length(source);
731 1 gate_memstream_create_static_unmanaged_readonly(&mem_stream, ptr_src, len_src, len_src);
732 1 return gate_inifile_parse((gate_stream_t*)&mem_stream, property_tree);
733 }
734
735 1 gate_result_t gate_inifile_build_string(gate_property_t const* property_tree, gate_strbuilder_t* dest_builder)
736 {
737 gate_result_t ret;
738 1 gate_stringstream_t* stream = gate_stringstream_create_builder(dest_builder);
739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == stream)
740 {
741 ✗ ret = GATE_RESULT_OUTOFMEMORY;
742 }
743 else
744 {
745 1 ret = gate_inifile_build(property_tree, (gate_stream_t*)stream);
746 1 gate_object_release(stream);
747 }
748 1 return ret;
749 }
750
751 2 gate_result_t gate_inifile_parse(gate_stream_t* source, gate_property_t* property_tree)
752 {
753 2 gate_result_t ret = GATE_RESULT_FAILED;
754 2 gate_inifile_store_t store = GATE_INIT_EMPTY;
755 do
756 {
757 2 ret = gate_inifile_store_create(&store);
758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
759
760 2 ret = gate_inifile_store_load(&store, source);
761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
762
763 2 ret = gate_inifile_store_export(&store, property_tree);
764 } while (0);
765
766 2 gate_inifile_store_destroy(&store);
767
768 2 return ret;
769 }
770 2 gate_result_t gate_inifile_build(gate_property_t const* property_tree, gate_stream_t* output)
771 {
772 2 gate_result_t ret = GATE_RESULT_FAILED;
773 2 gate_inifile_store_t store = GATE_INIT_EMPTY;
774 do
775 {
776 2 ret = gate_inifile_store_create(&store);
777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
778
779 2 ret = gate_inifile_store_import(&store, property_tree);
780
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
781
782 2 ret = gate_inifile_store_save(&store, output);
783 } while (0);
784
785 2 gate_inifile_store_destroy(&store);
786
787 2 return ret;
788 }
789