📄 xode.c
字号:
/* * $Id: xode.c,v 1.3 2004/08/24 08:58:30 janakj Exp $ * * 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/ */#include "xode.h"static int _xode_strcmp(const char *a, const char *b){ if(a == NULL || b == NULL) return -1; return strcmp(a,b);}/* 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -