Author: mikej Date: Mon Jan 29 11:58:37 2007 New Revision: 4081 Modified: freeswitch/trunk/src/include/switch_xml.h freeswitch/trunk/src/switch_xml.c Log: 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 Modified: freeswitch/trunk/src/include/switch_xml.h ============================================================================== --- freeswitch/trunk/src/include/switch_xml.h (original) +++ freeswitch/trunk/src/include/switch_xml.h Mon Jan 29 11:58:37 2007 @@ -256,9 +256,10 @@ ///\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 @@ ///\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) Modified: freeswitch/trunk/src/switch_xml.c ============================================================================== --- freeswitch/trunk/src/switch_xml.c (original) +++ freeswitch/trunk/src/switch_xml.c Mon Jan 29 11:58:37 2007 @@ -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 @@ 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 @@ } } -// 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,51 +1410,64 @@ return &root->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 -switch_xml_t switch_xml_add_child(switch_xml_t xml, const char *name, switch_size_t off) +// 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, head, child; + switch_xml_t cur, prev, head; - if (! xml) return NULL; - child = (switch_xml_t)memset(malloc(sizeof(struct switch_xml)), '\0', - sizeof(struct switch_xml)); - child->name = (char *)name; - child->attr = SWITCH_XML_NIL; - child->off = off; - child->parent = xml; - child->txt = ""; + xml->next = xml->sibling = xml->ordered = NULL; + xml->off = off; + xml->parent = dest; - if ((head = xml->child)) { // already have sub tags + 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); - child->ordered = cur->ordered; - cur->ordered = child; + xml->ordered = cur->ordered; + cur->ordered = xml; } else { // first subtag - child->ordered = head; - xml->child = child; + xml->ordered = head; + dest->child = xml; } - 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 + 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; - child->next = cur->next; - cur->next = child; + xml->next = cur->next; + cur->next = xml; } 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; + 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 xml->child = child; // only sub tag - - return child; + 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 +switch_xml_t switch_xml_add_child(switch_xml_t xml, const char *name, switch_size_t off) +{ + switch_xml_t child; + + if (! xml) return NULL; + child = (switch_xml_t)memset(malloc(sizeof(struct switch_xml)), '\0', + sizeof(struct switch_xml)); + child->name = (char *)name; + child->attr = SWITCH_XML_NIL; + child->off = off; + child->parent = xml; + child->txt = ""; + + return switch_xml_insert(child, xml, off); } // sets the character content for the given tag and returns the tag @@ -1468,15 +1481,15 @@ } // 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 @@ (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 @@ 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 @@ 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: