1 /* Copyright (c) 2007, 2008 by Adalin B.V.
2 * Copyright (c) 2007, 2008 by Erik Hofman
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of (any of) the copyrightholder(s) nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #define WIN32_LEAN_AND_MEAN
38 static SIMPLE_UNMMAP un;
41 * map 'filename' and return a pointer to it.
43 void *simple_mmap(int, unsigned int, SIMPLE_UNMMAP *);
44 void simple_unmmap(SIMPLE_UNMMAP *);
46 #define mmap(a,b,c,d,e,f) simple_mmap((e), (b), &un)
47 #define munmap(a,b) simple_unmmap(&un)
50 # include <sys/mman.h>
55 #include <sys/types.h>
72 static char *__xmlCopyNode(char *, size_t, const char *);
73 static char *__xmlGetNode(const char *, size_t *, char **, size_t *, int *);
74 static char *__xmlGetNodePath(const char *, size_t *, char **, size_t *);
75 static char *__xmlSkipComment(const char *, size_t);
76 static char *__xmlSkipInfo(const char *, size_t);
78 static void *__xml_memmem(const void *, size_t, const void *, size_t);
79 static void *__xml_memncasecmp(const void *, size_t *, void **, size_t *);
80 static void *__xml_memchr(const void *, int, size_t);
82 #define PRINT(a, b, c) { \
87 printf("(%i) '", len); \
88 for (q=0; q<len; q++) printf("%c", ((char *)(a))[q]); \
90 } else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
91 } else printf("NULL pointer at line %i\n", __LINE__); \
97 struct _xml_id *id = 0;
101 int fd = open(fn, O_RDONLY);
104 id = malloc(sizeof(struct _xml_id));
111 id->nlen = (size_t)fd;
112 id->len = statbuf.st_size;
113 id->start = mmap(0, id->len, PROT_READ, MAP_PRIVATE, fd, 0L);
127 struct _xml_id *xid = (struct _xml_id *)id;
128 assert(xid->name == 0);
130 munmap(xid->start, xid->len);
131 close((int)xid->nlen);
138 xmlCopyNode(const void *id, char *path)
140 struct _xml_id *xsid = 0;
144 struct _xml_id *xid = (struct _xml_id *)id;
145 char *ptr, *node, *p;
151 ptr = __xmlGetNodePath(xid->start, &len, &node, &slen);
154 xsid = malloc(sizeof(struct _xml_id) + len);
157 p = (char *)xsid + sizeof(struct _xml_id);
164 memcpy(xsid->start, ptr, len);
173 xmlGetNode(const void *id, char *path)
175 struct _xml_id *xsid = 0;
179 struct _xml_id *xid = (struct _xml_id *)id;
186 ptr = __xmlGetNodePath(xid->start, &len, &node, &slen);
189 xsid = malloc(sizeof(struct _xml_id));
204 xmlGetNodeName(const void *id)
206 struct _xml_id *xid = (struct _xml_id *)id;
214 memcpy(ret, xid->name, len);
222 xmlCopyNodeName(const void *id, const char *buf, size_t len)
224 struct _xml_id *xid = (struct _xml_id *)id;
230 if (slen > xid->nlen) slen = xid->nlen;
231 memcpy((char *)buf, xid->name, slen);
232 *((char *)buf + slen) = 0;
239 xmlGetNodeNum(const void *rid, void *id, char *element, int num)
241 struct _xml_id *xrid = (struct _xml_id *)rid;
246 struct _xml_id *xid = (struct _xml_id *)id;
251 slen = strlen(element);
253 ptr = __xmlGetNode(xrid->start, &len, &node, &slen, &num);
268 xmlCompareString(const void *id, const char *s)
270 struct _xml_id *xid = (struct _xml_id *)id;
273 if (xid && xid->len && s && (strlen(s) > 0))
281 while ((ps<pe) && isspace(*ps)) ps++;
282 while ((pe>ps) && isspace(*pe)) pe--;
285 ret = strncasecmp(ps, s, pe-ps);
292 xmlCompareNodeString(const void *id, const char *path, const char *s)
294 struct _xml_id *xid = (struct _xml_id *)id;
297 if (xid && xid->len && path && s && (strlen(s) > 0))
299 char *node, *str, *ps, *pe;
305 str = __xmlGetNodePath(xid->start, &len, &node, &slen);
312 while ((ps<pe) && isspace(*ps)) ps++;
313 while ((pe>ps) && isspace(*pe)) pe--;
316 ret = strncasecmp(pe, s, pe-ps);
324 xmlGetNodeString(const void *id, const char *path)
326 struct _xml_id *xid = (struct _xml_id *)id;
329 if (xid && xid->len && path)
331 str = __xmlCopyNode(xid->start, xid->len, path);
334 char *ps, *pe, *pend;
342 while ((ps<pe) && isspace(*ps)) ps++;
343 while ((pe>ps) && isspace(*pe)) pe--;
347 if (slen && (ps>str)) memmove(str, ps, slen);
348 else if (!slen) *str = 0;
356 xmlGetString(const void *id)
358 struct _xml_id *xid = (struct _xml_id *)id;
363 char *ps, *pe, *pend;
371 while ((ps<pe) && isspace(*ps)) ps++;
372 while ((pe>ps) && isspace(*pe)) pe--;
376 str = malloc(nlen+1);
379 memcpy(str, ps, nlen);
389 xmlCopyString(const void *id, char *buf, size_t len)
391 struct _xml_id *xid = (struct _xml_id *)id;
394 if (xid && xid->len && buf && len)
396 char *ps, *pe, *pend;
405 while ((ps<pe) && isspace(*ps)) ps++;
406 while ((pe>ps) && isspace(*pe)) pe--;
408 if (nlen > slen) nlen = slen;
412 memcpy(buf, ps, nlen);
421 xmlCopyNodeString(const void *id, const char *path, char *buffer, size_t buflen)
423 struct _xml_id *xid = (struct _xml_id *)id;
426 if (xid && xid->len && path && buffer && buflen)
435 str = __xmlGetNodePath(xid->start, &len, &node, &slen);
443 while ((ps<pe) && isspace(*ps)) ps++;
444 while ((pe>ps) && isspace(*pe)) pe--;
447 if (len >= buflen) len = buflen-1;
449 memcpy(buffer, ps, len);
459 xmlGetNodeInt(const void *id, const char *path)
461 struct _xml_id *xid = (struct _xml_id *)id;
464 if (path && xid && xid->len)
472 str = __xmlGetNodePath(xid->start, &len, &node, &slen);
476 li = strtol(str, &end, 10);
484 xmlGetInt(const void *id)
486 struct _xml_id *xid = (struct _xml_id *)id;
491 char *end = xid->start + xid->len;
492 li = strtol(xid->start, &end, 10);
499 xmlGetNodeDouble(const void *id, const char *path)
501 struct _xml_id *xid = (struct _xml_id *)id;
504 if (path && xid && xid->len)
512 str = __xmlGetNodePath(xid->start, &len, &node, &slen);
516 d = strtod(str, &end);
524 xmlGetDouble(const void *id)
526 struct _xml_id *xid = (struct _xml_id *)id;
531 char *end = xid->start + xid->len;
532 d = strtod(xid->start, &end);
540 xmlGetNumNodes(const void *id, const char *path)
542 struct _xml_id *xid = (struct _xml_id *)id;
545 if (xid && xid->len && path)
547 char *nodename, *pathname;
551 nodename = (char *)path;
552 if (*path == '/') nodename++;
553 slen = strlen(nodename);
555 pathname = strchr(nodename, '/');
562 slen -= pathname-nodename;
564 p = __xmlGetNodePath(xid->start, &len, &node, &slen);
568 p = (char *)xid->start;
574 char *node = nodename;
575 __xmlGetNode(p, &len, &node, &slen, &num);
583 xmlMarkId(const void *id)
585 struct _xml_id *xmid = 0;
589 xmid = malloc(sizeof(struct _xml_id));
592 memcpy(xmid, id, sizeof(struct _xml_id));
599 /* -------------------------------------------------------------------------- */
602 __xmlCopyNode(char *start, size_t len, const char *path)
604 char *node, *p, *ret = 0;
610 p = __xmlGetNodePath(start, &rlen, &node, &slen);
613 ret = calloc(1, rlen+1);
614 memcpy(ret, p, rlen);
621 __xmlGetNodePath(const char *start, size_t *len, char **name, size_t *plen)
632 if ((*len == 0) || (*plen == 0) || (*plen > *len))
635 node = (char *)*name;
636 if (*node == '/') node++;
644 path = strchr(node, '/');
646 if (!path) plen = slen;
647 else plen = path++ - node;
650 ret = __xmlGetNode(start, len, &node, &plen, &num);
653 plen = slen - (path - *name);
654 ret = __xmlGetNodePath(ret, len, &path, &plen);
664 __xmlGetNode(const char *start, size_t *len, char **name, size_t *rlen, int *nodenum)
666 char *new, *cur, *ne, *ret = 0;
667 size_t restlen, elementlen;
677 assert (nodenum != 0);
679 if ((*len == 0) || (*rlen == 0) || (*rlen > *len))
688 while ((new = memchr(cur, '<', restlen)) != 0)
690 if (*(new+1) == '/') /* cascading closing tag found */
702 new = __xmlSkipComment(cur, restlen);
708 else if (*cur == '?')
710 new = __xmlSkipInfo(cur, restlen);
718 element = (char *)*name;
720 new = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
724 if (found == num ) ret = new+1;
728 new = cur+elementlen;
729 if (new >= ne) return 0;
730 element = (char *)*name;
733 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
735 new = memchr(cur, '<', restlen);
740 if (*(cur+1) != '/') /* new node found */
743 size_t slen = restlen;
747 new = __xmlGetNode(cur, &slen, &node, &nlen, &pos);
750 if (slen == restlen) return 0;
751 else new = cur + slen;
757 new = memchr(cur, '<', restlen);
764 if (*(cur+1) == '/') /* closing tag found */
766 if (!strncasecmp(new+2, element, elementlen))
768 if (found == num) *len = new-ret;
773 new = memchr(cur, '>', restlen);
789 __xmlSkipComment(const char *start, size_t len)
796 if (memcmp(cur, "!--", 3) == 0)
798 if (len < 6) return 0;
805 new = memchr(cur, '-', len);
809 if ((len > 3) && (memcmp(new, "-->", 3) == 0))
819 while (new && (len > 2));
826 __xmlSkipInfo(const char *start, size_t len)
835 if (len < 3) return 0;
839 new = memchr(cur, '?', len);
840 if (!new || *(new+1) != '>') return 0;
850 __xml_memmem(const void *haystack, size_t haystacklen,
851 const void *needle, size_t needlelen)
855 if (haystack && needle && (needlelen > 0) && (haystacklen >= needlelen))
859 hs = (char *)haystack;
864 ptr = memchr(hs, *ns, haystacklen);
867 haystacklen -= (ptr - hs);
869 if (haystacklen < needlelen) break;
870 if (memcmp(ptr, needle, needlelen) == 0)
880 while (haystacklen > needlelen);
887 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
889 __xml_memncasecmp(const void *haystack, size_t *haystacklen,
890 void **needle, size_t *needlelen)
893 char *hs = (char *)haystack;
895 if (haystack && needle && needlelen && (*needlelen > 0)
896 && (*haystacklen >= *needlelen))
901 ns = (char *)*needle;
903 /* search for everything */
904 if ((*ns == '*') && (*needlelen == 1))
906 char *he = hs + *haystacklen;
908 while ((hs < he) && (*hs != ' ') && (*hs != '>')) hs++;
909 *needle = (void *)haystack;
910 *needlelen = hs - (char *)haystack;
911 while ((hs < he) && (*hs != '>')) hs++;
916 size_t nlen = *needlelen;
917 char *he = hs + *haystacklen;
919 for (i=0; i<nlen; i++)
921 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
922 if ((*hs == ' ') || (*hs == '>')) break;
929 while((hs < he) && (*hs != ' ') && (*hs != '>')) hs++;
930 *needle = (void *)haystack;
931 *needlelen = hs - (char *)haystack;
935 *needle = (void *)haystack;
936 *needlelen = hs - (char *)haystack;
937 while ((hs < he) && (*hs != '>')) hs++;
942 *haystacklen -= hs - (char *)haystack;
950 * https://mollyrocket.com/forums/viewtopic.php?p=2529
954 simple_mmap(int fd, unsigned int length, SIMPLE_UNMMAP *un)
960 f = (HANDLE)_get_osfhandle(fd);
963 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
966 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
973 if (n) *n = GetFileSize(f, NULL);
985 simple_unmmap(SIMPLE_UNMMAP *un)
987 UnmapViewOfFile(un->p);