forked from Mirrors/freeswitch
merge changes from ezXML 0.8.6
- fixed a bug in ezxml_add_child() that can occur when adding tags out of order - for consistency, ezxml_set_attr() now returns the tag given - added ezxml_move() and supporting functions ezxml_cut() and ezxml_insert() - fixed a bug where parsing an empty file could cause a segfault git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4081 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
e02299f8f6
commit
4b7f9bddf5
@ -256,9 +256,10 @@ switch_xml_t switch_xml_set_txt(switch_xml_t xml, const char *txt);
|
||||
///\param xml the xml node
|
||||
///\param name the attribute name
|
||||
///\param value the attribute value
|
||||
SWITCH_DECLARE(void) switch_xml_set_attr(switch_xml_t xml, const char *name, const char *value);
|
||||
///\return the tag given
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_set_attr(switch_xml_t xml, const char *name, const char *value);
|
||||
|
||||
///\ Wrapper for switch_xml_set_attr() that strdup()s name/value. Value cannot be NULL
|
||||
///\brief Wrapper for switch_xml_set_attr() that strdup()s name/value. Value cannot be NULL
|
||||
///\param xml the xml node
|
||||
///\param name the attribute name
|
||||
///\param value the attribute value
|
||||
@ -272,10 +273,19 @@ SWITCH_DECLARE(void) switch_xml_set_attr(switch_xml_t xml, const char *name, con
|
||||
///\return an xml node or NULL
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_set_flag(switch_xml_t xml, switch_xml_flag_t flag);
|
||||
|
||||
///\brief removes a tag along with its subtags without freeing its memory
|
||||
///\param xml the xml node
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_cut(switch_xml_t xml);
|
||||
|
||||
///\brief inserts an existing tag into an ezxml structure
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_insert(switch_xml_t xml, switch_xml_t dest, switch_size_t off);
|
||||
|
||||
///\brief Moves an existing tag to become a subtag of dest at the given offset from
|
||||
///\ the start of dest's character content. Returns the moved tag.
|
||||
#define switch_xml_move(xml, dest, off) switch_xml_insert(switch_xml_cut(xml), dest, off)
|
||||
|
||||
///\brief removes a tag along with all its subtags
|
||||
///\param xml the xml node
|
||||
SWITCH_DECLARE(void) switch_xml_remove(switch_xml_t xml);
|
||||
#define switch_xml_remove(xml) switch_xml_free(switch_xml_cut(xml))
|
||||
|
||||
///\brief open the Core xml root
|
||||
///\param reload if it's is already open close it and open it again as soon as permissable (blocking)
|
||||
|
107
src/switch_xml.c
107
src/switch_xml.c
@ -28,10 +28,10 @@
|
||||
*
|
||||
* switch_xml.c -- XML PARSER
|
||||
*
|
||||
* Derived from EZXML http://ezxml.sourceforge.net
|
||||
* Derived from switch_xml http://switch_xml.sourceforge.net
|
||||
* Original Copyright
|
||||
*
|
||||
* Copyright 2004, 2005 Aaron Voisine <aaron@voisine.org>
|
||||
* Copyright 2004, 2006 Aaron Voisine <aaron@voisine.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -696,7 +696,7 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_parse_str(char *s, switch_size_t len)
|
||||
if (switch_xml_close_tag(root, d, s)) return &root->xml;
|
||||
if (isspace((int)(*s = q))) s += strspn(s, SWITCH_XML_WS);
|
||||
}
|
||||
else if (! strncmp(s, "!--", 3)) { // comment
|
||||
else if (! strncmp(s, "!--", 3)) { // xml comment
|
||||
if (! (s = strstr(s + 3, "--")) || (*(s += 2) != '>' && *s) ||
|
||||
(! *s && e != '>')) return switch_xml_err(root, d, "unclosed <!--");
|
||||
}
|
||||
@ -1286,8 +1286,8 @@ static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len,
|
||||
}
|
||||
}
|
||||
|
||||
// converts an switch_xml structure back to xml, returning it as a string that must
|
||||
// be freed
|
||||
// converts an switch_xml structure back to xml, returning a string of xml date that
|
||||
// must be freed
|
||||
SWITCH_DECLARE(char *) switch_xml_toxml(switch_xml_t xml)
|
||||
{
|
||||
switch_xml_t p = (xml) ? xml->parent : NULL, o = (xml) ? xml->ordered : NULL;
|
||||
@ -1410,11 +1410,53 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_new(const char *name)
|
||||
return &root->xml;
|
||||
}
|
||||
|
||||
// inserts an existing tag into an switch_xml structure
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_insert(switch_xml_t xml, switch_xml_t dest, switch_size_t off)
|
||||
{
|
||||
switch_xml_t cur, prev, head;
|
||||
|
||||
xml->next = xml->sibling = xml->ordered = NULL;
|
||||
xml->off = off;
|
||||
xml->parent = dest;
|
||||
|
||||
if ((head = dest->child)) { // already have sub tags
|
||||
if (head->off <= off) { // not first subtag
|
||||
for (cur = head; cur->ordered && cur->ordered->off <= off;
|
||||
cur = cur->ordered);
|
||||
xml->ordered = cur->ordered;
|
||||
cur->ordered = xml;
|
||||
}
|
||||
else { // first subtag
|
||||
xml->ordered = head;
|
||||
dest->child = xml;
|
||||
}
|
||||
|
||||
for (cur = head, prev = NULL; cur && strcmp(cur->name, xml->name);
|
||||
prev = cur, cur = cur->sibling); // find tag type
|
||||
if (cur && cur->off <= off) { // not first of type
|
||||
while (cur->next && cur->next->off <= off) cur = cur->next;
|
||||
xml->next = cur->next;
|
||||
cur->next = xml;
|
||||
}
|
||||
else { // first tag of this type
|
||||
if (prev && cur) prev->sibling = cur->sibling; // remove old first
|
||||
xml->next = cur; // old first tag is now next
|
||||
for (cur = head, prev = NULL; cur && cur->off <= off;
|
||||
prev = cur, cur = cur->sibling); // new sibling insert point
|
||||
xml->sibling = cur;
|
||||
if (prev) prev->sibling = xml;
|
||||
}
|
||||
}
|
||||
else dest->child = xml; // only sub tag
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
// Adds a child tag. off is the offset of the child tag relative to the start
|
||||
// of the parent tag's character content. returns the child tag
|
||||
// of the parent tag's character content. Returns the child tag
|
||||
switch_xml_t switch_xml_add_child(switch_xml_t xml, const char *name, switch_size_t off)
|
||||
{
|
||||
switch_xml_t cur, head, child;
|
||||
switch_xml_t child;
|
||||
|
||||
if (! xml) return NULL;
|
||||
child = (switch_xml_t)memset(malloc(sizeof(struct switch_xml)), '\0',
|
||||
@ -1425,36 +1467,7 @@ switch_xml_t switch_xml_add_child(switch_xml_t xml, const char *name, switch_siz
|
||||
child->parent = xml;
|
||||
child->txt = "";
|
||||
|
||||
if ((head = xml->child)) { // already have sub tags
|
||||
if (head->off <= off) { // not first subtag
|
||||
for (cur = head; cur->ordered && cur->ordered->off <= off;
|
||||
cur = cur->ordered);
|
||||
child->ordered = cur->ordered;
|
||||
cur->ordered = child;
|
||||
}
|
||||
else { // first subtag
|
||||
child->ordered = head;
|
||||
xml->child = child;
|
||||
}
|
||||
|
||||
for (cur = head; cur->sibling && strcmp(cur->name, name);
|
||||
cur = cur->sibling); // find tag type
|
||||
if (! strcmp(cur->name, name) && cur->off <= off) { //not first of type
|
||||
while (cur->next && cur->next->off <= off) cur = cur->next;
|
||||
child->next = cur->next;
|
||||
cur->next = child;
|
||||
}
|
||||
else { // first tag of this type
|
||||
if (cur->off > off) child->next = cur; // not only tag of this type
|
||||
for (cur = head; cur->sibling && cur->sibling->off <= off;
|
||||
cur = cur->sibling);
|
||||
child->sibling = cur->sibling;
|
||||
cur->sibling = child;
|
||||
}
|
||||
}
|
||||
else xml->child = child; // only sub tag
|
||||
|
||||
return child;
|
||||
return switch_xml_insert(child, xml, off);
|
||||
}
|
||||
|
||||
// sets the character content for the given tag and returns the tag
|
||||
@ -1468,15 +1481,15 @@ switch_xml_t switch_xml_set_txt(switch_xml_t xml, const char *txt)
|
||||
}
|
||||
|
||||
// Sets the given tag attribute or adds a new attribute if not found. A value
|
||||
// of NULL will remove the specified attribute.
|
||||
SWITCH_DECLARE(void) switch_xml_set_attr(switch_xml_t xml, const char *name, const char *value)
|
||||
// of NULL will remove the specified attribute. Returns the tag given
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_set_attr(switch_xml_t xml, const char *name, const char *value)
|
||||
{
|
||||
int l = 0, c;
|
||||
|
||||
if (! xml) return;
|
||||
if (! xml) return NULL;
|
||||
while (xml->attr[l] && strcmp(xml->attr[l], name)) l += 2;
|
||||
if (! xml->attr[l]) { // not found, add as new attribute
|
||||
if (! value) return; // nothing to do
|
||||
if (! value) return xml; // nothing to do
|
||||
if (xml->attr == SWITCH_XML_NIL) { // first attribute
|
||||
xml->attr = malloc(4 * sizeof(char *));
|
||||
xml->attr[1] = strdup(""); // empty list of malloced names/vals
|
||||
@ -1506,6 +1519,8 @@ SWITCH_DECLARE(void) switch_xml_set_attr(switch_xml_t xml, const char *name, con
|
||||
(c / 2) - (l / 2)); // fix list of which name/vals are malloced
|
||||
}
|
||||
xml->flags &= ~SWITCH_XML_DUP; // clear strdup() flag
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
// sets a flag for the given tag and returns the tag
|
||||
@ -1515,12 +1530,12 @@ SWITCH_DECLARE(switch_xml_t) switch_xml_set_flag(switch_xml_t xml, switch_xml_fl
|
||||
return xml;
|
||||
}
|
||||
|
||||
// removes a tag along with all its subtags
|
||||
SWITCH_DECLARE(void) switch_xml_remove(switch_xml_t xml)
|
||||
// removes a tag along with its subtags without freeing its memory
|
||||
SWITCH_DECLARE(switch_xml_t) switch_xml_cut(switch_xml_t xml)
|
||||
{
|
||||
switch_xml_t cur;
|
||||
|
||||
if (! xml) return; // nothing to do
|
||||
if (! xml) return NULL; // nothing to do
|
||||
if (xml->next) xml->next->sibling = xml->sibling; // patch sibling list
|
||||
|
||||
if (xml->parent) { // not root tag
|
||||
@ -1545,8 +1560,8 @@ SWITCH_DECLARE(void) switch_xml_remove(switch_xml_t xml)
|
||||
if (cur->next) cur->next = cur->next->next; // patch next list
|
||||
}
|
||||
}
|
||||
xml->ordered = NULL; // prevent switch_xml_free() from clobbering ordered list
|
||||
switch_xml_free(xml);
|
||||
xml->ordered = xml->sibling = xml->next = NULL; // prevent switch_xml_free() from clobbering ordered list
|
||||
return xml;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
|
Loading…
Reference in New Issue
Block a user