GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/yaml.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 543 886 61.3%
Functions: 26 28 92.9%
Branches: 210 462 45.5%

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