1
0
Fork 0
flightgear/utils/xmlgrep/xml_cache.c
2009-06-03 00:18:56 +02:00

250 lines
6 KiB
C

/* Copyright (c) 2007-2009 by Adalin B.V.
* Copyright (c) 2007-2009 by Erik Hofman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of (any of) the copyrightholder(s) nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <assert.h>
#include "xml.h"
#ifndef NDEBUG
# define PRINT(a, b, c) { \
size_t l1 = (b), l2 = (c); \
char *s = (a); \
if (s) { \
size_t q, len = l2; \
if (l1 < l2) len = l1; \
if (len < 50000) { \
printf("(%i) '", len); \
for (q=0; q<len; q++) printf("%c", s[q]); \
printf("'\n"); \
} else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
} else printf("NULL pointer at line %i\n", __LINE__); \
}
#endif
#if !defined(XML_USE_NODECACHE)
void *
cacheNodeGet(void *id, const char *node)
{
return 0;
}
#else
#define NODE_BLOCKSIZE 16
struct _xml_node
{
void *parent;
char *name;
size_t name_len;
char *data;
size_t data_len;
void **node;
size_t no_nodes;
size_t first_free;
};
char *
__xmlNodeGetFromCache(void **nc, const char *start, size_t *len,
char **element, size_t *elementlen , size_t *nodenum)
{
struct _xml_node *cache;
size_t num = *nodenum;
char *name = *element;
void *rv = 0;
assert(nc != 0);
cache = (struct _xml_node *)*nc;
assert(cache != 0);
assert((cache->first_free > num) || (cache->first_free == 0));
if (cache->first_free == 0) /* leaf node */
{
rv = cache->data;
*len = cache->data_len;
*element = cache->name;
*elementlen = cache->name_len;
*nodenum = 0;
}
else if (*name == '*')
{
struct _xml_node *node = cache->node[num];
*nc = node;
rv = node->data;
*len = node->data_len;
*element = node->name;
*elementlen = node->name_len;
*nodenum = cache->first_free;
}
else
{
size_t namelen = *elementlen;
size_t i, pos = 0;
for (i=0; i<cache->first_free; i++)
{
struct _xml_node *node = cache->node[i];
assert(node);
if ((node->name_len == namelen) &&
(!strncasecmp(node->name, name, namelen)))
{
if (pos == num)
{
*nc = node;
rv = node->data;
*element = node->name;
*elementlen = node->name_len;
*len = node->data_len;
*nodenum = cache->first_free;
break;
}
pos++;
}
}
}
return rv;
}
void *
cacheInit()
{
return calloc(1, sizeof(struct _xml_node));
}
void
cacheInitLevel(void *nc)
{
struct _xml_node *cache = (struct _xml_node *)nc;
assert(cache != 0);
cache->node = calloc(NODE_BLOCKSIZE, sizeof(struct _xml_node *));
cache->no_nodes = NODE_BLOCKSIZE;
}
void
cacheFree(void *nc)
{
struct _xml_node *cache = (struct _xml_node *)nc;
assert(nc != 0);
if (cache->first_free)
{
struct _xml_node **node = (struct _xml_node **)cache->node;
size_t i = 0;
while(i < cache->first_free)
{
cacheFree(node[i++]);
}
free(node);
}
free(cache);
}
void *
cacheNodeGet(void *id)
{
struct _xml_id *xid = (struct _xml_id *)id;
struct _xml_node *cache = 0;
assert(xid != 0);
if (xid->name)
{
cache = xid->node;
}
else
{
struct _root_id *rid = (struct _root_id *)xid;
cache = rid->node;
}
return cache;
}
void *
cacheNodeNew(void *nc)
{
struct _xml_node *cache = (struct _xml_node *)nc;
struct _xml_node *rv = 0;
size_t i = 0;
assert(nc != 0);
i = cache->first_free;
if (i == cache->no_nodes)
{
size_t size, no_nodes;
void *p;
no_nodes = cache->no_nodes + NODE_BLOCKSIZE;
size = no_nodes * sizeof(struct _xml_node *);
p = realloc(cache->node, size);
if (!p) return 0;
cache->node = p;
cache->no_nodes = no_nodes;
}
rv = calloc(1, sizeof(struct _xml_node));
if (rv) rv->parent = cache;
cache->node[i] = rv;
cache->first_free++;
return rv;
}
void
cacheDataSet(void *n, char *name, size_t namelen, char *data, size_t datalen)
{
struct _xml_node *node = (struct _xml_node *)n;
assert(node != 0);
assert(name != 0);
assert(namelen != 0);
assert(data != 0);
node->name = name;
node->name_len = namelen;
node->data = data;
node->data_len = datalen;
}
#endif