GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/xml.c
Date: 2026-10-19 17:06:30
Exec Total Coverage
Lines: 572 707 80.9%
Functions: 34 38 89.5%
Branches: 237 371 63.9%

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/xml.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32 #include "gate/utilities.h"
33
34
35
36 #define GATE_XML_CHAR_OPEN '<'
37 #define GATE_XML_CHAR_CLOSE '>'
38 #define GATE_XML_CHAR_END '/'
39 #define GATE_XML_CHAR_QUOTE '\"'
40 #define GATE_XML_CHAR_APOS '\''
41 #define GATE_XML_CHAR_EQUAL '='
42 #define GATE_XML_CHAR_AMPERSAND '&'
43 #define GATE_XML_CHAR_QUEST '?'
44 #define GATE_XML_CHAR_COLON ':'
45 #define GATE_XML_CHAR_EXCLAMATION '!'
46 #define GATE_XML_CHAR_SEMICOLON ';'
47
48 static char const GATE_XML_WHITESPACES[] = { ' ', '\r', '\n', '\t' };
49 #define GATE_XML_WHITESPACES_COUNT sizeof(GATE_XML_WHITESPACES)
50
51 #define GATE_XML_ENTITY_OPEN "&lt;"
52 #define GATE_XML_ENTITY_OPEN_LEN 4
53 #define GATE_XML_ENTITY_CLOSE "&gt;"
54 #define GATE_XML_ENTITY_CLOSE_LEN 4
55 #define GATE_XML_ENTITY_QUOTE "&quot;"
56 #define GATE_XML_ENTITY_QUOTE_LEN 6
57 #define GATE_XML_ENTITY_APOS "&apos;"
58 #define GATE_XML_ENTITY_APOS_LEN 6
59 #define GATE_XML_ENTITY_AMP "&amp;"
60 #define GATE_XML_ENTITY_AMP_LEN 5
61 #define GATE_XML_ENTITY_UNICODE_HEX "&#x"
62 #define GATE_XML_ENTITY_UNICODE_HEX_LEN 3
63 #define GATE_XML_ENTITY_UNICODE_DEC "&#"
64 #define GATE_XML_ENTITY_UNICODE_DEC_LEN 2
65
66 #define GATE_XML_CDATABEGIN "<![CDATA["
67 #define GATE_XML_CDATABEGIN_LENGTH 9
68 #define GATE_XML_CDATAEND "]]>"
69 #define GATE_XML_CDATAEND_LENGTH 3
70
71 #define GATE_XML_COMMENTBEGIN "<!--"
72 #define GATE_XML_COMMENTBEGIN_LENGTH 4
73 #define GATE_XML_COMMENTEND "-->"
74 #define GATE_XML_COMMENTEND_LENGTH 3
75
76 #define GATE_XML_DECLBEGIN "<?"
77 #define GATE_XML_DECLBEGIN_LENGTH 2
78 #define GATE_XML_DECLEND "?>"
79 #define GATE_XML_DECLEND_LENGTH 2
80
81
82 static char const xml_escape_chars[] =
83 {
84 GATE_XML_CHAR_OPEN, GATE_XML_CHAR_CLOSE, GATE_XML_CHAR_QUOTE, GATE_XML_CHAR_APOS, GATE_XML_CHAR_AMPERSAND
85 };
86 static gate_size_t xml_escape_chars_count = sizeof(xml_escape_chars);
87
88
89 2 gate_result_t gate_xml_encode(gate_string_t const* plaintext, gate_string_t* xmltext)
90 {
91 2 gate_result_t ret = GATE_RESULT_OK;
92 2 gate_strbuilder_t builder = GATE_INIT_EMPTY;
93
94 do
95 {
96 2 char const* ptr = gate_string_ptr(plaintext, 0);
97 2 gate_size_t len = gate_string_length(plaintext);
98 2 gate_size_t pos = gate_str_find_first_of(ptr, len, xml_escape_chars, xml_escape_chars_count, 0);
99
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_STR_NPOS == pos)
100 {
101 /* nothing to encode, we can copy the string */
102 ✗ if (NULL == gate_string_duplicate(xmltext, plaintext))
103 {
104 ✗ ret = GATE_RESULT_OUTOFMEMORY;
105 ✗ break;
106 }
107 }
108 else
109 {
110 2 gate_strbuilder_create(&builder, plaintext->length + 16 + plaintext->length / 10);
111
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 2 times.
31 while (len-- != 0)
112 {
113
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 22 times.
29 switch (*ptr)
114 {
115 1 case GATE_XML_CHAR_OPEN:
116 {
117
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_text(&builder, GATE_XML_ENTITY_OPEN, GATE_XML_ENTITY_OPEN_LEN))
118 {
119 ✗ ret = GATE_RESULT_OUTOFMEMORY;
120 }
121 1 break;
122 }
123 1 case GATE_XML_CHAR_CLOSE:
124 {
125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_text(&builder, GATE_XML_ENTITY_CLOSE, GATE_XML_ENTITY_CLOSE_LEN))
126 {
127 ✗ ret = GATE_RESULT_OUTOFMEMORY;
128 }
129 1 break;
130 }
131 2 case GATE_XML_CHAR_QUOTE:
132 {
133
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (0 == gate_strbuilder_append_text(&builder, GATE_XML_ENTITY_QUOTE, GATE_XML_ENTITY_QUOTE_LEN))
134 {
135 ✗ ret = GATE_RESULT_OUTOFMEMORY;
136 }
137 2 break;
138 }
139 2 case GATE_XML_CHAR_APOS:
140 {
141
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (0 == gate_strbuilder_append_text(&builder, GATE_XML_ENTITY_APOS, GATE_XML_ENTITY_APOS_LEN))
142 {
143 ✗ ret = GATE_RESULT_OUTOFMEMORY;
144 }
145 2 break;
146 }
147 1 case GATE_XML_CHAR_AMPERSAND:
148 {
149
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_strbuilder_append_text(&builder, GATE_XML_ENTITY_AMP, GATE_XML_ENTITY_AMP_LEN))
150 {
151 ✗ ret = GATE_RESULT_OUTOFMEMORY;
152 }
153 1 break;
154 }
155 22 default:
156 {
157
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if (0 == gate_strbuilder_append_text(&builder, ptr, 1))
158 {
159 ✗ ret = GATE_RESULT_OUTOFMEMORY;
160 }
161 22 break;
162 }
163 }
164 29 ++ptr;
165 }
166
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
167 {
168
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_strbuilder_to_string(&builder, xmltext))
169 {
170 ✗ ret = GATE_RESULT_OUTOFMEMORY;
171 }
172 }
173 }
174
175 } while (0);
176
177 2 gate_strbuilder_release(&builder);
178
179 2 return ret;
180 }
181 126 gate_result_t gate_xml_decode(gate_string_t const* xmltext, gate_string_t* plaintext)
182 {
183 126 gate_result_t ret = GATE_RESULT_OK;
184 126 gate_strbuilder_t builder = GATE_INIT_EMPTY;
185
186 do
187 {
188 126 char const* ptr = gate_string_ptr(xmltext, 0);
189 126 gate_size_t len = gate_string_length(xmltext);
190 126 gate_size_t pos = gate_str_char_pos(ptr, len, GATE_XML_CHAR_AMPERSAND, 0);
191
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 44 times.
126 if (GATE_STR_NPOS == pos)
192 {
193 /* nothing to decode -> return copy of string */
194
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
82 if (NULL == gate_string_duplicate(plaintext, xmltext))
195 {
196 ✗ ret = GATE_RESULT_OUTOFMEMORY;
197 }
198 82 break;
199 }
200
201 44 gate_strbuilder_create(&builder, len);
202
203
2/2
✓ Branch 0 taken 23747 times.
✓ Branch 1 taken 44 times.
23791 while (len != 0)
204 {
205 char chars_to_add[8];
206 23747 gate_size_t chars_to_add_len = 1;
207 gate_size_t chars_decoded;
208 gate_uint64_t u64;
209 gate_char32_t chr32;
210
211
2/2
✓ Branch 0 taken 1242 times.
✓ Branch 1 taken 22505 times.
23747 if (*ptr == GATE_XML_CHAR_AMPERSAND)
212 {
213
2/2
✓ Branch 1 taken 570 times.
✓ Branch 2 taken 672 times.
1242 if (gate_str_starts_with(ptr, len, GATE_XML_ENTITY_OPEN, GATE_XML_ENTITY_OPEN_LEN))
214 {
215 570 chars_to_add[0] = GATE_XML_CHAR_OPEN;
216 570 chars_decoded = GATE_XML_ENTITY_OPEN_LEN;
217 }
218
2/2
✓ Branch 1 taken 570 times.
✓ Branch 2 taken 102 times.
672 else if (gate_str_starts_with(ptr, len, GATE_XML_ENTITY_CLOSE, GATE_XML_ENTITY_CLOSE_LEN))
219 {
220 570 chars_to_add[0] = GATE_XML_CHAR_CLOSE;
221 570 chars_decoded = GATE_XML_ENTITY_CLOSE_LEN;
222 }
223
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 100 times.
102 else if (gate_str_starts_with(ptr, len, GATE_XML_ENTITY_QUOTE, GATE_XML_ENTITY_QUOTE_LEN))
224 {
225 2 chars_to_add[0] = GATE_XML_CHAR_QUOTE;
226 2 chars_decoded = GATE_XML_ENTITY_QUOTE_LEN;
227 }
228
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 98 times.
100 else if (gate_str_starts_with(ptr, len, GATE_XML_ENTITY_APOS, GATE_XML_ENTITY_APOS_LEN))
229 {
230 2 chars_to_add[0] = GATE_XML_CHAR_APOS;
231 2 chars_decoded = GATE_XML_ENTITY_APOS_LEN;
232 }
233
2/2
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 47 times.
98 else if (gate_str_starts_with(ptr, len, GATE_XML_ENTITY_AMP, GATE_XML_ENTITY_AMP_LEN))
234 {
235 51 chars_to_add[0] = GATE_XML_CHAR_AMPERSAND;
236 51 chars_decoded = GATE_XML_ENTITY_AMP_LEN;
237 }
238
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 46 times.
47 else if (gate_str_starts_with(ptr, len, GATE_XML_ENTITY_UNICODE_HEX, GATE_XML_ENTITY_UNICODE_HEX_LEN))
239 {
240 1 pos = gate_str_char_pos(ptr, len, GATE_XML_CHAR_SEMICOLON, GATE_XML_ENTITY_UNICODE_HEX_LEN);
241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_STR_NPOS == pos)
242 {
243 ✗ ret = GATE_RESULT_INVALIDDATA;
244 ✗ break;
245 }
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (0 == gate_str_parse_hex_int(ptr + GATE_XML_ENTITY_UNICODE_HEX_LEN, pos - GATE_XML_ENTITY_UNICODE_HEX_LEN, &u64))
247 {
248 ✗ ret = GATE_RESULT_INVALIDDATA;
249 ✗ break;
250 }
251 1 chr32 = (gate_char32_t)u64;
252 1 chars_to_add_len = gate_char_write_utf8(chr32, chars_to_add, sizeof(chars_to_add));
253 1 chars_decoded = pos + 1;
254 }
255
1/2
✓ Branch 1 taken 46 times.
✗ Branch 2 not taken.
46 else if (gate_str_starts_with(ptr, len, GATE_XML_ENTITY_UNICODE_DEC, GATE_XML_ENTITY_UNICODE_DEC_LEN))
256 {
257 46 pos = gate_str_char_pos(ptr, len, GATE_XML_CHAR_SEMICOLON, GATE_XML_ENTITY_UNICODE_HEX_LEN);
258
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (GATE_STR_NPOS == pos)
259 {
260 ✗ ret = GATE_RESULT_INVALIDDATA;
261 ✗ break;
262 }
263
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46 times.
46 if (0 == gate_str_parse_uint64(ptr + GATE_XML_ENTITY_UNICODE_DEC_LEN, pos - GATE_XML_ENTITY_UNICODE_DEC_LEN, &u64))
264 {
265 ✗ ret = GATE_RESULT_INVALIDDATA;
266 ✗ break;
267 }
268 46 chr32 = (gate_char32_t)u64;
269 46 chars_to_add_len = gate_char_write_utf8(chr32, chars_to_add, sizeof(chars_to_add));
270 46 chars_decoded = pos + 1;
271 }
272 else
273 {
274 ✗ chars_to_add[0] = *ptr;
275 ✗ chars_decoded = 1;
276 }
277 }
278 else
279 {
280 22505 chars_to_add[0] = *ptr;
281 22505 chars_decoded = 1;
282 }
283
284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23747 times.
23747 if (chars_to_add_len == 0)
285 {
286 ✗ ret = GATE_RESULT_INVALIDOUTPUT;
287 ✗ break;
288 }
289
290
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 23747 times.
23747 if (0 == gate_strbuilder_append_text(&builder, chars_to_add, chars_to_add_len))
291 {
292 ✗ ret = GATE_RESULT_OUTOFMEMORY;
293 ✗ break;
294 }
295
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23747 times.
23747 if (chars_decoded > len)
297 {
298 ✗ ret = GATE_RESULT_CRITICALERROR;
299 ✗ break;
300 }
301
302 23747 len -= chars_decoded;
303 23747 ptr += chars_decoded;
304 }
305
306
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 if (GATE_SUCCEEDED(ret))
307 {
308
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
44 if (NULL == gate_strbuilder_to_string(&builder, plaintext))
309 {
310 ✗ ret = GATE_RESULT_OUTOFMEMORY;
311 ✗ break;
312 }
313 }
314 } while (0);
315
316 126 gate_strbuilder_release(&builder);
317
318 126 return ret;
319 }
320
321
322 203 static gate_result_t GATE_CALL gate_xml_pair_cctor(void* dest, void const* src)
323 {
324 203 gate_xml_pair_t* dest_pair = (gate_xml_pair_t*)dest;
325 203 gate_xml_pair_t const* src_pair = (gate_xml_pair_t const*)src;
326
327
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 203 times.
203 if (NULL == gate_string_duplicate(&dest_pair->key, &src_pair->key))
328 {
329 ✗ return GATE_RESULT_OUTOFMEMORY;
330 }
331
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 203 times.
203 if (NULL == gate_string_duplicate(&dest_pair->value, &src_pair->value))
332 {
333 ✗ gate_string_release(&dest_pair->key);
334 ✗ return GATE_RESULT_OUTOFMEMORY;
335 }
336 203 return GATE_RESULT_OK;
337 }
338 518 static void GATE_CALL gate_xml_pair_dtor(void* dest)
339 {
340 518 gate_xml_pair_t* dest_pair = (gate_xml_pair_t*)dest;
341 518 gate_string_release(&dest_pair->key);
342 518 gate_string_release(&dest_pair->value);
343 518 }
344
345
346 797 gate_result_t gate_xml_node_create(gate_xml_node_t* node, gate_enumint_t node_type,
347 gate_string_t const* tag, gate_array_t const* attributes,
348 gate_array_t const* child_nodes, gate_string_t const* content)
349 {
350 797 gate_result_t ret = GATE_RESULT_FAILED;
351 do
352 {
353 797 gate_mem_clear(node, sizeof(gate_xml_node_t));
354 797 node->node_type = node_type;
355
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 797 times.
797 if (NULL == gate_string_duplicate(&node->tag, tag))
356 {
357 ✗ ret = GATE_RESULT_OUTOFMEMORY;
358 ✗ break;
359 }
360
361
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 797 times.
797 if (NULL == gate_array_duplicate(&node->attributes, attributes))
362 {
363 ✗ ret = GATE_RESULT_OUTOFMEMORY;
364 ✗ break;
365 }
366
367
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 797 times.
797 if (NULL == gate_array_duplicate(&node->child_nodes, child_nodes))
368 {
369 ✗ ret = GATE_RESULT_OUTOFMEMORY;
370 ✗ break;
371 }
372
373
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 797 times.
797 if (NULL == gate_string_duplicate(&node->content, content))
374 {
375 ✗ ret = GATE_RESULT_OUTOFMEMORY;
376 ✗ break;
377 }
378 797 ret = GATE_RESULT_OK;
379 } while (0);
380
381
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 797 times.
797 if (GATE_FAILED(ret))
382 {
383 ✗ gate_xml_node_destroy(node);
384
385 }
386 797 return ret;
387 }
388
389 846 gate_xml_node_t* gate_xml_node_duplicate(gate_xml_node_t* dest, gate_xml_node_t const* src)
390 {
391 846 gate_mem_clear(dest, sizeof(gate_xml_node_t));
392
393 846 gate_string_duplicate(&dest->tag, &src->tag);
394 846 gate_array_duplicate(&dest->attributes, &src->attributes);
395 846 gate_array_duplicate(&dest->child_nodes, &src->child_nodes);
396 846 gate_string_duplicate(&dest->content, &src->content);
397 846 dest->node_type = src->node_type;
398 846 return dest;
399 }
400
401
402 2449 gate_result_t gate_xml_node_destroy(gate_xml_node_t* node)
403 {
404 2449 gate_result_t ret = GATE_RESULT_OK;
405
406 2449 gate_string_release(&node->tag);
407 2449 gate_array_release(&node->attributes);
408 2449 gate_array_release(&node->child_nodes);
409 2449 gate_string_release(&node->content);
410
411 2449 gate_mem_clear(node, sizeof(gate_xml_node_t));
412
413 2449 return ret;
414 }
415
416 844 gate_result_t gate_xml_node_copy_constructor(void* destMem, void const* srcMem)
417 {
418
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 844 times.
844 if (NULL == gate_xml_node_duplicate((gate_xml_node_t*)destMem, (gate_xml_node_t const*)srcMem))
419 {
420 ✗ return GATE_RESULT_OUTOFMEMORY;
421 }
422 else
423 {
424 844 return GATE_RESULT_OK;
425 }
426 }
427 844 void gate_xml_node_destructor(void* destMem)
428 {
429 844 gate_xml_node_destroy((gate_xml_node_t*)destMem);
430 844 }
431
432
433 2 gate_result_t gate_xml_node_attribute_by_name(gate_xml_node_t const* node, gate_string_t const* attr_name, gate_string_t* attr_value)
434 {
435 2 gate_size_t const length = gate_array_length(&node->attributes);
436 gate_size_t index;
437
438
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (index = 0; index != length; ++index)
439 {
440 2 gate_xml_pair_t const* ptr_pair = (gate_xml_pair_t const*)gate_array_get(&node->attributes, index);
441
442
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (0 == gate_string_comp(attr_name, &ptr_pair->key))
443 {
444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_string_duplicate(attr_value, &ptr_pair->value))
445 {
446 ✗ return GATE_RESULT_OUTOFMEMORY;
447 }
448 else
449 {
450 1 return GATE_RESULT_OK;
451 }
452 }
453 }
454 1 return GATE_RESULT_NOMATCH;
455 }
456
457 23 gate_string_t const* gate_xml_node_attribute_ptr_by_name(gate_xml_node_t const* node, gate_string_t const* attr_name)
458 {
459 23 gate_size_t const length = gate_array_length(&node->attributes);
460 gate_size_t index;
461
462
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 1 times.
66 for (index = 0; index != length; ++index)
463 {
464 65 gate_xml_pair_t const* ptr_pair = (gate_xml_pair_t const*)gate_array_get(&node->attributes, index);
465
466
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 43 times.
65 if (0 == gate_string_comp(attr_name, &ptr_pair->key))
467 {
468 22 return &ptr_pair->value;
469 }
470 }
471 1 return NULL;
472 }
473
474
475 1 gate_size_t gate_xml_node_attribute_count(gate_xml_node_t const* node)
476 {
477 1 return gate_array_length(&node->attributes);
478 }
479
480 1 gate_result_t gate_xml_node_attribute_by_index(gate_xml_node_t const* node, gate_size_t index,
481 gate_string_t* attr_name, gate_string_t* attr_value)
482 {
483 1 gate_xml_pair_t const* ptr_pair = (gate_xml_pair_t const*)gate_array_get(&node->attributes, index);
484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == ptr_pair)
485 {
486 ✗ return GATE_RESULT_OUTOFBOUNDS;
487 }
488 else
489 {
490
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (attr_name)
491 {
492 1 gate_string_duplicate(attr_name, &ptr_pair->key);
493 }
494
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (attr_value)
495 {
496 1 gate_string_duplicate(attr_value, &ptr_pair->value);
497 }
498 1 return GATE_RESULT_OK;
499 }
500 }
501
502 259 gate_size_t gate_xml_node_children_count(gate_xml_node_t const* node)
503 {
504 259 return gate_array_length(&node->child_nodes);
505 }
506
507 5 gate_result_t gate_xml_node_child(gate_xml_node_t const* node, gate_size_t index, gate_xml_node_t* child)
508 {
509 5 gate_xml_node_t const* const ptr = (gate_xml_node_t const*)gate_array_get(&node->child_nodes, index);
510
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (ptr)
511 {
512 5 return gate_xml_node_create(child, ptr->node_type, &ptr->tag, &ptr->attributes, &ptr->child_nodes, &ptr->content);
513 }
514 else
515 {
516 ✗ return GATE_RESULT_OUTOFBOUNDS;
517 }
518 }
519
520 1163 gate_xml_node_t const* gate_xml_node_child_ptr(gate_xml_node_t const* node, gate_size_t index)
521 {
522 1163 gate_xml_node_t const* const ptr = (gate_xml_node_t const*)gate_array_get(&node->child_nodes, index);
523 1163 return ptr;
524 }
525
526
527 796 gate_size_t gate_xml_parse_tag_content(gate_string_t const* text, gate_string_t* tag_content, gate_enumint_t* ptr_node_type)
528 {
529 796 gate_size_t chars_parsed = 0;
530 796 gate_enumint_t node_type = GATE_XML_NODE_TYPE_NONE;
531 796 gate_string_t dummy = GATE_STRING_INIT_EMPTY;
532
533 do
534 {
535 796 gate_size_t const text_len = gate_string_length(text);
536 796 char const* ptr_text = gate_string_ptr(text, 0);
537 gate_size_t pos;
538
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 796 times.
796 if (NULL == tag_content)
540 {
541 ✗ tag_content = &dummy;
542 }
543
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 796 times.
796 if (text_len < 3)
545 { /* smallest tag has at least 3 characters: e.g. "<a>" */
546 ✗ break;
547 }
548
549
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 795 times.
796 if (*ptr_text != GATE_XML_CHAR_OPEN)
550 { /* tag must begin with open-character */
551 1 break;
552 }
553
554 /* check for comment */
555
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 793 times.
795 if (gate_str_starts_with(ptr_text, text_len, GATE_XML_COMMENTBEGIN, GATE_XML_COMMENTBEGIN_LENGTH))
556 {
557 /* comment node detected */
558 2 node_type = GATE_XML_NODE_TYPE_COMMENT;
559 2 pos = gate_str_pos(ptr_text, text_len, GATE_XML_COMMENTEND, GATE_XML_COMMENTEND_LENGTH, GATE_XML_COMMENTBEGIN_LENGTH);
560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_STR_NPOS == pos)
561 {
562 /* comment-ending not found */
563 ✗ break;
564 }
565
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_string_substr(tag_content, text, GATE_XML_COMMENTBEGIN_LENGTH, pos - GATE_XML_COMMENTBEGIN_LENGTH))
566 {
567 /* substring allocation failed */
568 ✗ break;
569 }
570
571 2 chars_parsed = pos + GATE_XML_COMMENTEND_LENGTH;
572 2 break;
573 }
574
575 /* check for CDATA */
576
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 791 times.
793 if (gate_str_starts_with(ptr_text, text_len, GATE_XML_CDATABEGIN, GATE_XML_CDATABEGIN_LENGTH))
577 {
578 /* CDATA node detected */
579 2 node_type = GATE_XML_NODE_TYPE_CDATA;
580 2 pos = gate_str_pos(ptr_text, text_len, GATE_XML_CDATAEND, GATE_XML_CDATAEND_LENGTH, GATE_XML_CDATABEGIN_LENGTH);
581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_STR_NPOS == pos)
582 {
583 /* CDATA-ending not found */
584 ✗ break;
585 }
586
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_string_substr(tag_content, text, GATE_XML_CDATABEGIN_LENGTH, pos - GATE_XML_CDATABEGIN_LENGTH))
587 {
588 /* substring allocation failed */
589 ✗ break;
590 }
591
592 2 chars_parsed = pos + GATE_XML_CDATAEND_LENGTH;
593 2 break;
594 }
595
596 /* check for DECLARATION */
597
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 789 times.
791 if (gate_str_starts_with(ptr_text, text_len, GATE_XML_DECLBEGIN, GATE_XML_DECLBEGIN_LENGTH))
598 {
599 /* DECLARATION node detected */
600 2 node_type = GATE_XML_NODE_TYPE_DECLARATION;
601 2 pos = gate_str_pos(ptr_text, text_len, GATE_XML_DECLEND, GATE_XML_DECLEND_LENGTH, GATE_XML_DECLBEGIN_LENGTH);
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_STR_NPOS == pos)
603 {
604 /* DECLARATION-ending not found */
605 ✗ break;
606 }
607
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_string_substr(tag_content, text, GATE_XML_DECLBEGIN_LENGTH, pos - GATE_XML_DECLBEGIN_LENGTH))
608 {
609 /* substring allocation failed */
610 ✗ break;
611 }
612 2 gate_string_trim(tag_content, tag_content);
613
614 2 chars_parsed = pos + GATE_XML_DECLEND_LENGTH;
615 2 break;
616 }
617
618 /* generic DTD*/
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 789 times.
789 if (ptr_text[1] == GATE_XML_CHAR_EXCLAMATION)
620 {
621 /* DTD node detected */
622 ✗ node_type = GATE_XML_NODE_TYPE_DTD;
623 ✗ pos = gate_str_char_pos(ptr_text, text_len, GATE_XML_CHAR_CLOSE, 2);
624 ✗ if (GATE_STR_NPOS == pos)
625 {
626 /* TAG-ending not found */
627 ✗ break;
628 }
629 ✗ if (NULL == gate_string_substr(tag_content, text, 2, pos - 2))
630 {
631 /* substring allocation failed */
632 ✗ break;
633 }
634
635 ✗ chars_parsed = pos + 1;
636 ✗ break;
637 }
638
639 /* otherwise: assume a regular ELEMENT tag */
640 789 node_type = GATE_XML_NODE_TYPE_ELEMENT;
641 789 pos = gate_str_char_pos(ptr_text, text_len, GATE_XML_CHAR_CLOSE, 1);
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 789 times.
789 if (GATE_STR_NPOS == pos)
643 {
644 /* TAG-ending not found */
645 ✗ break;
646 }
647
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 789 times.
789 if (NULL == gate_string_substr(tag_content, text, 1, pos - 1))
648 {
649 /* substring allocation failed */
650 ✗ break;
651 }
652 789 gate_string_trim(tag_content, tag_content);
653
654 789 chars_parsed = pos + 1;
655 789 break;
656
657
658 } while (0);
659
660
1/2
✓ Branch 0 taken 796 times.
✗ Branch 1 not taken.
796 if (NULL != ptr_node_type)
661 {
662 796 *ptr_node_type = node_type;
663 }
664
665 796 gate_string_release(&dummy);
666
667 796 return chars_parsed;
668 }
669
670
671 2 gate_result_t gate_xml_parse_decompose_name(gate_string_t const* attribname, gate_string_t* prefix, gate_string_t* localname)
672 {
673 2 gate_result_t ret = GATE_RESULT_OK;
674 2 gate_size_t pos = gate_string_char_pos(attribname, GATE_XML_CHAR_COLON, 0);
675
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_STR_NPOS == pos)
676 {
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (prefix)
678 {
679 ✗ gate_string_create_empty(prefix);
680 }
681
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (attribname)
682 {
683 2 gate_string_duplicate(localname, attribname);
684 }
685 }
686 else
687 {
688 ✗ gate_size_t len = gate_string_length(attribname);
689 ✗ if ((pos == 0) && (pos + 1 == len))
690 {
691 ✗ ret = GATE_RESULT_INVALIDCONTENT;
692 }
693 else
694 {
695 ✗ if (prefix)
696 {
697 ✗ gate_string_substr(prefix, attribname, 0, pos);
698 }
699 ✗ if (attribname)
700 {
701 ✗ gate_string_substr(localname, attribname, pos + 1, len - pos - 1);
702 }
703 }
704 }
705 2 return ret;
706 }
707
708 103 static gate_result_t gate_xml_node_parse_attributes(gate_string_t* tag_attribs, gate_arraylist_t list)
709 {
710 103 gate_result_t ret = GATE_RESULT_OK;
711 103 gate_xml_pair_t attr_pair = GATE_INIT_EMPTY;
712
713 103 gate_mem_clear(&attr_pair, sizeof(attr_pair));
714
715
2/2
✓ Branch 2 taken 205 times.
✓ Branch 3 taken 100 times.
305 while (!gate_string_is_empty(gate_string_ltrim(tag_attribs, tag_attribs)))
716 {
717 char quot_char;
718 205 gate_size_t pos = gate_string_char_pos(tag_attribs, GATE_XML_CHAR_EQUAL, 0);
719
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 204 times.
205 if (GATE_STR_NPOS == pos)
720 {
721 1 ret = GATE_RESULT_INVALIDCONTENT;
722 1 break;
723 }
724
725 204 gate_string_substr(&attr_pair.key, tag_attribs, 0, pos);
726
727 204 gate_string_substr(tag_attribs, tag_attribs, pos + 1, GATE_STR_NPOS);
728 204 gate_string_ltrim(tag_attribs, tag_attribs);
729
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 204 times.
204 if (gate_string_is_empty(tag_attribs))
730 {
731 ✗ ret = GATE_RESULT_INVALIDCONTENT;
732 ✗ break;
733 }
734 204 quot_char = tag_attribs->str[0];
735 204 pos = gate_str_char_pos(tag_attribs->str, tag_attribs->length, quot_char, 1);
736
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 202 times.
204 if (GATE_STR_NPOS == pos)
737 {
738 2 ret = GATE_RESULT_INVALIDCONTENT;
739 2 break;
740 }
741 202 gate_string_substr(&attr_pair.value, tag_attribs, 1, pos - 1);
742
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 202 times.
202 if (NULL == gate_arraylist_add(list, &attr_pair))
743 {
744 ✗ ret = GATE_RESULT_OUTOFMEMORY;
745 ✗ break;
746 }
747 202 gate_xml_pair_dtor(&attr_pair);
748
749 202 gate_string_substr(tag_attribs, tag_attribs, pos + 1, GATE_STR_NPOS);
750
751 }
752 103 gate_xml_pair_dtor(&attr_pair);
753
754 103 return ret;
755 }
756
757 791 static gate_result_t gate_xml_node_parse_tag_content(gate_string_t const* tag_content, gate_string_t* tag_name, gate_array_t* attribs)
758 {
759 791 gate_result_t ret = GATE_RESULT_OK;
760 791 gate_string_t attrib_content = GATE_STRING_INIT_EMPTY;
761 791 gate_arraylist_t attrib_list = GATE_INIT_EMPTY;
762
763 do
764 {
765 791 gate_size_t pos = gate_str_find_first_of(tag_content->str, tag_content->length, GATE_XML_WHITESPACES, GATE_XML_WHITESPACES_COUNT, 0);
766
2/2
✓ Branch 0 taken 688 times.
✓ Branch 1 taken 103 times.
791 if (GATE_STR_NPOS == pos)
767 {
768 688 gate_string_duplicate(tag_name, tag_content);
769
1/2
✓ Branch 0 taken 688 times.
✗ Branch 1 not taken.
688 if (attribs != NULL)
770 {
771 688 gate_array_create_empty(attribs);
772 }
773 /* done, no attributes, tag completed */
774 688 break;
775 }
776
777 103 gate_string_substr(tag_name, tag_content, 0, pos);
778 103 gate_string_substr(&attrib_content, tag_content, pos + 1, GATE_STR_NPOS);
779 103 attrib_list = gate_arraylist_create(sizeof(gate_xml_pair_t), NULL, 8, &gate_xml_pair_cctor, &gate_xml_pair_dtor);
780
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 103 times.
103 if (gate_arraylist_is_null(attrib_list))
781 {
782 ✗ ret = GATE_RESULT_OUTOFMEMORY;
783 ✗ break;
784 }
785 103 ret = gate_xml_node_parse_attributes(&attrib_content, attrib_list);
786
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 100 times.
103 GATE_BREAK_IF_FAILED(ret);
787
1/2
✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
100 if (attribs != NULL)
788 {
789 100 gate_array_create(attribs, attrib_list);
790 }
791 100 ret = GATE_RESULT_OK;
792 } while (0);
793
794 791 gate_arraylist_release(&attrib_list);
795 791 gate_string_release(&attrib_content);
796 791 return ret;
797 }
798
799 796 gate_result_t gate_xml_node_parse(gate_string_t const* source, gate_xml_node_t* node, gate_size_t* bytes_parsed)
800 {
801 796 gate_result_t ret = GATE_RESULT_FAILED;
802 796 gate_string_t tag = GATE_STRING_INIT_EMPTY;
803 796 gate_string_t tag_content = GATE_STRING_INIT_EMPTY;
804 796 gate_string_t tag_name = GATE_STRING_INIT_EMPTY;
805 796 gate_array_t tag_attribs = GATE_INIT_EMPTY;
806 796 gate_arraylist_t sub_node_list = GATE_INIT_EMPTY;
807 796 gate_xml_node_t sub_node = GATE_INIT_EMPTY;
808 796 gate_array_t sub_nodes = GATE_INIT_EMPTY;
809 796 gate_string_t post_tag_data = GATE_STRING_INIT_EMPTY;
810 796 gate_string_t tag_text = GATE_STRING_INIT_EMPTY;
811 796 gate_enumint_t node_type = 0;
812 796 gate_size_t bytes_processed = 0;
813 796 gate_size_t subnode_bytes = 0;
814 gate_size_t count;
815 gate_bool_t single_tag;
816 gate_size_t pos;
817 gate_bool_t continue_sub_node_parsing;
818
819 do
820 {
821 796 gate_string_ltrim(&tag, source);
822
823 796 bytes_processed += gate_string_length(source) - gate_string_length(&tag);
824
825 796 count = gate_xml_parse_tag_content(&tag, &tag_content, &node_type);
826
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 795 times.
796 if (count == 0)
827 {
828 1 ret = GATE_RESULT_INVALIDCONTENT;
829 1 break;
830 }
831 795 gate_string_substr(&post_tag_data, &tag, count, GATE_STR_NPOS);
832 795 bytes_processed += count;
833
834 795 gate_string_trim(&tag_content, &tag_content);
835
836
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 789 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
795 switch (node_type)
837 {
838 ✗ case GATE_XML_NODE_TYPE_DTD:
839 {
840 ✗ ret = GATE_RESULT_NOTSUPPORTED;
841 ✗ break;
842 }
843 2 case GATE_XML_NODE_TYPE_DECLARATION:
844 {
845 2 ret = gate_xml_node_parse_tag_content(&tag_content, &tag_name, &tag_attribs);
846
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
847 2 ret = gate_xml_node_create(node, GATE_XML_NODE_TYPE_DECLARATION, &tag_name, &tag_attribs, NULL, NULL);
848 2 break;
849 }
850 2 case GATE_XML_NODE_TYPE_COMMENT:
851 {
852 2 ret = gate_xml_node_create(node, GATE_XML_NODE_TYPE_COMMENT, NULL, NULL, NULL, &tag_content);
853 2 break;
854 }
855 789 case GATE_XML_NODE_TYPE_ELEMENT:
856 {
857 789 single_tag = false;
858
2/2
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 747 times.
789 if (gate_string_ends_with_char(&tag_content, GATE_XML_CHAR_END))
859 {
860 42 single_tag = true;
861 42 gate_string_substr(&tag_content, &tag_content, 0, gate_string_length(&tag_content) - 1);
862 42 gate_string_rtrim(&tag_content, &tag_content);
863 }
864
2/2
✓ Branch 1 taken 371 times.
✓ Branch 2 taken 376 times.
747 else if (gate_string_starts_with_char(&tag_content, GATE_XML_CHAR_END))
865 {
866 371 single_tag = true;
867 371 gate_string_trim(&tag_content, &tag_content);
868 }
869
870 789 ret = gate_xml_node_parse_tag_content(&tag_content, &tag_name, &tag_attribs);
871
872
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 786 times.
789 if (GATE_FAILED(ret))
873 {
874 3 break;
875 }
876
877
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 413 times.
786 if (!single_tag)
878 {
879 373 continue_sub_node_parsing = true;
880 373 sub_node_list = gate_arraylist_create(sizeof(gate_xml_node_t), NULL, 0, &gate_xml_node_copy_constructor, &gate_xml_node_destructor);
881
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 373 times.
373 if (gate_arraylist_is_null(sub_node_list))
882 {
883 ✗ ret = GATE_RESULT_OUTOFMEMORY;
884 }
885 else
886 {
887
2/2
✓ Branch 0 taken 784 times.
✓ Branch 1 taken 371 times.
1155 while (continue_sub_node_parsing)
888 {
889 784 pos = gate_string_char_pos(&post_tag_data, GATE_XML_CHAR_OPEN, 0);
890
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 783 times.
784 if (pos == GATE_STR_NPOS)
891 {
892 /* error: missing xml end tag */
893 1 ret = GATE_RESULT_INVALIDDATA;
894 1 break;
895 }
896 783 gate_string_substr(&tag_text, &post_tag_data, 0, pos);
897 783 gate_string_substr(&post_tag_data, &post_tag_data, pos, GATE_STR_NPOS);
898 783 bytes_processed += pos;
899 783 ret = gate_xml_node_parse(&post_tag_data, &sub_node, &subnode_bytes);
900
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 782 times.
783 GATE_BREAK_IF_FAILED(ret);
901
902 782 bytes_processed += subnode_bytes;
903 782 gate_string_substr(&post_tag_data, &post_tag_data, subnode_bytes, GATE_STR_NPOS);
904
905
2/2
✓ Branch 1 taken 371 times.
✓ Branch 2 taken 411 times.
782 if (gate_string_starts_with_char(&sub_node.tag, GATE_XML_CHAR_END))
906 {
907
2/2
✓ Branch 1 taken 369 times.
✓ Branch 2 taken 2 times.
371 if (0 == gate_str_compare(tag_name.str, tag_name.length, sub_node.tag.str + 1, sub_node.tag.length - 1))
908 {
909 /* end tag found */
910 369 continue_sub_node_parsing = false;
911 }
912 else
913 {
914 /* end tag does not match the opening tag -> XML corrupt */
915 2 ret = GATE_RESULT_INVALIDDATA;
916 2 continue_sub_node_parsing = false;
917 }
918 }
919 else
920 {
921 411 gate_string_release(&tag_text);
922
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 411 times.
411 if (NULL == gate_arraylist_add(sub_node_list, &sub_node))
923 {
924 ✗ ret = GATE_RESULT_OUTOFMEMORY;
925 ✗ continue_sub_node_parsing = false;
926 }
927 }
928 782 gate_xml_node_destroy(&sub_node);
929 }
930
2/2
✓ Branch 0 taken 369 times.
✓ Branch 1 taken 4 times.
373 if (GATE_SUCCEEDED(ret))
931 {
932 369 gate_array_create(&sub_nodes, sub_node_list);
933 }
934 }
935 }
936
937
2/2
✓ Branch 0 taken 782 times.
✓ Branch 1 taken 4 times.
786 if (GATE_SUCCEEDED(ret))
938 {
939
4/4
✓ Branch 0 taken 363 times.
✓ Branch 1 taken 419 times.
✓ Branch 2 taken 74 times.
✓ Branch 3 taken 708 times.
1564 ret = gate_xml_node_create(node, GATE_XML_NODE_TYPE_ELEMENT, &tag_name, &tag_attribs,
940 782 (gate_array_length(&sub_nodes) > 0) ? &sub_nodes : NULL,
941 782 gate_string_is_empty(&tag_text) ? NULL : &tag_text);
942
943 }
944
945 786 gate_xml_node_destroy(&sub_node);
946 786 gate_arraylist_release(&sub_node_list);
947 786 gate_array_release(&sub_nodes);
948 786 gate_string_release(&tag_text);
949 786 break;
950 }
951 2 case GATE_XML_NODE_TYPE_CDATA:
952 {
953 2 ret = gate_xml_node_create(node, GATE_XML_NODE_TYPE_CDATA, NULL, NULL, NULL, &tag_content);
954 2 break;
955 }
956
957 ✗ case GATE_XML_NODE_TYPE_NONE:
958 default:
959 {
960 ✗ ret = GATE_RESULT_NOTSUPPORTED;
961 ✗ break;
962 }
963 }
964
965 } while (0);
966
967 796 gate_array_release(&sub_nodes);
968 796 gate_arraylist_release(&sub_node_list);
969 796 gate_string_release(&tag_text);
970 796 gate_string_release(&tag_name);
971 796 gate_string_release(&post_tag_data);
972 796 gate_string_release(&tag_content);
973 796 gate_string_release(&tag);
974 796 gate_array_release(&tag_attribs);
975
976
1/2
✓ Branch 0 taken 796 times.
✗ Branch 1 not taken.
796 if (NULL != bytes_parsed)
977 {
978 796 *bytes_parsed = bytes_processed;
979 }
980
981 796 return ret;
982 }
983
984
985 29 static gate_result_t gate_xml_indent(gate_stream_t* stream, gate_size_t spaces)
986 {
987 29 gate_result_t ret = GATE_RESULT_OK;
988 gate_size_t written;
989 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
990
991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (spaces > sizeof(buffer))
992 {
993 ✗ spaces = sizeof(buffer);
994 }
995
996 29 gate_mem_fill(buffer, ' ', spaces);
997 29 ret = gate_stream_write_block(stream, buffer, spaces, &written);
998 29 return ret;
999 }
1000
1001 20 static gate_result_t gate_xml_print(gate_xml_node_t const* node, gate_stream_t* stream, gate_size_t level, gate_size_t indent_spaces)
1002 {
1003 20 gate_result_t ret = GATE_RESULT_OK;
1004 gate_size_t index;
1005 20 gate_size_t attr_length = gate_array_length(&node->attributes);
1006 20 gate_size_t child_count = gate_array_length(&node->child_nodes);
1007 20 gate_size_t content_length = gate_string_length(&node->content);
1008 gate_xml_pair_t const* pair;
1009 gate_xml_node_t const* child;
1010 20 gate_size_t spaces = level * indent_spaces;
1011
1012 do
1013 {
1014
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 1 times.
20 switch (node->node_type)
1015 {
1016 ✗ case GATE_XML_NODE_TYPE_DTD:
1017 case GATE_XML_NODE_TYPE_DECLARATION:
1018 {
1019 ✗ ret = GATE_RESULT_NOTSUPPORTED;
1020 ✗ break;
1021 }
1022 3 case GATE_XML_NODE_TYPE_COMMENT:
1023 {
1024 3 ret = gate_xml_indent(stream, spaces);
1025
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1026 3 ret = gate_stream_print(stream,
1027 GATE_PRINT_CSTR, GATE_XML_COMMENTBEGIN,
1028 GATE_PRINT_STRING, &node->content,
1029 GATE_PRINT_CSTR, GATE_XML_COMMENTEND,
1030 GATE_PRINT_END);
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1032 3 break;
1033 }
1034 3 case GATE_XML_NODE_TYPE_CDATA:
1035 {
1036 3 ret = gate_xml_indent(stream, spaces);
1037
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1038 /* TODO: Split items if content contains CDATA tokens*/
1039 3 ret = gate_stream_print(stream,
1040 GATE_PRINT_CSTR, GATE_XML_CDATABEGIN,
1041 GATE_PRINT_STRING, &node->content,
1042 GATE_PRINT_CSTR, GATE_XML_CDATAEND,
1043 GATE_PRINT_END);
1044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1045 3 break;
1046 }
1047 13 case GATE_XML_NODE_TYPE_ELEMENT:
1048 {
1049 13 ret = gate_xml_indent(stream, spaces);
1050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_BREAK_IF_FAILED(ret);
1051
1052 13 ret = gate_stream_print(stream,
1053 GATE_PRINT_CHAR, GATE_XML_CHAR_OPEN,
1054 GATE_PRINT_STRING, &node->tag,
1055 GATE_PRINT_END);
1056
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_BREAK_IF_FAILED(ret);
1057
1058
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 13 times.
16 for (index = 0; index != attr_length; ++index)
1059 {
1060 3 pair = (gate_xml_pair_t const*)gate_array_get(&node->attributes, index);
1061
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (pair)
1062 {
1063 3 ret = gate_stream_print(stream,
1064 GATE_PRINT_CHAR, ' ',
1065 GATE_PRINT_STRING, &pair->key,
1066 GATE_PRINT_CHAR, GATE_XML_CHAR_EQUAL,
1067 GATE_PRINT_CHAR, GATE_XML_CHAR_QUOTE,
1068 GATE_PRINT_STRING, &pair->value,
1069 GATE_PRINT_CHAR, GATE_XML_CHAR_QUOTE,
1070 GATE_PRINT_END);
1071
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1072 }
1073 }
1074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 GATE_BREAK_IF_FAILED(ret);
1075
1076
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
13 if ((child_count == 0) && (content_length == 0))
1077 {
1078 ✗ ret = gate_stream_print(stream,
1079 GATE_PRINT_CHAR, GATE_XML_CHAR_END,
1080 GATE_PRINT_CHAR, GATE_XML_CHAR_CLOSE,
1081 ((indent_spaces == 0) ? GATE_PRINT_END : GATE_PRINT_NEWLINE),
1082 GATE_PRINT_END);
1083 ✗ GATE_BREAK_IF_FAILED(ret);
1084 }
1085
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 3 times.
13 else if (child_count != 0)
1086 {
1087
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 ret = gate_stream_print(stream,
1088 GATE_PRINT_CHAR, GATE_XML_CHAR_CLOSE,
1089 ((indent_spaces == 0) ? GATE_PRINT_END : GATE_PRINT_NEWLINE),
1090 GATE_PRINT_END);
1091
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 GATE_BREAK_IF_FAILED(ret);
1092
1093
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 10 times.
26 for (index = 0; index != child_count; ++index)
1094 {
1095 16 child = (gate_xml_node_t const*)gate_array_get(&node->child_nodes, index);
1096
1/2
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
16 if (child)
1097 {
1098 16 ret = gate_xml_print(child, stream, level + 1, indent_spaces);
1099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 GATE_BREAK_IF_FAILED(ret);
1100 }
1101 }
1102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 GATE_BREAK_IF_FAILED(ret);
1103
1104 10 ret = gate_xml_indent(stream, spaces);
1105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 GATE_BREAK_IF_FAILED(ret);
1106
1107
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 ret = gate_stream_print(stream,
1108 GATE_PRINT_CHAR, GATE_XML_CHAR_OPEN,
1109 GATE_PRINT_CHAR, GATE_XML_CHAR_END,
1110 GATE_PRINT_STRING, &node->tag,
1111 GATE_PRINT_CHAR, GATE_XML_CHAR_CLOSE,
1112 ((indent_spaces == 0) ? GATE_PRINT_END : GATE_PRINT_NEWLINE),
1113 GATE_PRINT_END);
1114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 GATE_BREAK_IF_FAILED(ret);
1115 }
1116 else
1117 {
1118
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ret = gate_stream_print(stream,
1119 GATE_PRINT_CHAR, GATE_XML_CHAR_CLOSE,
1120 GATE_PRINT_STRING, &node->content,
1121 GATE_PRINT_CHAR, GATE_XML_CHAR_OPEN,
1122 GATE_PRINT_CHAR, GATE_XML_CHAR_END,
1123 GATE_PRINT_STRING, &node->tag,
1124 GATE_PRINT_CHAR, GATE_XML_CHAR_CLOSE,
1125 ((indent_spaces == 0) ? GATE_PRINT_END : GATE_PRINT_NEWLINE),
1126 GATE_PRINT_END);
1127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1128 }
1129 13 break;
1130 }
1131 }
1132
1133 20 } while (0);
1134
1135 20 return ret;
1136 }
1137
1138
1139 4 gate_result_t gate_xml_node_print(gate_xml_node_t const* node, gate_stream_t* stream, gate_size_t indent_spaces)
1140 {
1141 4 gate_result_t ret = GATE_RESULT_FAILED;
1142 do
1143 {
1144 4 ret = gate_xml_print(node, stream, 0, indent_spaces);
1145 } while (0);
1146 4 return ret;
1147 }
1148
1149
1150
1151
1152 13 gate_result_t gate_xml_doc_create(gate_xml_doc_t* doc, gate_xml_node_t const* document_element)
1153 {
1154 13 gate_result_t ret = GATE_RESULT_FAILED;
1155
1156 do
1157 {
1158 13 gate_mem_clear(doc, sizeof(gate_xml_doc_t));
1159
1160
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (NULL == gate_util_stringset_create(&doc->token_map))
1161 {
1162 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1163 ✗ break;
1164 }
1165
1166 13 doc->elemements = gate_arraylist_create(sizeof(gate_xml_node_t), NULL, 2, &gate_xml_node_copy_constructor, &gate_xml_node_destructor);
1167
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if (gate_arraylist_is_null(doc->elemements))
1168 {
1169 ✗ ret = GATE_RESULT_OUTOFBOUNDS;
1170 ✗ break;
1171 }
1172
1173
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 12 times.
13 if (document_element != NULL)
1174 {
1175 1 ret = gate_xml_doc_add_node(doc, NULL, document_element);
1176 }
1177 else
1178 {
1179 12 ret = GATE_RESULT_OK;
1180 }
1181
1182 } while (0);
1183
1184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (GATE_FAILED(ret))
1185 {
1186 ✗ gate_xml_doc_destroy(doc);
1187 }
1188
1189 13 return ret;
1190 }
1191 13 gate_result_t gate_xml_doc_destroy(gate_xml_doc_t* doc)
1192 {
1193 13 gate_set_destroy(&doc->token_map);
1194 13 gate_arraylist_release(&doc->elemements);
1195 13 gate_mem_clear(doc, sizeof(gate_xml_doc_t));
1196 13 return GATE_RESULT_OK;
1197 }
1198 3 gate_result_t gate_xml_doc_load(gate_xml_doc_t* doc, gate_stream_t* stream)
1199 {
1200 3 gate_result_t ret = GATE_RESULT_FAILED;
1201 3 gate_stringstream_t* ss = NULL;
1202 3 gate_string_t str = GATE_STRING_INIT_EMPTY;
1203
1204 do
1205 {
1206 3 ss = gate_stringstream_create(4096);
1207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ss == NULL)
1208 {
1209 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1210 ✗ break;
1211 }
1212
1213 3 ret = gate_stream_transfer(stream, (gate_stream_t*)ss);
1214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1215
1216 3 ret = gate_stringstream_to_string(ss, &str);
1217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
1218
1219 3 ret = gate_xml_doc_load_text(doc, &str);
1220 } while (0);
1221
1222
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ss)
1223 {
1224 3 gate_object_release(ss);
1225 }
1226 3 gate_string_release(&str);
1227
1228 3 return ret;
1229
1230
1231 }
1232 2 gate_result_t gate_xml_doc_store(gate_xml_doc_t* doc, gate_stream_t* stream, gate_size_t indent_spaces)
1233 {
1234 2 gate_result_t ret = GATE_RESULT_FAILED;
1235 gate_size_t index;
1236 gate_size_t count;
1237 gate_xml_node_t const* ptr_node;
1238 do
1239 {
1240
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_arraylist_is_null(doc->elemements))
1241 {
1242 /* seems to be an empty document -> no serialization -> nothing to do */
1243 ✗ ret = GATE_RESULT_OK;
1244 ✗ break;
1245 }
1246
1247 2 count = gate_arraylist_length(doc->elemements);
1248
1249 2 ret = GATE_RESULT_OK;
1250
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 for (index = 0; index != count; ++index)
1251 {
1252 2 ptr_node = (gate_xml_node_t const*)gate_arraylist_get(doc->elemements, index);
1253
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr_node)
1254 {
1255 2 ret = gate_xml_node_print(ptr_node, stream, indent_spaces);
1256
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1257 }
1258 }
1259 } while (0);
1260
1261 2 return ret;
1262 }
1263
1264 11 gate_result_t gate_xml_doc_load_text(gate_xml_doc_t* doc, gate_string_t const* text)
1265 {
1266 11 gate_result_t ret = GATE_RESULT_FAILED;
1267 11 gate_string_t xml = GATE_STRING_INIT_EMPTY;
1268 11 gate_xml_node_t node = GATE_INIT_EMPTY;
1269 11 gate_size_t bytes_parsed = 0;
1270 gate_enumint_t node_type;
1271 do
1272 {
1273 11 gate_string_clone(&xml, text);
1274
1275 11 ret = gate_xml_doc_create(doc, NULL);
1276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 GATE_BREAK_IF_FAILED(ret);
1277
1278 11 node_type = GATE_XML_NODE_TYPE_NONE;
1279
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
17 while ((node_type != GATE_XML_NODE_TYPE_ELEMENT)
1280
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 7 times.
13 && (GATE_RESULT_OK == (ret = gate_xml_node_parse(&xml, &node, &bytes_parsed))))
1281 {
1282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (bytes_parsed == 0)
1283 {
1284 ✗ ret = GATE_RESULT_INVALIDDATA;
1285 ✗ break;
1286 }
1287
1288 6 gate_string_substr(&xml, &xml, bytes_parsed, GATE_STR_NPOS);
1289
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (NULL == gate_arraylist_add(doc->elemements, &node))
1290 {
1291 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1292 ✗ break;
1293 }
1294 6 node_type = node.node_type;
1295 6 gate_xml_node_destroy(&node);
1296 }
1297
1298
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
11 if (GATE_SUCCEEDED(ret) && (node_type != GATE_XML_NODE_TYPE_ELEMENT))
1299 {
1300 /* there was no XML root element decoded */
1301 ✗ ret = GATE_RESULT_INVALIDCONTENT;
1302 }
1303 } while (0);
1304
1305
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 if (GATE_FAILED(ret))
1306 {
1307 7 gate_xml_doc_destroy(doc);
1308 }
1309 11 gate_xml_node_destroy(&node);
1310 11 gate_string_release(&xml);
1311
1312 11 return ret;
1313 }
1314 1 gate_result_t gate_xml_doc_store_text(gate_xml_doc_t* doc, gate_string_t* text, gate_size_t indent_spaces)
1315 {
1316 1 gate_result_t ret = GATE_RESULT_FAILED;
1317 1 gate_stringstream_t* ss = NULL;
1318 do
1319 {
1320 1 ss = gate_stringstream_create(1024);
1321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == ss)
1322 {
1323 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1324 ✗ break;
1325 }
1326 1 ret = gate_xml_doc_store(doc, (gate_stream_t*)ss, indent_spaces);
1327
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
1328 {
1329 1 ret = gate_stringstream_to_string(ss, text);
1330 }
1331
1332 } while (0);
1333
1334
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (NULL != ss)
1335 {
1336 1 gate_object_release(ss);
1337 }
1338
1339 1 return ret;
1340 }
1341
1342 4 gate_result_t gate_xml_doc_root_element(gate_xml_doc_t* doc, gate_xml_node_t const** ptr_document_element)
1343 {
1344 4 gate_result_t ret = GATE_RESULT_NOMATCH;
1345 gate_size_t count;
1346 gate_size_t index;
1347 4 gate_xml_node_t const* ptr_node = NULL;
1348 do
1349 {
1350 4 count = gate_arraylist_length(doc->elemements);
1351
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
6 for (index = 0; index != count; ++index)
1352 {
1353 5 ptr_node = (gate_xml_node_t const*)gate_arraylist_get(doc->elemements, index);
1354
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (ptr_node)
1355 {
1356
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
5 if (ptr_node->node_type == GATE_XML_NODE_TYPE_ELEMENT)
1357 {
1358
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ptr_document_element)
1359 {
1360 3 *ptr_document_element = ptr_node;
1361 3 ret = GATE_RESULT_OK;
1362 3 break;
1363 }
1364 }
1365 }
1366 }
1367 } while (0);
1368 4 return ret;
1369 }
1370
1371 20 static gate_string_t const* resolve_string(gate_set_t* s, gate_string_t const* str)
1372 {
1373 20 gate_set_iterator_t iter = gate_set_get(s, str);
1374
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 7 times.
20 if (iter == NULL)
1375 {
1376 13 iter = gate_set_add(s, str);
1377
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 if (iter == NULL)
1378 {
1379 ✗ return str;
1380 }
1381 }
1382 20 return (gate_string_t const*)gate_map_iterator_key(iter);
1383 }
1384
1385
1386 9 static gate_result_t gate_xml_doc_add(gate_xml_doc_t* doc, gate_arraylist_t parent_list, gate_xml_node_t const* child_node)
1387 {
1388 9 gate_result_t ret = GATE_RESULT_FAILED;
1389 9 gate_string_t tag_name = GATE_STRING_INIT_EMPTY;
1390 9 gate_string_t tag_content = GATE_STRING_INIT_EMPTY;
1391 9 gate_xml_pair_t new_pair = GATE_INIT_EMPTY;
1392 9 gate_xml_node_t new_node = GATE_INIT_EMPTY;
1393 9 gate_arraylist_t attribs = GATE_INIT_EMPTY;
1394 9 gate_arraylist_t children = GATE_INIT_EMPTY;
1395 gate_size_t count;
1396 gate_size_t index;
1397 9 gate_xml_node_t const* ptr_node = NULL;
1398 9 gate_xml_pair_t const* ptr_pair = NULL;
1399
1400 do
1401 {
1402 9 ret = GATE_RESULT_OK;
1403 9 count = gate_array_length(&child_node->child_nodes);
1404
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
9 if (count > 0)
1405 {
1406 4 children = gate_arraylist_create(sizeof(gate_xml_node_t), NULL, count, &gate_xml_node_copy_constructor, &gate_xml_node_destructor);
1407
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (gate_arraylist_is_null(children))
1408 {
1409 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1410 ✗ break;
1411 }
1412
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
10 for (index = 0; index != count; ++index)
1413 {
1414 6 ptr_node = (gate_xml_node_t const*)gate_array_get(&child_node->child_nodes, index);
1415
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (ptr_node)
1416 {
1417 6 ret = gate_xml_doc_add(doc, children, ptr_node);
1418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 GATE_BREAK_IF_FAILED(ret);
1419 }
1420 }
1421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 GATE_BREAK_IF_FAILED(ret);
1422 }
1423
1424 9 count = gate_array_length(&child_node->attributes);
1425
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
9 if (count > 0)
1426 {
1427 1 attribs = gate_arraylist_create(sizeof(gate_xml_node_t), NULL, count, &gate_xml_pair_cctor, &gate_xml_pair_dtor);
1428
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_arraylist_is_null(attribs))
1429 {
1430 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1431 ✗ break;
1432 }
1433
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (index = 0; index != count; ++index)
1434 {
1435 1 ptr_pair = (gate_xml_pair_t const*)gate_array_get(&child_node->attributes, index);
1436
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_pair)
1437 {
1438 1 gate_string_duplicate(&new_pair.key, resolve_string(&doc->token_map, &ptr_pair->key));
1439 1 gate_string_duplicate(&new_pair.value, resolve_string(&doc->token_map, &ptr_pair->value));
1440
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_arraylist_add(attribs, &new_pair))
1441 {
1442 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1443 ✗ break;
1444 }
1445 1 gate_xml_pair_dtor(&new_pair);
1446 }
1447 }
1448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
1449 }
1450
1451
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (NULL == gate_array_create(&new_node.child_nodes, children))
1452 {
1453 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1454 ✗ break;
1455 }
1456
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (NULL == gate_array_create(&new_node.attributes, attribs))
1457 {
1458 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1459 ✗ break;
1460 }
1461
1462 9 gate_string_duplicate(&new_node.tag, resolve_string(&doc->token_map, &child_node->tag));
1463 9 gate_string_duplicate(&new_node.content, resolve_string(&doc->token_map, &child_node->content));
1464
1465
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (NULL == gate_arraylist_add(parent_list, &new_node))
1466 {
1467 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1468 ✗ break;
1469 }
1470
1471 9 ret = GATE_RESULT_OK;
1472 } while (0);
1473
1474 9 gate_xml_node_destroy(&new_node);
1475
1476 9 gate_xml_pair_dtor(&new_pair);
1477 9 gate_arraylist_release(&attribs);
1478 9 gate_arraylist_release(&children);
1479 9 gate_string_release(&tag_name);
1480 9 gate_string_release(&tag_content);
1481
1482 9 return ret;
1483 }
1484
1485 3 gate_result_t gate_xml_doc_add_node(gate_xml_doc_t* doc, gate_xml_node_t* parent_node, gate_xml_node_t const* child_node)
1486 {
1487 gate_result_t ret;
1488 3 gate_arraylist_t list = GATE_INIT_EMPTY;
1489 3 gate_array_t new_children = GATE_INIT_EMPTY;
1490
1491 do
1492 {
1493
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (parent_node != NULL)
1494 {
1495 2 list = gate_arraylist_create(sizeof(gate_xml_node_t),
1496 2 gate_array_get(&parent_node->child_nodes, 0), gate_array_length(&parent_node->child_nodes),
1497 &gate_xml_node_copy_constructor, &gate_xml_node_destructor);
1498
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_arraylist_is_null(list))
1499 {
1500 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1501 ✗ break;
1502 }
1503 2 ret = gate_xml_doc_add(doc, list, child_node);
1504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
1505
1506
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_array_create(&new_children, list))
1507 {
1508 ✗ ret = GATE_RESULT_OUTOFMEMORY;
1509 ✗ break;
1510 }
1511 2 gate_array_release(&parent_node->child_nodes);
1512 2 gate_array_duplicate(&parent_node->child_nodes, &new_children);
1513 }
1514 else
1515 {
1516 1 ret = gate_xml_doc_root_element(doc, NULL);
1517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
1518 {
1519 /* element is already present -> we cannot add another one! */
1520 ✗ ret = GATE_RESULT_INVALIDSTATE;
1521 ✗ break;
1522 }
1523
1524 /* add element as new root element */
1525 1 ret = gate_xml_doc_add(doc, doc->elemements, child_node);
1526 }
1527 } while (0);
1528
1529 3 gate_arraylist_release(&list);
1530 3 gate_array_release(&new_children);
1531 3 return ret;
1532 }
1533
1534 ✗ gate_result_t gate_xml_doc_add_attribute(gate_xml_doc_t* doc, gate_xml_node_t* target_node,
1535 gate_string_t const* name, gate_string_t const* value)
1536 {
1537 /* TODO */
1538 ✗ return GATE_RESULT_NOTIMPLEMENTED;
1539 }
1540
1541 ✗ gate_result_t gate_xml_doc_remove_attribute(gate_xml_doc_t* doc, gate_xml_node_t* target_node, gate_string_t const* name)
1542 {
1543 /* TODO */
1544 ✗ return GATE_RESULT_NOTIMPLEMENTED;
1545 }
1546
1547 ✗ gate_result_t gate_xml_doc_remove_node(gate_xml_doc_t* doc, gate_xml_node_t* target_node, gate_size_t index)
1548 {
1549 /* TODO */
1550 ✗ return GATE_RESULT_NOTIMPLEMENTED;
1551 }
1552
1553 ✗ gate_result_t gate_xml_doc_set_node_content(gate_xml_doc_t* doc, gate_xml_node_t* target_node, gate_string_t const* content)
1554 {
1555 /* TODO */
1556 ✗ return GATE_RESULT_NOTIMPLEMENTED;
1557 }
1558