+24-05-2009
+ * Add a node cache that can be enabled at compile time.
+ the node cache prevents recursively walking the xml tree over and over
+ again to find the specified nodes.
+
05-05-2009
* Various bugfixes, required to get fgrun working
* add testxml as sort of a stress test application
+noinst_HEADERS = xml_cache.h xml.h
+
+noinst_LIBRARIES = libxmlconf.a
+
+libxmlconf_a_SOURCES = xml_cache.c xml.c
+
noinst_PROGRAMS = testxml printxml xmlgrep
-testxml_SOURCES = testxml.c xml.c
-printxml_SOURCES = printxml.c xml.c
-xmlgrep_SOURCES = xmlgrep.c xml.c xml.h
+testxml_SOURCES = testxml.c
+testxml_LDADD = libxmlconf.a
+
+printxml_SOURCES = $(xml_SOURCE) printxml.c
+printxml_LDADD = libxmlconf.a
+
+xmlgrep_SOURCES = $(xml_SOURCE) xmlgrep.c xml.c xml.h
+xmlgrep_LDADD = libxmlconf.a
+
+INCLUDES = -DSRC_DIR=\"$(top_srcdir)/utils/xmlgrep\" -DXML_USE_NODECACHE
printf("\n");
for(q=0; q<level; q++) printf(" ");
printf("<%s>", name);
-
level++;
print_xml(xid);
level--;
-
printf("</%s>", name);
}
else printf("error\n");
#include <stdio.h>
#include <malloc.h>
+#include <assert.h>
#include "xml.h"
#define ROOTNODE "/Configuration/output/menu"
#define LEAFNODE "name"
#define PATH ROOTNODE"/"LEAFNODE
#define BUFLEN 4096
+
+#define PRINT_ERROR_AND_EXIT(id) \
+ if (xmlErrorGetNo(id, 0) != XML_NO_ERROR) { \
+ const char *errstr = xmlErrorGetString(id, 0); \
+ size_t column = xmlErrorGetColumnNo(id, 0); \
+ size_t lineno = xmlErrorGetLineNo(id, 1); \
+ printf("Error at line %i, column %i: %s\n", lineno, column, errstr); \
+ exit(-1); \
+ }
+
int main()
{
void *root_id;
void *path_id, *node_id;
char *s;
- printf("\nTesting xmlNodeGetString for /Configuration/output/test:\t\t");
- s = xmlNodeGetString(root_id , "/Configuration/output/test");
+ printf("\nTesting xmlNodeGetString for /*/*/test:\t\t\t\t\t");
+ s = xmlNodeGetString(root_id , "/*/*/test");
if (s)
{
printf("failed.\n\t'%s' should be empty\n", s);
else
printf("succes.\n");
- printf("Testing xmlGetString for Configuration/output/test:\t\t\t");
- path_id = xmlNodeGet(root_id, "*/*/test");
+ printf("Testing xmlGetString for /Configuration/output/test:\t\t\t");
+ path_id = xmlNodeGet(root_id, "/Configuration/output/test");
if (path_id)
{
s = xmlGetString(path_id);
else
printf("succes.\n");
}
+ else
+ PRINT_ERROR_AND_EXIT(root_id);
path_id = xmlNodeGet(root_id, PATH);
node_id = xmlNodeGet(root_id, ROOTNODE);
size_t len;
xmlCopyString(path_id, buf, BUFLEN);
-
printf("Testing xmlNodeCopyString against xmlGetString:\t\t\t\t");
if ((s = xmlGetString(path_id)) != 0)
{
printf("Testing xmlCopyString against xmlGetString:\t\t\t\t");
xmlCopyString(path_id, buf, BUFLEN);
if (strcmp(s, buf)) /* not the same */
- printf("failed.\n\t'%s' differs from '%s'\n", s, buf);
+ printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
- free(s);
}
else
- printf("Error while fetching node's value.\n");
+ PRINT_ERROR_AND_EXIT(path_id);
printf("Testing xmlCopyString against xmlCompareString:\t\t\t\t");
if (xmlCompareString(path_id, buf)) /* not the same */
- printf ("failed.\n\t'%s' differs\n", buf);
+ printf ("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
printf("Testing xmlCopyString against xmlNodeCompareString:\t\t\t");
if (xmlNodeCompareString(node_id, LEAFNODE, buf)) /* not the same */
- printf ("failed.\n\t'%s' differs\n", buf);
+ printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
+
+ if (s) free(s);
printf("Testing xmlCopyString against xmlNodeGetString:\t\t\t\t");
if ((s = xmlNodeGetString(node_id, LEAFNODE)) != 0)
{
if (strcmp(s, buf)) /* not the same */
- printf("failed.\n\t'%s' differs from '%s'\n", s, buf);
+ printf("failed.\n\t'%s' differs from\n\t'%s'\n", s, buf);
else
printf("succes.\n");
free(s);
}
else
- printf("Error while fetching value from node.\n");
+ PRINT_ERROR_AND_EXIT(node_id);
free(path_id);
path_id = xmlNodeGet(root_id, "/Configuration/backend/name");
if (path_id)
{
- xmlAttributeCopyString(path_id, "type", buf, BUFLEN);
-
printf("Testing xmlAttributeCopyString against xmlAttributeCompareString:\t");
+ xmlAttributeCopyString(path_id, "type", buf, BUFLEN);
if (xmlAttributeCompareString(path_id, "type", buf)) /* no match */
printf("failed.\n\t'%s' differs\n", buf);
else
free(s);
}
else
- printf("Error while fetching value from attribute.\n");
+ PRINT_ERROR_AND_EXIT(path_id);
}
else
- printf("Error while fetching node's attribute.\n");
+ PRINT_ERROR_AND_EXIT(root_id);
free(node_id);
free(path_id);
free(s);
}
+ else
+ PRINT_ERROR_AND_EXIT(path_id);
free(path_id);
}
}
- else
+
+ if (xmlErrorGetNo(root_id, 0) != XML_NO_ERROR)
{
- printf("Error: %s\n", xmlErrorGetString(root_id, 1));
+ const char *errstr = xmlErrorGetString(root_id, 0);
+ size_t column = xmlErrorGetColumnNo(root_id, 0);
+ size_t lineno = xmlErrorGetLineNo(root_id, 1);
+
+ printf("Error at line %i, column %i: %s\n", lineno, column, errstr);
}
xmlClose(root_id);
*/
#ifdef WIN32
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
# include <io.h>
-typedef struct
-{
- HANDLE m;
- void *p;
-} SIMPLE_UNMMAP;
-
#else /* !WIN32 */
# include <sys/mman.h>
# include <unistd.h>
#ifndef XML_NONVALIDATING
static const char *__xml_error_str[XML_MAX_ERROR];
-struct _xml_error
-{
- char *pos;
- int err_no;
-};
-
static void __xmlErrorSet(const void *, const char *, unsigned int);
# define xmlErrorSet(a, b, c) __xmlErrorSet(a, b, c)
# define SET_ERROR_AND_RETURN(a, b) return 0;
#endif
-/*
- * It is required for both the rood node and the normal xml nodes to both
- * have 'char *name' defined as the first entry. The code tests whether
- * name == 0 to detect the root node.
- */
-struct _root_id
-{
- char *name;
- char *start;
- size_t len;
- int fd;
-#ifndef XML_NONVALIDATING
- struct _xml_error *info;
-#endif
-# ifdef WIN32
- SIMPLE_UNMMAP un;
-# endif
-};
-
-struct _xml_id
-{
- char *name;
- char *start;
- size_t len;
- size_t name_len;
-#ifndef XML_NONVALIDATING
- struct _root_id *root;
-#endif
-};
-
-static char *__xmlNodeGetPath(const char *, size_t *, char **, size_t *);
-static char *__xmlNodeGet(const char *, size_t *, char **, size_t *, size_t *);
+static char *__xmlNodeGetPath(void **, const char *, size_t *, char **, size_t *);
+static char *__xmlNodeGet(void *, const char *, size_t *, char **, size_t *, size_t *);
static char *__xmlProcessCDATA(char **, size_t *);
static char *__xmlCommentSkip(const char *, size_t);
static char *__xmlInfoProcess(const char *, size_t);
#ifndef NDEBUG
# define PRINT(a, b, c) { \
- if (a) { \
- size_t q, len = c; \
- if (b < c) len = b; \
+ 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", ((char *)(a))[q]); \
+ 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__); \
mm = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0L);
if (mm != (void *)-1)
{
- rid = malloc(sizeof(struct _root_id));
+ rid = calloc(1, sizeof(struct _root_id));
if (rid)
{
+ size_t blen = statbuf.st_size;
+#ifdef XML_USE_NODECACHE
+ size_t num = 0, nlen = 1;
+ char *n = "*";
+
+ rid->node = cacheInit();
+ __xmlNodeGet(rid->node, mm, &blen, &n, &nlen, &num);
+#endif
rid->fd = fd;
rid->start = mm;
- rid->len = statbuf.st_size;
- rid->name = 0;
-#ifndef XML_NONVALIDATING
- rid->info = 0;
-#endif
+ rid->len = blen;
}
}
}
if (buffer && (size > 0))
{
- rid = malloc(sizeof(struct _root_id));
+ rid = calloc(1, sizeof(struct _root_id));
if (rid)
{
- rid->fd = -1;
+#ifdef XML_USE_NODECACHE
+ size_t num = 0, nlen = 1;
+ size_t blen = size;
+ char *n = "*";
+
+ rid->node = cacheInit();
+ __xmlNodeGet(rid->node, buffer, &blen, &n, &nlen, &num);
+#endif
+ rid->fd = -1;
rid->start = (char *)buffer;
rid->len = size;
- rid->name = 0;
-#ifndef XML_NONVALIDATING
- rid->info = 0;
-#endif
}
}
close(rid->fd);
}
+#ifdef XML_USE_NODECACHE
+ if (rid->node) cacheFree(rid->node);
+#endif
#ifndef XML_NONVALIDATING
if (rid->info) free(rid->info);
#endif
struct _xml_id *xsid = 0;
size_t len, slen;
char *ptr, *node;
+ void *nc, *nnc;
assert(id != 0);
assert(path != 0);
node = (char *)path;
len = xid->len;
slen = strlen(path);
- ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+
+ nnc = nc = cacheNodeGet(xid);
+ ptr = __xmlNodeGetPath(&nnc, xid->start, &len, &node, &slen);
if (ptr)
{
xsid = malloc(sizeof(struct _xml_id));
if (xsid)
{
- xsid->len = len;
- xsid->start = ptr;
- xsid->name_len = slen;
xsid->name = node;
+ xsid->name_len = slen;
+ xsid->start = ptr;
+ xsid->len = len;
+#ifdef XML_USE_NODECACHE
+ xsid->node = nnc;
+#endif
#ifndef XML_NONVALIDATING
if (xid->name)
xsid->root = xid->root;
struct _xml_id *xsid = 0;
char *ptr, *node, *p;
size_t slen, len;
+ void *nc, *nnc;
node = (char *)path;
len = xid->len;
slen = strlen(path);
- ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+
+ nnc = nc = cacheNodeGet(xid);
+ ptr = __xmlNodeGetPath(&nnc, xid->start, &len, &node, &slen);
if (ptr)
{
xsid = malloc(sizeof(struct _xml_id) + len);
xsid->start = p;
xsid->name_len = slen;
xsid->name = node;
+#ifdef XML_USE_NODECACHE
+ xsid->node = nc;
+#endif
#ifndef XML_NONVALIDATING
if (xid->name)
xsid->root = xid->root;
{
char *nodename, *pathname;
size_t len, slen;
+ void *nc;
char *p;
nodename = (char *)path;
if (*path == '/') nodename++;
slen = strlen(nodename);
+ nc = cacheNodeGet(xid);
pathname = strchr(nodename, '/');
if (pathname)
{
pathname++;
slen -= pathname-nodename;
node = pathname;
- p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ p = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (p == 0 && slen == 0)
{
xmlErrorSet(xid, node, len);
if (p)
{
char *ret, *node = nodename;
- ret = __xmlNodeGet(p, &len, &node, &slen, &num);
+#ifndef XML_USE_NODECACHE
+ ret = __xmlNodeGet(nc, p, &len, &node, &slen, &num);
+#else
+ ret = __xmlNodeGetFromCache(&nc, p, &len, &node, &slen, &num);
+#endif
if (ret == 0 && slen == 0)
{
xmlErrorSet(xid, node, len);
size_t len, slen;
char *ptr, *node;
void *ret = 0;
+ void *nc;
assert(xpid != 0);
assert(xid != 0);
len = xpid->len;
slen = strlen(element);
node = (char *)element;
- ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
+ nc = cacheNodeGet(xpid);
+#ifndef XML_USE_NODECACHE
+ ptr = __xmlNodeGet(nc, xpid->start, &len, &node, &slen, &num);
+#else
+ ptr = __xmlNodeGetFromCache(&nc, xpid->start, &len, &node, &slen, &num);
+#endif
if (ptr)
{
xid->len = len;
xid->start = ptr;
xid->name = node;
xid->name_len = slen;
+#ifdef XML_USE_NODECACHE
+ /* unused for the cache but tested at the start of this function */
+ if (len == 0) xid->len = 1;
+ xid->node = nc;
+#endif
ret = xid;
}
else if (slen == 0)
char *ps;
ps = xid->start;
- len = xid->len-1;
+ len = xid->len;
__xmlPrepareData(&ps, &len);
-
if (len)
{
- len++;
str = malloc(len+1);
if (str)
{
if (xid->len)
{
size_t len;
- char *p;
+ char *ps;
- p = xid->start;
- len = xid->len-1;
- __xmlPrepareData(&p, &len);
+ ps = xid->start;
+ len = xid->len;
+ __xmlPrepareData(&ps, &len);
if (len)
{
- len++;
if (len >= buflen)
{
len = buflen-1;
xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
}
- memcpy(buffer, p, len);
+ memcpy(buffer, ps, len);
*(buffer+len) = 0;
}
ret = len;
char *ps;
ps = xid->start;
- len = xid->len-1;
+ len = xid->len;
__xmlPrepareData(&ps, &len);
- ret = strncasecmp(ps, s, len+1);
+ ret = strncasecmp(ps, s, len);
}
return ret;
if (xid->len)
{
- char *p, *node = (char *)path;
+ char *ptr, *node = (char *)path;
size_t slen = strlen(node);
size_t len = xid->len;
+ void *nc;
- slen = strlen(node);
- p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
- if (p && len)
+ nc = cacheNodeGet(xid);
+ ptr = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
+ if (ptr && len)
{
- __xmlPrepareData(&p, &len);
-
+ __xmlPrepareData(&ptr, &len);
str = malloc(len+1);
if (str)
{
- memcpy(str, p, len);
+ memcpy(str, ptr, len);
*(str+len) = '\0';
}
else
char *p, *node = (char *)path;
size_t slen = strlen(node);
size_t len = xid->len;
+ void *nc;
- p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ nc = cacheNodeGet(xid);
+ p = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (p)
{
__xmlPrepareData(&p, &len);
{
char *node, *str, *ps, *pe;
size_t len, slen;
+ void *nc;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ nc = cacheNodeGet(xid);
+ str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (str)
{
ps = str;
{
size_t len, slen;
char *str, *node;
+ void *nc;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ nc = cacheNodeGet(xid);
+ str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (str)
{
char *end = str+len;
{
size_t len, slen;
char *str, *node;
+ void *nc;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ nc = cacheNodeGet(xid);
+ str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (str)
{
char *end = str+len;
if (xrid->name == 0)
{
xmid->name = "";
+ xmid->name_len = 0;
xmid->start = xrid->start;
xmid->len = xrid->len;
- xmid->name_len = 0;
+#ifdef XML_USE_NODECACHE
+ xmid->node = xrid->node;
+#endif
#ifndef XML_NONVALIDATING
xmid->root = xrid;
#endif
#endif
char *
-__xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *nlen)
+__xmlNodeGetPath(void **nc, const char *start, size_t *len, char **name, size_t *nlen)
{
char *path;
char *ret = 0;
num = 0;
blocklen = *len;
- ret = __xmlNodeGet(start, &blocklen, &node, &nodelen, &num);
+
+#ifndef XML_USE_NODECACHE
+ ret = __xmlNodeGet(nc, start, &blocklen, &node, &nodelen, &num);
+#else
+ ret = __xmlNodeGetFromCache(nc, start, &blocklen, &node, &nodelen, &num);
+#endif
if (ret)
{
if (path)
{
- ret = __xmlNodeGetPath(ret, &blocklen, &path, &pathlen);
+ ret = __xmlNodeGetPath(nc, ret, &blocklen, &path, &pathlen);
*name = path;
*len = blocklen;
*nlen = pathlen;
}
char *
-__xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
+__xmlNodeGet(void *nc, const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
{
char *cdata, *open_element = *name;
char *element, *start_tag=0;
size_t open_len = *rlen;
size_t return_len = 0;
int found, num;
+ void *nnc = 0;
assert(start != 0);
assert(len != 0);
cur = (char *)start;
ne = cur + restlen;
+#ifdef XML_USE_NODECACHE
+ cacheInitLevel(nc);
+#endif
+
/* search for an opening tag */
while ((new = memchr(cur, '<', restlen)) != 0)
{
element = *name;
elementlen = *rlen;
len_remaining = restlen;
- new = rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
+ rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
if (rptr) /* requested element was found */
{
+ new = rptr;
return_len = elementlen;
if (found == num)
{
element = *name;
}
+#ifdef XML_USE_NODECACHE
+ nnc = cacheNodeNew(nc);
+#endif
+
if (*(new-2) == '/') /* e.g. <test/> */
{
cur = new;
if (rptr)
{
+#ifdef XML_USE_NODECACHE
+ cacheDataSet(nnc, element, elementlen, rptr, 0);
+#endif
if (found == num)
{
open_element = start_tag;
{
if (!strncasecmp(new+1, element, elementlen))
{
+#ifdef XML_USE_NODECACHE
+ cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
+#endif
if (*(new+elementlen+1) != '>')
SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
/*
* recursively walk the xml tree from here
*/
- new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos);
+ new = __xmlNodeGet(nnc, cur-1, &slen, &node, &nlen, &pos);
if (!new)
{
if (nlen == 0) /* error upstream */
if (*(new+elementlen+1) != '>')
SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
+#ifdef XML_USE_NODECACHE
+ cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
+#endif
if (found == num)
{
if (start_tag)
size_t len = *blocklen;
char *pe, *ps = *start;
- pe = ps + len;
- while ((ps<pe) && isspace(*ps)) ps++;
- while ((pe>ps) && isspace(*pe)) pe--;
- len = (pe-ps);
+ if (len > 1)
+ {
+ pe = ps + len-1;
+ while ((ps<pe) && isspace(*ps)) ps++;
+ while ((pe>ps) && isspace(*pe)) pe--;
+ len = (pe-ps)+1;
+ }
+ else if (isspace(*(ps+1))) len--;
/* CDATA or comment */
if ((len >= 2) && !strncmp(ps, "<!", 2))
-/* Copyright (c) 2007, 2008 by Adalin B.V.
- * Copyright (c) 2007, 2008 by Erik Hofman
+/* 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
extern "C" {
#endif
+#undef XML_NONVALIDATING
+
+#ifdef XML_USE_NODECACHE
+#include "xml_cache.h"
+#else
+void *cacheGet(void *);
+#endif
+
enum
{
XML_NO_ERROR = 0,
XML_MAX_ERROR
};
+#ifdef WIN32
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+typedef struct
+{
+ HANDLE m;
+ void *p;
+} SIMPLE_UNMMAP;
+#endif
+
+#ifndef XML_NONVALIDATING
+struct _xml_error
+{
+ char *pos;
+ int err_no;
+};
+#endif
+
+/*
+ * It is required for both the rood node and the normal xml nodes to both
+ * have 'char *name' defined as the first entry. The code tests whether
+ * name == 0 to detect the root node.
+ */
+struct _root_id
+{
+ char *name;
+ char *start;
+ size_t len;
+ int fd;
+#ifdef XML_USE_NODECACHE
+ void *node;
+#endif
+#ifndef XML_NONVALIDATING
+ struct _xml_error *info;
+#endif
+#ifdef WIN32
+ SIMPLE_UNMMAP un;
+#endif
+};
+
+struct _xml_id
+{
+ char *name;
+ char *start;
+ size_t len;
+ size_t name_len;
+#ifndef XML_NONVALIDATING
+ struct _root_id *root;
+#endif
+#ifdef XML_USE_NODECACHE
+ void *node;
+#endif
+};
+
+
+
/**
* Open an XML file for processing.
*
--- /dev/null
+/* 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) &&
+ (!memcmp(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;
+ struct _xml_node *ptr, **node;
+ size_t i = 0;
+
+ assert(nc != 0);
+
+ node = (struct _xml_node **)cache->node;
+ while((i < cache->no_nodes) && (ptr = node[i++]) != 0)
+ {
+ cacheFree(ptr);
+ }
+
+ 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;
+ size_t len = datalen;
+ char *ptr = data;
+
+ 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
+
--- /dev/null
+/* 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.
+ */
+
+#ifndef __XML_NODECACHE
+#define __XML_NODECACHE 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *cacheInit();
+void cacheInitLevel(void *);
+void cacheFree(void *);
+void *cacheNodeNew(void *);
+
+void *cacheNodeGet(void *);
+void cacheDataSet(void *, char *, size_t, char *, size_t);
+
+char *__xmlNodeGetFromCache(void **, const char *, size_t *, char **, size_t *, size_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_NODECACHE */
+
value = xmlGetString(xmid);
if (_value && _attribute && value)
{
+#if 1
+ char *a = xmlAttributeGetString(xmid, _attribute);
+ if (a && !strcmp(a, _value))
+#else
if (!xmlAttributeCompareString(xmid, _attribute, _value))
+#endif
{
printf("%s: <%s %s=\"%s\">%s</%s>\n",
_filenames[num], _print, _attribute, _value,