⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nad.c

📁 这是一个完全开放的
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * 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, MA02111-1307USA *//** * !!! Things to do (after 2.0) * * - make nad_find_scoped_namespace() take an element index, and only search *   the scope on that element (currently, it searchs all elements from *   end to start, which isn't really correct, though it works in most cases * * - new functions: *     * insert one nad (or part thereof) into another nad *     * clear a part of a nad (like xmlnode_hide) * * - audit use of depth array and parent (see j2 bug #792) */#include "util.h"#ifdef HAVE_EXPAT#include "expat/expat.h"#endif/* define NAD_DEBUG to get pointer tracking - great for weird bugs that you can't reproduce */#ifdef NAD_DEBUGstatic xht _nad_alloc_tracked = NULL;static xht _nad_free_tracked = NULL;static void _nad_ptr_check(const char *func, nad_t nad) {    char loc[24];    snprintf(loc, sizeof(loc), "%x", (int) nad);    if(xhash_get(_nad_alloc_tracked, loc) == NULL) {        fprintf(stderr, ">>> NAD OP %s: 0x%x not allocated!\n", func, (int) nad);        abort();    }    if(xhash_get(_nad_free_tracked, loc) != NULL) {        fprintf(stderr, ">>> NAD OP %s: 0x%x previously freed!\n", func, (int) nad);        abort();    }    fprintf(stderr, ">>> NAD OP %s: 0x%x\n", func, (int) nad);}#else#define _nad_ptr_check(func,nad)#endif#define BLOCKSIZE 1024/** internal: do and return the math and ensure it gets realloc'd */int _nad_realloc(void **oblocks, int len){    void *nblocks;    int nlen;    /* round up to standard block sizes */    nlen = (((len-1)/BLOCKSIZE)+1)*BLOCKSIZE;    /* keep trying till we get it */    while((nblocks = realloc(*oblocks, nlen)) == NULL) sleep(1);    *oblocks = nblocks;    return nlen;}/** this is the safety check used to make sure there's always enough mem */#define NAD_SAFE(blocks, size, len) if((size) > len) len = _nad_realloc((void**)&(blocks),(size));/** internal: append some cdata and return the index to it */int _nad_cdata(nad_t nad, const char *cdata, int len){    NAD_SAFE(nad->cdata, nad->ccur + len, nad->clen);    memcpy(nad->cdata + nad->ccur, cdata, len);    nad->ccur += len;    return nad->ccur - len;}/** internal: create a new attr on any given elem */int _nad_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen){    int attr;    /* make sure there's mem for us */    NAD_SAFE(nad->attrs, (nad->acur + 1) * sizeof(struct nad_attr_st), nad->alen);    attr = nad->acur;    nad->acur++;    nad->attrs[attr].next = nad->elems[elem].attr;    nad->elems[elem].attr = attr;    nad->attrs[attr].lname = strlen(name);    nad->attrs[attr].iname = _nad_cdata(nad,name,nad->attrs[attr].lname);    if(vallen > 0)        nad->attrs[attr].lval = vallen;    else        nad->attrs[attr].lval = strlen(val);    nad->attrs[attr].ival = _nad_cdata(nad,val,nad->attrs[attr].lval);        nad->attrs[attr].my_ns = ns;    return attr;}/** create a new cache, simple pointer to a list of nads */nad_cache_t nad_cache_new(void){    nad_cache_t cache;    while((cache = malloc(sizeof(nad_cache_t))) == NULL) sleep(1);    *cache = NULL;#ifdef NAD_DEBUG    if(_nad_alloc_tracked == NULL) _nad_alloc_tracked = xhash_new(501);    if(_nad_free_tracked == NULL) _nad_free_tracked = xhash_new(501);#endif        return cache;}/** free the cache and any nads in it */void nad_cache_free(nad_cache_t cache){    nad_t cur;    while((cur = *cache) != NULL)    {        *cache = cur->next;        free(cur->elems);        free(cur->attrs);        free(cur->nss);        free(cur->cdata);        free(cur->depths);        free(cur);    }    free(cache);}/** get the next nad from the cache, or create some */nad_t nad_new(nad_cache_t cache){    nad_t nad;#ifndef NAD_DEBUG    /* If cache==NULL, then this NAD is not in a cache */    if ((cache!=NULL) && (*cache != NULL))    {        nad = *cache;        *cache = nad->next;        nad->ccur = nad->ecur = nad->acur = nad->ncur = 0;        nad->scope = -1;        nad->cache = cache;        nad->next = NULL;        return nad;    }#endif    while((nad = malloc(sizeof(struct nad_st))) == NULL) sleep(1);    memset(nad,0,sizeof(struct nad_st));    nad->scope = -1;    nad->cache = cache;#ifdef NAD_DEBUG    {    char loc[24];    snprintf(loc, sizeof(loc), "%x", (int) nad);    xhash_put(_nad_alloc_tracked, pstrdup(xhash_pool(_nad_alloc_tracked), loc), (void *) 1);    }    _nad_ptr_check(__func__, nad);#endif    return nad;}nad_t nad_copy(nad_t nad){    nad_t copy;    _nad_ptr_check(__func__, nad);    if(nad == NULL) return NULL;    /* create a new nad not participating in a cache */    copy = nad_new(NULL);    /* if it's not large enough, make bigger */    NAD_SAFE(copy->elems, nad->elen, copy->elen);    NAD_SAFE(copy->attrs, nad->alen, copy->alen);    NAD_SAFE(copy->nss, nad->nlen, copy->nlen);    NAD_SAFE(copy->cdata, nad->clen, copy->clen);    /* copy all data */    memcpy(copy->elems, nad->elems, nad->elen);    memcpy(copy->attrs, nad->attrs, nad->alen);    memcpy(copy->nss, nad->nss, nad->nlen);    memcpy(copy->cdata, nad->cdata, nad->clen);    /* sync data */    copy->ecur = nad->ecur;    copy->acur = nad->acur;    copy->ncur = nad->ncur;    copy->ccur = nad->ccur;    copy->scope = nad->scope;    return copy;}/** free nad, or plug nad back in the cache */void nad_free(nad_t nad){    if(nad == NULL) return;#ifdef NAD_DEBUG    _nad_ptr_check(__func__, nad);    {    char loc[24];    snprintf(loc, sizeof(loc), "%x", (int) nad);    xhash_zap(_nad_alloc_tracked, loc);    xhash_put(_nad_free_tracked, pstrdup(xhash_pool(_nad_free_tracked), loc), (void *) nad);    }#else    /* If nad->cache != NULL, then put back into cache, otherwise this nad is not in a cache */    if (nad->cache != NULL) {       nad->next = *(nad->cache);       *(nad->cache) = nad;       return;    } #endif    /* Free nad */    free(nad->elems);    free(nad->attrs);    free(nad->cdata);    free(nad->nss);    free(nad->depths);#ifndef NAD_DEBUG    free(nad);#endif}/** locate the next elem at a given depth with an optional matching name */int nad_find_elem(nad_t nad, int elem, int ns, const char *name, int depth){    int my_ns;    int lname = 0;    _nad_ptr_check(__func__, nad);    /* make sure there are valid args */    if(elem >= nad->ecur || name == NULL) return -1;    /* set up args for searching */    depth = nad->elems[elem].depth + depth;    if(name != NULL) lname = strlen(name);    /* search */    for(elem++;elem < nad->ecur;elem++)    {        /* if we hit one with a depth less than ours, then we don't have the         * same parent anymore, bail */        if(nad->elems[elem].depth < depth)            return -1;        if(nad->elems[elem].depth == depth && (lname <= 0 || (lname == nad->elems[elem].lname && strncmp(name,nad->cdata + nad->elems[elem].iname, lname) == 0)) &&          (ns < 0 || ((my_ns = nad->elems[elem].my_ns) >= 0 && NAD_NURI_L(nad, ns) == NAD_NURI_L(nad, my_ns) && strncmp(NAD_NURI(nad, ns), NAD_NURI(nad, my_ns), NAD_NURI_L(nad, ns)) == 0)))            return elem;    }    return -1;}/** get a matching attr on this elem, both name and optional val */int nad_find_attr(nad_t nad, int elem, int ns, const char *name, const char *val){    int attr, my_ns;    int lname, lval = 0;    _nad_ptr_check(__func__, nad);    /* make sure there are valid args */    if(elem >= nad->ecur || name == NULL) return -1;    attr = nad->elems[elem].attr;    lname = strlen(name);    if(val != NULL) lval = strlen(val);    while(attr >= 0)    {        /* hefty, match name and if a val, also match that */        if(lname == nad->attrs[attr].lname && strncmp(name,nad->cdata + nad->attrs[attr].iname, lname) == 0 &&           (lval <= 0 || (lval == nad->attrs[attr].lval && strncmp(val,nad->cdata + nad->attrs[attr].ival, lval) == 0)) &&          (ns < 0 || ((my_ns = nad->attrs[attr].my_ns) >= 0 && NAD_NURI_L(nad, ns) == NAD_NURI_L(nad, my_ns) && strncmp(NAD_NURI(nad, ns), NAD_NURI(nad, my_ns), NAD_NURI_L(nad, ns)) == 0)))            return attr;        attr = nad->attrs[attr].next;    }    return -1;}/** get a matching ns on this elem, both uri and optional prefix */int nad_find_namespace(nad_t nad, int elem, const char *uri, const char *prefix){    int check, ns;    _nad_ptr_check(__func__, nad);    if(uri == NULL)        return -1;    /* work backwards through our parents, looking for our namespace on each one.     * if we find it, link it. if not, the namespace is undeclared - for now, just drop it */    check = elem;    while(check >= 0)    {        ns = nad->elems[check].ns;        while(ns >= 0)        {            if(strlen(uri) == NAD_NURI_L(nad, ns) && strncmp(uri, NAD_NURI(nad, ns), NAD_NURI_L(nad, ns)) == 0 && (prefix == NULL || (nad->nss[ns].iprefix >= 0 && strlen(prefix) == NAD_NPREFIX_L(nad, ns) && strncmp(prefix, NAD_NPREFIX(nad, ns), NAD_NPREFIX_L(nad, ns)) == 0)))                return ns;            ns = nad->nss[ns].next;        }        check = nad->elems[check].parent;    }    return -1;}/** find a namespace in scope */int nad_find_scoped_namespace(nad_t nad, const char *uri, const char *prefix){    int ns;    _nad_ptr_check(__func__, nad);    if(uri == NULL)        return -1;    for(ns = 0; ns < nad->ncur; ns++)    {        if(strlen(uri) == NAD_NURI_L(nad, ns) && strncmp(uri, NAD_NURI(nad, ns), NAD_NURI_L(nad, ns)) == 0 &&           (prefix == NULL ||             (nad->nss[ns].iprefix >= 0 &&              strlen(prefix) == NAD_NPREFIX_L(nad, ns) && strncmp(prefix, NAD_NPREFIX(nad, ns), NAD_NPREFIX_L(nad, ns)) == 0)))            return ns;    }    return -1;}/** create, update, or zap any matching attr on this elem */void nad_set_attr(nad_t nad, int elem, int ns, const char *name, const char *val, int vallen){    int attr;    _nad_ptr_check(__func__, nad);    /* find one to replace first */    if((attr = nad_find_attr(nad, elem, ns, name, NULL)) < 0)    {        /* only create new if there's a value to store */        if(val != NULL)            _nad_attr(nad, elem, ns, name, val, vallen);        return;    }    /* got matching, update value or zap */    if(val == NULL)    {        nad->attrs[attr].lval = nad->attrs[attr].lname = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -