GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/yaml.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 638 824 77.4%
Functions: 28 28 100.0%
Branches: 257 462 55.6%

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/yaml.h"
30 #include "gate/results.h"
31 #include "gate/mathematics.h"
32 #include "gate/debugging.h"
33
34 static gate_string_t const indention_chars = GATE_STRING_INIT_STATIC(" \t");
35
36 #define LINE_TYPE_UNKNOWN 0
37 #define LINE_TYPE_EMPTY 1
38 #define LINE_TYPE_VALUE 2
39 #define LINE_TYPE_KEY 3 /* key-only entry, eg. "'key':" */
40 #define LINE_TYPE_MEMBER 4 /* key-value entry, eg. "'key': 'value'" */
41 #define LINE_TYPE_ARRAY_VALUE 5 /* array entry value, eg. "- 'value'" */
42 #define LINE_TYPE_ARRAY_KEY 6 /* array entry key-only, eg. "- 'key':" */
43 #define LINE_TYPE_ARRAY_MEMBER 7 /* array entry key-value, eg. "- 'key': 'value'" */
44
45
46 static char const* gate_yaml_bool_true_values[] =
47 {
48 "y", "Y", "yes", "Yes", "YES",
49 "true", "True", "TRUE",
50 "on", "On", "ON"
51 };
52
53 static char const* gate_yaml_bool_false_values[] =
54 {
55 "n", "N", "no", "No", "NO",
56 "false", "False", "FALSE",
57 "off", "Off", "OFF"
58 };
59
60 26 static gate_bool_t is_yaml_bool_true(gate_string_t const* str)
61 {
62 gate_size_t index;
63 26 gate_size_t len = sizeof(gate_yaml_bool_true_values) / sizeof(gate_yaml_bool_true_values[0]);
64
2/2
✓ Branch 0 taken 276 times.
✓ Branch 1 taken 24 times.
300 for (index = 0; index != len; ++index)
65 {
66
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 274 times.
276 if (gate_string_equals_str(str, gate_yaml_bool_true_values[index]))
67 {
68 2 return true;
69 }
70 }
71 24 return false;
72 }
73 24 static gate_bool_t is_yaml_bool_false(gate_string_t const* str)
74 {
75 gate_size_t index;
76 24 gate_size_t len = sizeof(gate_yaml_bool_false_values) / sizeof(gate_yaml_bool_false_values[0]);
77
2/2
✓ Branch 0 taken 254 times.
✓ Branch 1 taken 22 times.
276 for (index = 0; index != len; ++index)
78 {
79
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 252 times.
254 if (gate_string_equals_str(str, gate_yaml_bool_false_values[index]))
80 {
81 2 return true;
82 }
83 }
84 22 return false;
85 }
86 22 static gate_bool_t is_yaml_int(gate_string_t const* str, gate_int64_t* int_value)
87 {
88 22 gate_size_t len_parsed = gate_str_parse_int64(str->str, str->length, int_value);
89 22 return (len_parsed == str->length);
90 }
91 10 static gate_bool_t is_yaml_real(gate_string_t const* str, gate_real64_t* real_value)
92 {
93 10 gate_size_t len_parsed = gate_str_parse_real(str->str, str->length, real_value);
94 10 return (len_parsed == str->length);
95 }
96
97
98 8 static gate_size_t parse_quoted_string(gate_string_t const* source, gate_string_t* text)
99 {
100 8 gate_size_t parsed = 0;
101 8 gate_strbuilder_t builder = GATE_INIT_EMPTY;
102
103 do
104 {
105 8 char const* ptr = gate_string_ptr(source, 0);
106 8 gate_size_t len = gate_string_length(source);
107 8 char quote_char = *ptr;
108 8 ++ptr;
109 8 --len;
110 8 ++parsed;
111
112 8 gate_strbuilder_create(&builder, len);
113
114
1/2
✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
114 while (len != 0)
115 {
116
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 105 times.
114 if (*ptr == '\\')
117 {
118 9 ++ptr;
119 9 --len;
120 9 ++parsed;
121
6/9
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
9 switch (*ptr)
122 {
123 1 case '\\':
124 1 gate_strbuilder_append_chars(&builder, 1, '\\');
125 1 break;
126 2 case '\"':
127 2 gate_strbuilder_append_chars(&builder, 1, '\"');
128 2 break;
129 case '\'':
130 gate_strbuilder_append_chars(&builder, 1, '\'');
131 break;
132 2 case 'r':
133 2 gate_strbuilder_append_chars(&builder, 1, '\r');
134 2 break;
135 2 case 'n':
136 2 gate_strbuilder_append_chars(&builder, 1, '\n');
137 2 break;
138 1 case 't':
139 1 gate_strbuilder_append_chars(&builder, 1, '\t');
140 1 break;
141 case 'v':
142 gate_strbuilder_append_chars(&builder, 1, '\v');
143 break;
144 case 'b':
145 gate_strbuilder_append_chars(&builder, 1, '\b');
146 break;
147 1 default:
148 1 gate_strbuilder_append_chars(&builder, 1, '\\');
149 1 gate_strbuilder_append_chars(&builder, 1, *ptr);
150 1 break;
151 }
152 }
153 else
154 {
155
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 97 times.
105 if (*ptr == quote_char)
156 {
157 /* end of string reached */
158 8 ++parsed;
159 8 break;
160 }
161 else
162 {
163 97 gate_strbuilder_append_chars(&builder, 1, *ptr);
164 }
165 }
166
167 106 ++ptr;
168 106 --len;
169 106 ++parsed;
170 }
171 } while (0);
172
173
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (NULL == gate_strbuilder_to_string(&builder, text))
174 {
175 parsed = 0;
176 }
177 8 gate_strbuilder_release(&builder);
178
179 8 return parsed;
180 }
181
182 36 static gate_size_t skip_whitespaces(gate_string_t* text)
183 {
184 static gate_string_t const white_spaces = GATE_STRING_INIT_STATIC(GATE_STR_WHITESPACES);
185 36 gate_size_t ret = gate_string_find_first_not_of(text, &white_spaces, 0);
186
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 31 times.
36 if (ret == GATE_STR_NPOS)
187 {
188 5 ret = gate_string_length(text);
189 5 gate_string_release(text);
190 }
191 else
192 {
193 31 gate_string_substr(text, text, ret, GATE_STR_NPOS);
194 }
195 36 return ret;
196 }
197
198 static gate_size_t gate_yaml_parse_inline_object(gate_string_t const* token, gate_property_t* prop);
199 static gate_size_t gate_yaml_parse_inline_array(gate_string_t* token, gate_property_t* prop);
200
201 #define YAML_LOG_SETRET_BREAK(error_msg) \
202 GATE_DEBUG_TRACE( error_msg ); \
203 ret = 0; \
204 break;
205
206 #define YAML_BREAK_ON_ERROR(error_condition, error_msg) \
207 if ( error_condition ) \
208 { \
209 YAML_LOG_SETRET_BREAK( error_msg ); \
210 }
211
212
213 11 static gate_size_t gate_yaml_parse_inline_item(gate_string_t const* token, gate_property_t* prop, gate_string_t const* terminator_chars)
214 {
215 11 gate_size_t ret = 0;
216 11 gate_string_t text = GATE_STRING_INIT_EMPTY;
217 11 gate_string_t value = GATE_STRING_INIT_EMPTY;
218
219 do
220 {
221 11 gate_size_t pos = 0;
222 char chr;
223
224 11 gate_string_duplicate(&text, token);
225 11 ret += skip_whitespaces(&text);
226
227
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 if (gate_string_is_empty(&text))
228 {
229 ret = 0;
230 break;
231 }
232 11 chr = gate_string_char_at(&text, 0);
233
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
11 if ((chr == '\"') || (chr == '\''))
234 1 {
235 /* quoted string */
236 gate_property_t* ptr_prop;
237 1 pos = parse_quoted_string(&text, &value);
238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 YAML_BREAK_ON_ERROR((pos == 0), "Failed to parse quoted YAML string");
239 1 ptr_prop = gate_property_create_string(prop, &value);
240
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 YAML_BREAK_ON_ERROR(NULL == ptr_prop, "Failed to create string property object");
241 1 ret += pos;
242 }
243
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 7 times.
10 else if (chr == '{')
244 {
245 /* inline object */
246 3 pos = gate_yaml_parse_inline_object(&text, prop);
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 YAML_BREAK_ON_ERROR((pos == 0), "Failed to parse inline YAML object");
248 3 ret += pos;
249 }
250
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 else if (chr == '[')
251 {
252 /* inline array */
253 3 pos = gate_yaml_parse_inline_array(&text, prop);
254
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 YAML_BREAK_ON_ERROR((pos == 0), "Failed to parse inline YAML array");
255 3 ret += pos;
256 }
257 else
258 {
259 /* primitive elment */
260 4 gate_int64_t i64 = 0;
261 4 gate_real64_t r64 = 0.0;
262
263 4 pos = gate_string_find_first_of(&text, terminator_chars, 0);
264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pos == GATE_STR_NPOS)
265 {
266 /* possibly the last element in document */
267 pos = gate_string_length(&text);
268 }
269 4 gate_string_substr(&value, &text, 0, pos);
270 4 ret += pos;
271 4 gate_string_trim(&value, &value);
272
273
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (is_yaml_bool_true(&value))
274 {
275 gate_property_t* ptr_prop = gate_property_create_bool(prop, true);
276 YAML_BREAK_ON_ERROR((NULL == ptr_prop), "Failed to create bool property ojbect");
277 }
278
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 else if (is_yaml_bool_false(&value))
279 {
280 gate_property_t* ptr_prop = gate_property_create_bool(prop, false);
281 YAML_BREAK_ON_ERROR((NULL == ptr_prop), "Failed to create bool property ojbect");
282 }
283
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 else if (is_yaml_int(&value, &i64))
284 {
285 4 gate_property_t* const ptr_prop = gate_property_create_int(prop, i64);
286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 YAML_BREAK_ON_ERROR((NULL == ptr_prop), "Failed to create integer property ojbect");
287 }
288 else if (is_yaml_real(&value, &r64))
289 {
290 gate_property_t* const ptr_prop = gate_property_create_real(prop, r64);
291 YAML_BREAK_ON_ERROR((NULL == ptr_prop), "Failed to create real property ojbect");
292 }
293 else
294 {
295 /* OK, it is just a string */
296 gate_property_t* const ptr_prop = gate_property_create_string(prop, &value);
297 YAML_BREAK_ON_ERROR((NULL == ptr_prop), "Failed to create string property ojbect");
298 }
299 }
300 } while (0);
301
302 11 gate_string_release(&text);
303 11 gate_string_release(&value);
304
305 11 return ret;
306 }
307
308 3 static gate_size_t gate_yaml_parse_inline_object(gate_string_t const* token, gate_property_t* prop)
309 {
310 static gate_string_t obj_item_terminator_chars = GATE_STRING_INIT_STATIC(",}");
311 3 gate_size_t ret = 0;
312 3 gate_string_t text = GATE_STRING_INIT_EMPTY;
313 3 gate_string_t member_name = GATE_STRING_INIT_EMPTY;
314 3 gate_string_t member_value = GATE_STRING_INIT_EMPTY;
315 3 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
316 gate_bool_t succeeded;
317 gate_bool_t tmp_empty;
318 3 gate_property_t member_prop = GATE_INIT_EMPTY;
319 gate_size_t pos;
320 3 gate_string_duplicate(&text, token);
321
322 3 ret += skip_whitespaces(&text);
323
324 do
325 {
326 3 gate_mem_clear(prop, sizeof(gate_property_t));
327
328
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!gate_string_starts_with_char(&text, '{'))
329 {
330 /* token does not start with object indicator */
331 YAML_LOG_SETRET_BREAK("Missing YAML object indicator");
332 }
333 3 gate_string_substr(&text, &text, 1, GATE_STR_NPOS);
334 3 ++ret;
335
336
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_property_create_object(prop))
337 {
338 /* failed to create property object */
339 YAML_LOG_SETRET_BREAK("Failed to create object property object");
340 }
341
342 for (;;)
343 {
344 3 ret += skip_whitespaces(&text);
345
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (gate_string_is_empty(&text))
346 {
347 /* missing object content */
348 YAML_LOG_SETRET_BREAK("Missing YAML object content");
349 }
350
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 if (gate_string_starts_with_char(&text, '}'))
351 {
352 /* end of object reached */
353 2 ++ret;
354 2 break;
355 }
356
357 /* parse key:*/
358
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_starts_with_char(&text, '\"'))
359 {
360 1 pos = parse_quoted_string(&text, &member_name);
361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 YAML_BREAK_ON_ERROR((pos == 0), "Failed to parse quoted YAML string");
362 1 ret += pos;
363 1 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
364 1 pos = gate_string_char_pos(&text, ':', 0);
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 YAML_BREAK_ON_ERROR((pos == GATE_STR_NPOS), "Missing YAML object key/value separator");
366 1 gate_string_substr(&text, &text, pos + 1, GATE_STR_NPOS);
367 1 ret += (pos + 1);
368 }
369 else
370 {
371 pos = gate_string_char_pos(&text, ':', 0);
372 YAML_BREAK_ON_ERROR((pos == GATE_STR_NPOS), "Missing YAML object key/value separator");
373 gate_string_substr(&member_name, &text, 0, pos);
374 gate_string_substr(&text, &text, pos + 1, GATE_STR_NPOS);
375 ret += (pos + 1);
376 }
377
378 /* parse value: */
379 1 ret += skip_whitespaces(&text);
380 1 pos = gate_yaml_parse_inline_item(&text, &member_prop, &obj_item_terminator_chars);
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 YAML_BREAK_ON_ERROR((pos == 0), "Failed to parse YAML object member value");
382 1 ret += pos;
383 1 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
384
385 1 succeeded = (NULL != gate_property_member_add(prop, &member_name, &member_prop));
386 1 gate_string_release(&member_name);
387 1 gate_property_destroy(&member_prop);
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!succeeded)
389 {
390 /* failed to add new property to object */
391 YAML_LOG_SETRET_BREAK("Failed to add key/value member to property object");
392 }
393
394 1 pos = gate_string_find_first_of(&text, &obj_item_terminator_chars, 0);
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos == GATE_STR_NPOS)
396 {
397 /* broken object -> corruption */
398 YAML_LOG_SETRET_BREAK("Missing YAML object member seperator or terminator");
399 }
400 1 gate_string_substr(&tmp, &text, 0, pos);
401 1 ret += pos;
402 1 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
403
404 1 skip_whitespaces(&tmp);
405 1 tmp_empty = gate_string_is_empty(&tmp);
406 1 gate_string_release(&tmp);
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tmp_empty)
408 {
409 /* no non-whitespace-chars allowed until terminator chars show up */
410 YAML_LOG_SETRET_BREAK("Unexpected characters after YAML member value detected");
411 }
412
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_starts_with_char(&text, '}'))
413 {
414 /* end of object reached */
415 1 ++ret;
416 1 break;
417 }
418 if (!gate_string_starts_with_char(&text, ','))
419 {
420 /* object corrupted */
421 YAML_LOG_SETRET_BREAK("Missing YAML object member separator");
422 }
423 else
424 {
425 /* another key/value pair is showing up */
426 ++ret;
427 gate_string_substr(&text, &text, 1, GATE_STR_NPOS);
428 }
429 }
430 } while (0);
431
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret == 0)
433 {
434 gate_property_destroy(prop);
435 }
436
437 3 gate_string_release(&tmp);
438 3 gate_string_release(&member_name);
439 3 gate_string_release(&member_value);
440 3 gate_property_destroy(&member_prop);
441 3 gate_string_release(&text);
442 3 return ret;
443 }
444 3 static gate_size_t gate_yaml_parse_inline_array(gate_string_t* token, gate_property_t* prop)
445 {
446 static gate_string_t arr_item_terminator_chars = GATE_STRING_INIT_STATIC(",]");
447 3 gate_size_t ret = 0;
448 3 gate_string_t text = GATE_STRING_INIT_EMPTY;
449 3 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
450 gate_bool_t succeeded;
451 gate_bool_t tmp_empty;
452 3 gate_property_t item_prop = GATE_INIT_EMPTY;
453 gate_size_t pos;
454 3 gate_string_duplicate(&text, token);
455
456 3 ret += skip_whitespaces(&text);
457
458 do
459 {
460 3 gate_mem_clear(prop, sizeof(gate_property_t));
461
462
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!gate_string_starts_with_char(&text, '['))
463 {
464 /* token does not start with an array indicator */
465 YAML_LOG_SETRET_BREAK("Missing YAML array indicator");
466 }
467 3 gate_string_substr(&text, &text, 1, GATE_STR_NPOS);
468 3 ++ret;
469
470
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_property_create_array(prop, NULL, 0))
471 {
472 YAML_LOG_SETRET_BREAK("Failed to create array property object");
473 }
474
475 for (;;)
476 {
477 6 ret += skip_whitespaces(&text);
478
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (gate_string_is_empty(&text))
479 {
480 /* missing array content */
481 YAML_LOG_SETRET_BREAK("Missing YAML array content");
482 }
483
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (gate_string_starts_with_char(&text, ']'))
484 {
485 /* end of array reached */
486 2 ++ret;
487 2 break;
488 }
489
490 /* parse value: */
491 4 ret += skip_whitespaces(&text);
492 4 pos = gate_yaml_parse_inline_item(&text, &item_prop, &arr_item_terminator_chars);
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pos == 0)
494 {
495 /* failed to parse member property */
496 YAML_LOG_SETRET_BREAK("Failed to parse YAML array item");
497 }
498 4 ret += pos;
499 4 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
500
501 4 succeeded = (NULL != gate_property_array_add(prop, &item_prop));
502 4 gate_property_destroy(&item_prop);
503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!succeeded)
504 {
505 /* failed to add new item to array */
506 YAML_LOG_SETRET_BREAK("Failed to add item to array property object");
507 }
508
509 4 pos = gate_string_find_first_of(&text, &arr_item_terminator_chars, 0);
510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pos == GATE_STR_NPOS)
511 {
512 /* broken array -> corruption */
513 YAML_LOG_SETRET_BREAK("Missing YAML array item separator or terminator");
514 }
515 4 gate_string_substr(&tmp, &text, 0, pos);
516 4 ret += pos;
517 4 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
518
519 4 skip_whitespaces(&tmp);
520 4 tmp_empty = gate_string_is_empty(&tmp);
521 4 gate_string_release(&tmp);
522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tmp_empty)
523 {
524 /* no non-whitespace-chars allowed until terminator chars show up */
525 YAML_LOG_SETRET_BREAK("Unexpected characters after YAML array item detected");
526 }
527
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if (gate_string_starts_with_char(&text, ']'))
528 {
529 /* end of object reached */
530 1 ++ret;
531 1 break;
532 }
533
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!gate_string_starts_with_char(&text, ','))
534 {
535 /* object corrupted */
536 YAML_LOG_SETRET_BREAK("Missing YAML array separator");
537 }
538 else
539 {
540 /* another key/value pair is showing up */
541 3 ++ret;
542 3 gate_string_substr(&text, &text, 1, GATE_STR_NPOS);
543 }
544 }
545 } while (0);
546
547
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret == 0)
548 {
549 gate_property_destroy(prop);
550 }
551
552 3 gate_string_release(&tmp);
553 3 gate_property_destroy(&item_prop);
554 3 gate_string_release(&text);
555 3 return ret;
556 }
557
558 63 static gate_property_t* gate_yaml_parse_entry(gate_string_t* line, gate_property_t* prop, gate_bool_t* incomplete)
559 {
560 static gate_string_t end_of_line = GATE_STRING_INIT_STATIC("\n");
561 63 gate_property_t* ret = NULL;
562 63 gate_string_t text = GATE_STRING_INIT_EMPTY;
563 63 gate_property_t subprop = GATE_INIT_EMPTY;
564 gate_size_t parsed;
565 gate_size_t pos;
566 63 gate_bool_t valueonly = false;
567 63 gate_bool_t keyonly = false;
568 63 gate_bool_t keyvalue = false;
569 63 gate_bool_t subprop_incomplete = false;
570 63 gate_bool_t quoted_value = false;
571 63 gate_int64_t i64 = 0;
572 63 gate_real64_t r64 = 0.0;
573 do
574 {
575 63 gate_string_ltrim(line, line);
576
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
63 if (gate_string_is_empty(line))
577 {
578 GATE_DEBUG_TRACE("Missing YAML line content");
579 /* error, nothing to parse */
580 break;
581 }
582
583
4/4
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 57 times.
63 if (gate_string_starts_with_char(line, '{') || gate_string_starts_with_char(line, '['))
584 {
585 /* inline object or inline array */
586 6 *incomplete = false;
587 6 pos = gate_yaml_parse_inline_item(line, prop, &end_of_line);
588
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pos == 0)
589 {
590 GATE_DEBUG_TRACE("Failed to parse inline YAML entry");
591 ret = NULL;
592 }
593 else
594 {
595 6 ret = prop;
596 }
597 6 break;
598 }
599
600
4/4
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 5 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 51 times.
57 if (gate_string_starts_with_char(line, '\"') || gate_string_starts_with_char(line, '\''))
601 {
602 /* quoted string */
603 6 parsed = parse_quoted_string(line, &text);
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (parsed == 0)
605 {
606 GATE_DEBUG_TRACE("Failed to parse quoted YAML string");
607 break;
608 }
609 6 gate_string_substr(line, line, parsed, GATE_STR_NPOS);
610 6 gate_string_ltrim(line, line);
611
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
12 if (gate_string_starts_with_char(line, ':'))
612 {
613 /* key - value pair: */
614 1 gate_string_substr(line, line, 1, GATE_STR_NPOS);
615 1 gate_string_ltrim(line, line);
616
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_string_is_empty(line))
617 {
618 keyonly = true;
619 }
620 else
621 {
622
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_yaml_parse_entry(line, &subprop, &subprop_incomplete))
623 {
624 GATE_DEBUG_TRACE("Failed to parse YAML entry member value");
625 /* error case: failed to parse sub-property */
626 break;
627 }
628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (subprop_incomplete)
629 {
630 GATE_DEBUG_TRACE("Incomplete sub property dtected");
631 /* error case: sub-property is incomplete*/
632 break;
633 }
634 1 keyvalue = true;
635 }
636 }
637 else
638 {
639 /* value-only */
640 5 valueonly = true;
641 5 quoted_value = true;
642 }
643 }
644 else
645 {
646 51 pos = gate_string_char_pos(line, ':', 0);
647
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 29 times.
51 if (pos == GATE_STR_NPOS)
648 {
649 22 gate_string_duplicate(&text, line);
650 22 valueonly = true;
651 /* value only */
652 }
653 else
654 {
655 29 gate_string_substr(&text, line, 0, pos);
656 29 gate_string_ltrim(&text, &text);
657 29 gate_string_substr(line, line, pos + 1, GATE_STR_NPOS);
658 29 gate_string_ltrim(line, line);
659
660
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 22 times.
29 if (gate_string_is_empty(line))
661 {
662 7 keyonly = true;
663 }
664 else
665 {
666
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (NULL == gate_yaml_parse_entry(line, &subprop, &subprop_incomplete))
667 {
668 GATE_DEBUG_TRACE("Failed to parse YAML entry member value");
669 /* error case: failed to parse sub-property */
670 break;
671 }
672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (subprop_incomplete)
673 {
674 GATE_DEBUG_TRACE("Incomplete sub property dtected");
675 /* error case: sub-property is incomplete*/
676 break;
677 }
678 22 keyvalue = true;
679 }
680 }
681 }
682
683 57 *incomplete = keyonly;
684
685
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 30 times.
57 if (valueonly)
686 {
687
1/3
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 switch (gate_property_get_type(prop))
688 {
689 case GATE_PROPERTY_TYPE_ARRAY:
690 {
691 GATE_DEBUG_TRACE("Internal error, property of type array detected");
692 /* error case: arrays are handled outside */
693 break;
694 }
695 case GATE_PROPERTY_TYPE_OBJECT:
696 {
697 GATE_DEBUG_TRACE("Internal error, property of type object detected");
698 /* error case: cannot attach value-only to object*/
699 break;
700 }
701 27 default:
702 {
703 27 gate_property_destroy(prop);
704
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 22 times.
27 if (quoted_value)
705 {
706 5 ret = gate_property_create_string(prop, &text);
707 }
708 else
709 {
710
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
22 if (is_yaml_bool_true(&text))
711 {
712 2 ret = gate_property_create_bool(prop, true);
713 }
714
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
20 else if (is_yaml_bool_false(&text))
715 {
716 2 ret = gate_property_create_bool(prop, false);
717 }
718
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
18 else if (is_yaml_int(&text, &i64))
719 {
720 8 ret = gate_property_create_int(prop, i64);
721 }
722
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
10 else if (is_yaml_real(&text, &r64))
723 {
724 2 ret = gate_property_create_real(prop, r64);
725 }
726 else
727 {
728 8 ret = gate_property_create_string(prop, &text);
729 }
730 }
731
732 27 break;
733 }
734 }
735 }
736
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
30 else if (keyonly || keyvalue)
737 {
738
1/3
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
30 switch (gate_property_get_type(prop))
739 {
740 case GATE_PROPERTY_TYPE_ARRAY:
741 {
742 GATE_DEBUG_TRACE("Internal error, property of type array detected");
743 /* error case: arrays are handled outside */
744 break;
745 }
746 case GATE_PROPERTY_TYPE_OBJECT:
747 {
748 ret = gate_property_member_add(prop, &text, &subprop);
749 break;
750 }
751 30 default:
752 {
753 30 gate_property_destroy(prop);
754 30 ret = gate_property_create_object(prop);
755
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (ret != NULL)
756 {
757
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (NULL == gate_property_member_add(prop, &text, &subprop))
758 {
759 gate_property_destroy(prop);
760 ret = NULL;
761 }
762 }
763 30 break;
764 }
765 }
766 }
767 else
768 {
769 /* error case: unsupported behavior */
770 break;
771 }
772 } while (0);
773
774 63 gate_string_release(&text);
775 63 gate_property_destroy(&subprop);
776 63 return ret;
777 }
778
779 41 static gate_result_t gate_yaml_parse_indent(gate_string_t* line, gate_uint16_t* indent)
780 {
781 41 gate_result_t ret = GATE_RESULT_FAILED;
782 41 gate_size_t const pos = gate_string_find_first_not_of(line, &indention_chars, 0);
783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (pos == GATE_STR_NPOS)
784 {
785 /* impossible, should be detected by is_empty() */
786 GATE_DEBUG_TRACE("Internal error, missing indention");
787 ret = GATE_RESULT_CRITICALERROR;
788 }
789 else
790 {
791 41 *indent = (gate_uint16_t)pos;
792 41 gate_string_substr(line, line, pos, GATE_STR_NPOS);
793 41 ret = GATE_RESULT_OK;
794 }
795 41 return ret;
796 }
797
798
799 #define GATE_YAML_MAX_LEVELS 64
800 #define GATE_YAML_UNKNOWN_INDENTION ((gate_uint16_t)(-1))
801
802 33 static gate_result_t gate_yaml_merge_properties(gate_property_t* target, gate_property_t const* source, gate_bool_t source_is_array_entry)
803 {
804 33 gate_result_t ret = GATE_RESULT_FAILED;
805 33 gate_uint32_t target_type = gate_property_get_type(target);
806 33 gate_uint32_t source_type = gate_property_get_type(source);
807 gate_size_t index;
808 gate_size_t len;
809 33 gate_array_t name_array = GATE_INIT_EMPTY;
810 gate_property_t const* ptr_prop;
811
812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (source_type == GATE_PROPERTY_TYPE_EMPTY)
813 {
814 /* nothing to do */
815 ret = GATE_RESULT_OK;
816 }
817
3/6
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
33 switch (target_type)
818 {
819 8 case GATE_PROPERTY_TYPE_EMPTY:
820 {
821
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 if (source_is_array_entry)
822 {
823
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_property_create_array(target, source, 1))
824 {
825 ret = GATE_RESULT_OUTOFMEMORY;
826 }
827 else
828 {
829 3 ret = GATE_RESULT_OK;
830 }
831 }
832 else
833 {
834
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (NULL == gate_property_copy(target, source))
835 {
836 ret = GATE_RESULT_OUTOFMEMORY;
837 }
838 else
839 {
840 5 ret = GATE_RESULT_OK;
841 }
842 }
843 8 break;
844 }
845 case GATE_PROPERTY_TYPE_BOOL:
846 case GATE_PROPERTY_TYPE_INT:
847 case GATE_PROPERTY_TYPE_REAL:
848 {
849 if (source_type == target_type)
850 {
851 if (NULL == gate_property_copy(target, source))
852 {
853 ret = GATE_RESULT_OUTOFMEMORY;
854 }
855 else
856 {
857 ret = GATE_RESULT_OK;
858 }
859 }
860 else
861 {
862 ret = GATE_RESULT_INCORRECTTYPE;
863 }
864 break;
865 }
866 case GATE_PROPERTY_TYPE_STRING:
867 {
868 if (source_type == target_type)
869 {
870 ret = gate_property_set_string(target, &source->data.string_value);
871 }
872 else
873 {
874 ret = GATE_RESULT_INCORRECTTYPE;
875 }
876 break;
877 }
878 7 case GATE_PROPERTY_TYPE_ARRAY:
879 {
880
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if (!source_is_array_entry && (source_type == GATE_PROPERTY_TYPE_OBJECT))
881 {
882 /* this might be an additional object member entry for the previously added object */
883 len = gate_property_array_length(target);
884 if (len > 0)
885 {
886 ptr_prop = gate_property_array_get(target, len - 1);
887 if (ptr_prop)
888 {
889 if (gate_property_get_type(ptr_prop) == GATE_PROPERTY_TYPE_OBJECT)
890 {
891 /* add new member to last object-entry in array */
892 ret = gate_yaml_merge_properties((gate_property_t*)ptr_prop, source, false);
893 break;
894 }
895 }
896 }
897
898 }
899 /* otherwise just add array item */
900
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (NULL == gate_property_array_add(target, source))
901 {
902 ret = GATE_RESULT_OUTOFMEMORY;
903 }
904 else
905 {
906 7 ret = GATE_RESULT_OK;
907 }
908 7 break;
909 }
910 18 case GATE_PROPERTY_TYPE_OBJECT:
911 {
912
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (source_is_array_entry)
913 {
914 ret = GATE_RESULT_INCORRECTTYPE;
915 break;
916 }
917
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if (NULL == gate_property_member_names(source, &name_array))
918 {
919 ret = GATE_RESULT_OUTOFMEMORY;
920 }
921 else
922 {
923 18 ret = GATE_RESULT_OK;
924 18 len = gate_array_length(&name_array);
925
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
36 for (index = 0; index != len; ++index)
926 {
927 18 gate_string_t const* ptr_name = gate_array_get(&name_array, index);
928
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (ptr_name)
929 {
930 18 ptr_prop = gate_property_member_get(source, ptr_name);
931
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (ptr_prop)
932 {
933
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if (NULL == gate_property_member_add(target, ptr_name, ptr_prop))
934 {
935 ret = GATE_RESULT_FAILED;
936 break;
937 }
938 }
939 }
940 }
941 18 gate_array_release(&name_array);
942 }
943 18 break;
944 }
945 default:
946 {
947 ret = GATE_RESULT_NOTSUPPORTED;
948 break;
949 }
950 }
951 33 return ret;
952 }
953
954 6 static gate_result_t gate_yaml_integrate(gate_property_t* target, gate_string_t const* key, gate_property_t const* source)
955 {
956 6 gate_property_typeid_t target_type = gate_property_get_type(target);
957
958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (target_type == GATE_PROPERTY_TYPE_EMPTY)
959 {
960 if (NULL == gate_property_create_object(target))
961 {
962 return GATE_RESULT_OUTOFMEMORY;
963 }
964 target_type = GATE_PROPERTY_TYPE_OBJECT;
965 }
966
967
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 switch (target_type)
968 {
969 case GATE_PROPERTY_TYPE_ARRAY:
970 {
971 /* check if target is an array of objects -> add member to last object */
972 gate_size_t len = gate_property_array_length(target);
973 if (len > 0)
974 {
975 gate_property_t* ptr_prop = (gate_property_t*)gate_property_array_get(target, len - 1);
976 if (ptr_prop)
977 {
978 if (gate_property_get_type(ptr_prop) == GATE_PROPERTY_TYPE_OBJECT)
979 {
980 if (NULL != gate_property_member_add(ptr_prop, key, source))
981 {
982 return GATE_RESULT_OK;
983 }
984 else
985 {
986 return GATE_RESULT_OUTOFMEMORY;
987 }
988 }
989 }
990 }
991 return GATE_RESULT_INVALIDSTATE;
992 }
993 6 case GATE_PROPERTY_TYPE_OBJECT:
994 {
995
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 if (NULL != gate_property_member_add(target, key, source))
996 {
997 6 return GATE_RESULT_OK;
998 }
999 else
1000 {
1001 return GATE_RESULT_OUTOFMEMORY;
1002 }
1003 }
1004 default:
1005 {
1006 return GATE_RESULT_INCORRECTTYPE;
1007 }
1008 }
1009 }
1010
1011 7 static gate_result_t gate_yaml_extract_name_of_incomplete_object(gate_property_t const* prop, gate_string_t* name)
1012 {
1013 7 gate_result_t ret = GATE_RESULT_FAILED;
1014 do
1015 {
1016 7 gate_property_typeid_t prop_type = gate_property_get_type(prop);
1017
1/3
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
7 switch (prop_type)
1018 {
1019 7 case GATE_PROPERTY_TYPE_OBJECT:
1020 {
1021 gate_array_t prop_names;
1022
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if (NULL != gate_property_member_names(prop, &prop_names))
1023 {
1024 7 gate_string_t const* ptr_name = gate_array_get(&prop_names, 0);
1025
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (ptr_name)
1026 {
1027
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if (NULL != gate_string_duplicate(name, ptr_name))
1028 {
1029 7 ret = GATE_RESULT_OK;
1030 }
1031 }
1032 7 gate_array_release(&prop_names);
1033 }
1034 7 break;
1035 }
1036 case GATE_PROPERTY_TYPE_STRING:
1037 {
1038 ret = gate_property_get_string(prop, name);
1039 break;
1040 }
1041 default:
1042 {
1043 ret = GATE_RESULT_INCORRECTTYPE;
1044 break;
1045 }
1046 }
1047 } while (0);
1048
1049 7 return ret;
1050 }
1051
1052 #define GATE_YAML_UNKNOWN_NEXT_INDENT 65535
1053
1054
1055 3 gate_result_t gate_yaml_parse_string(gate_string_t const* source, gate_property_t* target_prop, gate_yaml_result_t* result)
1056 {
1057 gate_property_t levels[GATE_YAML_MAX_LEVELS];
1058 3 gate_uint16_t indents[GATE_YAML_MAX_LEVELS] = GATE_INIT_EMPTY;
1059 3 gate_string_t keys[GATE_YAML_MAX_LEVELS] = GATE_INIT_EMPTY;
1060 3 gate_size_t const max_levels = GATE_YAML_MAX_LEVELS;
1061 3 gate_size_t current_level = 0;
1062 gate_size_t index;
1063 3 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1064 3 gate_string_t line = GATE_STRING_INIT_EMPTY;
1065 3 gate_string_t yaml = GATE_STRING_INIT_EMPTY;
1066 gate_uint16_t current_indent;
1067 3 gate_property_t entry_prop = GATE_INIT_EMPTY;
1068 3 gate_bool_t entry_incomplete = false;
1069 3 gate_bool_t entry_is_array = false;
1070 3 gate_uint16_t array_indent = 0;
1071 gate_size_t pos;
1072 3 gate_size_t lines_parsed = 0;
1073
1074 do
1075 {
1076 3 gate_mem_clear(levels, sizeof(levels));
1077 3 gate_mem_clear(result, sizeof(gate_yaml_result_t));
1078
1079
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_string_duplicate(&yaml, source))
1080 {
1081 ret = GATE_RESULT_OUTOFMEMORY;
1082 break;
1083 }
1084
1085 3 indents[0] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1086 3 current_level = 0;
1087
1088
2/2
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 2 times.
43 while (gate_string_read_line(&line, &yaml, &yaml))
1089 {
1090 41 ++lines_parsed;
1091 41 gate_string_rtrim(&line, &line);
1092
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
41 if (gate_string_is_empty(&line))
1093 {
1094 /* skip empty lines */
1095 continue;
1096 }
1097
1098 41 ret = gate_yaml_parse_indent(&line, &current_indent);
1099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 GATE_BREAK_IF_FAILED(ret);
1100
1101 41 entry_is_array = false;
1102
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 30 times.
41 if (gate_string_starts_with_char(&line, '-'))
1103 {
1104 /* array entry: */
1105 11 pos = gate_string_find_first_not_of(&line, &indention_chars, 1);
1106
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (pos == GATE_STR_NPOS)
1107 {
1108 /* error case: empty array entry */
1109 1 ret = GATE_RESULT_INVALIDDATA;
1110 1 break;
1111 }
1112 10 entry_is_array = true;
1113 10 array_indent = current_indent;
1114 10 current_indent += (gate_uint16_t)pos;
1115 10 gate_string_substr(&line, &line, pos, GATE_STR_NPOS);
1116 }
1117
1118
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 if (NULL == gate_yaml_parse_entry(&line, &entry_prop, &entry_incomplete))
1119 {
1120 ret = GATE_RESULT_FAILED;
1121 break;
1122 }
1123
1124
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 31 times.
40 if (indents[current_level] == GATE_YAML_UNKNOWN_NEXT_INDENT)
1125 {
1126
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
9 if ((current_level > 0) && (current_indent < indents[current_level - 1]))
1127 {
1128 /* new advanced indention must be greater than parent element */
1129 ret = GATE_RESULT_INVALIDHEADER;
1130 break;
1131 }
1132 9 indents[current_level] = current_indent;
1133 }
1134
1135
1136
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 40 times.
46 while (current_indent < indents[current_level])
1137 {
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (current_level == 0)
1139 {
1140 ret = GATE_RESULT_CRITICALERROR;
1141 break;
1142 }
1143
1144 6 ret = gate_yaml_integrate(&levels[current_level - 1], &keys[current_level], &levels[current_level]);
1145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1146 6 gate_property_destroy(&levels[current_level]);
1147 6 gate_string_release(&keys[current_level]);
1148 6 indents[current_level] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1149 6 --current_level;
1150 }
1151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 GATE_BREAK_IF_FAILED(ret);
1152
1153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (current_indent > indents[current_level])
1154 {
1155 /* unexpected indention */
1156 ret = GATE_RESULT_INVALIDHEADER;
1157 break;
1158 }
1159
1160
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 33 times.
40 if (entry_incomplete)
1161 {
1162 7 ++current_level;
1163 7 gate_property_create_empty(&levels[current_level]);
1164 7 indents[current_level] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1165 7 ret = gate_yaml_extract_name_of_incomplete_object(&entry_prop, &keys[current_level]);
1166 }
1167 else
1168 {
1169 33 ret = gate_yaml_merge_properties(&levels[current_level], &entry_prop, entry_is_array);
1170 }
1171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 GATE_BREAK_IF_FAILED(ret);
1172
1173 40 gate_property_destroy(&entry_prop);
1174 40 gate_string_release(&line);
1175 }
1176
1177 } while (0);
1178
1179
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (GATE_SUCCEEDED(ret))
1180 {
1181
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 while (current_level > 0)
1182 {
1183 ret = gate_yaml_integrate(&levels[current_level - 1], &keys[current_level], &levels[current_level]);
1184 GATE_BREAK_IF_FAILED(ret);
1185 gate_property_destroy(&levels[current_level]);
1186 gate_string_release(&keys[current_level]);
1187 indents[current_level] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1188 --current_level;
1189 }
1190
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
1191 {
1192 2 gate_mem_copy(target_prop, &levels[0], sizeof(gate_property_t));
1193 2 gate_mem_clear(&levels[0], sizeof(gate_property_t));
1194 }
1195 }
1196
1197
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (result != NULL)
1198 {
1199 3 gate_mem_clear(result, sizeof(gate_yaml_result_t));
1200
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (GATE_SUCCEEDED(ret))
1201 {
1202 2 result->succeeded = true;
1203 }
1204 3 result->lines_processed = lines_parsed;
1205 3 result->chars_processed = 0;
1206 }
1207
1208 3 gate_property_destroy(&entry_prop);
1209 3 gate_string_release(&line);
1210 3 gate_string_release(&yaml);
1211
1212
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 3 times.
195 for (index = 0; index != max_levels; ++index)
1213 {
1214 192 gate_property_destroy(&levels[index]);
1215 192 gate_string_release(&keys[index]);
1216 }
1217 3 return ret;
1218 }
1219
1220 1 gate_result_t gate_yaml_parse(gate_stream_t* input_source, gate_property_t* target_prop, gate_yaml_result_t* result)
1221 {
1222 1 gate_result_t ret = GATE_RESULT_FAILED;
1223 1 gate_stringstream_t* str_stream = NULL;
1224 1 gate_string_t str = GATE_STRING_INIT_EMPTY;
1225 do
1226 {
1227 1 str_stream = gate_stringstream_create(256);
1228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (str_stream == NULL)
1229 {
1230 ret = GATE_RESULT_OUTOFMEMORY;
1231 break;
1232 }
1233 1 ret = gate_stream_transfer(input_source, (gate_stream_t*)str_stream);
1234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1235
1236 1 ret = gate_stringstream_to_string(str_stream, &str);
1237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1238
1239 1 ret = gate_yaml_parse_string(&str, target_prop, result);
1240 } while (0);
1241
1242 1 gate_string_release(&str);
1243
1244
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (str_stream != NULL)
1245 {
1246 1 gate_object_release(str_stream);
1247 }
1248 1 return ret;
1249 }
1250
1251
1252
1253 6 static gate_result_t gate_yaml_print_bool(gate_stream_t* stream, gate_bool_t value)
1254 {
1255
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 return gate_stream_print_cstr(stream, value ? "true" : "false");
1256 }
1257
1258 12 static gate_result_t gate_yaml_print_int(gate_stream_t* stream, gate_int64_t value)
1259 {
1260 12 return gate_stream_print_int64(stream, value);
1261 }
1262
1263 3 static gate_result_t gate_yaml_print_real(gate_stream_t* stream, gate_real64_t value)
1264 {
1265 3 return gate_stream_print_real(stream, value, 0, gate_math_decimal_length(value), 0);
1266 }
1267
1268 44 static gate_result_t gate_yaml_print_string(gate_stream_t* stream, gate_string_t const* value)
1269 {
1270 44 gate_result_t ret = GATE_RESULT_FAILED;
1271 44 gate_size_t const special_chars_count
1272 44 = gate_string_count_chars(value, ' ')
1273 44 + gate_string_count_chars(value, ':')
1274 44 + gate_string_count_chars(value, '\"')
1275 44 + gate_string_count_chars(value, '\'')
1276 44 + gate_string_count_chars(value, '\n');
1277
1278
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 4 times.
44 if (special_chars_count == 0)
1279 {
1280 40 return gate_stream_print_string(stream, value);
1281 }
1282 else
1283 {
1284 do
1285 {
1286 gate_size_t written;
1287 4 ret = gate_stream_write(stream, "\"", 1, &written);
1288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1289
1290
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (value)
1291 {
1292 4 char const* ptr = gate_string_ptr(value, 0);
1293 4 gate_size_t len = gate_string_length(value);
1294
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 4 times.
88 while (len-- != 0)
1295 {
1296 84 char chr = *ptr;
1297
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 78 times.
84 switch (chr)
1298 {
1299 2 case '\"':
1300 case '\'':
1301 2 ret = gate_stream_write_block(stream, "\\", 1, &written);
1302 2 break;
1303 2 case '\r':
1304 2 ret = gate_stream_write_block(stream, "\\", 1, &written);
1305 2 chr = 'r';
1306 2 break;
1307 2 case '\n':
1308 2 ret = gate_stream_write_block(stream, "\\", 1, &written);
1309 2 chr = 'n';
1310 2 break;
1311 78 default:
1312 78 break;
1313 }
1314
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 GATE_BREAK_IF_FAILED(ret);
1315
1316 84 ret = gate_stream_write(stream, &chr, 1, &written);
1317
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 GATE_BREAK_IF_FAILED(ret);
1318 84 ++ptr;
1319 }
1320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1321 }
1322
1323 4 ret = gate_stream_write(stream, "\"", 1, &written);
1324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1325 } while (0);
1326 4 return ret;
1327 }
1328 }
1329
1330 static gate_result_t gate_yaml_print_inline(gate_property_t const* prop, gate_stream_t* stream);
1331
1332 2 static gate_result_t gate_yaml_print_array(gate_stream_t* stream, gate_arraylist_t value)
1333 {
1334 gate_result_t ret;
1335 2 gate_size_t const count = gate_arraylist_length(value);
1336 gate_size_t index;
1337 do
1338 {
1339 2 ret = gate_stream_print_cstr(stream, "[ ");
1340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1341
1342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (index = 0; index != count; ++index)
1343 {
1344 gate_property_t const* prop;
1345 if (index != 0)
1346 {
1347 ret = gate_stream_print_cstr(stream, ", ");
1348 GATE_BREAK_IF_FAILED(ret);
1349 }
1350
1351 prop = (gate_property_t const*)gate_arraylist_get(value, index);
1352 if (prop != NULL)
1353 {
1354 ret = gate_yaml_print_inline(prop, stream);
1355 GATE_BREAK_IF_FAILED(ret);
1356 }
1357 }
1358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1359
1360 2 ret = gate_stream_print_cstr(stream, " ]");
1361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1362
1363 } while (0);
1364 2 return ret;
1365 }
1366
1367 2 static gate_result_t gate_yaml_print_object(gate_stream_t* stream, gate_property_t const* value)
1368 {
1369 gate_result_t ret;
1370 2 gate_array_t names = GATE_INIT_EMPTY;
1371
1372 do
1373 {
1374 gate_size_t count;
1375 gate_size_t index;
1376
1377
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!gate_property_member_names(value, &names))
1378 {
1379 ret = GATE_RESULT_INVALIDCONTENT;
1380 break;
1381 }
1382
1383 2 count = gate_array_length(&names);
1384
1385 2 ret = gate_stream_print_cstr(stream, "{ ");
1386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1387
1388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (index = 0; index != count; ++index)
1389 {
1390 gate_string_t const* ptr_name = (gate_string_t const*)gate_array_get(&names, index);
1391 if (ptr_name)
1392 {
1393 gate_property_t const* prop = gate_property_member_get(value, ptr_name);
1394 if (prop)
1395 {
1396 if (index != 0)
1397 {
1398 ret = gate_stream_print_cstr(stream, ", ");
1399 GATE_BREAK_IF_FAILED(ret);
1400 }
1401 ret = gate_yaml_print_string(stream, ptr_name);
1402 GATE_BREAK_IF_FAILED(ret);
1403 ret = gate_stream_print_cstr(stream, ": ");
1404 GATE_BREAK_IF_FAILED(ret);
1405 ret = gate_yaml_print_inline(prop, stream);
1406 GATE_BREAK_IF_FAILED(ret);
1407 }
1408 }
1409 }
1410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1411
1412 2 ret = gate_stream_print_cstr(stream, " }");
1413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1414
1415 } while (0);
1416
1417 2 gate_array_release(&names);
1418 2 return ret;
1419 }
1420
1421 22 static gate_result_t gate_yaml_print_inline(gate_property_t const* prop, gate_stream_t* stream)
1422 {
1423 22 gate_property_typeid_t const prop_type = gate_property_get_type(prop);
1424
6/8
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
22 switch (prop_type)
1425 {
1426 case GATE_PROPERTY_TYPE_EMPTY: return GATE_RESULT_FAILED;
1427 4 case GATE_PROPERTY_TYPE_BOOL: return gate_yaml_print_bool(stream, prop->data.bool_value);
1428 4 case GATE_PROPERTY_TYPE_INT: return gate_yaml_print_int(stream, prop->data.int_value);
1429 2 case GATE_PROPERTY_TYPE_REAL: return gate_yaml_print_real(stream, prop->data.real_value);
1430 8 case GATE_PROPERTY_TYPE_STRING: return gate_yaml_print_string(stream, &prop->data.string_value);
1431 2 case GATE_PROPERTY_TYPE_ARRAY: return gate_yaml_print_array(stream, prop->data.array_value);
1432 2 case GATE_PROPERTY_TYPE_OBJECT: return gate_yaml_print_object(stream, prop);
1433 default: return GATE_RESULT_NOTSUPPORTED;
1434 }
1435 }
1436
1437 49 static gate_result_t gate_yaml_print_spaces(gate_size_t count, gate_stream_t* stream)
1438 {
1439 static gate_string_t const spaces = GATE_STRING_INIT_STATIC(" ");
1440 49 gate_result_t ret = GATE_RESULT_OK;
1441
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 49 times.
69 while (count > 0)
1442 {
1443 20 gate_size_t len = (count > spaces.length) ? spaces.length : count;
1444 gate_size_t lenwritten;
1445 20 ret = gate_stream_write_block(stream, spaces.str, len, &lenwritten);
1446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 GATE_BREAK_IF_FAILED(ret);
1447 20 count -= lenwritten;
1448 }
1449 49 return ret;
1450 }
1451
1452 49 static gate_result_t gate_yaml_print_indention(gate_stream_t* stream, gate_size_t spaces, gate_bool_t array_indicator)
1453 {
1454 gate_result_t ret;
1455 do
1456 {
1457
3/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
49 if ((spaces < 2) && array_indicator)
1458 {
1459 ret = GATE_RESULT_INVALIDSTATE;
1460 break;
1461 }
1462
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 35 times.
49 if (array_indicator)
1463 {
1464 14 ret = gate_yaml_print_spaces(spaces - 2, stream);
1465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 GATE_BREAK_IF_FAILED(ret);
1466 14 ret = gate_stream_print_cstr(stream, "- ");
1467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 GATE_BREAK_IF_FAILED(ret);
1468 }
1469 else
1470 {
1471 35 ret = gate_yaml_print_spaces(spaces, stream);
1472
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 GATE_BREAK_IF_FAILED(ret);
1473 }
1474 } while (0);
1475 49 return ret;
1476 }
1477
1478 29 static gate_result_t gate_yaml_print(gate_property_t const* prop, gate_stream_t* stream, gate_size_t spaces, gate_bool_t array_indicator)
1479 {
1480 29 gate_result_t ret = GATE_RESULT_FAILED;
1481 29 gate_array_t names = GATE_INIT_EMPTY;
1482
1483 do
1484 {
1485 29 gate_property_typeid_t const prop_type = gate_property_get_type(prop);
1486 gate_property_t const* ptr_item;
1487 gate_size_t count, index;
1488
1489
6/7
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
29 switch (prop_type)
1490 {
1491 2 case GATE_PROPERTY_TYPE_BOOL:
1492 {
1493 2 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1495 2 ret = gate_yaml_print_bool(stream, prop->data.bool_value);
1496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1497 2 ret = gate_stream_println_cstr(stream, NULL);
1498 2 break;
1499 }
1500 8 case GATE_PROPERTY_TYPE_INT:
1501 {
1502 8 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
1504 8 ret = gate_yaml_print_int(stream, prop->data.int_value);
1505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
1506 8 ret = gate_stream_println_cstr(stream, NULL);
1507 8 break;
1508 }
1509 1 case GATE_PROPERTY_TYPE_REAL:
1510 {
1511 1 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1513 1 ret = gate_yaml_print_real(stream, prop->data.real_value);
1514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1515 1 ret = gate_stream_println_cstr(stream, NULL);
1516 1 break;
1517 }
1518 6 case GATE_PROPERTY_TYPE_STRING:
1519 {
1520 6 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1521
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1522 6 ret = gate_yaml_print_string(stream, &prop->data.string_value);
1523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1524 6 ret = gate_stream_println_cstr(stream, NULL);
1525 6 break;
1526 }
1527 5 case GATE_PROPERTY_TYPE_ARRAY:
1528 {
1529 5 count = gate_property_array_length(prop);
1530
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (count == 0)
1531 {
1532 1 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1533
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1534 1 ret = gate_stream_println_cstr(stream, "[]");
1535 }
1536 else
1537 {
1538
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 for (index = 0; index != count; ++index)
1539 {
1540 14 ptr_item = gate_property_array_get(prop, index);
1541
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (ptr_item)
1542 {
1543 14 ret = gate_yaml_print(ptr_item, stream, spaces + 2, true);
1544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 GATE_BREAK_IF_FAILED(ret);
1545 }
1546 }
1547 }
1548 5 break;
1549 }
1550 7 case GATE_PROPERTY_TYPE_OBJECT:
1551 {
1552
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (NULL == gate_property_member_names(prop, &names))
1553 {
1554 ret = GATE_RESULT_FAILED;
1555 break;
1556 }
1557 7 count = gate_array_length(&names);
1558
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (count == 0)
1559 {
1560 1 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1562 1 ret = gate_stream_print_cstr(stream, "{}");
1563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1564 }
1565 else
1566 {
1567
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
36 for (index = 0; index != count; ++index)
1568 {
1569 30 gate_string_t const* ptr_name = (gate_string_t const*)gate_array_get(&names, index);
1570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!ptr_name)
1571 {
1572 continue;
1573 }
1574 30 ptr_item = gate_property_member_get(prop, ptr_name);
1575
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!ptr_item)
1576 {
1577 continue;
1578 }
1579 30 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1581 30 ret = gate_yaml_print_string(stream, ptr_name);
1582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1583 30 ret = gate_stream_print_cstr(stream, ": ");
1584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1585 30 switch (gate_property_get_type(ptr_item))
1586 {
1587 18 case GATE_PROPERTY_TYPE_BOOL:
1588 case GATE_PROPERTY_TYPE_INT:
1589 case GATE_PROPERTY_TYPE_REAL:
1590 case GATE_PROPERTY_TYPE_STRING:
1591 {
1592 18 ret = gate_yaml_print_inline(ptr_item, stream);
1593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 GATE_BREAK_IF_FAILED(ret);
1594 18 ret = gate_stream_println_cstr(stream, NULL);
1595 18 break;
1596 }
1597 6 case GATE_PROPERTY_TYPE_ARRAY:
1598 {
1599
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (gate_property_array_length(ptr_item) == 0)
1600 {
1601 2 ret = gate_yaml_print_inline(ptr_item, stream);
1602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1603 2 ret = gate_stream_println_cstr(stream, NULL);
1604 }
1605 else
1606 {
1607 4 ret = gate_stream_println_cstr(stream, NULL);
1608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1609 4 ret = gate_yaml_print(ptr_item, stream, spaces + 2, false);
1610 }
1611 6 break;
1612 }
1613 6 case GATE_PROPERTY_TYPE_OBJECT:
1614 {
1615
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (gate_property_member_count(ptr_item) == 0)
1616 {
1617 2 ret = gate_yaml_print_inline(ptr_item, stream);
1618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1619 2 ret = gate_stream_println_cstr(stream, NULL);
1620 }
1621 else
1622 {
1623 4 ret = gate_stream_println_cstr(stream, NULL);
1624
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1625 4 ret = gate_yaml_print(ptr_item, stream, spaces + 2, false);
1626 }
1627 6 break;
1628 }
1629 }
1630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1631 30 array_indicator = false;
1632 } /* for() */
1633 }
1634 7 break;
1635 }
1636 case GATE_PROPERTY_TYPE_EMPTY:
1637 default:
1638 {
1639 ret = GATE_RESULT_NOTSUPPORTED;
1640 break;
1641 }
1642 }
1643 } while (0);
1644
1645 29 gate_array_release(&names);
1646
1647 29 return ret;
1648 }
1649
1650 7 gate_result_t gate_yaml_build(gate_property_t const* prop, gate_stream_t* dest_builder)
1651 {
1652 7 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1653
1654 char spaces[4096 * 2];
1655 gate_uint16_t indent_stack[1024];
1656
1657 7 gate_mem_fill(spaces, ' ', sizeof(spaces));
1658 7 gate_mem_clear(indent_stack, sizeof(indent_stack));
1659
1660 7 ret = gate_yaml_print(prop, dest_builder, 0, false);
1661
1662 7 return ret;
1663 }
1664
1665 6 gate_result_t gate_yaml_build_string(gate_property_t const* prop, gate_string_t* output)
1666 {
1667 6 gate_result_t ret = GATE_RESULT_FAILED;
1668 6 gate_stringstream_t* str_stream = NULL;
1669
1670 do
1671 {
1672 6 str_stream = gate_stringstream_create(256);
1673
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (str_stream == NULL)
1674 {
1675 ret = GATE_RESULT_OUTOFMEMORY;
1676 break;
1677 }
1678
1679 6 ret = gate_yaml_build(prop, (gate_stream_t*)str_stream);
1680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1681
1682 6 ret = gate_stringstream_to_string(str_stream, output);
1683 } while (0);
1684
1685
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (str_stream)
1686 {
1687 6 gate_object_release(str_stream);
1688 }
1689 6 return ret;
1690 }
1691