1 /* EINA - EFL data type library
2 * Copyright (C) 2011 Gustavo Sverzut Barbieri
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library;
17 * if not, see <http://www.gnu.org/licenses/>.
26 #elif defined __GNUC__
27 # define alloca __builtin_alloca
29 # define alloca __alloca
30 #elif defined _MSC_VER
32 # define alloca _alloca
38 void *alloca (size_t);
52 #include "eina_private.h"
54 #include "eina_mempool.h"
55 #include "eina_stringshare.h"
56 #include "eina_strbuf.h"
57 #include "eina_simple_xml_parser.h"
59 /*============================================================================*
61 *============================================================================*/
67 static Eina_Mempool *_eina_simple_xml_tag_mp = NULL;
68 static Eina_Mempool *_eina_simple_xml_attribute_mp = NULL;
69 static int _eina_simple_xml_log_dom = -1;
71 static const char EINA_MAGIC_SIMPLE_XML_TAG_STR[] = "Eina Simple XML Tag";
72 static const char EINA_MAGIC_SIMPLE_XML_DATA_STR[] = "Eina Simple XML Data";
73 static const char EINA_MAGIC_SIMPLE_XML_ATTRIBUTE_STR[] = "Eina Simple XML Attribute";
75 #define EINA_MAGIC_CHECK_TAG(d, ...) \
77 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_TAG)) \
79 EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_TAG); \
84 #define EINA_MAGIC_CHECK_DATA(d, ...) \
86 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_DATA)) \
88 EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_DATA); \
93 #define EINA_MAGIC_CHECK_ATTRIBUTE(d, ...) \
95 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE)) \
97 EINA_MAGIC_FAIL(d, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE); \
103 #ifndef EINA_LOG_COLOR_DEFAULT
104 #define EINA_LOG_COLOR_DEFAULT EINA_COLOR_CYAN
110 #define ERR(...) EINA_LOG_DOM_ERR(_eina_simple_xml_log_dom, __VA_ARGS__)
115 #define WRN(...) EINA_LOG_DOM_WARN(_eina_simple_xml_log_dom, __VA_ARGS__)
120 #define DBG(...) EINA_LOG_DOM_DBG(_eina_simple_xml_log_dom, __VA_ARGS__)
123 static inline const char *
124 _eina_simple_xml_whitespace_find(const char *itr, const char *itr_end)
126 for (; itr < itr_end; itr++)
127 if (isspace((unsigned char)*itr)) break;
131 static inline const char *
132 _eina_simple_xml_whitespace_skip(const char *itr, const char *itr_end)
134 for (; itr < itr_end; itr++)
135 if (!isspace((unsigned char)*itr)) break;
139 static inline const char *
140 _eina_simple_xml_whitespace_unskip(const char *itr, const char *itr_start)
142 for (itr--; itr > itr_start; itr--)
143 if (!isspace((unsigned char)*itr)) break;
147 static inline const char *
148 _eina_simple_xml_tag_start_find(const char *itr, const char *itr_end)
150 return memchr(itr, '<', itr_end - itr);
153 static inline const char *
154 _eina_simple_xml_tag_end_find(const char *itr, const char *itr_end)
156 for (; itr < itr_end; itr++)
157 if ((*itr == '>') || (*itr == '<')) /* consider < also ends a tag */
162 static inline const char *
163 _eina_simple_xml_tag_comment_end_find(const char *itr, const char *itr_end)
165 for (; itr < itr_end; itr++)
167 ((itr + 1 < itr_end) && (*(itr + 1) == '-')) &&
168 ((itr + 2 < itr_end) && (*(itr + 2) == '>')))
173 static inline const char *
174 _eina_simple_xml_tag_cdata_end_find(const char *itr, const char *itr_end)
176 for (; itr < itr_end; itr++)
178 ((itr + 1 < itr_end) && (*(itr + 1) == ']')) &&
179 ((itr + 2 < itr_end) && (*(itr + 2) == '>')))
188 /*============================================================================*
190 *============================================================================*/
195 * @brief Initialize the simple xml parser module.
197 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
199 * This function sets up the simple xml parser module of Eina. It is called by
205 eina_simple_xml_init(void)
207 const char *choice, *tmp;
209 _eina_simple_xml_log_dom = eina_log_domain_register("eina_simple_xml",
210 EINA_LOG_COLOR_DEFAULT);
211 if (_eina_simple_xml_log_dom < 0)
213 EINA_LOG_ERR("Could not register log domain: eina_simple_xml");
217 #ifdef EINA_DEFAULT_MEMPOOL
218 choice = "pass_through";
220 choice = "chained_mempool";
222 tmp = getenv("EINA_MEMPOOL");
226 _eina_simple_xml_tag_mp = eina_mempool_add
227 (choice, "simple_xml_tag", NULL,
228 sizeof(Eina_Simple_XML_Node_Tag), 32);
229 if (!_eina_simple_xml_tag_mp)
231 ERR("Mempool for simple_xml_tag cannot be allocated in init.");
235 _eina_simple_xml_attribute_mp = eina_mempool_add
236 (choice, "simple_xml_attribute", NULL,
237 sizeof(Eina_Simple_XML_Attribute), 8);
238 if (!_eina_simple_xml_attribute_mp)
240 ERR("Mempool for simple_xml_attribute cannot be allocated in init.");
241 eina_mempool_del(_eina_simple_xml_tag_mp);
245 #define EMS(n) eina_magic_string_static_set(n, n ## _STR)
246 EMS(EINA_MAGIC_SIMPLE_XML_TAG);
247 EMS(EINA_MAGIC_SIMPLE_XML_DATA);
248 EMS(EINA_MAGIC_SIMPLE_XML_ATTRIBUTE);
254 eina_log_domain_unregister(_eina_simple_xml_log_dom);
255 _eina_simple_xml_log_dom = -1;
261 * @brief Shut down the simple xml parser module.
263 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
265 * This function shuts down the simple xml parser module set
266 * up by eina_simple_xml_init(). It is called by
269 * @see eina_shutdown()
272 eina_simple_xml_shutdown(void)
274 eina_mempool_del(_eina_simple_xml_attribute_mp);
275 eina_mempool_del(_eina_simple_xml_tag_mp);
277 eina_log_domain_unregister(_eina_simple_xml_log_dom);
278 _eina_simple_xml_log_dom = -1;
283 /*============================================================================*
285 *============================================================================*/
289 eina_simple_xml_parse(const char *buf, unsigned buflen, Eina_Bool strip, Eina_Simple_XML_Cb func, const void *data)
291 const char *itr = buf, *itr_end = buf + buflen;
293 if (!buf) return EINA_FALSE;
294 if (!func) return EINA_FALSE;
296 #define CB(type, start, end) \
299 size_t _sz = end - start; \
301 _ret = func((void*)data, type, start, start - buf, _sz); \
302 if (!_ret) return EINA_FALSE; \
306 while (itr < itr_end)
310 if (itr + 1 >= itr_end)
312 CB(EINA_SIMPLE_XML_ERROR, itr, itr_end);
317 Eina_Simple_XML_Type type;
323 type = EINA_SIMPLE_XML_CLOSE;
326 else if (itr[1] == '?')
328 type = EINA_SIMPLE_XML_PROCESSING;
331 else if (itr[1] == '!')
333 if ((itr + sizeof("<!DOCTYPE>") - 1 < itr_end) &&
334 (!memcmp(itr + 2, "DOCTYPE",
335 sizeof("DOCTYPE") - 1)) &&
336 ((itr[2 + sizeof("DOCTYPE") - 1] == '>') ||
337 (isspace((unsigned char)itr[2 + sizeof("DOCTYPE") - 1]))))
339 type = EINA_SIMPLE_XML_DOCTYPE;
340 toff = sizeof("!DOCTYPE") - 1;
342 else if ((itr + sizeof("<!---->") - 1 < itr_end) &&
343 (!memcmp(itr + 2, "--", sizeof("--") - 1)))
345 type = EINA_SIMPLE_XML_COMMENT;
346 toff = sizeof("!--") - 1;
348 else if ((itr + sizeof("<![CDATA[]]>") - 1 < itr_end) &&
349 (!memcmp(itr + 2, "[CDATA[",
350 sizeof("[CDATA[") - 1)))
352 type = EINA_SIMPLE_XML_CDATA;
353 toff = sizeof("![CDATA[") - 1;
357 type = EINA_SIMPLE_XML_OPEN;
363 type = EINA_SIMPLE_XML_OPEN;
367 if (type == EINA_SIMPLE_XML_CDATA)
368 p = _eina_simple_xml_tag_cdata_end_find(itr + 1 + toff, itr_end);
369 else if (type == EINA_SIMPLE_XML_COMMENT)
370 p = _eina_simple_xml_tag_comment_end_find(itr + 1 + toff, itr_end);
372 p = _eina_simple_xml_tag_end_find(itr + 1 + toff, itr_end);
374 if ((p) && (*p == '<'))
376 type = EINA_SIMPLE_XML_ERROR;
382 const char *start, *end;
384 start = itr + 1 + toff;
389 case EINA_SIMPLE_XML_OPEN:
392 type = EINA_SIMPLE_XML_OPEN_EMPTY;
396 case EINA_SIMPLE_XML_CDATA:
397 if (!memcmp(p - 2, "]]", 2)) end -= 2;
399 case EINA_SIMPLE_XML_PROCESSING:
400 if (p[-1] == '?') end--;
402 case EINA_SIMPLE_XML_COMMENT:
403 if (!memcmp(p - 2, "--", 2)) end -= 2;
405 case EINA_SIMPLE_XML_OPEN_EMPTY:
406 case EINA_SIMPLE_XML_CLOSE:
407 case EINA_SIMPLE_XML_DATA:
408 case EINA_SIMPLE_XML_ERROR:
409 case EINA_SIMPLE_XML_DOCTYPE:
410 case EINA_SIMPLE_XML_IGNORED:
414 if ((strip) && (type != EINA_SIMPLE_XML_ERROR))
416 start = _eina_simple_xml_whitespace_skip
418 end = _eina_simple_xml_whitespace_unskip
422 CB(type, start, end);
424 if (type != EINA_SIMPLE_XML_ERROR)
431 CB(EINA_SIMPLE_XML_ERROR, itr, itr_end);
442 p = _eina_simple_xml_whitespace_skip(itr, itr_end);
445 CB(EINA_SIMPLE_XML_IGNORED, itr, p);
450 p = _eina_simple_xml_tag_start_find(itr, itr_end);
455 end = _eina_simple_xml_whitespace_unskip(end, itr);
458 CB(EINA_SIMPLE_XML_DATA, itr, end);
460 if ((strip) && (end < p))
461 CB(EINA_SIMPLE_XML_IGNORED, end, p);
473 eina_simple_xml_tag_attributes_find(const char *buf, unsigned buflen)
475 const char *itr = buf, *itr_end = buf + buflen;
477 for (; itr < itr_end; itr++)
479 if (!isspace((unsigned char)*itr))
481 /* user skip tagname and already gave it the attributes */
487 itr = _eina_simple_xml_whitespace_skip(itr + 1, itr_end);
498 eina_simple_xml_attributes_parse(const char *buf, unsigned buflen, Eina_Simple_XML_Attribute_Cb func, const void *data)
500 const char *itr = buf, *itr_end = buf + buflen;
501 char *tmpbuf = alloca(buflen + 1);
503 if (!buf) return EINA_FALSE;
504 if (!func) return EINA_FALSE;
506 while (itr < itr_end)
508 const char *p = _eina_simple_xml_whitespace_skip(itr, itr_end);
509 const char *key, *key_end, *value, *value_end;
512 if (p == itr_end) return EINA_TRUE;
515 for (key_end = key; key_end < itr_end; key_end++)
516 if ((*key_end == '=') || (isspace((unsigned char)*key_end))) break;
517 if (key_end == itr_end) return EINA_FALSE;
518 if (key_end == key) continue;
520 if (*key_end == '=') value = key_end + 1;
523 value = memchr(key_end, '=', itr_end - key_end);
524 if (!value) return EINA_FALSE;
527 for (; value < itr_end; value++)
528 if (!isspace((unsigned char)*value)) break;
529 if (value == itr_end) return EINA_FALSE;
531 if ((*value == '"') || (*value == '\''))
533 value_end = memchr(value + 1, *value, itr_end - value);
534 if (!value_end) return EINA_FALSE;
539 value_end = _eina_simple_xml_whitespace_find(value, itr_end);
542 memcpy(tmpbuf, key, key_end - key);
543 tmpbuf[key_end - key] = '\0';
545 tval = tmpbuf + (key_end - key) + 1;
546 memcpy(tval, value, value_end - value);
547 tval[value_end - value] = '\0';
549 if (!func((void*)data, tmpbuf, tval))
557 /* Node loader *************************************************************/
559 EAPI Eina_Simple_XML_Attribute *
560 eina_simple_xml_attribute_new(Eina_Simple_XML_Node_Tag *parent, const char *key, const char *value)
562 Eina_Simple_XML_Attribute *attr;
564 if (!key) return NULL;
566 attr = eina_mempool_malloc(_eina_simple_xml_attribute_mp, sizeof(*attr));
569 ERR("could not allocate memory for attribute from mempool");
573 EINA_MAGIC_SET(attr, EINA_MAGIC_SIMPLE_XML_ATTRIBUTE);
574 attr->parent = parent;
575 attr->key = eina_stringshare_add(key);
576 attr->value = eina_stringshare_add(value ? value : "");
579 parent->attributes = eina_inlist_append
580 (parent->attributes, EINA_INLIST_GET(attr));
586 eina_simple_xml_attribute_free(Eina_Simple_XML_Attribute *attr)
591 EINA_MAGIC_CHECK_ATTRIBUTE(attr);
594 attr->parent->attributes = eina_inlist_remove
595 (attr->parent->attributes, EINA_INLIST_GET(attr));
597 eina_stringshare_del(attr->key);
598 eina_stringshare_del(attr->value);
599 EINA_MAGIC_SET(attr, EINA_MAGIC_NONE);
600 eina_mempool_free(_eina_simple_xml_attribute_mp, attr);
604 _eina_simple_xml_node_data_free(Eina_Simple_XML_Node_Data *node)
606 if (node->base.parent)
607 node->base.parent->children = eina_inlist_remove
608 (node->base.parent->children, EINA_INLIST_GET(&node->base));
610 EINA_MAGIC_SET(&node->base, EINA_MAGIC_NONE);
614 EAPI Eina_Simple_XML_Node_Tag *
615 eina_simple_xml_node_tag_new(Eina_Simple_XML_Node_Tag *parent, const char *name)
617 Eina_Simple_XML_Node_Tag *n;
619 if (!name) return NULL;
621 n = eina_mempool_malloc(_eina_simple_xml_tag_mp, sizeof(*n));
624 ERR("could not allocate memory for node from mempool");
628 memset(n, 0, sizeof(*n));
630 EINA_MAGIC_SET(&n->base, EINA_MAGIC_SIMPLE_XML_TAG);
632 n->base.type = EINA_SIMPLE_XML_NODE_TAG;
633 n->base.parent = parent;
634 n->name = eina_stringshare_add(name);
637 parent->children = eina_inlist_append
638 (parent->children, EINA_INLIST_GET(&n->base));
644 _eina_simple_xml_node_tag_free(Eina_Simple_XML_Node_Tag *tag)
646 while (tag->children)
648 Eina_Simple_XML_Node *n = EINA_INLIST_CONTAINER_GET
649 (tag->children, Eina_Simple_XML_Node);
650 if (n->type == EINA_SIMPLE_XML_NODE_TAG)
651 _eina_simple_xml_node_tag_free((Eina_Simple_XML_Node_Tag *)n);
653 _eina_simple_xml_node_data_free((Eina_Simple_XML_Node_Data *)n);
656 while (tag->attributes)
658 Eina_Simple_XML_Attribute *a = EINA_INLIST_CONTAINER_GET
659 (tag->attributes, Eina_Simple_XML_Attribute);
660 eina_simple_xml_attribute_free(a);
663 if (tag->base.parent)
664 tag->base.parent->children = eina_inlist_remove
665 (tag->base.parent->children, EINA_INLIST_GET(&tag->base));
667 eina_stringshare_del(tag->name);
668 EINA_MAGIC_SET(&tag->base, EINA_MAGIC_NONE);
669 eina_mempool_free(_eina_simple_xml_tag_mp, tag);
673 eina_simple_xml_node_tag_free(Eina_Simple_XML_Node_Tag *tag)
678 EINA_MAGIC_CHECK_TAG(&tag->base);
679 if (tag->base.type != EINA_SIMPLE_XML_NODE_TAG)
681 ERR("expected tag node!");
684 _eina_simple_xml_node_tag_free(tag);
687 static Eina_Simple_XML_Node_Data *
688 _eina_simple_xml_node_data_new(Eina_Simple_XML_Node_Tag *parent, Eina_Simple_XML_Node_Type type, const char *content, unsigned length)
690 Eina_Simple_XML_Node_Data *n;
692 if (!content) return NULL;
694 n = malloc(sizeof(*n) + length + 1);
698 ERR("could not allocate memory for node");
702 EINA_MAGIC_SET(&n->base, EINA_MAGIC_SIMPLE_XML_DATA);
704 n->base.parent = parent;
707 memcpy(n->data, content, length);
708 n->data[length] = '\0';
711 parent->children = eina_inlist_append
712 (parent->children, EINA_INLIST_GET(&n->base));
717 EAPI Eina_Simple_XML_Node_Data *
718 eina_simple_xml_node_data_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
720 return _eina_simple_xml_node_data_new
721 (parent, EINA_SIMPLE_XML_NODE_DATA, contents, length);
725 eina_simple_xml_node_data_free(Eina_Simple_XML_Node_Data *node)
730 EINA_MAGIC_CHECK_DATA(&node->base);
731 if (node->base.type != EINA_SIMPLE_XML_NODE_DATA)
733 ERR("expected node of type: data!");
736 _eina_simple_xml_node_data_free(node);
739 EAPI Eina_Simple_XML_Node_CData *
740 eina_simple_xml_node_cdata_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
742 return _eina_simple_xml_node_data_new
743 (parent, EINA_SIMPLE_XML_NODE_CDATA, contents, length);
747 eina_simple_xml_node_cdata_free(Eina_Simple_XML_Node_Data *node)
752 EINA_MAGIC_CHECK_DATA(&node->base);
753 if (node->base.type != EINA_SIMPLE_XML_NODE_CDATA)
755 ERR("expected node of type: cdata!");
758 _eina_simple_xml_node_data_free(node);
761 EAPI Eina_Simple_XML_Node_Processing *
762 eina_simple_xml_node_processing_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
764 return _eina_simple_xml_node_data_new
765 (parent, EINA_SIMPLE_XML_NODE_PROCESSING, contents, length);
769 eina_simple_xml_node_processing_free(Eina_Simple_XML_Node_Data *node)
774 EINA_MAGIC_CHECK_DATA(&node->base);
775 if (node->base.type != EINA_SIMPLE_XML_NODE_PROCESSING)
777 ERR("expected node of type: processing!");
780 _eina_simple_xml_node_data_free(node);
783 EAPI Eina_Simple_XML_Node_Doctype *
784 eina_simple_xml_node_doctype_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
786 return _eina_simple_xml_node_data_new
787 (parent, EINA_SIMPLE_XML_NODE_DOCTYPE, contents, length);
791 eina_simple_xml_node_doctype_free(Eina_Simple_XML_Node_Data *node)
796 EINA_MAGIC_CHECK_DATA(&node->base);
797 if (node->base.type != EINA_SIMPLE_XML_NODE_DOCTYPE)
799 ERR("expected node of type: doctype!");
802 _eina_simple_xml_node_data_free(node);
805 EAPI Eina_Simple_XML_Node_Comment *
806 eina_simple_xml_node_comment_new(Eina_Simple_XML_Node_Tag *parent, const char *contents, size_t length)
808 return _eina_simple_xml_node_data_new
809 (parent, EINA_SIMPLE_XML_NODE_COMMENT, contents, length);
813 eina_simple_xml_node_comment_free(Eina_Simple_XML_Node_Data *node)
818 EINA_MAGIC_CHECK_DATA(&node->base);
819 if (node->base.type != EINA_SIMPLE_XML_NODE_COMMENT)
821 ERR("expected node of type: comment!");
824 _eina_simple_xml_node_data_free(node);
827 struct eina_simple_xml_node_load_ctxt
829 Eina_Simple_XML_Node_Root *root;
830 Eina_Simple_XML_Node_Tag *current;
834 _eina_simple_xml_attrs_parse(void *data, const char *key, const char *value)
836 Eina_Simple_XML_Node_Tag *n = data;
837 Eina_Simple_XML_Attribute *attr;
839 attr = eina_simple_xml_attribute_new(n, key, value);
844 _eina_simple_xml_node_parse(void *data, Eina_Simple_XML_Type type, const char *content, unsigned offset, unsigned length)
846 struct eina_simple_xml_node_load_ctxt *ctx = data;
850 case EINA_SIMPLE_XML_OPEN:
851 case EINA_SIMPLE_XML_OPEN_EMPTY:
853 Eina_Simple_XML_Node_Tag *n;
854 const char *name, *name_end, *attrs;
856 attrs = eina_simple_xml_tag_attributes_find(content, length);
858 name_end = content + length;
862 name_end = _eina_simple_xml_whitespace_unskip(name_end, content);
864 name = eina_stringshare_add_length(content, name_end - content);
865 n = eina_simple_xml_node_tag_new(ctx->current, name);
866 eina_stringshare_del(name);
867 if (!n) return EINA_FALSE;
870 eina_simple_xml_attributes_parse
871 (attrs, length - (attrs - content),
872 _eina_simple_xml_attrs_parse, n);
874 if (type == EINA_SIMPLE_XML_OPEN)
879 case EINA_SIMPLE_XML_CLOSE:
880 if (ctx->current->base.parent)
882 const char *end = _eina_simple_xml_whitespace_unskip
883 (content + length, content);
886 if ((len == 0) /* </> closes the tag for us. */ ||
887 ((eina_stringshare_strlen(ctx->current->name) == len) &&
888 (memcmp(ctx->current->name, content, len) == 0)))
889 ctx->current = ctx->current->base.parent;
891 WRN("closed incorrect tag: '%.*s', '%s' was expected!",
892 len, content, ctx->current->name);
895 WRN("closed tag '%.*s' but already at document root!",
899 case EINA_SIMPLE_XML_DATA:
900 return !!eina_simple_xml_node_data_new
901 (ctx->current, content, length);
902 case EINA_SIMPLE_XML_CDATA:
903 return !!eina_simple_xml_node_cdata_new
904 (ctx->current, content, length);
905 case EINA_SIMPLE_XML_PROCESSING:
906 return !!eina_simple_xml_node_processing_new
907 (ctx->current, content, length);
908 case EINA_SIMPLE_XML_DOCTYPE:
909 return !!eina_simple_xml_node_doctype_new
910 (ctx->current, content, length);
911 case EINA_SIMPLE_XML_COMMENT:
912 return !!eina_simple_xml_node_comment_new
913 (ctx->current, content, length);
915 case EINA_SIMPLE_XML_ERROR:
916 ERR("parser error at offset %u-%u: %.*s",
917 offset, length, length, content);
919 case EINA_SIMPLE_XML_IGNORED:
920 DBG("ignored contents at offset %u-%u: %.*s",
921 offset, length, length, content);
928 EAPI Eina_Simple_XML_Node_Root *
929 eina_simple_xml_node_load(const char *buf, unsigned buflen, Eina_Bool strip)
931 Eina_Simple_XML_Node_Root *root;
932 struct eina_simple_xml_node_load_ctxt ctx;
934 if (!buf) return NULL;
936 root = eina_mempool_malloc(_eina_simple_xml_tag_mp, sizeof(*root));
937 if (!root) return NULL;
939 memset(root, 0, sizeof(*root));
940 EINA_MAGIC_SET(&root->base, EINA_MAGIC_SIMPLE_XML_TAG);
941 root->base.type = EINA_SIMPLE_XML_NODE_ROOT;
945 eina_simple_xml_parse(buf, buflen, strip, _eina_simple_xml_node_parse, &ctx);
951 eina_simple_xml_node_root_free(Eina_Simple_XML_Node_Root *root)
954 EINA_MAGIC_CHECK_TAG(&root->base);
955 if (root->base.type != EINA_SIMPLE_XML_NODE_ROOT)
957 ERR("expected root node!");
960 _eina_simple_xml_node_tag_free(root);
964 _eina_simple_xml_node_dump_indent(Eina_Strbuf *buf, const char *indent, unsigned level)
966 unsigned i, indent_len = strlen(indent);
967 for (i = 0; i < level; i++)
968 eina_strbuf_append_length(buf, indent, indent_len);
972 _eina_simple_xml_node_tag_attributes_append(Eina_Strbuf *buf, Eina_Simple_XML_Node_Tag *tag)
974 Eina_Simple_XML_Attribute *a;
976 EINA_INLIST_FOREACH(tag->attributes, a)
977 eina_strbuf_append_printf(buf, " %s=\"%s\"", a->key, a->value);
980 static void _eina_simple_xml_node_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node *node, const char *indent, unsigned level);
983 _eina_simple_xml_node_children_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node_Tag *tag, const char *indent, unsigned level)
985 Eina_Simple_XML_Node *node;
987 EINA_INLIST_FOREACH(tag->children, node)
988 _eina_simple_xml_node_dump(buf, node, indent, level);
992 _eina_simple_xml_node_dump(Eina_Strbuf *buf, Eina_Simple_XML_Node *node, const char *indent, unsigned level)
996 case EINA_SIMPLE_XML_NODE_ROOT:
997 _eina_simple_xml_node_children_dump
998 (buf, (Eina_Simple_XML_Node_Tag *)node, indent, level);
1001 case EINA_SIMPLE_XML_NODE_TAG:
1003 Eina_Simple_XML_Node_Tag *n = (Eina_Simple_XML_Node_Tag *)node;
1005 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1007 eina_strbuf_append_char(buf, '<');
1008 eina_strbuf_append_length
1009 (buf, n->name, eina_stringshare_strlen(n->name));
1012 _eina_simple_xml_node_tag_attributes_append(buf, n);
1015 eina_strbuf_append_char(buf, '>');
1017 eina_strbuf_append_length(buf, "/>", sizeof("/>") - 1);
1019 if (indent) eina_strbuf_append_char(buf, '\n');
1023 _eina_simple_xml_node_children_dump(buf, n, indent, level + 1);
1026 _eina_simple_xml_node_dump_indent(buf, indent, level);
1028 eina_strbuf_append_length(buf, "</", sizeof("</") - 1);
1029 eina_strbuf_append_length
1030 (buf, n->name, eina_stringshare_strlen(n->name));
1031 eina_strbuf_append_char(buf, '>');
1033 if (indent) eina_strbuf_append_char(buf, '\n');
1037 case EINA_SIMPLE_XML_NODE_DATA:
1039 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1041 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1042 eina_strbuf_append_length(buf, n->data, n->length);
1043 if (indent) eina_strbuf_append_char(buf, '\n');
1047 case EINA_SIMPLE_XML_NODE_CDATA:
1049 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1051 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1052 eina_strbuf_append_length(buf, "<![CDATA[", sizeof("<![CDATA[") - 1);
1053 eina_strbuf_append_length(buf, n->data, n->length);
1054 eina_strbuf_append_length(buf, "]]>", sizeof("]]>") - 1);
1055 if (indent) eina_strbuf_append_char(buf, '\n');
1059 case EINA_SIMPLE_XML_NODE_PROCESSING:
1061 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1063 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1064 eina_strbuf_append_length(buf, "<?", sizeof("<?") - 1);
1065 eina_strbuf_append_length(buf, n->data, n->length);
1066 eina_strbuf_append_length(buf, " ?>", sizeof(" ?>") - 1);
1067 if (indent) eina_strbuf_append_char(buf, '\n');
1071 case EINA_SIMPLE_XML_NODE_DOCTYPE:
1073 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1075 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1076 eina_strbuf_append_length
1077 (buf, "<!DOCTYPE ", sizeof("<!DOCTYPE ") - 1);
1078 eina_strbuf_append_length(buf, n->data, n->length);
1079 eina_strbuf_append_char(buf, '>');
1080 if (indent) eina_strbuf_append_char(buf, '\n');
1084 case EINA_SIMPLE_XML_NODE_COMMENT:
1086 Eina_Simple_XML_Node_Data *n = (Eina_Simple_XML_Node_Data *)node;
1088 if (indent) _eina_simple_xml_node_dump_indent(buf, indent, level);
1089 eina_strbuf_append_length(buf, "<!-- ", sizeof("<!-- ") - 1);
1090 eina_strbuf_append_length(buf, n->data, n->length);
1091 eina_strbuf_append_length(buf, " -->", sizeof(" -->") - 1);
1092 if (indent) eina_strbuf_append_char(buf, '\n');
1099 eina_simple_xml_node_dump(Eina_Simple_XML_Node *node, const char *indent)
1104 if (!node) return NULL;
1106 buf = eina_strbuf_new();
1107 if (!buf) return NULL;
1109 _eina_simple_xml_node_dump(buf, node, indent, 0);
1111 ret = eina_strbuf_string_steal(buf);
1112 eina_strbuf_free(buf);