]> git.mxchange.org Git - flightgear.git/commitdiff
* Implement a node cache that can be enabled at compile time.
authorehofman <ehofman>
Sun, 24 May 2009 14:09:46 +0000 (14:09 +0000)
committerTim Moore <timoore@redhat.com>
Tue, 2 Jun 2009 22:18:55 +0000 (00:18 +0200)
    the node cache prevents recursively walking the xml tree over and over
    again to find the specified nodes.

utils/xmlgrep/ChangeLog
utils/xmlgrep/Makefile.am
utils/xmlgrep/printxml.c
utils/xmlgrep/testxml.c
utils/xmlgrep/xml.c
utils/xmlgrep/xml.h
utils/xmlgrep/xml_cache.c [new file with mode: 0644]
utils/xmlgrep/xml_cache.h [new file with mode: 0644]
utils/xmlgrep/xmlgrep.c

index 789549a2a7540a26e8faad73f5e47940a0b76492..2f8e4c26b7699196f2ac146687a5dc96408ea98d 100644 (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
index 84db180516e84531016c03639d9a1f19b513d4fa..167f15a9dc37f14fba258f69cfe7edf24d0bcebf 100644 (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
index 470465d87243bac08ec0a1f487dea9b59ba1bcc0..119c1a14821fae8dc9368e46f32694bfc23523be 100644 (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");
index 42fd5d3bf1a63227b5a4dfc29a093dff77300cc3..732f0815a815ea0f620cfbcbf465143d3569fb66 100644 (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);
index b9016c08e77f041c9d7c2b4a70c4bcd0877d7cff..c021422800d246bc1ed802a3e0b05c514d96fd2d 100644 (file)
  */
 
 #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))
index 52843857e209402f6eba5a1af9b5eec3c87b4964..7431b4b5b03e47821c02176090a5addb5f5867b6 100644 (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
 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.
  *
diff --git a/utils/xmlgrep/xml_cache.c b/utils/xmlgrep/xml_cache.c
new file mode 100644 (file)
index 0000000..08ac771
--- /dev/null
@@ -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
+
diff --git a/utils/xmlgrep/xml_cache.h b/utils/xmlgrep/xml_cache.h
new file mode 100644 (file)
index 0000000..b94fb53
--- /dev/null
@@ -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 */
+
index 35add47a5d65ca7022108200db213bedfb873149..23577b0c8d2415a25343817e413c1dcd33836cf1 100644 (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,