GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/yaml.c
Date: 2026-06-21 00:38:37
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 ret = 0;
400 break;
401 }
402 1 gate_string_substr(&tmp, &text, 0, pos);
403 1 ret += pos;
404 1 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
405
406 1 skip_whitespaces(&tmp);
407 1 tmp_empty = gate_string_is_empty(&tmp);
408 1 gate_string_release(&tmp);
409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tmp_empty)
410 {
411 /* no non-whitespace-chars allowed until terminator chars show up */
412 YAML_LOG_SETRET_BREAK("Unexpected characters after YAML member value detected");
413 }
414
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_starts_with_char(&text, '}'))
415 {
416 /* end of object reached */
417 1 ++ret;
418 1 break;
419 }
420 if (!gate_string_starts_with_char(&text, ','))
421 {
422 /* object corrupted */
423 YAML_LOG_SETRET_BREAK("Missing YAML object member separator");
424 }
425 else
426 {
427 /* another key/value pair is showing up */
428 ++ret;
429 gate_string_substr(&text, &text, 1, GATE_STR_NPOS);
430 }
431 }
432 } while (0);
433
434
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret == 0)
435 {
436 gate_property_destroy(prop);
437 }
438
439 3 gate_string_release(&tmp);
440 3 gate_string_release(&member_name);
441 3 gate_string_release(&member_value);
442 3 gate_property_destroy(&member_prop);
443 3 gate_string_release(&text);
444 3 return ret;
445 }
446 3 static gate_size_t gate_yaml_parse_inline_array(gate_string_t* token, gate_property_t* prop)
447 {
448 static gate_string_t arr_item_terminator_chars = GATE_STRING_INIT_STATIC(",]");
449 3 gate_size_t ret = 0;
450 3 gate_string_t text = GATE_STRING_INIT_EMPTY;
451 3 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
452 gate_bool_t succeeded;
453 gate_bool_t tmp_empty;
454 3 gate_property_t item_prop = GATE_INIT_EMPTY;
455 gate_size_t pos;
456 3 gate_string_duplicate(&text, token);
457
458 3 ret += skip_whitespaces(&text);
459
460 do
461 {
462 3 gate_mem_clear(prop, sizeof(gate_property_t));
463
464
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!gate_string_starts_with_char(&text, '['))
465 {
466 /* token does not start with an array indicator */
467 YAML_LOG_SETRET_BREAK("Missing YAML array indicator");
468 }
469 3 gate_string_substr(&text, &text, 1, GATE_STR_NPOS);
470 3 ++ret;
471
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_property_create_array(prop, NULL, 0))
473 {
474 YAML_LOG_SETRET_BREAK("Failed to create array property object");
475 }
476
477 for (;;)
478 {
479 6 ret += skip_whitespaces(&text);
480
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (gate_string_is_empty(&text))
481 {
482 /* missing array content */
483 YAML_LOG_SETRET_BREAK("Missing YAML array content");
484 }
485
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (gate_string_starts_with_char(&text, ']'))
486 {
487 /* end of array reached */
488 2 ++ret;
489 2 break;
490 }
491
492 /* parse value: */
493 4 ret += skip_whitespaces(&text);
494 4 pos = gate_yaml_parse_inline_item(&text, &item_prop, &arr_item_terminator_chars);
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pos == 0)
496 {
497 /* failed to parse member property */
498 YAML_LOG_SETRET_BREAK("Failed to parse YAML array item");
499 }
500 4 ret += pos;
501 4 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
502
503 4 succeeded = (NULL != gate_property_array_add(prop, &item_prop));
504 4 gate_property_destroy(&item_prop);
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!succeeded)
506 {
507 /* failed to add new item to array */
508 YAML_LOG_SETRET_BREAK("Failed to add item to array property object");
509 }
510
511 4 pos = gate_string_find_first_of(&text, &arr_item_terminator_chars, 0);
512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pos == GATE_STR_NPOS)
513 {
514 /* broken array -> corruption */
515 YAML_LOG_SETRET_BREAK("Missing YAML array item separator or terminator");
516 }
517 4 gate_string_substr(&tmp, &text, 0, pos);
518 4 ret += pos;
519 4 gate_string_substr(&text, &text, pos, GATE_STR_NPOS);
520
521 4 skip_whitespaces(&tmp);
522 4 tmp_empty = gate_string_is_empty(&tmp);
523 4 gate_string_release(&tmp);
524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!tmp_empty)
525 {
526 /* no non-whitespace-chars allowed until terminator chars show up */
527 YAML_LOG_SETRET_BREAK("Unexpected characters after YAML array item detected");
528 }
529
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if (gate_string_starts_with_char(&text, ']'))
530 {
531 /* end of object reached */
532 1 ++ret;
533 1 break;
534 }
535
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!gate_string_starts_with_char(&text, ','))
536 {
537 /* object corrupted */
538 YAML_LOG_SETRET_BREAK("Missing YAML array separator");
539 }
540 else
541 {
542 /* another key/value pair is showing up */
543 3 ++ret;
544 3 gate_string_substr(&text, &text, 1, GATE_STR_NPOS);
545 }
546 }
547 } while (0);
548
549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret == 0)
550 {
551 gate_property_destroy(prop);
552 }
553
554 3 gate_string_release(&tmp);
555 3 gate_property_destroy(&item_prop);
556 3 gate_string_release(&text);
557 3 return ret;
558 }
559
560 63 static gate_property_t* gate_yaml_parse_entry(gate_string_t* line, gate_property_t* prop, gate_bool_t* incomplete)
561 {
562 static gate_string_t end_of_line = GATE_STRING_INIT_STATIC("\n");
563 63 gate_property_t* ret = NULL;
564 63 gate_string_t text = GATE_STRING_INIT_EMPTY;
565 63 gate_property_t subprop = GATE_INIT_EMPTY;
566 gate_size_t parsed;
567 gate_size_t pos;
568 63 gate_bool_t valueonly = false;
569 63 gate_bool_t keyonly = false;
570 63 gate_bool_t keyvalue = false;
571 63 gate_bool_t subprop_incomplete = false;
572 63 gate_bool_t quoted_value = false;
573 63 gate_int64_t i64 = 0;
574 63 gate_real64_t r64 = 0.0;
575 do
576 {
577 63 gate_string_ltrim(line, line);
578
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
63 if (gate_string_is_empty(line))
579 {
580 GATE_DEBUG_TRACE("Missing YAML line content");
581 /* error, nothing to parse */
582 break;
583 }
584
585
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, '['))
586 {
587 /* inline object or inline array */
588 6 *incomplete = false;
589 6 pos = gate_yaml_parse_inline_item(line, prop, &end_of_line);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (pos == 0)
591 {
592 GATE_DEBUG_TRACE("Failed to parse inline YAML entry");
593 ret = NULL;
594 }
595 else
596 {
597 6 ret = prop;
598 }
599 6 break;
600 }
601
602
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, '\''))
603 {
604 /* quoted string */
605 6 parsed = parse_quoted_string(line, &text);
606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (parsed == 0)
607 {
608 GATE_DEBUG_TRACE("Failed to parse quoted YAML string");
609 break;
610 }
611 6 gate_string_substr(line, line, parsed, GATE_STR_NPOS);
612 6 gate_string_ltrim(line, line);
613
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
12 if (gate_string_starts_with_char(line, ':'))
614 {
615 /* key - value pair: */
616 1 gate_string_substr(line, line, 1, GATE_STR_NPOS);
617 1 gate_string_ltrim(line, line);
618
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_string_is_empty(line))
619 {
620 keyonly = true;
621 }
622 else
623 {
624
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_yaml_parse_entry(line, &subprop, &subprop_incomplete))
625 {
626 GATE_DEBUG_TRACE("Failed to parse YAML entry member value");
627 /* error case: failed to parse sub-property */
628 break;
629 }
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (subprop_incomplete)
631 {
632 GATE_DEBUG_TRACE("Incomplete sub property dtected");
633 /* error case: sub-property is incomplete*/
634 break;
635 }
636 1 keyvalue = true;
637 }
638 }
639 else
640 {
641 /* value-only */
642 5 valueonly = true;
643 5 quoted_value = true;
644 }
645 }
646 else
647 {
648 51 pos = gate_string_char_pos(line, ':', 0);
649
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 29 times.
51 if (pos == GATE_STR_NPOS)
650 {
651 22 gate_string_duplicate(&text, line);
652 22 valueonly = true;
653 /* value only */
654 }
655 else
656 {
657 29 gate_string_substr(&text, line, 0, pos);
658 29 gate_string_ltrim(&text, &text);
659 29 gate_string_substr(line, line, pos + 1, GATE_STR_NPOS);
660 29 gate_string_ltrim(line, line);
661
662
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 22 times.
29 if (gate_string_is_empty(line))
663 {
664 7 keyonly = true;
665 }
666 else
667 {
668
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (NULL == gate_yaml_parse_entry(line, &subprop, &subprop_incomplete))
669 {
670 GATE_DEBUG_TRACE("Failed to parse YAML entry member value");
671 /* error case: failed to parse sub-property */
672 break;
673 }
674
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (subprop_incomplete)
675 {
676 GATE_DEBUG_TRACE("Incomplete sub property dtected");
677 /* error case: sub-property is incomplete*/
678 break;
679 }
680 22 keyvalue = true;
681 }
682 }
683 }
684
685 57 *incomplete = keyonly;
686
687
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 30 times.
57 if (valueonly)
688 {
689
1/3
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 switch (gate_property_get_type(prop))
690 {
691 case GATE_PROPERTY_TYPE_ARRAY:
692 {
693 GATE_DEBUG_TRACE("Internal error, property of type array detected");
694 /* error case: arrays are handled outside */
695 break;
696 }
697 case GATE_PROPERTY_TYPE_OBJECT:
698 {
699 GATE_DEBUG_TRACE("Internal error, property of type object detected");
700 /* error case: cannot attach value-only to object*/
701 break;
702 }
703 27 default:
704 {
705 27 gate_property_destroy(prop);
706
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 22 times.
27 if (quoted_value)
707 {
708 5 ret = gate_property_create_string(prop, &text);
709 }
710 else
711 {
712
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
22 if (is_yaml_bool_true(&text))
713 {
714 2 ret = gate_property_create_bool(prop, true);
715 }
716
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
20 else if (is_yaml_bool_false(&text))
717 {
718 2 ret = gate_property_create_bool(prop, false);
719 }
720
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
18 else if (is_yaml_int(&text, &i64))
721 {
722 8 ret = gate_property_create_int(prop, i64);
723 }
724
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
10 else if (is_yaml_real(&text, &r64))
725 {
726 2 ret = gate_property_create_real(prop, r64);
727 }
728 else
729 {
730 8 ret = gate_property_create_string(prop, &text);
731 }
732 }
733
734 27 break;
735 }
736 }
737 }
738
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)
739 {
740
1/3
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
30 switch (gate_property_get_type(prop))
741 {
742 case GATE_PROPERTY_TYPE_ARRAY:
743 {
744 GATE_DEBUG_TRACE("Internal error, property of type array detected");
745 /* error case: arrays are handled outside */
746 break;
747 }
748 case GATE_PROPERTY_TYPE_OBJECT:
749 {
750 ret = gate_property_member_add(prop, &text, &subprop);
751 break;
752 }
753 30 default:
754 {
755 30 gate_property_destroy(prop);
756 30 ret = gate_property_create_object(prop);
757
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if (ret != NULL)
758 {
759
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if (NULL == gate_property_member_add(prop, &text, &subprop))
760 {
761 gate_property_destroy(prop);
762 ret = NULL;
763 }
764 }
765 30 break;
766 }
767 }
768 }
769 else
770 {
771 /* error case: unsupported behavior */
772 break;
773 }
774 } while (0);
775
776 63 gate_string_release(&text);
777 63 gate_property_destroy(&subprop);
778 63 return ret;
779 }
780
781 41 static gate_result_t gate_yaml_parse_indent(gate_string_t* line, gate_uint16_t* indent)
782 {
783 41 gate_result_t ret = GATE_RESULT_FAILED;
784 41 gate_size_t const pos = gate_string_find_first_not_of(line, &indention_chars, 0);
785
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (pos == GATE_STR_NPOS)
786 {
787 /* impossible, should be detected by is_empty() */
788 GATE_DEBUG_TRACE("Internal error, missing indention");
789 ret = GATE_RESULT_CRITICALERROR;
790 }
791 else
792 {
793 41 *indent = (gate_uint16_t)pos;
794 41 gate_string_substr(line, line, pos, GATE_STR_NPOS);
795 41 ret = GATE_RESULT_OK;
796 }
797 41 return ret;
798 }
799
800
801 #define GATE_YAML_MAX_LEVELS 64
802 #define GATE_YAML_UNKNOWN_INDENTION ((gate_uint16_t)(-1))
803
804 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)
805 {
806 33 gate_result_t ret = GATE_RESULT_FAILED;
807 33 gate_uint32_t target_type = gate_property_get_type(target);
808 33 gate_uint32_t source_type = gate_property_get_type(source);
809 gate_size_t index;
810 gate_size_t len;
811 33 gate_array_t name_array = GATE_INIT_EMPTY;
812 gate_property_t const* ptr_prop;
813
814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 if (source_type == GATE_PROPERTY_TYPE_EMPTY)
815 {
816 /* nothing to do */
817 ret = GATE_RESULT_OK;
818 }
819
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)
820 {
821 8 case GATE_PROPERTY_TYPE_EMPTY:
822 {
823
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 if (source_is_array_entry)
824 {
825
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_property_create_array(target, source, 1))
826 {
827 ret = GATE_RESULT_OUTOFMEMORY;
828 }
829 else
830 {
831 3 ret = GATE_RESULT_OK;
832 }
833 }
834 else
835 {
836
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (NULL == gate_property_copy(target, source))
837 {
838 ret = GATE_RESULT_OUTOFMEMORY;
839 }
840 else
841 {
842 5 ret = GATE_RESULT_OK;
843 }
844 }
845 8 break;
846 }
847 case GATE_PROPERTY_TYPE_BOOL:
848 case GATE_PROPERTY_TYPE_INT:
849 case GATE_PROPERTY_TYPE_REAL:
850 {
851 if (source_type == target_type)
852 {
853 if (NULL == gate_property_copy(target, source))
854 {
855 ret = GATE_RESULT_OUTOFMEMORY;
856 }
857 else
858 {
859 ret = GATE_RESULT_OK;
860 }
861 }
862 else
863 {
864 ret = GATE_RESULT_INCORRECTTYPE;
865 }
866 break;
867 }
868 case GATE_PROPERTY_TYPE_STRING:
869 {
870 if (source_type == target_type)
871 {
872 ret = gate_property_set_string(target, &source->data.string_value);
873 }
874 else
875 {
876 ret = GATE_RESULT_INCORRECTTYPE;
877 }
878 break;
879 }
880 7 case GATE_PROPERTY_TYPE_ARRAY:
881 {
882
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))
883 {
884 /* this might be an additional object member entry for the previously added object */
885 len = gate_property_array_length(target);
886 if (len > 0)
887 {
888 ptr_prop = gate_property_array_get(target, len - 1);
889 if (ptr_prop)
890 {
891 if (gate_property_get_type(ptr_prop) == GATE_PROPERTY_TYPE_OBJECT)
892 {
893 /* add new member to last object-entry in array */
894 ret = gate_yaml_merge_properties((gate_property_t*)ptr_prop, source, false);
895 break;
896 }
897 }
898 }
899
900 }
901 /* otherwise just add array item */
902
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (NULL == gate_property_array_add(target, source))
903 {
904 ret = GATE_RESULT_OUTOFMEMORY;
905 }
906 else
907 {
908 7 ret = GATE_RESULT_OK;
909 }
910 7 break;
911 }
912 18 case GATE_PROPERTY_TYPE_OBJECT:
913 {
914
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (source_is_array_entry)
915 {
916 ret = GATE_RESULT_INCORRECTTYPE;
917 break;
918 }
919
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if (NULL == gate_property_member_names(source, &name_array))
920 {
921 ret = GATE_RESULT_OUTOFMEMORY;
922 }
923 else
924 {
925 18 ret = GATE_RESULT_OK;
926 18 len = gate_array_length(&name_array);
927
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
36 for (index = 0; index != len; ++index)
928 {
929 18 gate_string_t const* ptr_name = gate_array_get(&name_array, index);
930
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (ptr_name)
931 {
932 18 ptr_prop = gate_property_member_get(source, ptr_name);
933
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (ptr_prop)
934 {
935
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if (NULL == gate_property_member_add(target, ptr_name, ptr_prop))
936 {
937 ret = GATE_RESULT_FAILED;
938 break;
939 }
940 }
941 }
942 }
943 18 gate_array_release(&name_array);
944 }
945 18 break;
946 }
947 default:
948 {
949 ret = GATE_RESULT_NOTSUPPORTED;
950 break;
951 }
952 }
953 33 return ret;
954 }
955
956 6 static gate_result_t gate_yaml_integrate(gate_property_t* target, gate_string_t const* key, gate_property_t const* source)
957 {
958 6 gate_property_typeid_t target_type = gate_property_get_type(target);
959
960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (target_type == GATE_PROPERTY_TYPE_EMPTY)
961 {
962 if (NULL == gate_property_create_object(target))
963 {
964 return GATE_RESULT_OUTOFMEMORY;
965 }
966 target_type = GATE_PROPERTY_TYPE_OBJECT;
967 }
968
969
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 switch (target_type)
970 {
971 case GATE_PROPERTY_TYPE_ARRAY:
972 {
973 /* check if target is an array of objects -> add member to last object */
974 gate_size_t len = gate_property_array_length(target);
975 if (len > 0)
976 {
977 gate_property_t* ptr_prop = (gate_property_t*)gate_property_array_get(target, len - 1);
978 if (ptr_prop)
979 {
980 if (gate_property_get_type(ptr_prop) == GATE_PROPERTY_TYPE_OBJECT)
981 {
982 if (NULL != gate_property_member_add(ptr_prop, key, source))
983 {
984 return GATE_RESULT_OK;
985 }
986 else
987 {
988 return GATE_RESULT_OUTOFMEMORY;
989 }
990 }
991 }
992 }
993 return GATE_RESULT_INVALIDSTATE;
994 }
995 6 case GATE_PROPERTY_TYPE_OBJECT:
996 {
997
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 if (NULL != gate_property_member_add(target, key, source))
998 {
999 6 return GATE_RESULT_OK;
1000 }
1001 else
1002 {
1003 return GATE_RESULT_OUTOFMEMORY;
1004 }
1005 }
1006 default:
1007 {
1008 return GATE_RESULT_INCORRECTTYPE;
1009 }
1010 }
1011 }
1012
1013 7 static gate_result_t gate_yaml_extract_name_of_incomplete_object(gate_property_t const* prop, gate_string_t* name)
1014 {
1015 7 gate_result_t ret = GATE_RESULT_FAILED;
1016 do
1017 {
1018 7 gate_property_typeid_t prop_type = gate_property_get_type(prop);
1019
1/3
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
7 switch (prop_type)
1020 {
1021 7 case GATE_PROPERTY_TYPE_OBJECT:
1022 {
1023 gate_array_t prop_names;
1024
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if (NULL != gate_property_member_names(prop, &prop_names))
1025 {
1026 7 gate_string_t const* ptr_name = gate_array_get(&prop_names, 0);
1027
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (ptr_name)
1028 {
1029
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if (NULL != gate_string_duplicate(name, ptr_name))
1030 {
1031 7 ret = GATE_RESULT_OK;
1032 }
1033 }
1034 7 gate_array_release(&prop_names);
1035 }
1036 7 break;
1037 }
1038 case GATE_PROPERTY_TYPE_STRING:
1039 {
1040 ret = gate_property_get_string(prop, name);
1041 break;
1042 }
1043 default:
1044 {
1045 ret = GATE_RESULT_INCORRECTTYPE;
1046 break;
1047 }
1048 }
1049 } while (0);
1050
1051 7 return ret;
1052 }
1053
1054 #define GATE_YAML_UNKNOWN_NEXT_INDENT 65535
1055
1056
1057 3 gate_result_t gate_yaml_parse_string(gate_string_t const* source, gate_property_t* target_prop, gate_yaml_result_t* result)
1058 {
1059 gate_property_t levels[GATE_YAML_MAX_LEVELS];
1060 3 gate_uint16_t indents[GATE_YAML_MAX_LEVELS] = GATE_INIT_EMPTY;
1061 3 gate_string_t keys[GATE_YAML_MAX_LEVELS] = GATE_INIT_EMPTY;
1062 3 gate_size_t const max_levels = GATE_YAML_MAX_LEVELS;
1063 3 gate_size_t current_level = 0;
1064 gate_size_t index;
1065 3 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1066 3 gate_string_t line = GATE_STRING_INIT_EMPTY;
1067 3 gate_string_t yaml = GATE_STRING_INIT_EMPTY;
1068 gate_uint16_t current_indent;
1069 3 gate_property_t entry_prop = GATE_INIT_EMPTY;
1070 3 gate_bool_t entry_incomplete = false;
1071 3 gate_bool_t entry_is_array = false;
1072 3 gate_uint16_t array_indent = 0;
1073 gate_size_t pos;
1074 3 gate_size_t lines_parsed = 0;
1075
1076 do
1077 {
1078 3 gate_mem_clear(levels, sizeof(levels));
1079 3 gate_mem_clear(result, sizeof(gate_yaml_result_t));
1080
1081
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (NULL == gate_string_duplicate(&yaml, source))
1082 {
1083 ret = GATE_RESULT_OUTOFMEMORY;
1084 break;
1085 }
1086
1087 3 indents[0] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1088 3 current_level = 0;
1089
1090
2/2
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 2 times.
43 while (gate_string_read_line(&line, &yaml, &yaml))
1091 {
1092 41 ++lines_parsed;
1093 41 gate_string_rtrim(&line, &line);
1094
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 41 times.
41 if (gate_string_is_empty(&line))
1095 {
1096 /* skip empty lines */
1097 continue;
1098 }
1099
1100 41 ret = gate_yaml_parse_indent(&line, &current_indent);
1101
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 GATE_BREAK_IF_FAILED(ret);
1102
1103 41 entry_is_array = false;
1104
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 30 times.
41 if (gate_string_starts_with_char(&line, '-'))
1105 {
1106 /* array entry: */
1107 11 pos = gate_string_find_first_not_of(&line, &indention_chars, 1);
1108
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (pos == GATE_STR_NPOS)
1109 {
1110 /* error case: empty array entry */
1111 1 ret = GATE_RESULT_INVALIDDATA;
1112 1 break;
1113 }
1114 10 entry_is_array = true;
1115 10 array_indent = current_indent;
1116 10 current_indent += (gate_uint16_t)pos;
1117 10 gate_string_substr(&line, &line, pos, GATE_STR_NPOS);
1118 }
1119
1120
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 if (NULL == gate_yaml_parse_entry(&line, &entry_prop, &entry_incomplete))
1121 {
1122 ret = GATE_RESULT_FAILED;
1123 break;
1124 }
1125
1126
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 31 times.
40 if (indents[current_level] == GATE_YAML_UNKNOWN_NEXT_INDENT)
1127 {
1128
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]))
1129 {
1130 /* new advanced indention must be greater than parent element */
1131 ret = GATE_RESULT_INVALIDHEADER;
1132 break;
1133 }
1134 9 indents[current_level] = current_indent;
1135 }
1136
1137
1138
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 40 times.
46 while (current_indent < indents[current_level])
1139 {
1140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (current_level == 0)
1141 {
1142 ret = GATE_RESULT_CRITICALERROR;
1143 break;
1144 }
1145
1146 6 ret = gate_yaml_integrate(&levels[current_level - 1], &keys[current_level], &levels[current_level]);
1147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1148 6 gate_property_destroy(&levels[current_level]);
1149 6 gate_string_release(&keys[current_level]);
1150 6 indents[current_level] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1151 6 --current_level;
1152 }
1153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 GATE_BREAK_IF_FAILED(ret);
1154
1155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if (current_indent > indents[current_level])
1156 {
1157 /* unexpected indention */
1158 ret = GATE_RESULT_INVALIDHEADER;
1159 break;
1160 }
1161
1162
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 33 times.
40 if (entry_incomplete)
1163 {
1164 7 ++current_level;
1165 7 gate_property_create_empty(&levels[current_level]);
1166 7 indents[current_level] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1167 7 ret = gate_yaml_extract_name_of_incomplete_object(&entry_prop, &keys[current_level]);
1168 }
1169 else
1170 {
1171 33 ret = gate_yaml_merge_properties(&levels[current_level], &entry_prop, entry_is_array);
1172 }
1173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 GATE_BREAK_IF_FAILED(ret);
1174
1175 40 gate_property_destroy(&entry_prop);
1176 40 gate_string_release(&line);
1177 }
1178
1179 } while (0);
1180
1181
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (GATE_SUCCEEDED(ret))
1182 {
1183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 while (current_level > 0)
1184 {
1185 ret = gate_yaml_integrate(&levels[current_level - 1], &keys[current_level], &levels[current_level]);
1186 GATE_BREAK_IF_FAILED(ret);
1187 gate_property_destroy(&levels[current_level]);
1188 gate_string_release(&keys[current_level]);
1189 indents[current_level] = GATE_YAML_UNKNOWN_NEXT_INDENT;
1190 --current_level;
1191 }
1192
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
1193 {
1194 2 gate_mem_copy(target_prop, &levels[0], sizeof(gate_property_t));
1195 2 gate_mem_clear(&levels[0], sizeof(gate_property_t));
1196 }
1197 }
1198
1199
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (result != NULL)
1200 {
1201 3 gate_mem_clear(result, sizeof(gate_yaml_result_t));
1202
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (GATE_SUCCEEDED(ret))
1203 {
1204 2 result->succeeded = true;
1205 }
1206 3 result->lines_processed = lines_parsed;
1207 3 result->chars_processed = 0;
1208 }
1209
1210 3 gate_property_destroy(&entry_prop);
1211 3 gate_string_release(&line);
1212 3 gate_string_release(&yaml);
1213
1214
2/2
✓ Branch 0 taken 192 times.
✓ Branch 1 taken 3 times.
195 for (index = 0; index != max_levels; ++index)
1215 {
1216 192 gate_property_destroy(&levels[index]);
1217 192 gate_string_release(&keys[index]);
1218 }
1219 3 return ret;
1220 }
1221
1222 1 gate_result_t gate_yaml_parse(gate_stream_t* input_source, gate_property_t* target_prop, gate_yaml_result_t* result)
1223 {
1224 1 gate_result_t ret = GATE_RESULT_FAILED;
1225 1 gate_stringstream_t* str_stream = NULL;
1226 1 gate_string_t str = GATE_STRING_INIT_EMPTY;
1227 do
1228 {
1229 1 str_stream = gate_stringstream_create(256);
1230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (str_stream == NULL)
1231 {
1232 ret = GATE_RESULT_OUTOFMEMORY;
1233 break;
1234 }
1235 1 ret = gate_stream_transfer(input_source, (gate_stream_t*)str_stream);
1236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1237
1238 1 ret = gate_stringstream_to_string(str_stream, &str);
1239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1240
1241 1 ret = gate_yaml_parse_string(&str, target_prop, result);
1242 } while (0);
1243
1244 1 gate_string_release(&str);
1245
1246
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (str_stream != NULL)
1247 {
1248 1 gate_object_release(str_stream);
1249 }
1250 1 return ret;
1251 }
1252
1253
1254
1255 6 static gate_result_t gate_yaml_print_bool(gate_stream_t* stream, gate_bool_t value)
1256 {
1257
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 return gate_stream_print_cstr(stream, value ? "true" : "false");
1258 }
1259
1260 12 static gate_result_t gate_yaml_print_int(gate_stream_t* stream, gate_int64_t value)
1261 {
1262 12 return gate_stream_print_int64(stream, value);
1263 }
1264
1265 3 static gate_result_t gate_yaml_print_real(gate_stream_t* stream, gate_real64_t value)
1266 {
1267 3 return gate_stream_print_real(stream, value, 0, gate_math_decimal_length(value), 0);
1268 }
1269
1270 44 static gate_result_t gate_yaml_print_string(gate_stream_t* stream, gate_string_t const* value)
1271 {
1272 44 gate_result_t ret = GATE_RESULT_FAILED;
1273 44 gate_size_t const special_chars_count
1274 44 = gate_string_count_chars(value, ' ')
1275 44 + gate_string_count_chars(value, ':')
1276 44 + gate_string_count_chars(value, '\"')
1277 44 + gate_string_count_chars(value, '\'')
1278 44 + gate_string_count_chars(value, '\n');
1279
1280
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 4 times.
44 if (special_chars_count == 0)
1281 {
1282 40 return gate_stream_print_string(stream, value);
1283 }
1284 else
1285 {
1286 do
1287 {
1288 gate_size_t written;
1289 4 ret = gate_stream_write(stream, "\"", 1, &written);
1290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1291
1292
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (value)
1293 {
1294 4 char const* ptr = gate_string_ptr(value, 0);
1295 4 gate_size_t len = gate_string_length(value);
1296
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 4 times.
88 while (len-- != 0)
1297 {
1298 84 char chr = *ptr;
1299
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)
1300 {
1301 2 case '\"':
1302 case '\'':
1303 2 ret = gate_stream_write_block(stream, "\\", 1, &written);
1304 2 break;
1305 2 case '\r':
1306 2 ret = gate_stream_write_block(stream, "\\", 1, &written);
1307 2 chr = 'r';
1308 2 break;
1309 2 case '\n':
1310 2 ret = gate_stream_write_block(stream, "\\", 1, &written);
1311 2 chr = 'n';
1312 2 break;
1313 78 default:
1314 78 break;
1315 }
1316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 GATE_BREAK_IF_FAILED(ret);
1317
1318 84 ret = gate_stream_write(stream, &chr, 1, &written);
1319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 GATE_BREAK_IF_FAILED(ret);
1320 84 ++ptr;
1321 }
1322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1323 }
1324
1325 4 ret = gate_stream_write(stream, "\"", 1, &written);
1326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1327 } while (0);
1328 4 return ret;
1329 }
1330 }
1331
1332 static gate_result_t gate_yaml_print_inline(gate_property_t const* prop, gate_stream_t* stream);
1333
1334 2 static gate_result_t gate_yaml_print_array(gate_stream_t* stream, gate_arraylist_t value)
1335 {
1336 gate_result_t ret;
1337 2 gate_size_t const count = gate_arraylist_length(value);
1338 gate_size_t index;
1339 do
1340 {
1341 2 ret = gate_stream_print_cstr(stream, "[ ");
1342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1343
1344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (index = 0; index != count; ++index)
1345 {
1346 gate_property_t const* prop;
1347 if (index != 0)
1348 {
1349 ret = gate_stream_print_cstr(stream, ", ");
1350 GATE_BREAK_IF_FAILED(ret);
1351 }
1352
1353 prop = (gate_property_t const*)gate_arraylist_get(value, index);
1354 if (prop != NULL)
1355 {
1356 ret = gate_yaml_print_inline(prop, stream);
1357 GATE_BREAK_IF_FAILED(ret);
1358 }
1359 }
1360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1361
1362 2 ret = gate_stream_print_cstr(stream, " ]");
1363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1364
1365 } while (0);
1366 2 return ret;
1367 }
1368
1369 2 static gate_result_t gate_yaml_print_object(gate_stream_t* stream, gate_property_t const* value)
1370 {
1371 gate_result_t ret;
1372 2 gate_array_t names = GATE_INIT_EMPTY;
1373
1374 do
1375 {
1376 gate_size_t count;
1377 gate_size_t index;
1378
1379
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!gate_property_member_names(value, &names))
1380 {
1381 ret = GATE_RESULT_INVALIDCONTENT;
1382 break;
1383 }
1384
1385 2 count = gate_array_length(&names);
1386
1387 2 ret = gate_stream_print_cstr(stream, "{ ");
1388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1389
1390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for (index = 0; index != count; ++index)
1391 {
1392 gate_string_t const* ptr_name = (gate_string_t const*)gate_array_get(&names, index);
1393 if (ptr_name)
1394 {
1395 gate_property_t const* prop = gate_property_member_get(value, ptr_name);
1396 if (prop)
1397 {
1398 if (index != 0)
1399 {
1400 ret = gate_stream_print_cstr(stream, ", ");
1401 GATE_BREAK_IF_FAILED(ret);
1402 }
1403 ret = gate_yaml_print_string(stream, ptr_name);
1404 GATE_BREAK_IF_FAILED(ret);
1405 ret = gate_stream_print_cstr(stream, ": ");
1406 GATE_BREAK_IF_FAILED(ret);
1407 ret = gate_yaml_print_inline(prop, stream);
1408 GATE_BREAK_IF_FAILED(ret);
1409 }
1410 }
1411 }
1412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1413
1414 2 ret = gate_stream_print_cstr(stream, " }");
1415
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1416
1417 } while (0);
1418
1419 2 gate_array_release(&names);
1420 2 return ret;
1421 }
1422
1423 22 static gate_result_t gate_yaml_print_inline(gate_property_t const* prop, gate_stream_t* stream)
1424 {
1425 22 gate_property_typeid_t const prop_type = gate_property_get_type(prop);
1426
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)
1427 {
1428 case GATE_PROPERTY_TYPE_EMPTY: return GATE_RESULT_FAILED;
1429 4 case GATE_PROPERTY_TYPE_BOOL: return gate_yaml_print_bool(stream, prop->data.bool_value);
1430 4 case GATE_PROPERTY_TYPE_INT: return gate_yaml_print_int(stream, prop->data.int_value);
1431 2 case GATE_PROPERTY_TYPE_REAL: return gate_yaml_print_real(stream, prop->data.real_value);
1432 8 case GATE_PROPERTY_TYPE_STRING: return gate_yaml_print_string(stream, &prop->data.string_value);
1433 2 case GATE_PROPERTY_TYPE_ARRAY: return gate_yaml_print_array(stream, prop->data.array_value);
1434 2 case GATE_PROPERTY_TYPE_OBJECT: return gate_yaml_print_object(stream, prop);
1435 default: return GATE_RESULT_NOTSUPPORTED;
1436 }
1437 }
1438
1439 49 static gate_result_t gate_yaml_print_spaces(gate_size_t count, gate_stream_t* stream)
1440 {
1441 static gate_string_t const spaces = GATE_STRING_INIT_STATIC(" ");
1442 49 gate_result_t ret = GATE_RESULT_OK;
1443
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 49 times.
69 while (count > 0)
1444 {
1445 20 gate_size_t len = (count > spaces.length) ? spaces.length : count;
1446 gate_size_t lenwritten;
1447 20 ret = gate_stream_write_block(stream, spaces.str, len, &lenwritten);
1448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 GATE_BREAK_IF_FAILED(ret);
1449 20 count -= lenwritten;
1450 }
1451 49 return ret;
1452 }
1453
1454 49 static gate_result_t gate_yaml_print_indention(gate_stream_t* stream, gate_size_t spaces, gate_bool_t array_indicator)
1455 {
1456 gate_result_t ret;
1457 do
1458 {
1459
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)
1460 {
1461 ret = GATE_RESULT_INVALIDSTATE;
1462 break;
1463 }
1464
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 35 times.
49 if (array_indicator)
1465 {
1466 14 ret = gate_yaml_print_spaces(spaces - 2, stream);
1467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 GATE_BREAK_IF_FAILED(ret);
1468 14 ret = gate_stream_print_cstr(stream, "- ");
1469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 GATE_BREAK_IF_FAILED(ret);
1470 }
1471 else
1472 {
1473 35 ret = gate_yaml_print_spaces(spaces, stream);
1474
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 GATE_BREAK_IF_FAILED(ret);
1475 }
1476 } while (0);
1477 49 return ret;
1478 }
1479
1480 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)
1481 {
1482 29 gate_result_t ret = GATE_RESULT_FAILED;
1483 29 gate_array_t names = GATE_INIT_EMPTY;
1484
1485 do
1486 {
1487 29 gate_property_typeid_t const prop_type = gate_property_get_type(prop);
1488 gate_property_t const* ptr_item;
1489 gate_size_t count, index;
1490
1491
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)
1492 {
1493 2 case GATE_PROPERTY_TYPE_BOOL:
1494 {
1495 2 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1497 2 ret = gate_yaml_print_bool(stream, prop->data.bool_value);
1498
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1499 2 ret = gate_stream_println_cstr(stream, NULL);
1500 2 break;
1501 }
1502 8 case GATE_PROPERTY_TYPE_INT:
1503 {
1504 8 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
1506 8 ret = gate_yaml_print_int(stream, prop->data.int_value);
1507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 GATE_BREAK_IF_FAILED(ret);
1508 8 ret = gate_stream_println_cstr(stream, NULL);
1509 8 break;
1510 }
1511 1 case GATE_PROPERTY_TYPE_REAL:
1512 {
1513 1 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1515 1 ret = gate_yaml_print_real(stream, prop->data.real_value);
1516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1517 1 ret = gate_stream_println_cstr(stream, NULL);
1518 1 break;
1519 }
1520 6 case GATE_PROPERTY_TYPE_STRING:
1521 {
1522 6 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1524 6 ret = gate_yaml_print_string(stream, &prop->data.string_value);
1525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1526 6 ret = gate_stream_println_cstr(stream, NULL);
1527 6 break;
1528 }
1529 5 case GATE_PROPERTY_TYPE_ARRAY:
1530 {
1531 5 count = gate_property_array_length(prop);
1532
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if (count == 0)
1533 {
1534 1 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1535
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1536 1 ret = gate_stream_println_cstr(stream, "[]");
1537 }
1538 else
1539 {
1540
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 for (index = 0; index != count; ++index)
1541 {
1542 14 ptr_item = gate_property_array_get(prop, index);
1543
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
14 if (ptr_item)
1544 {
1545 14 ret = gate_yaml_print(ptr_item, stream, spaces + 2, true);
1546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 GATE_BREAK_IF_FAILED(ret);
1547 }
1548 }
1549 }
1550 5 break;
1551 }
1552 7 case GATE_PROPERTY_TYPE_OBJECT:
1553 {
1554
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (NULL == gate_property_member_names(prop, &names))
1555 {
1556 ret = GATE_RESULT_FAILED;
1557 break;
1558 }
1559 7 count = gate_array_length(&names);
1560
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (count == 0)
1561 {
1562 1 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1564 1 ret = gate_stream_print_cstr(stream, "{}");
1565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1566 }
1567 else
1568 {
1569
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 6 times.
36 for (index = 0; index != count; ++index)
1570 {
1571 30 gate_string_t const* ptr_name = (gate_string_t const*)gate_array_get(&names, index);
1572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!ptr_name)
1573 {
1574 continue;
1575 }
1576 30 ptr_item = gate_property_member_get(prop, ptr_name);
1577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (!ptr_item)
1578 {
1579 continue;
1580 }
1581 30 ret = gate_yaml_print_indention(stream, spaces, array_indicator);
1582
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1583 30 ret = gate_yaml_print_string(stream, ptr_name);
1584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1585 30 ret = gate_stream_print_cstr(stream, ": ");
1586
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1587 30 switch (gate_property_get_type(ptr_item))
1588 {
1589 18 case GATE_PROPERTY_TYPE_BOOL:
1590 case GATE_PROPERTY_TYPE_INT:
1591 case GATE_PROPERTY_TYPE_REAL:
1592 case GATE_PROPERTY_TYPE_STRING:
1593 {
1594 18 ret = gate_yaml_print_inline(ptr_item, stream);
1595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 GATE_BREAK_IF_FAILED(ret);
1596 18 ret = gate_stream_println_cstr(stream, NULL);
1597 18 break;
1598 }
1599 6 case GATE_PROPERTY_TYPE_ARRAY:
1600 {
1601
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (gate_property_array_length(ptr_item) == 0)
1602 {
1603 2 ret = gate_yaml_print_inline(ptr_item, stream);
1604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1605 2 ret = gate_stream_println_cstr(stream, NULL);
1606 }
1607 else
1608 {
1609 4 ret = gate_stream_println_cstr(stream, NULL);
1610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1611 4 ret = gate_yaml_print(ptr_item, stream, spaces + 2, false);
1612 }
1613 6 break;
1614 }
1615 6 case GATE_PROPERTY_TYPE_OBJECT:
1616 {
1617
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (gate_property_member_count(ptr_item) == 0)
1618 {
1619 2 ret = gate_yaml_print_inline(ptr_item, stream);
1620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1621 2 ret = gate_stream_println_cstr(stream, NULL);
1622 }
1623 else
1624 {
1625 4 ret = gate_stream_println_cstr(stream, NULL);
1626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1627 4 ret = gate_yaml_print(ptr_item, stream, spaces + 2, false);
1628 }
1629 6 break;
1630 }
1631 }
1632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 GATE_BREAK_IF_FAILED(ret);
1633 30 array_indicator = false;
1634 } /* for() */
1635 }
1636 7 break;
1637 }
1638 case GATE_PROPERTY_TYPE_EMPTY:
1639 default:
1640 {
1641 ret = GATE_RESULT_NOTSUPPORTED;
1642 break;
1643 }
1644 }
1645 } while (0);
1646
1647 29 gate_array_release(&names);
1648
1649 29 return ret;
1650 }
1651
1652 7 gate_result_t gate_yaml_build(gate_property_t const* prop, gate_stream_t* dest_builder)
1653 {
1654 7 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
1655
1656 char spaces[4096 * 2];
1657 gate_uint16_t indent_stack[1024];
1658
1659 7 gate_mem_fill(spaces, ' ', sizeof(spaces));
1660 7 gate_mem_clear(indent_stack, sizeof(indent_stack));
1661
1662 7 ret = gate_yaml_print(prop, dest_builder, 0, false);
1663
1664 7 return ret;
1665 }
1666
1667 6 gate_result_t gate_yaml_build_string(gate_property_t const* prop, gate_string_t* output)
1668 {
1669 6 gate_result_t ret = GATE_RESULT_FAILED;
1670 6 gate_stringstream_t* str_stream = NULL;
1671
1672 do
1673 {
1674 6 str_stream = gate_stringstream_create(256);
1675
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (str_stream == NULL)
1676 {
1677 ret = GATE_RESULT_OUTOFMEMORY;
1678 break;
1679 }
1680
1681 6 ret = gate_yaml_build(prop, (gate_stream_t*)str_stream);
1682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1683
1684 6 ret = gate_stringstream_to_string(str_stream, output);
1685 } while (0);
1686
1687
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (str_stream)
1688 {
1689 6 gate_object_release(str_stream);
1690 }
1691 6 return ret;
1692 }
1693