* 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:
parent
301efcd529
commit
fc0b771cdf
9 changed files with 566 additions and 128 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
249
utils/xmlgrep/xml_cache.c
Normal 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
50
utils/xmlgrep/xml_cache.h
Normal 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 */
|
||||
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Reference in a new issue