123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869 |
- /*
- * $Id$
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Jabber
- * Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
- */
- /*! \file
- * \ingroup xmpp
- */
- #include "xode.h"
- static int _xode_strcmp(const char *a, const char *b)
- {
- if(a == NULL || b == NULL) return -1;
- return strcmp(a,b);
- }
- /*! \brief Internal routines */
- static xode _xode_new(xode_pool p, const char* name, unsigned int type)
- {
- xode result = NULL;
- if (type > XODE_TYPE_LAST)
- return NULL;
- if (type != XODE_TYPE_CDATA && name == NULL)
- return NULL;
- if (p == NULL)
- {
- p = xode_pool_heap(1*1024);
- }
- /* Allocate & zero memory */
- result = (xode)xode_pool_malloc(p, sizeof(_xode));
- memset(result, '\0', sizeof(_xode));
- /* Initialize fields */
- if (type != XODE_TYPE_CDATA)
- result->name = xode_pool_strdup(p,name);
- result->type = type;
- result->p = p;
- return result;
- }
- static xode _xode_appendsibling(xode lastsibling, const char* name, unsigned int type)
- {
- xode result;
- result = _xode_new(xode_get_pool(lastsibling), name, type);
- if (result != NULL)
- {
- /* Setup sibling pointers */
- result->prev = lastsibling;
- lastsibling->next = result;
- }
- return result;
- }
- static xode _xode_insert(xode parent, const char* name, unsigned int type)
- {
- xode result;
- if(parent == NULL || name == NULL) return NULL;
- /* If parent->firstchild is NULL, simply create a new node for the first child */
- if (parent->firstchild == NULL)
- {
- result = _xode_new(parent->p, name, type);
- parent->firstchild = result;
- }
- /* Otherwise, append this to the lastchild */
- else
- {
- result= _xode_appendsibling(parent->lastchild, name, type);
- }
- result->parent = parent;
- parent->lastchild = result;
- return result;
- }
- static xode _xode_search(xode firstsibling, const char* name, unsigned int type)
- {
- xode current;
- /* Walk the sibling list, looking for a XODE_TYPE_TAG xode with
- the specified name */
- current = firstsibling;
- while (current != NULL)
- {
- if (name != NULL && (current->type == type) && (_xode_strcmp(current->name, name) == 0))
- return current;
- else
- current = current->next;
- }
- return NULL;
- }
- static char* _xode_merge(xode_pool p, char* dest, unsigned int destsize, const char* src, unsigned int srcsize)
- {
- char* result;
- result = (char*)xode_pool_malloc(p, destsize + srcsize + 1);
- memcpy(result, dest, destsize);
- memcpy(result+destsize, src, srcsize);
- result[destsize + srcsize] = '\0';
- /* WARNING: major ugly hack: since we're throwing the old data away, let's jump in the xode_pool and subtract it from the size, this is for xmlstream's big-node checking */
- p->size -= destsize;
- return result;
- }
- static void _xode_hidesibling(xode child)
- {
- if(child == NULL)
- return;
- if(child->prev != NULL)
- child->prev->next = child->next;
- if(child->next != NULL)
- child->next->prev = child->prev;
- }
- static void _xode_tag2str(xode_spool s, xode node, int flag)
- {
- xode tmp;
- if(flag==0 || flag==1)
- {
- xode_spooler(s,"<",xode_get_name(node),s);
- tmp = xode_get_firstattrib(node);
- while(tmp) {
- xode_spooler(s," ",xode_get_name(tmp),"='",xode_strescape(xode_get_pool(node),xode_get_data(tmp)),"'",s);
- tmp = xode_get_nextsibling(tmp);
- }
- if(flag==0)
- xode_spool_add(s,"/>");
- else
- xode_spool_add(s,">");
- }
- else
- {
- xode_spooler(s,"</",xode_get_name(node),">",s);
- }
- }
- static xode_spool _xode_tospool(xode node)
- {
- xode_spool s;
- int level=0,dir=0;
- xode tmp;
- if(!node || xode_get_type(node) != XODE_TYPE_TAG)
- return NULL;
- s = xode_spool_newfrompool(xode_get_pool(node));
- if(!s) return(NULL);
- while(1)
- {
- if(dir==0)
- {
- if(xode_get_type(node) == XODE_TYPE_TAG)
- {
- if(xode_has_children(node))
- {
- _xode_tag2str(s,node,1);
- node = xode_get_firstchild(node);
- level++;
- continue;
- }
- else
- {
- _xode_tag2str(s,node,0);
- }
- }
- else
- {
- xode_spool_add(s,xode_strescape(xode_get_pool(node),xode_get_data(node)));
- }
- }
- tmp = xode_get_nextsibling(node);
- if(!tmp)
- {
- node = xode_get_parent(node);
- level--;
- if(level>=0) _xode_tag2str(s,node,2);
- if(level<1) break;
- dir = 1;
- }
- else
- {
- node = tmp;
- dir = 0;
- }
- }
- return s;
- }
- /* External routines */
- /*
- * xode_new_tag -- create a tag node
- * Automatically creates a memory xode_pool for the node.
- *
- * parameters
- * name -- name of the tag
- *
- * returns
- * a pointer to the tag node
- * or NULL if it was unsuccessful
- */
- xode xode_new(const char* name)
- {
- return _xode_new(NULL, name, XODE_TYPE_TAG);
- }
- /*
- * alias for 'xode_new'
- */
- xode xode_new_tag(const char* name)
- {
- return _xode_new(NULL, name, XODE_TYPE_TAG);
- }
- /*
- * xode_new_tag_pool -- create a tag node within given pool
- *
- * parameters
- * p -- previously created memory pool
- * name -- name of the tag
- *
- * returns
- * a pointer to the tag node
- * or NULL if it was unsuccessful
- */
- xode xode_new_frompool(xode_pool p, const char* name)
- {
- return _xode_new(p, name, XODE_TYPE_TAG);
- }
- /*
- * xode_insert_tag -- append a child tag to a tag
- *
- * parameters
- * parent -- pointer to the parent tag
- * name -- name of the child tag
- *
- * returns
- * a pointer to the child tag node
- * or NULL if it was unsuccessful
- */
- xode xode_insert_tag(xode parent, const char* name)
- {
- return _xode_insert(parent, name, XODE_TYPE_TAG);
- }
- /*
- * xode_insert_cdata -- append character data to a tag
- * If last child of the parent is CDATA, merges CDATA nodes. Otherwise
- * creates a CDATA node, and appends it to the parent's child list.
- *
- * parameters
- * parent -- parent tag
- * CDATA -- character data
- * size -- size of CDATA
- * or -1 for null-terminated CDATA strings
- *
- * returns
- * a pointer to the child CDATA node
- * or NULL if it was unsuccessful
- */
- xode xode_insert_cdata(xode parent, const char* CDATA, unsigned int size)
- {
- xode result;
- if(CDATA == NULL || parent == NULL)
- return NULL;
- if(size == -1)
- size = strlen(CDATA);
- if ((parent->lastchild != NULL) && (parent->lastchild->type == XODE_TYPE_CDATA))
- {
- result = parent->lastchild;
- result->data = _xode_merge(result->p, result->data, result->data_sz, CDATA, size);
- result->data_sz = result->data_sz + size;
- }
- else
- {
- result = _xode_insert(parent, "", XODE_TYPE_CDATA);
- if (result != NULL)
- {
- result->data = (char*)xode_pool_malloc(result->p, size + 1);
- memcpy(result->data, CDATA, size);
- result->data[size] = '\0';
- result->data_sz = size;
- }
- }
- return result;
- }
- /*
- * xode_gettag -- find given tag in an xode tree
- *
- * parameters
- * parent -- pointer to the parent tag
- * name -- "name" for the child tag of that name
- * "name/name" for a sub child (recurses)
- * "?attrib" to match the first tag with that attrib defined
- * "?attrib=value" to match the first tag with that attrib and value
- * or any combination: "name/name/?attrib", etc
- *
- * results
- * a pointer to the tag matching search criteria
- * or NULL if search was unsuccessful
- */
- xode xode_get_tag(xode parent, const char* name)
- {
- char *str, *slash, *qmark, *equals;
- xode step, ret;
- if(parent == NULL || parent->firstchild == NULL || name == NULL || name == '\0') return NULL;
- if(strstr(name, "/") == NULL && strstr(name,"?") == NULL)
- return _xode_search(parent->firstchild, name, XODE_TYPE_TAG);
- /* jer's note: why can't I modify the name directly, why do I have to strdup it? damn c grrr! */
- str = strdup(name);
- slash = strstr(str, "/");
- qmark = strstr(str, "?");
- equals = strstr(str, "=");
- if(qmark != NULL && (slash == NULL || qmark < slash))
- { /* of type ?attrib */
- *qmark = '\0';
- qmark++;
- if(equals != NULL)
- {
- *equals = '\0';
- equals++;
- }
- for(step = parent->firstchild; step != NULL; step = xode_get_nextsibling(step))
- {
- if(xode_get_type(step) != XODE_TYPE_TAG)
- continue;
- if(*str != '\0')
- if(_xode_strcmp(xode_get_name(step),str) != 0)
- continue;
- if(xode_get_attrib(step,qmark) == NULL)
- continue;
- if(equals != NULL && _xode_strcmp(xode_get_attrib(step,qmark),equals) != 0)
- continue;
- break;
- }
- free(str);
- return step;
- }
- *slash = '\0';
- ++slash;
- for(step = parent->firstchild; step != NULL; step = xode_get_nextsibling(step))
- {
- if(xode_get_type(step) != XODE_TYPE_TAG) continue;
- if(_xode_strcmp(xode_get_name(step),str) != 0)
- continue;
- ret = xode_get_tag(step, slash);
- if(ret != NULL)
- {
- free(str);
- return ret;
- }
- }
- free(str);
- return NULL;
- }
- /* return the cdata from any tag */
- char *xode_get_tagdata(xode parent, const char *name)
- {
- xode tag;
- tag = xode_get_tag(parent, name);
- if(tag == NULL) return NULL;
- return xode_get_data(tag);
- }
- void xode_put_attrib(xode owner, const char* name, const char* value)
- {
- xode attrib;
- if(owner == NULL || name == NULL || value == NULL) return;
- /* If there are no existing attributes, allocate a new one to start
- the list */
- if (owner->firstattrib == NULL)
- {
- attrib = _xode_new(owner->p, name, XODE_TYPE_ATTRIB);
- owner->firstattrib = attrib;
- owner->lastattrib = attrib;
- }
- else
- {
- attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
- if(attrib == NULL)
- {
- attrib = _xode_appendsibling(owner->lastattrib, name, XODE_TYPE_ATTRIB);
- owner->lastattrib = attrib;
- }
- }
- /* Update the value of the attribute */
- attrib->data_sz = strlen(value);
- attrib->data = xode_pool_strdup(owner->p, value);
- }
- char* xode_get_attrib(xode owner, const char* name)
- {
- xode attrib;
- if (owner != NULL && owner->firstattrib != NULL)
- {
- attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
- if (attrib != NULL)
- return (char*)attrib->data;
- }
- return NULL;
- }
- void xode_put_vattrib(xode owner, const char* name, void *value)
- {
- xode attrib;
- if (owner != NULL)
- {
- attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
- if (attrib == NULL)
- {
- xode_put_attrib(owner, name, "");
- attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
- }
- if (attrib != NULL)
- attrib->firstchild = (xode)value;
- }
- }
- void* xode_get_vattrib(xode owner, const char* name)
- {
- xode attrib;
- if (owner != NULL && owner->firstattrib != NULL)
- {
- attrib = _xode_search(owner->firstattrib, name, XODE_TYPE_ATTRIB);
- if (attrib != NULL)
- return (void*)attrib->firstchild;
- }
- return NULL;
- }
- xode xode_get_firstattrib(xode parent)
- {
- if (parent != NULL)
- return parent->firstattrib;
- return NULL;
- }
- xode xode_get_firstchild(xode parent)
- {
- if (parent != NULL)
- return parent->firstchild;
- return NULL;
- }
- xode xode_get_lastchild(xode parent)
- {
- if (parent != NULL)
- return parent->lastchild;
- return NULL;
- }
- xode xode_get_nextsibling(xode sibling)
- {
- if (sibling != NULL)
- return sibling->next;
- return NULL;
- }
- xode xode_get_prevsibling(xode sibling)
- {
- if (sibling != NULL)
- return sibling->prev;
- return NULL;
- }
- xode xode_get_parent(xode node)
- {
- if (node != NULL)
- return node->parent;
- return NULL;
- }
- char* xode_get_name(xode node)
- {
- if (node != NULL)
- return node->name;
- return NULL;
- }
- char* xode_get_data(xode node)
- {
- xode cur;
- if(node == NULL) return NULL;
- if(xode_get_type(node) == XODE_TYPE_TAG) /* loop till we find a CDATA */
- {
- for(cur = xode_get_firstchild(node); cur != NULL; cur = xode_get_nextsibling(cur))
- if(xode_get_type(cur) == XODE_TYPE_CDATA)
- return cur->data;
- }else{
- return node->data;
- }
- return NULL;
- }
- int xode_get_datasz(xode node)
- {
-
- if( node == NULL )
- {
- return (int)(long)NULL;
- }
- else if(xode_get_type(node) == XODE_TYPE_TAG) /* loop till we find a CDATA */
- {
- xode cur;
- for(cur = xode_get_firstchild(node); cur != NULL; cur = xode_get_nextsibling(cur))
- if(xode_get_type(cur) == XODE_TYPE_CDATA)
- return cur->data_sz;
- }else{
- return node->data_sz;
- }
- return (int)(long)NULL;
- }
- int xode_get_type(xode node)
- {
- if (node != NULL)
- {
- return node->type;
- }
- return (int)(long)NULL;
- }
- int xode_has_children(xode node)
- {
- if ((node != NULL) && (node->firstchild != NULL))
- return 1;
- return 0;
- }
- int xode_has_attribs(xode node)
- {
- if ((node != NULL) && (node->firstattrib != NULL))
- return 1;
- return 0;
- }
- xode_pool xode_get_pool(xode node)
- {
- if (node != NULL)
- return node->p;
- return (xode_pool)NULL;
- }
- void xode_hide(xode child)
- {
- xode parent;
- if(child == NULL || child->parent == NULL)
- return;
- parent = child->parent;
- /* first fix up at the child level */
- _xode_hidesibling(child);
- /* next fix up at the parent level */
- if(parent->firstchild == child)
- parent->firstchild = child->next;
- if(parent->lastchild == child)
- parent->lastchild = child->prev;
- }
- void xode_hide_attrib(xode parent, const char *name)
- {
- xode attrib;
- if(parent == NULL || parent->firstattrib == NULL || name == NULL)
- return;
- attrib = _xode_search(parent->firstattrib, name, XODE_TYPE_ATTRIB);
- if(attrib == NULL)
- return;
- /* first fix up at the child level */
- _xode_hidesibling(attrib);
- /* next fix up at the parent level */
- if(parent->firstattrib == attrib)
- parent->firstattrib = attrib->next;
- if(parent->lastattrib == attrib)
- parent->lastattrib = attrib->prev;
- }
- /*
- * xode2str -- convert given xode tree into a string
- *
- * parameters
- * node -- pointer to the xode structure
- *
- * results
- * a pointer to the created string
- * or NULL if it was unsuccessful
- */
- char *xode_to_str(xode node)
- {
- return xode_spool_tostr(_xode_tospool(node));
- }
- /* loop through both a and b comparing everything, attribs, cdata, children, etc */
- int xode_cmp(xode a, xode b)
- {
- int ret = 0;
- while(1)
- {
- if(a == NULL && b == NULL)
- return 0;
- if(a == NULL || b == NULL)
- return -1;
- if(xode_get_type(a) != xode_get_type(b))
- return -1;
- switch(xode_get_type(a))
- {
- case XODE_TYPE_ATTRIB:
- ret = _xode_strcmp(xode_get_name(a), xode_get_name(b));
- if(ret != 0)
- return -1;
- ret = _xode_strcmp(xode_get_data(a), xode_get_data(b));
- if(ret != 0)
- return -1;
- break;
- case XODE_TYPE_TAG:
- ret = _xode_strcmp(xode_get_name(a), xode_get_name(b));
- if(ret != 0)
- return -1;
- ret = xode_cmp(xode_get_firstattrib(a), xode_get_firstattrib(b));
- if(ret != 0)
- return -1;
- ret = xode_cmp(xode_get_firstchild(a), xode_get_firstchild(b));
- if(ret != 0)
- return -1;
- break;
- case XODE_TYPE_CDATA:
- ret = _xode_strcmp(xode_get_data(a), xode_get_data(b));
- if(ret != 0)
- return -1;
- }
- a = xode_get_nextsibling(a);
- b = xode_get_nextsibling(b);
- }
- }
- xode xode_insert_tagnode(xode parent, xode node)
- {
- xode child;
- child = xode_insert_tag(parent, xode_get_name(node));
- if (xode_has_attribs(node))
- xode_insert_node(child, xode_get_firstattrib(node));
- if (xode_has_children(node))
- xode_insert_node(child, xode_get_firstchild(node));
- return child;
- }
- /* places copy of node and node's siblings in parent */
- void xode_insert_node(xode parent, xode node)
- {
- if(node == NULL || parent == NULL)
- return;
- while(node != NULL)
- {
- switch(xode_get_type(node))
- {
- case XODE_TYPE_ATTRIB:
- xode_put_attrib(parent, xode_get_name(node), xode_get_data(node));
- break;
- case XODE_TYPE_TAG:
- xode_insert_tagnode(parent, node);
- break;
- case XODE_TYPE_CDATA:
- xode_insert_cdata(parent, xode_get_data(node), xode_get_datasz(node));
- }
- node = xode_get_nextsibling(node);
- }
- }
- /* produce full duplicate of x with a new xode_pool, x must be a tag! */
- xode xode_dup(xode x)
- {
- xode x2;
- if(x == NULL)
- return NULL;
- x2 = xode_new(xode_get_name(x));
- if (xode_has_attribs(x))
- xode_insert_node(x2, xode_get_firstattrib(x));
- if (xode_has_children(x))
- xode_insert_node(x2, xode_get_firstchild(x));
- return x2;
- }
- xode xode_dup_frompool(xode_pool p, xode x)
- {
- xode x2;
- if(x == NULL)
- return NULL;
- x2 = xode_new_frompool(p, xode_get_name(x));
- if (xode_has_attribs(x))
- xode_insert_node(x2, xode_get_firstattrib(x));
- if (xode_has_children(x))
- xode_insert_node(x2, xode_get_firstchild(x));
- return x2;
- }
- xode xode_wrap(xode x,const char *wrapper)
- {
- xode wrap;
- if(x==NULL||wrapper==NULL) return NULL;
- wrap=xode_new_frompool(xode_get_pool(x),wrapper);
- if(wrap==NULL) return NULL;
- wrap->firstchild=x;
- wrap->lastchild=x;
- x->parent=wrap;
- return wrap;
- }
- void xode_free(xode node)
- {
- if(node == NULL)
- return;
- xode_pool_free(node->p);
- }
- void
- _xode_to_prettystr( xode_spool s, xode x, int deep )
- {
- int i;
- xode y;
- if(xode_get_type(x) != XODE_TYPE_TAG) return;
-
- for(i=0; i<deep; i++) xode_spool_add(s, "\t");
- xode_spooler( s , "<" , xode_get_name(x) , s );
- y = xode_get_firstattrib(x);
- while( y )
- {
- xode_spooler( s , " " , xode_get_name(y) , "='", xode_get_data(y) , "'" , s );
- y = xode_get_nextsibling( y );
- }
- xode_spool_add(s,">");
- xode_spool_add(s,"\n");
-
- if( xode_get_data(x))
- {
- for(i=0; i<=deep; i++) xode_spool_add(s, "\t");
- xode_spool_add( s , xode_get_data(x));
- }
-
- y = xode_get_firstchild(x);
- while( y )
- {
- _xode_to_prettystr(s , y, deep+1);
- y = xode_get_nextsibling(y);
- xode_spool_add(s,"\n");
- }
-
- for(i=0; i<deep; i++) xode_spool_add(s, "\t");
- xode_spooler( s , "</" , xode_get_name(x) , ">" , s );
- return;
- }
- char *
- xode_to_prettystr( xode x )
- {
- xode_spool s;
- if( !x) return NULL;
-
- s = xode_spool_newfrompool( xode_get_pool(x));
- _xode_to_prettystr( s , x, 0 );
- return xode_spool_tostr(s);
- }
|