From: ehofman Date: Sun, 24 May 2009 14:09:46 +0000 (+0000) Subject: * Implement a node cache that can be enabled at compile time. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=fc0b771cdfee454914b085eb07a9060a43a7d17d;p=flightgear.git * 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. --- diff --git a/utils/xmlgrep/ChangeLog b/utils/xmlgrep/ChangeLog index 789549a2a..2f8e4c26b 100644 --- a/utils/xmlgrep/ChangeLog +++ b/utils/xmlgrep/ChangeLog @@ -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 diff --git a/utils/xmlgrep/Makefile.am b/utils/xmlgrep/Makefile.am index 84db18051..167f15a9d 100644 --- a/utils/xmlgrep/Makefile.am +++ b/utils/xmlgrep/Makefile.am @@ -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 diff --git a/utils/xmlgrep/printxml.c b/utils/xmlgrep/printxml.c index 470465d87..119c1a148 100644 --- a/utils/xmlgrep/printxml.c +++ b/utils/xmlgrep/printxml.c @@ -82,11 +82,9 @@ void print_xml(void *id) printf("\n"); for(q=0; q", name); - level++; print_xml(xid); level--; - printf("", name); } else printf("error\n"); diff --git a/utils/xmlgrep/testxml.c b/utils/xmlgrep/testxml.c index 42fd5d3bf..732f0815a 100644 --- a/utils/xmlgrep/testxml.c +++ b/utils/xmlgrep/testxml.c @@ -1,11 +1,22 @@ #include #include +#include #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); diff --git a/utils/xmlgrep/xml.c b/utils/xmlgrep/xml.c index b9016c08e..c02142280 100644 --- a/utils/xmlgrep/xml.c +++ b/utils/xmlgrep/xml.c @@ -26,16 +26,8 @@ */ #ifdef WIN32 -# define WIN32_LEAN_AND_MEAN -# include # include -typedef struct -{ - HANDLE m; - void *p; -} SIMPLE_UNMMAP; - #else /* !WIN32 */ # include # include @@ -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; qnode = 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. */ { 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 ((psps) && isspace(*pe)) pe--; - len = (pe-ps); + if (len > 1) + { + pe = ps + len-1; + while ((psps) && isspace(*pe)) pe--; + len = (pe-ps)+1; + } + else if (isspace(*(ps+1))) len--; /* CDATA or comment */ if ((len >= 2) && !strncmp(ps, " + +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. * diff --git a/utils/xmlgrep/xml_cache.c b/utils/xmlgrep/xml_cache.c new file mode 100644 index 000000000..08ac771d6 --- /dev/null +++ b/utils/xmlgrep/xml_cache.c @@ -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 +#include +#include + +#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; qfirst_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; ifirst_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 + diff --git a/utils/xmlgrep/xml_cache.h b/utils/xmlgrep/xml_cache.h new file mode 100644 index 000000000..b94fb53ee --- /dev/null +++ b/utils/xmlgrep/xml_cache.h @@ -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 */ + diff --git a/utils/xmlgrep/xmlgrep.c b/utils/xmlgrep/xmlgrep.c index 35add47a5..23577b0c8 100644 --- a/utils/xmlgrep/xmlgrep.c +++ b/utils/xmlgrep/xmlgrep.c @@ -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\n", _filenames[num], _print, _attribute, _value,