Nyx Node
Loading...
Searching...
No Matches
xml.c
1/* NyxNode
2 * Author: Jérôme ODIER <jerome.odier@lpsc.in2p3.fr>
3 * SPDX-License-Identifier: GPL-2.0-only (Mongoose backend) or GPL-3.0+
4 */
5
6/*--------------------------------------------------------------------------------------------------------------------*/
7#if !defined(ARDUINO)
8/*--------------------------------------------------------------------------------------------------------------------*/
9
10#include <ctype.h>
11#include <string.h>
12
13#include "../nyx_node_internal.h"
14
15/*--------------------------------------------------------------------------------------------------------------------*/
16/* DEFINITIONS */
17/*--------------------------------------------------------------------------------------------------------------------*/
18
19typedef enum
20{
21 XML_TOKEN_EOF,
22 XML_TOKEN_LT1,
23 XML_TOKEN_LT2,
24 XML_TOKEN_GT,
25 XML_TOKEN_SLASH,
26 XML_TOKEN_EQUALS,
27 XML_TOKEN_IDENT,
28 XML_TOKEN_STRING,
29 XML_TOKEN_COMMENT,
30 XML_TOKEN_CDATA,
31 XML_TOKEN_TEXT,
32 XML_TOKEN_ERROR,
33
34} xml_token_type_t;
35
36/*--------------------------------------------------------------------------------------------------------------------*/
37
38typedef struct
39{
40 str_t value;
41
42 xml_token_type_t token_type;
43
44} xml_token_t;
45
46/*--------------------------------------------------------------------------------------------------------------------*/
47
48typedef struct
49{
50 bool tag;
51
52 size_t size;
53 STR_t buff;
54
55 xml_token_t curr_token;
56
57} xml_parser_t;
58
59/*--------------------------------------------------------------------------------------------------------------------*/
60/* TOKENIZER */
61/*--------------------------------------------------------------------------------------------------------------------*/
62
63#define NEXT() \
64 tokenizer_next(parser)
65
66/*--------------------------------------------------------------------------------------------------------------------*/
67
68#define PEEK() \
69 (parser->curr_token)
70
71/*--------------------------------------------------------------------------------------------------------------------*/
72
73#define CHECK(t) \
74 (parser->curr_token.token_type == (t))
75
76/*--------------------------------------------------------------------------------------------------------------------*/
77
78static const int XML_IDENT_TAB[256] = {
79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
81 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
82 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
86 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87};
88
89/*--------------------------------------------------------------------------------------------------------------------*/
90
91static bool xmlcpy(str_t p, STR_t s, STR_t e)
92{
93 while(s < e)
94 {
95 if(*s == '&')
96 {
97 s++;
98
99 size_t size = (size_t) e - (size_t) s;
100
101 /**/ if(size >= 3 && strncmp(s, "lt;", 3) == 0)
102 {
103 *p++ = '<';
104 s += 3;
105 }
106 else if(size >= 3 && strncmp(s, "gt;", 3) == 0)
107 {
108 *p++ = '>';
109 s += 3;
110 }
111 else if(size >= 4 && strncmp(s, "amp;", 4) == 0)
112 {
113 *p++ = '&';
114 s += 4;
115 }
116 else if(size >= 5 && strncmp(s, "quot;", 5) == 0)
117 {
118 *p++ = '\"';
119 s += 5;
120 }
121 else if(size >= 5 && strncmp(s, "apos;", 5) == 0)
122 {
123 *p++ = '\'';
124 s += 5;
125 }
126 else
127 {
128 return false;
129 }
130 }
131 else
132 {
133 *p++ = *s++;
134 }
135 }
136
137 *p = '\0';
138
139 return true;
140}
141
142/*--------------------------------------------------------------------------------------------------------------------*/
143
144static void tokenizer_next(xml_parser_t *parser)
145{
146 /*----------------------------------------------------------------------------------------------------------------*/
147
148 PEEK().value = NULL;
149
150 /*----------------------------------------------------------------------------------------------------------------*/
151
152 while(parser->size > 0 && isspace((unsigned char) *parser->buff))
153 {
154 parser->buff++;
155 parser->size--;
156 }
157
158 /*----------------------------------------------------------------------------------------------------------------*/
159
160 if(parser->size == 0)
161 {
162 parser->curr_token.token_type = XML_TOKEN_EOF;
163
164 return;
165 }
166
167 /*----------------------------------------------------------------------------------------------------------------*/
168
169 STR_t start = parser->buff;
170 STR_t end = parser->buff;
171
172 xml_token_type_t type;
173
174 switch(*parser->buff)
175 {
176 /*------------------------------------------------------------------------------------------------------------*/
177
178 case '\0':
179 type = XML_TOKEN_EOF;
180 break;
181
182 /*------------------------------------------------------------------------------------------------------------*/
183
184 case '<':
185 /*--------------------------------------------------------------------------------------------------------*/
186
187 /**/ if(parser->size >= 4 && strncmp(end, "<!--", 4) == 0)
188 {
189 end += 4;
190 parser->size -= 4;
191 while(parser->size >= 3 && strncmp(end, "-->", 3) != 0)
192 {
193 if(*end == '\0')
194 {
195 type = XML_TOKEN_ERROR;
196 goto _bye;
197 }
198 end++;
199 parser->size--;
200 }
201 if(parser->size < 3)
202 {
203 type = XML_TOKEN_ERROR;
204 goto _bye;
205 }
206 end += 3;
207 parser->size -= 3;
208 type = XML_TOKEN_COMMENT;
209 }
210
211 /*--------------------------------------------------------------------------------------------------------*/
212
213 else if(parser->size >= 9 && strncmp(end, "<![CDATA[", 9) == 0)
214 {
215 end += 9;
216 parser->size -= 9;
217 while(parser->size >= 3 && strncmp(end, "]]>", 3) != 0)
218 {
219 if(*end == '\0')
220 {
221 type = XML_TOKEN_ERROR;
222 goto _bye;
223 }
224 end++;
225 parser->size--;
226 }
227 if(parser->size < 3)
228 {
229 type = XML_TOKEN_ERROR;
230 goto _bye;
231 }
232 end += 3;
233 parser->size -= 3;
234 type = XML_TOKEN_CDATA;
235 }
236
237 /*--------------------------------------------------------------------------------------------------------*/
238
239 else
240 {
241 parser->tag = true;
242
243 if(parser->size >= 2 && *(end + 1) == '/')
244 {
245 end += 2;
246 parser->size -= 2;
247 type = XML_TOKEN_LT2;
248 }
249 else
250 {
251 end += 1;
252 parser->size -= 1;
253 type = XML_TOKEN_LT1;
254 }
255 }
256
257 /*--------------------------------------------------------------------------------------------------------*/
258 break;
259
260 /*------------------------------------------------------------------------------------------------------------*/
261
262 case '>':
263 parser->tag = false;
264
265 end++;
266 parser->size--;
267 type = XML_TOKEN_GT;
268 break;
269
270 /*------------------------------------------------------------------------------------------------------------*/
271
272 case '/':
273 if(parser->tag == false) {
274 goto /* NOSONAR */ _text;
275 }
276
277 end++;
278 parser->size--;
279 type = XML_TOKEN_SLASH;
280 break;
281
282 /*------------------------------------------------------------------------------------------------------------*/
283
284 case '=':
285 if(parser->tag == false) {
286 goto /* NOSONAR */ _text;
287 }
288
289 end++;
290 parser->size--;
291 type = XML_TOKEN_EQUALS;
292 break;
293
294 /*------------------------------------------------------------------------------------------------------------*/
295
296 case '\"':
297 if(parser->tag == false) {
298 goto /* NOSONAR */ _text;
299 }
300
301 end++;
302 parser->size--;
303 while(parser->size >= 1 && *end != '\"')
304 {
305 if(*end == '\0')
306 {
307 type = XML_TOKEN_ERROR;
308 goto _bye;
309 }
310 end++;
311 parser->size--;
312 }
313 if(parser->size < 1)
314 {
315 type = XML_TOKEN_ERROR;
316 goto _bye;
317 }
318 end++;
319 parser->size--;
320 type = XML_TOKEN_STRING;
321 break;
322
323 /*------------------------------------------------------------------------------------------------------------*/
324
325 case '\'':
326 if(parser->tag == false) {
327 goto /* NOSONAR */ _text;
328 }
329
330 end++;
331 parser->size--;
332 while(parser->size >= 1 && *end != '\'')
333 {
334 if(*end == '\0')
335 {
336 type = XML_TOKEN_ERROR;
337 goto _bye;
338 }
339 end++;
340 parser->size--;
341 }
342 if(parser->size < 1)
343 {
344 type = XML_TOKEN_ERROR;
345 goto _bye;
346 }
347 end++;
348 parser->size--;
349 type = XML_TOKEN_STRING;
350 break;
351
352 /*------------------------------------------------------------------------------------------------------------*/
353
354 default:
355 if(parser->tag)
356 {
357 /*----------------------------------------------------------------------------------------------------*/
358
359 while(parser->size >= 1 && XML_IDENT_TAB[(unsigned int) *end & 0xFFU])
360 {
361 if(*end == '\0')
362 {
363 type = XML_TOKEN_ERROR;
364 goto _bye;
365 }
366 end++;
367 parser->size--;
368 }
369
370 type = XML_TOKEN_IDENT;
371
372 /*----------------------------------------------------------------------------------------------------*/
373 }
374 else
375 {
376 /*----------------------------------------------------------------------------------------------------*/
377/* NOSONAR */ _text:
378 while(parser->size >= 1 && *end != '<')
379 {
380 if(*end == '\0')
381 {
382 type = XML_TOKEN_ERROR;
383 goto _bye;
384 }
385 end++;
386 parser->size--;
387 }
388
389 type = XML_TOKEN_TEXT;
390
391 /*----------------------------------------------------------------------------------------------------*/
392 }
393
394 break;
395
396 /*------------------------------------------------------------------------------------------------------------*/
397 }
398
399 /*----------------------------------------------------------------------------------------------------------------*/
400
401 /**/ if(type == XML_TOKEN_COMMENT) // <!-- ... -->
402 {
403 STR_t s = start + 4;
404 STR_t e = end - 3;
405
406 parser->curr_token.value = nyx_string_ndup(s, (size_t) e - (size_t) s);
407 }
408
409 /*----------------------------------------------------------------------------------------------------------------*/
410
411 else if(type == XML_TOKEN_CDATA) // <![CDATA[ ... ]]>
412 {
413 STR_t s = start + 9;
414 STR_t e = end - 3;
415
416 parser->curr_token.value = nyx_string_ndup(s, (size_t) e - (size_t) s);
417 }
418
419 /*----------------------------------------------------------------------------------------------------------------*/
420
421 else if(type == XML_TOKEN_IDENT)
422 {
423 STR_t s = start;
424 STR_t e = end ;
425
426 size_t length = (size_t) e - (size_t) s;
427
428 if(length > 0)
429 {
430 parser->curr_token.value = nyx_string_ndup(s, length);
431 }
432 else
433 {
434 type = XML_TOKEN_ERROR;
435 }
436 }
437
438 /*----------------------------------------------------------------------------------------------------------------*/
439
440 else if(type == XML_TOKEN_STRING)
441 {
442 STR_t s = start + 1;
443 STR_t e = end - 1;
444
445 size_t length = (size_t) e - (size_t) s;
446
447 str_t p = parser->curr_token.value = nyx_memory_alloc(length + 1);
448
449 if(xmlcpy(p, s, e) == false)
450 {
451 nyx_memory_free(parser->curr_token.value);
452 parser->curr_token.value = NULL;
453 type = XML_TOKEN_ERROR;
454 goto _bye;
455 }
456 }
457
458 /*----------------------------------------------------------------------------------------------------------------*/
459
460 else if(type == XML_TOKEN_TEXT)
461 {
462 STR_t s = start;
463 STR_t e = end ;
464
465 size_t length = (size_t) e - (size_t) s;
466
467 if(length > 0)
468 {
469 str_t p = parser->curr_token.value = nyx_memory_alloc(length + 1);
470
471 if(xmlcpy(p, s, e) == false)
472 {
473 nyx_memory_free(parser->curr_token.value);
474 parser->curr_token.value = NULL;
475 type = XML_TOKEN_ERROR;
476 goto _bye;
477 }
478 }
479 else
480 {
481 type = XML_TOKEN_ERROR;
482 }
483 }
484
485 /*----------------------------------------------------------------------------------------------------------------*/
486
487_bye:
488 parser->curr_token.token_type = type;
489
490 parser->buff = end;
491}
492
493/*--------------------------------------------------------------------------------------------------------------------*/
494/* PARSER */
495/*--------------------------------------------------------------------------------------------------------------------*/
496
497static nyx_xmldoc_t *xml_parse_content(xml_parser_t *parser, nyx_xmldoc_t *parent);
498
499/*--------------------------------------------------------------------------------------------------------------------*/
500
501static nyx_xmldoc_t *xml_parse_comment_node(xml_parser_t *parser, nyx_xmldoc_t *parent)
502{
503 /*----------------------------------------------------------------------------------------------------------------*/
504
505 if(CHECK(XML_TOKEN_COMMENT) == false)
506 {
507 return NULL;
508 }
509
510 str_t data = PEEK().value;
511
512 NEXT();
513
514 /*----------------------------------------------------------------------------------------------------------------*/
515
516 nyx_xmldoc_t *result = nyx_xmldoc_new(NYX_XML_COMMENT);
517 result->data = data;
518 result->parent = parent;
519
520 return result;
521}
522
523/*--------------------------------------------------------------------------------------------------------------------*/
524
525static nyx_xmldoc_t *xml_parse_cdata_node(xml_parser_t *parser, nyx_xmldoc_t *parent)
526{
527 /*----------------------------------------------------------------------------------------------------------------*/
528
529 if(CHECK(XML_TOKEN_CDATA) == false)
530 {
531 return NULL;
532 }
533
534 str_t data = PEEK().value;
535
536 NEXT();
537
538 /*----------------------------------------------------------------------------------------------------------------*/
539
540 nyx_xmldoc_t *result = nyx_xmldoc_new(NYX_XML_CDATA);
541 result->data = data;
542 result->parent = parent;
543
544 return result;
545}
546
547/*--------------------------------------------------------------------------------------------------------------------*/
548
549static nyx_xmldoc_t *xml_parse_text_node(xml_parser_t *parser, nyx_xmldoc_t *parent)
550{
551 /*----------------------------------------------------------------------------------------------------------------*/
552
553 if(CHECK(XML_TOKEN_TEXT) == false)
554 {
555 return NULL;
556 }
557
558 str_t data = PEEK().value;
559
560 NEXT();
561
562 /*----------------------------------------------------------------------------------------------------------------*/
563
564 nyx_xmldoc_t *result = nyx_xmldoc_new(NYX_XML_TEXT);
565 result->data = data;
566 result->parent = parent;
567
568 return result;
569}
570
571/*--------------------------------------------------------------------------------------------------------------------*/
572
573static nyx_xmldoc_t *xml_parse_attribute_node(xml_parser_t *parser)
574{
575 /*----------------------------------------------------------------------------------------------------------------*/
576
577 if(CHECK(XML_TOKEN_IDENT) == false)
578 {
579 ///_memory_free(name);
580 return NULL;
581 }
582
583 str_t name = PEEK().value;
584
585 NEXT();
586
587 /*----------------------------------------------------------------------------------------------------------------*/
588
589 if(CHECK(XML_TOKEN_EQUALS) == false)
590 {
591 nyx_memory_free(name);
592 return NULL;
593 }
594
595 NEXT();
596
597 /*----------------------------------------------------------------------------------------------------------------*/
598
599 if(CHECK(XML_TOKEN_STRING) == false)
600 {
601 nyx_memory_free(name);
602 return NULL;
603 }
604
605 str_t data = PEEK().value;
606
607 NEXT();
608
609 /*----------------------------------------------------------------------------------------------------------------*/
610
611 nyx_xmldoc_t *result = nyx_xmldoc_new(NYX_XML_ATTR);
612 result->name = name;
613 result->data = data;
614
615 return result;
616}
617
618/*--------------------------------------------------------------------------------------------------------------------*/
619
620static nyx_xmldoc_t *xml_parse_opening_tag(xml_parser_t *parser, nyx_xmldoc_t *parent)
621{
622 /*----------------------------------------------------------------------------------------------------------------*/
623
624 if(CHECK(XML_TOKEN_LT1) == false)
625 {
626 return NULL;
627 }
628
629 NEXT();
630
631 /*----------------------------------------------------------------------------------------------------------------*/
632
633 if(CHECK(XML_TOKEN_IDENT) == false)
634 {
635 return NULL;
636 }
637
638 str_t name = PEEK().value;
639
640 NEXT();
641
642 /*----------------------------------------------------------------------------------------------------------------*/
643
644 nyx_xmldoc_t *first_attr = NULL;
645 nyx_xmldoc_t *last_attr = NULL;
646
647 while(CHECK(XML_TOKEN_IDENT))
648 {
649 /*------------------------------------------------------------------------------------------------------------*/
650
651 nyx_xmldoc_t *node = xml_parse_attribute_node(parser);
652
653 if(node == NULL)
654 {
655 goto _err;
656 }
657
658 /*------------------------------------------------------------------------------------------------------------*/
659
660 if(last_attr != NULL) {
661 last_attr->next = node;
662 } else {
663 first_attr = node;
664 }
665
666 last_attr = node;
667
668 /*------------------------------------------------------------------------------------------------------------*/
669 }
670
671 /*----------------------------------------------------------------------------------------------------------------*/
672
673 bool self_closing;
674
675 if(CHECK(XML_TOKEN_SLASH) == false)
676 {
677 self_closing = false;
678
679 ////();
680 }
681 else
682 {
683 self_closing = true;
684
685 NEXT();
686 }
687
688 /*----------------------------------------------------------------------------------------------------------------*/
689
690 if(CHECK(XML_TOKEN_GT) == false)
691 {
692 goto _err;
693 }
694
695 NEXT();
696
697 /*----------------------------------------------------------------------------------------------------------------*/
698
699 nyx_xmldoc_t *result = nyx_xmldoc_new(NYX_XML_ELEM);
700 result->name = name;
701 result->parent = parent;
702 result->attributes = first_attr;
703 result->self_closing = self_closing;
704
705 return result;
706
707_err:
708 while(first_attr != NULL)
709 {
710 nyx_xmldoc_t *tmp_attr = first_attr;
711 first_attr = first_attr->next;
712 nyx_xmldoc_free(tmp_attr);
713 }
714
715 nyx_memory_free(name);
716
717 return NULL;
718}
719
720/*--------------------------------------------------------------------------------------------------------------------*/
721
722static bool xml_parse_closing_tag(xml_parser_t *parser, const nyx_xmldoc_t *current)
723{
724 if(current->self_closing == false)
725 {
726 /*------------------------------------------------------------------------------------------------------------*/
727
728 if(CHECK(XML_TOKEN_LT2) == false)
729 {
730 return false;
731 }
732
733 NEXT();
734
735 /*------------------------------------------------------------------------------------------------------------*/
736
737 if(CHECK(XML_TOKEN_IDENT) == false)
738 {
739 return false;
740 }
741
742 bool bad = strcmp(PEEK().value, current->name) != 0;
743
744 nyx_memory_free(PEEK().value);
745
746 PEEK().value = NULL;
747
748 if(bad) {
749 return false;
750 }
751 else {
752 NEXT();
753 }
754
755 /*------------------------------------------------------------------------------------------------------------*/
756
757 if(CHECK(XML_TOKEN_GT) == false)
758 {
759 return false;
760 }
761
762 NEXT();
763
764 /*------------------------------------------------------------------------------------------------------------*/
765 }
766
767 return true;
768}
769
770/*--------------------------------------------------------------------------------------------------------------------*/
771
772static nyx_xmldoc_t *xml_parse_element_node(xml_parser_t *parser, nyx_xmldoc_t *parent) // NOLINT(*-no-recursion)
773{
774 /*----------------------------------------------------------------------------------------------------------------*/
775
776 nyx_xmldoc_t *result = xml_parse_opening_tag(parser, parent);
777
778 if(result == NULL)
779 {
780 ///_xmldoc_free(result);
781 return NULL;
782 }
783
784 /*----------------------------------------------------------------------------------------------------------------*/
785
786 result->children = xml_parse_content(parser, result);
787
788 /*----------------------------------------------------------------------------------------------------------------*/
789
790 bool okay = xml_parse_closing_tag(parser, result);
791
792 if(okay == false)
793 {
794 nyx_xmldoc_free(result);
795 return NULL;
796 }
797
798 /*----------------------------------------------------------------------------------------------------------------*/
799
800 return result;
801}
802
803/*--------------------------------------------------------------------------------------------------------------------*/
804
805static nyx_xmldoc_t *xml_parse_content(xml_parser_t *parser, nyx_xmldoc_t *parent) // NOLINT(*-no-recursion)
806{
807 if(parent->self_closing)
808 {
809 return NULL;
810 }
811
812 /*----------------------------------------------------------------------------------------------------------------*/
813
814 nyx_xmldoc_t *first_child = NULL;
815 nyx_xmldoc_t *last_child = NULL;
816
817 for(nyx_xmldoc_t *node;;)
818 {
819 /*------------------------------------------------------------------------------------------------------------*/
820
821 node = xml_parse_element_node(parser, parent);
822 if(node == NULL)
823 {
824 node = xml_parse_comment_node(parser, parent);
825 if(node == NULL)
826 {
827 node = xml_parse_cdata_node(parser, parent);
828 if(node == NULL)
829 {
830 node = xml_parse_text_node(parser, parent);
831 if(node == NULL)
832 {
833 break;
834 }
835 }
836 }
837 }
838
839 /*------------------------------------------------------------------------------------------------------------*/
840
841 if(last_child != NULL) {
842 last_child->next = node;
843 } else {
844 first_child = node;
845 }
846
847 last_child = node;
848
849 /*------------------------------------------------------------------------------------------------------------*/
850
851 node->parent = parent;
852
853 /*------------------------------------------------------------------------------------------------------------*/
854 }
855
856 /*----------------------------------------------------------------------------------------------------------------*/
857
858 return first_child;
859}
860
861/*--------------------------------------------------------------------------------------------------------------------*/
862
863nyx_xmldoc_t *nyx_xmldoc_parse_buff(size_t size, BUFF_t buff)
864{
865 if(size == 0x00
866 ||
867 buff == NULL
868 ) {
869 return NULL;
870 }
871
872 /*----------------------------------------------------------------------------------------------------------------*/
873
874 xml_parser_t *parser = &(xml_parser_t) {
875 .tag = false,
876 .size = size,
877 .buff = buff,
878 .curr_token = {
879 .value = NULL,
880 .token_type = XML_TOKEN_ERROR,
881 },
882 };
883
884 /*----------------------------------------------------------------------------------------------------------------*/
885
886 NEXT();
887
888 /*----------------------------------------------------------------------------------------------------------------*/
889
890 nyx_xmldoc_t *result = xml_parse_element_node(parser, NULL);
891
892 /*----------------------------------------------------------------------------------------------------------------*/
893
894 if(result == NULL || CHECK(XML_TOKEN_EOF) == false)
895 {
896 if(parser->curr_token.value != NULL)
897 {
898 nyx_memory_free(parser->curr_token.value);
899
900 parser->curr_token.value = NULL;
901 }
902
903 nyx_xmldoc_free(result);
904
905 result = NULL;
906 }
907
908 /*----------------------------------------------------------------------------------------------------------------*/
909
910 return result;
911}
912
913/*--------------------------------------------------------------------------------------------------------------------*/
914
915nyx_xmldoc_t *nyx_xmldoc_parse(STR_t string)
916{
917 if(string == NULL)
918 {
919 return NULL;
920 }
921
922 return nyx_xmldoc_parse_buff(
923 strlen(string),
924 buffof(string)
925 );
926}
927
928/*--------------------------------------------------------------------------------------------------------------------*/
929#endif
930/*--------------------------------------------------------------------------------------------------------------------*/
#define STR_t
Alias for const char *.
Definition nyx_node.h:71
__NYX_NULLABLE__ buff_t nyx_memory_alloc(__NYX_ZEROABLE__ size_t size)
Similar to libc malloc except that a memory overflow causes the node to stop.
__NYX_ZEROABLE__ size_t nyx_memory_free(__NYX_NULLABLE__ buff_t buff)
Similar to libc free except that it returns the amount of memory freed.
#define BUFF_t
Alias for const void *.
Definition nyx_node.h:68
__NYX_NULLABLE__ str_t nyx_string_ndup(__NYX_NULLABLE__ STR_t s, __NYX_ZEROABLE__ size_t n)
Similar to libc strndup.
#define str_t
Alias for char *.
Definition nyx_node.h:70
Struct describing an XML document.