1 /* Copyright (c) 2007-2009 by Adalin B.V.
2 * Copyright (c) 2007-2009 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
40 # include <sys/mman.h>
47 #include <stdlib.h> /* free, malloc */
51 #include <sys/types.h>
55 # include <strings.h> /* strncasecmp */
57 # define strncasecmp strnicmp
60 #ifndef XML_NONVALIDATING
63 static const char *__xml_error_str[XML_MAX_ERROR];
71 static void __xmlErrorSet(const void *, const char *, unsigned int);
72 # define xmlErrorSet(a, b, c) __xmlErrorSet(a, b, c)
73 #else /* !XML_NONVALIDATING */
74 # define xmlErrorSet(a, b, c)
78 * It is required for both the rood node and the normal xml nodes to both
79 * have 'char *name' defined as the first entry. The code tests whether
80 * name == 0 to detect the root node.
88 #ifndef XML_NONVALIDATING
89 struct _xml_error *info;
102 #ifndef XML_NONVALIDATING
103 struct _root_id *root;
107 static char *__xmlNodeCopy(const char *, size_t *, const char **);
108 static char *__xmlNodeGetPath(const char *, size_t *, char **, size_t *);
109 static char *__xmlNodeGet(const char *, size_t *, char **, size_t *, size_t *);
110 static char *__xmlCommentSkip(const char *, size_t);
111 static char *__xmlInfoProcess(const char *, size_t);
113 static void *__xml_memncasecmp(const char *, size_t *, char **, size_t *);
117 * map 'filename' and return a pointer to it.
119 static void *simple_mmap(int, size_t, SIMPLE_UNMMAP *);
120 static void simple_unmmap(SIMPLE_UNMMAP *);
122 # define mmap(a,b,c,d,e,f) simple_mmap((e), (b), &rid->un)
123 # define munmap(a,b) simple_unmmap(&rid->un)
127 # define PRINT(a, b, c) { \
130 if (b < c) len = b; \
132 printf("(%i) '", len); \
133 for (q=0; q<len; q++) printf("%c", ((char *)(a))[q]); \
135 } else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
136 } else printf("NULL pointer at line %i\n", __LINE__); \
141 xmlOpen(const char *filename)
143 struct _root_id *rid = 0;
147 int fd = open(filename, O_RDONLY);
150 rid = malloc(sizeof(struct _root_id));
157 mm = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0L);
158 if (mm != (void *)-1)
162 rid->len = statbuf.st_size;
164 #ifndef XML_NONVALIDATING
178 struct _root_id *rid = (struct _root_id *)id;
181 assert(rid->name == 0);
183 munmap(rid->start, rid->len);
186 if (rid->info) free(rid->info);
192 xmlNodeGet(const void *id, const char *path)
194 struct _xml_id *xid = (struct _xml_id *)id;
195 struct _xml_id *xsid = 0;
205 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
208 xsid = malloc(sizeof(struct _xml_id));
213 xsid->name_len = slen;
215 #ifndef XML_NONVALIDATING
217 xsid->root = xid->root;
219 xsid->root = (struct _root_id *)xid;
224 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
229 xmlErrorSet(xid, node, len);
236 xmlNodeCopy(const void *id, const char *path)
238 struct _xml_id *xid = (struct _xml_id *)id;
239 struct _xml_id *xsid = 0;
240 char *ptr, *node, *p;
246 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
249 xsid = malloc(sizeof(struct _xml_id) + len);
252 p = (char *)xsid + sizeof(struct _xml_id);
256 xsid->name_len = slen;
258 #ifndef XML_NONVALIDATING
260 xsid->root = xid->root;
262 xsid->root = (struct _root_id *)xid;
265 memcpy(xsid->start, ptr, len);
269 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
274 xmlErrorSet(xid, node, len);
281 xmlNodeGetName(const void *id)
283 struct _xml_id *xid = (struct _xml_id *)id;
293 memcpy(ret, xid->name, len);
298 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
305 xmlNodeCopyName(const void *id, char *buf, size_t buflen)
307 struct _xml_id *xid = (struct _xml_id *)id;
313 slen = xid->name_len;
317 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
319 memcpy(buf, xid->name, slen);
326 xmlNodeGetNum(const void *id, const char *path)
328 struct _xml_id *xid = (struct _xml_id *)id;
336 char *nodename, *pathname;
340 nodename = (char *)path;
341 if (*path == '/') nodename++;
342 slen = strlen(nodename);
344 pathname = strchr(nodename, '/');
351 slen -= pathname-nodename;
353 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
354 if (p == 0 && slen == 0)
356 xmlErrorSet(xid, node, len);
367 char *ret, *node = nodename;
368 ret = __xmlNodeGet(p, &len, &node, &slen, &num);
369 if (ret == 0 && slen == 0)
371 xmlErrorSet(xid, node, len);
381 xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
383 struct _xml_id *xpid = (struct _xml_id *)pid;
384 struct _xml_id *xid = (struct _xml_id *)id;
391 assert(element != 0);
394 slen = strlen(element);
395 node = (char *)element;
396 ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
402 xid->name_len = slen;
407 xmlErrorSet(xpid, node, len);
414 xmlGetString(const void *id)
416 struct _xml_id *xid = (struct _xml_id *)id;
423 char *ps, *pe, *pend;
431 while ((ps<pe) && isspace(*ps)) ps++;
432 while ((pe>ps) && isspace(*pe)) pe--;
436 str = malloc(nlen+1);
439 memcpy(str, ps, nlen);
444 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
453 xmlCopyString(const void *id, char *buffer, size_t buflen)
455 struct _xml_id *xid = (struct _xml_id *)id;
464 char *ps, *pe, *pend;
474 while ((ps<pe) && isspace(*ps)) ps++;
475 while ((pe>ps) && isspace(*pe)) pe--;
477 if (nlen > slen) nlen = slen;
484 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
486 memcpy(buffer, ps, nlen);
496 xmlCompareString(const void *id, const char *s)
498 struct _xml_id *xid = (struct _xml_id *)id;
504 if (xid->len && (strlen(s) > 0))
512 while ((ps<pe) && isspace(*ps)) ps++;
513 while ((pe>ps) && isspace(*pe)) pe--;
516 ret = strncasecmp(ps, s, pe-ps);
523 xmlNodeGetString(const void *id, const char *path)
525 struct _xml_id *xid = (struct _xml_id *)id;
533 size_t len = xid->len;
534 char *node = (char *)path;
536 str = __xmlNodeCopy(xid->start, &len, &path);
539 char *ps, *pe, *pend;
547 while ((ps<pe) && isspace(*ps)) ps++;
548 while ((pe>ps) && isspace(*pe)) pe--;
552 if (slen && (ps>str)) memmove(str, ps, slen);
553 else if (!slen) *str = 0;
557 xmlErrorSet(xid, node, len);
565 xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
567 struct _xml_id *xid = (struct _xml_id *)id;
584 str = __xmlNodeGetPath(xid->start, &nlen, &node, &slen);
592 while ((ps<pe) && isspace(*ps)) ps++;
593 while ((pe>ps) && isspace(*pe)) pe--;
599 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
602 memcpy(buffer, ps, nlen);
603 *(buffer + nlen) = '\0';
608 xmlErrorSet(xid, node, nlen);
616 xmlNodeCompareString(const void *id, const char *path, const char *s)
618 struct _xml_id *xid = (struct _xml_id *)id;
625 if (xid->len && (strlen(s) > 0))
627 char *node, *str, *ps, *pe;
633 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
640 while ((ps<pe) && isspace(*ps)) ps++;
641 while ((pe>ps) && isspace(*pe)) pe--;
644 ret = strncasecmp(ps, s, pe-ps);
648 xmlErrorSet(xid, node, len);
656 xmlGetInt(const void *id)
658 struct _xml_id *xid = (struct _xml_id *)id;
665 char *end = xid->start + xid->len;
666 li = strtol(xid->start, &end, 10);
673 xmlNodeGetInt(const void *id, const char *path)
675 struct _xml_id *xid = (struct _xml_id *)id;
689 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
693 li = strtol(str, &end, 10);
697 xmlErrorSet(xid, node, len);
705 xmlGetDouble(const void *id)
707 struct _xml_id *xid = (struct _xml_id *)id;
714 char *end = xid->start + xid->len;
715 d = strtod(xid->start, &end);
722 xmlNodeGetDouble(const void *id, const char *path)
724 struct _xml_id *xid = (struct _xml_id *)id;
738 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
742 d = strtod(str, &end);
746 xmlErrorSet(xid, node, len);
754 xmlMarkId(const void *id)
756 struct _xml_id *xmid = 0;
760 xmid = malloc(sizeof(struct _xml_id));
763 struct _root_id *xrid = (struct _root_id *)id;
767 xmid->start = xrid->start;
768 xmid->len = xrid->len;
770 #ifndef XML_NONVALIDATING
776 memcpy(xmid, id, sizeof(struct _xml_id));
781 xmlErrorSet(id, 0, XML_OUT_OF_MEMORY);
788 xmlAttributeGetDouble(const void *id, const char *name)
790 struct _xml_id *xid = (struct _xml_id *)id;
798 size_t slen = strlen(name);
801 assert(xid->start > xid->name);
803 ps = xid->name + xid->name_len + 1;
807 while ((ps<pe) && isspace(*ps)) ps++;
808 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
811 if ((ps<pe) && (*ps == '='))
816 if (*ps == '"' || *ps == '\'') ps++;
819 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
824 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
827 ret = strtod(start, &ps);
831 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
837 while ((ps<pe) && !isspace(*ps)) ps++;
844 while ((ps<pe) && !isspace(*ps)) ps++;
852 xmlAttributeGetInt(const void *id, const char *name)
854 struct _xml_id *xid = (struct _xml_id *)id;
862 size_t slen = strlen(name);
865 assert(xid->start > xid->name);
867 ps = xid->name + xid->name_len + 1;
871 while ((ps<pe) && isspace(*ps)) ps++;
872 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
875 if ((ps<pe) && (*ps == '='))
880 if (*ps == '"' || *ps == '\'') ps++;
883 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
888 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
891 ret = strtol(start, &ps, 10);
895 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
901 while ((ps<pe) && isspace(*ps)) ps++;
908 while ((ps<pe) && !isspace(*ps)) ps++;
916 xmlAttributeGetString(const void *id, const char *name)
918 struct _xml_id *xid = (struct _xml_id *)id;
926 size_t slen = strlen(name);
929 assert(xid->start > xid->name);
931 ps = xid->name + xid->name_len + 1;
935 while ((ps<pe) && isspace(*ps)) ps++;
936 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
939 if ((ps<pe) && (*ps == '='))
944 if (*ps == '"' || *ps == '\'') ps++;
947 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
952 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
955 ret = malloc(ps-start);
958 memcpy(ret, start, (ps-start));
959 *(ret+(ps-start)) = '\0';
963 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
968 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
974 while ((ps<pe) && !isspace(*ps)) ps++;
982 while ((ps<pe) && !isspace(*ps)) ps++;
990 xmlAttributeCopyString(const void *id, const char *name,
991 char *buffer, size_t buflen)
993 struct _xml_id *xid = (struct _xml_id *)id;
1003 size_t slen = strlen(name);
1006 assert(xid->start > xid->name);
1009 ps = xid->name + xid->name_len + 1;
1010 pe = xid->start - 1;
1013 while ((ps<pe) && isspace(*ps)) ps++;
1014 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1017 if ((ps<pe) && (*ps == '='))
1022 if (*ps == '"' || *ps == '\'') ps++;
1025 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1030 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1033 size_t restlen = ps-start;
1034 if (restlen >= buflen)
1037 xmlErrorSet(xid, ps, XML_TRUNCATE_RESULT);
1040 memcpy(buffer, start, restlen);
1041 *(buffer+restlen) = 0;
1046 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1052 while ((ps<pe) && isspace(*ps)) ps++;
1059 while ((ps<pe) && !isspace(*ps)) ps++;
1067 xmlAttributeCompareString(const void *id, const char *name, const char *s)
1069 struct _xml_id *xid = (struct _xml_id *)id;
1076 if (xid->name_len && strlen(s))
1078 size_t slen = strlen(name);
1081 assert(xid->start > xid->name);
1083 ps = xid->name + xid->name_len + 1;
1084 pe = xid->start - 1;
1087 while ((ps<pe) && isspace(*ps)) ps++;
1088 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1091 if ((ps<pe) && (*ps == '='))
1096 if (*ps == '"' || *ps == '\'') ps++;
1099 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1104 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1107 ret = strncasecmp(start, s, ps-start);
1111 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1117 while ((ps<pe) && !isspace(*ps)) ps++;
1124 while ((ps<pe) && !isspace(*ps)) ps++;
1132 #ifndef XML_NONVALIDATING
1134 xmlErrorGetNo(const void *id, int clear)
1140 struct _xml_id *xid = (struct _xml_id *)id;
1141 struct _root_id *rid;
1143 if (xid->name) rid = xid->root;
1144 else rid = (struct _root_id *)xid;
1150 struct _xml_error *err = rid->info;
1153 if (clear) err->err_no = 0;
1161 xmlErrorGetLineNo(const void *id, int clear)
1167 struct _xml_id *xid = (struct _xml_id *)id;
1168 struct _root_id *rid;
1170 if (xid->name) rid = xid->root;
1171 else rid = (struct _root_id *)xid;
1177 struct _xml_error *err = rid->info;
1178 char *ps = rid->start;
1179 char *pe = err->pos;
1185 new = memchr(ps, '\n', pe-ps);
1194 if (clear) err->err_no = 0;
1202 xmlErrorGetString(const void *id, int clear)
1208 struct _xml_id *xid = (struct _xml_id *)id;
1209 struct _root_id *rid;
1211 if (xid->name) rid = xid->root;
1212 else rid = (struct _root_id *)xid;
1218 struct _xml_error *err = rid->info;
1219 if (XML_NO_ERROR <= err->err_no && err->err_no < XML_MAX_ERROR)
1221 ret = (char *)__xml_error_str[err->err_no];
1225 ret = "incorrect error number.";
1228 if (clear) err->err_no = 0;
1236 /* -------------------------------------------------------------------------- */
1238 #ifndef XML_NONVALIDATING
1239 static const char *__xml_error_str[XML_MAX_ERROR] =
1242 "unable to allocate enough memory.",
1243 "unable to open file for reading.",
1244 "buffer too small to hold all data, truncating.",
1245 "incorrect comment section.",
1246 "bad information block.",
1247 "unexpected end of section.",
1248 "incompatible opening tag for element.",
1249 "missing or invalid closing tag for element.",
1250 "missing or invalid opening quote for attribute.",
1251 "missing or invalid closing quote for attribute."
1256 __xmlNodeCopy(const char *start, size_t *len, const char **path)
1258 char *node, *p, *ret = 0;
1262 slen = strlen(*path);
1263 node = (char *)*path;
1264 p = __xmlNodeGetPath(start, &rlen, &node, &slen);
1267 ret = malloc(rlen+1);
1270 memcpy(ret, p, rlen);
1275 xmlErrorSet(0, 0, XML_OUT_OF_MEMORY);
1288 __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen)
1301 if (*plen > *len) return 0;
1304 if (*node == '/') node++;
1311 slen = strlen(node);
1312 path = strchr(node, '/');
1314 if (!path) plen = slen;
1315 else plen = path++ - node;
1318 ret = __xmlNodeGet(start, len, &node, &plen, &num);
1321 plen = slen - (path - *name);
1322 ret = __xmlNodeGetPath(ret, len, &path, &plen);
1335 __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1337 char *new, *cur, *ne, *ret = 0;
1338 char *element, *start_tag=0;
1339 size_t restlen, elementlen;
1340 size_t return_len = 0;
1350 assert(nodenum != 0);
1355 *name = (char *)start;
1356 *len = XML_UNEXPECTED_EOF;
1363 cur = (char *)start;
1366 /* search for an opening tag */
1367 while ((new = memchr(cur, '<', restlen)) != 0)
1369 size_t len_remaining;
1372 if (*(new+1) == '/') /* end of section */
1382 if (*cur == '!') /* comment */
1384 new = __xmlCommentSkip(cur, restlen);
1389 *len = XML_INVALID_COMMENT;
1396 else if (*cur == '?') /* info block */
1398 new = __xmlInfoProcess(cur, restlen);
1403 *len = XML_INVALID_INFO_BLOCK;
1413 * get element name and a pointer to after the opening tag
1417 len_remaining = restlen;
1418 new = rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1419 if (rptr) /* requested element was found */
1421 return_len = elementlen;
1425 start_tag = element;
1430 else /* different element name was foud */
1432 new = cur + (len_remaining - restlen);
1437 *len = XML_UNEXPECTED_EOF;
1443 if (*(new-2) == '/') /* e.g. <test/> */
1459 * get the next xml tag
1461 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1463 new = memchr(cur, '<', restlen);
1468 *len = XML_ELEMENT_NO_CLOSING_TAG;
1475 if (*cur == '!') /* comment */
1477 new = __xmlCommentSkip(cur, restlen);
1482 *len = XML_INVALID_COMMENT;
1489 * look for the closing tag of the cascading block
1491 new = memchr(cur, '<', restlen);
1496 *len = XML_ELEMENT_NO_CLOSING_TAG;
1504 if (*cur != '/') /* cascading tag found */
1507 size_t slen = restlen+1;
1512 * recursively walk the xml tree from here
1514 new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos);
1517 if (slen == restlen)
1521 *len = XML_UNEXPECTED_EOF;
1524 else new = cur + slen;
1531 * look for the closing tag of the cascading block
1533 new = memchr(cur, '<', restlen);
1538 *len = XML_ELEMENT_NO_CLOSING_TAG;
1546 if (*cur == '/') /* closing tag found */
1548 if (!strncasecmp(new+1, element, elementlen))
1550 if (*(new+elementlen+1) != '>')
1554 *len = XML_ELEMENT_NO_CLOSING_TAG;
1565 else /* report error */
1569 *len = XML_ELEMENT_NO_OPENING_TAG;
1575 /* else proper closing tag not yet found, continue. */
1576 /* TODO: could be a bad match to the opening tag though */
1577 /* like: <test></teft> */
1579 new = memchr(cur, '>', restlen);
1584 *len = XML_ELEMENT_NO_CLOSING_TAG;
1595 *len = XML_ELEMENT_NO_CLOSING_TAG;
1605 *len = XML_NO_ERROR; /* element not found, no real error */
1617 __xmlCommentSkip(const char *start, size_t len)
1621 cur = (char *)start;
1624 if (memcmp(cur, "!--", 3) == 0)
1626 if (len < 6) return 0; /* <!-- --> */
1632 new = memchr(cur, '-', len);
1636 if ((len > 3) && (memcmp(new, "-->", 3) == 0))
1646 while (new && (len > 2));
1653 __xmlInfoProcess(const char *start, size_t len)
1657 cur = (char *)start;
1662 if (len < 3) return 0; /* <? ?> */
1666 new = memchr(cur, '?', len);
1667 if (!new || *(new+1) != '>') return 0;
1676 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1678 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1679 char **needle, size_t *needlelen)
1683 if (haystack && needle && needlelen && (*needlelen > 0)
1684 && (*haystacklen >= *needlelen))
1686 char *hs = (char *)haystack;
1692 /* search for everything */
1693 if ((*ns == '*') && (*needlelen == 1))
1695 char *p, *he = hs + *haystacklen;
1697 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1698 if (*(hs-1) == '/') hs--;
1700 *needle = (char *)haystack;
1701 *needlelen = hs - haystack;
1704 while ((hs < he) && (*hs != '>')) hs++;
1711 size_t nlen = *needlelen;
1712 char *he = hs + *haystacklen;
1714 for (i=0; i<nlen; i++)
1716 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1717 if (isspace(*hs) || (*hs == '/') || (*hs == '>')) break;
1724 *needle = (char *)haystack;
1725 *needlelen = hs - haystack;
1727 while ((hs < he) && (*hs != '>')) hs++;
1732 else /* not found */
1734 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1735 if (*(hs-1) == '/') hs--;
1737 *needle = (char *)haystack;
1738 *needlelen = hs - haystack;
1740 while ((hs < he) && (*hs != '>')) hs++;
1745 *haystacklen -= hs - haystack;
1751 #ifndef XML_NONVALIDATING
1753 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1755 struct _xml_id *xid = (struct _xml_id *)id;
1756 struct _root_id *rid;
1760 if (xid->name) rid = xid->root;
1761 else rid = (struct _root_id *)xid;
1766 rid->info = malloc(sizeof(struct _xml_error));
1771 struct _xml_error *err = rid->info;
1773 err->pos = (char *)pos;
1774 err->err_no = err_no;
1781 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1785 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1791 f = (HANDLE)_get_osfhandle(fd);
1792 if (!f) return NULL;
1794 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1795 if (!m) return NULL;
1797 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1814 simple_unmmap(SIMPLE_UNMMAP *un)
1816 UnmapViewOfFile(un->p);