1
0
Fork 0

* Implement 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.
This commit is contained in:
ehofman 2009-05-24 14:09:46 +00:00 committed by Tim Moore
parent 301efcd529
commit fc0b771cdf
9 changed files with 566 additions and 128 deletions

View file

@ -1,3 +1,8 @@
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

View file

@ -1,5 +1,18 @@
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

View file

@ -82,11 +82,9 @@ void print_xml(void *id)
printf("\n");
for(q=0; q<level; q++) printf(" ");
printf("<%s>", name);
level++;
print_xml(xid);
level--;
printf("</%s>", name);
}
else printf("error\n");

View file

@ -1,11 +1,22 @@
#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;
@ -16,8 +27,8 @@ int main()
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);
@ -26,8 +37,8 @@ int main()
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);
@ -39,6 +50,8 @@ int main()
else
printf("succes.\n");
}
else
PRINT_ERROR_AND_EXIT(root_id);
path_id = xmlNodeGet(root_id, PATH);
node_id = xmlNodeGet(root_id, ROOTNODE);
@ -49,7 +62,6 @@ int main()
size_t len;
xmlCopyString(path_id, buf, BUFLEN);
printf("Testing xmlNodeCopyString against xmlGetString:\t\t\t\t");
if ((s = xmlGetString(path_id)) != 0)
{
@ -61,45 +73,45 @@ int main()
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
@ -115,11 +127,11 @@ int main()
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);
@ -152,13 +164,20 @@ int main()
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);

View file

@ -26,16 +26,8 @@
*/
#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>
@ -63,12 +55,6 @@ typedef struct
#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)
@ -88,38 +74,8 @@ static void __xmlErrorSet(const void *, const char *, unsigned int);
# 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);
@ -140,12 +96,14 @@ static void simple_unmmap(SIMPLE_UNMMAP *);
#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__); \
@ -169,16 +127,20 @@ xmlOpen(const char *filename)
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;
}
}
}
@ -194,16 +156,20 @@ xmlInitBuffer(const char *buffer, size_t size)
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
}
}
@ -224,6 +190,9 @@ xmlClose(void *id)
close(rid->fd);
}
#ifdef XML_USE_NODECACHE
if (rid->node) cacheFree(rid->node);
#endif
#ifndef XML_NONVALIDATING
if (rid->info) free(rid->info);
#endif
@ -238,6 +207,7 @@ xmlNodeGet(const void *id, const char *path)
struct _xml_id *xsid = 0;
size_t len, slen;
char *ptr, *node;
void *nc, *nnc;
assert(id != 0);
assert(path != 0);
@ -245,16 +215,21 @@ xmlNodeGet(const void *id, const char *path)
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;
@ -282,11 +257,14 @@ xmlNodeCopy(const void *id, const char *path)
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);
@ -298,6 +276,9 @@ xmlNodeCopy(const void *id, const char *path)
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;
@ -378,12 +359,14 @@ xmlNodeGetNum(const void *id, const char *path)
{
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)
{
@ -393,7 +376,7 @@ xmlNodeGetNum(const void *id, const char *path)
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);
@ -408,7 +391,11 @@ xmlNodeGetNum(const void *id, const char *path)
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);
@ -428,6 +415,7 @@ xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
size_t len, slen;
char *ptr, *node;
void *ret = 0;
void *nc;
assert(xpid != 0);
assert(xid != 0);
@ -436,13 +424,23 @@ xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
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)
@ -467,12 +465,10 @@ xmlGetString(const void *id)
char *ps;
ps = xid->start;
len = xid->len-1;
len = xid->len;
__xmlPrepareData(&ps, &len);
if (len)
{
len++;
str = malloc(len+1);
if (str)
{
@ -503,20 +499,19 @@ xmlCopyString(const void *id, char *buffer, size_t buflen)
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;
@ -540,9 +535,9 @@ xmlCompareString(const void *id, const char *s)
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;
@ -559,20 +554,20 @@ xmlNodeGetString(const void *id, const char *path)
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
@ -606,8 +601,10 @@ xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
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);
@ -647,11 +644,13 @@ xmlNodeCompareString(const void *id, const char *path, const char *s)
{
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;
@ -697,11 +696,13 @@ xmlNodeGetInt(const void *id, const char *path)
{
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;
@ -746,11 +747,13 @@ xmlNodeGetDouble(const void *id, const char *path)
{
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;
@ -779,9 +782,12 @@ xmlMarkId(const void *id)
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
@ -1332,7 +1338,7 @@ static const char *__xml_error_str[XML_MAX_ERROR] =
#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;
@ -1363,12 +1369,17 @@ __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *nlen)
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;
@ -1391,7 +1402,7 @@ __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *nlen)
}
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;
@ -1400,6 +1411,7 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
size_t open_len = *rlen;
size_t return_len = 0;
int found, num;
void *nnc = 0;
assert(start != 0);
assert(len != 0);
@ -1420,6 +1432,10 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
cur = (char *)start;
ne = cur + restlen;
#ifdef XML_USE_NODECACHE
cacheInitLevel(nc);
#endif
/* search for an opening tag */
while ((new = memchr(cur, '<', restlen)) != 0)
{
@ -1465,9 +1481,10 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
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)
{
@ -1486,11 +1503,18 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
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;
@ -1544,6 +1568,9 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
{
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);
@ -1582,7 +1609,7 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
/*
* 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 */
@ -1622,6 +1649,9 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
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)
@ -1787,10 +1817,14 @@ __xmlPrepareData(char **start, size_t *blocklen)
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))

View file

@ -1,5 +1,5 @@
/* 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
@ -32,6 +32,14 @@
extern "C" {
#endif
#undef XML_NONVALIDATING
#ifdef XML_USE_NODECACHE
#include "xml_cache.h"
#else
void *cacheGet(void *);
#endif
enum
{
XML_NO_ERROR = 0,
@ -49,6 +57,63 @@ enum
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.
*

249
utils/xmlgrep/xml_cache.c Normal file
View file

@ -0,0 +1,249 @@
/* 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

50
utils/xmlgrep/xml_cache.h Normal file
View file

@ -0,0 +1,50 @@
/* 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 */

View file

@ -218,7 +218,12 @@ void walk_the_tree(size_t num, void *xid, char *tree)
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,