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));
158 rid->len = statbuf.st_size;
159 rid->start = mmap(0, rid->len, PROT_READ, MAP_PRIVATE, fd, 0L);
161 #ifndef XML_NONVALIDATING
174 struct _root_id *rid = (struct _root_id *)id;
177 assert(rid->name == 0);
179 munmap(rid->start, rid->len);
182 if (rid->info) free(rid->info);
188 xmlNodeGet(const void *id, const char *path)
190 struct _xml_id *xid = (struct _xml_id *)id;
191 struct _xml_id *xsid = 0;
201 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
204 xsid = malloc(sizeof(struct _xml_id));
209 xsid->name_len = slen;
211 #ifndef XML_NONVALIDATING
213 xsid->root = xid->root;
215 xsid->root = (struct _root_id *)xid;
220 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
225 xmlErrorSet(xid, node, len);
232 xmlNodeCopy(const void *id, const char *path)
234 struct _xml_id *xid = (struct _xml_id *)id;
235 struct _xml_id *xsid = 0;
236 char *ptr, *node, *p;
242 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
245 xsid = malloc(sizeof(struct _xml_id) + len);
248 p = (char *)xsid + sizeof(struct _xml_id);
252 xsid->name_len = slen;
254 #ifndef XML_NONVALIDATING
256 xsid->root = xid->root;
258 xsid->root = (struct _root_id *)xid;
261 memcpy(xsid->start, ptr, len);
265 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
270 xmlErrorSet(xid, node, len);
277 xmlNodeGetName(const void *id)
279 struct _xml_id *xid = (struct _xml_id *)id;
289 memcpy(ret, xid->name, len);
294 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
301 xmlNodeCopyName(const void *id, char *buf, size_t buflen)
303 struct _xml_id *xid = (struct _xml_id *)id;
309 slen = xid->name_len;
313 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
315 memcpy(buf, xid->name, slen);
322 xmlNodeGetNum(const void *id, const char *path)
324 struct _xml_id *xid = (struct _xml_id *)id;
332 char *nodename, *pathname;
336 nodename = (char *)path;
337 if (*path == '/') nodename++;
338 slen = strlen(nodename);
340 pathname = strchr(nodename, '/');
347 slen -= pathname-nodename;
349 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
350 if (p == 0 && slen == 0)
352 xmlErrorSet(xid, node, len);
363 char *ret, *node = nodename;
365 ret = __xmlNodeGet(p, &len, &node, &slen, &num);
366 if (ret == 0 && slen == 0)
368 xmlErrorSet(xid, node, len);
378 xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
380 struct _xml_id *xpid = (struct _xml_id *)pid;
381 struct _xml_id *xid = (struct _xml_id *)id;
388 assert(element != 0);
391 slen = strlen(element);
392 node = (char *)element;
393 ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
399 xid->name_len = slen;
404 xmlErrorSet(xpid, node, len);
411 xmlGetString(const void *id)
413 struct _xml_id *xid = (struct _xml_id *)id;
420 char *ps, *pe, *pend;
428 while ((ps<pe) && isspace(*ps)) ps++;
429 while ((pe>ps) && isspace(*pe)) pe--;
433 str = malloc(nlen+1);
436 memcpy(str, ps, nlen);
441 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
450 xmlCopyString(const void *id, char *buffer, size_t buflen)
452 struct _xml_id *xid = (struct _xml_id *)id;
461 char *ps, *pe, *pend;
471 while ((ps<pe) && isspace(*ps)) ps++;
472 while ((pe>ps) && isspace(*pe)) pe--;
474 if (nlen > slen) nlen = slen;
481 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
483 memcpy(buffer, ps, nlen);
493 xmlCompareString(const void *id, const char *s)
495 struct _xml_id *xid = (struct _xml_id *)id;
501 if (xid->len && (strlen(s) > 0))
509 while ((ps<pe) && isspace(*ps)) ps++;
510 while ((pe>ps) && isspace(*pe)) pe--;
513 ret = strncasecmp(ps, s, pe-ps);
520 xmlNodeGetString(const void *id, const char *path)
522 struct _xml_id *xid = (struct _xml_id *)id;
530 size_t len = xid->len;
531 char *node = (char *)path;
533 str = __xmlNodeCopy(xid->start, &len, &path);
536 char *ps, *pe, *pend;
544 while ((ps<pe) && isspace(*ps)) ps++;
545 while ((pe>ps) && isspace(*pe)) pe--;
549 if (slen && (ps>str)) memmove(str, ps, slen);
550 else if (!slen) *str = 0;
554 xmlErrorSet(xid, node, len);
562 xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
564 struct _xml_id *xid = (struct _xml_id *)id;
581 str = __xmlNodeGetPath(xid->start, &nlen, &node, &slen);
589 while ((ps<pe) && isspace(*ps)) ps++;
590 while ((pe>ps) && isspace(*pe)) pe--;
596 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
599 memcpy(buffer, ps, nlen);
600 *(buffer + nlen) = '\0';
605 xmlErrorSet(xid, node, nlen);
613 xmlNodeCompareString(const void *id, const char *path, const char *s)
615 struct _xml_id *xid = (struct _xml_id *)id;
622 if (xid->len && (strlen(s) > 0))
624 char *node, *str, *ps, *pe;
630 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
637 while ((ps<pe) && isspace(*ps)) ps++;
638 while ((pe>ps) && isspace(*pe)) pe--;
641 ret = strncasecmp(ps, s, pe-ps);
645 xmlErrorSet(xid, node, len);
653 xmlGetInt(const void *id)
655 struct _xml_id *xid = (struct _xml_id *)id;
662 char *end = xid->start + xid->len;
663 li = strtol(xid->start, &end, 10);
670 xmlNodeGetInt(const void *id, const char *path)
672 struct _xml_id *xid = (struct _xml_id *)id;
686 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
690 li = strtol(str, &end, 10);
694 xmlErrorSet(xid, node, len);
702 xmlGetDouble(const void *id)
704 struct _xml_id *xid = (struct _xml_id *)id;
711 char *end = xid->start + xid->len;
712 d = strtod(xid->start, &end);
719 xmlNodeGetDouble(const void *id, const char *path)
721 struct _xml_id *xid = (struct _xml_id *)id;
735 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
739 d = strtod(str, &end);
743 xmlErrorSet(xid, node, len);
751 xmlMarkId(const void *id)
753 struct _xml_id *xmid = 0;
757 xmid = malloc(sizeof(struct _xml_id));
760 struct _root_id *xrid = (struct _root_id *)id;
764 xmid->start = xrid->start;
765 xmid->len = xrid->len;
767 #ifndef XML_NONVALIDATING
773 memcpy(xmid, id, sizeof(struct _xml_id));
778 xmlErrorSet(id, 0, XML_OUT_OF_MEMORY);
785 xmlAttributeGetDouble(const void *id, const char *name)
787 struct _xml_id *xid = (struct _xml_id *)id;
793 if (xid->len && xid->name_len)
795 size_t slen = strlen(name);
798 assert(xid->start > xid->name);
800 ps = xid->name + xid->name_len + 1;
804 while ((ps<pe) && isspace(*ps)) ps++;
805 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
808 if ((ps<pe) && (*ps == '='))
813 if (*ps == '"' || *ps == '\'') ps++;
816 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
821 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
824 ret = strtod(start, &ps);
828 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
834 while ((ps<pe) && !isspace(*ps)) ps++;
841 while ((ps<pe) && !isspace(*ps)) ps++;
849 xmlAttributeGetInt(const void *id, const char *name)
851 struct _xml_id *xid = (struct _xml_id *)id;
857 if (xid->len && xid->name_len)
859 size_t slen = strlen(name);
862 assert(xid->start > xid->name);
864 ps = xid->name + xid->name_len + 1;
868 while ((ps<pe) && isspace(*ps)) ps++;
869 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
872 if ((ps<pe) && (*ps == '='))
877 if (*ps == '"' || *ps == '\'') ps++;
880 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
885 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
888 ret = strtol(start, &ps, 10);
892 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
898 while ((ps<pe) && isspace(*ps)) ps++;
905 while ((ps<pe) && !isspace(*ps)) ps++;
913 xmlAttributeGetString(const void *id, const char *name)
915 struct _xml_id *xid = (struct _xml_id *)id;
921 if (xid->len && xid->name_len)
923 size_t slen = strlen(name);
926 assert(xid->start > xid->name);
928 ps = xid->name + xid->name_len + 1;
932 while ((ps<pe) && isspace(*ps)) ps++;
933 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
936 if ((ps<pe) && (*ps == '='))
941 if (*ps == '"' || *ps == '\'') ps++;
944 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
949 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
952 ret = malloc(ps-start);
955 memcpy(ret, start, (ps-start));
956 *(ret+(ps-start)) = '\0';
960 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
965 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
971 while ((ps<pe) && !isspace(*ps)) ps++;
979 while ((ps<pe) && !isspace(*ps)) ps++;
987 xmlAttributeCopyString(const void *id, const char *name,
988 char *buffer, size_t buflen)
990 struct _xml_id *xid = (struct _xml_id *)id;
998 if (xid->len && xid->name_len)
1000 size_t slen = strlen(name);
1003 assert(xid->start > xid->name);
1006 ps = xid->name + xid->name_len + 1;
1007 pe = xid->start - 1;
1010 while ((ps<pe) && isspace(*ps)) ps++;
1011 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1014 if ((ps<pe) && (*ps == '='))
1019 if (*ps == '"' || *ps == '\'') ps++;
1022 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1027 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1030 size_t restlen = ps-start;
1031 if (restlen >= buflen)
1034 xmlErrorSet(xid, ps, XML_TRUNCATE_RESULT);
1037 memcpy(buffer, start, restlen);
1038 *(buffer+restlen) = 0;
1043 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1049 while ((ps<pe) && isspace(*ps)) ps++;
1056 while ((ps<pe) && !isspace(*ps)) ps++;
1064 xmlAttributeCompareString(const void *id, const char *name, const char *s)
1066 struct _xml_id *xid = (struct _xml_id *)id;
1073 if (xid->len && xid->name_len && strlen(s))
1075 size_t slen = strlen(name);
1078 assert(xid->start > xid->name);
1080 ps = xid->name + xid->name_len + 1;
1081 pe = xid->start - 1;
1084 while ((ps<pe) && isspace(*ps)) ps++;
1085 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1088 if ((ps<pe) && (*ps == '='))
1093 if (*ps == '"' || *ps == '\'') ps++;
1096 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1101 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1104 ret = strncasecmp(start, s, ps-start);
1108 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1114 while ((ps<pe) && !isspace(*ps)) ps++;
1121 while ((ps<pe) && !isspace(*ps)) ps++;
1129 #ifndef XML_NONVALIDATING
1131 xmlErrorGetNo(const void *id, int clear)
1137 struct _xml_id *xid = (struct _xml_id *)id;
1138 struct _root_id *rid;
1140 if (xid->name) rid = xid->root;
1141 else rid = (struct _root_id *)xid;
1147 struct _xml_error *err = rid->info;
1150 if (clear) err->err_no = 0;
1158 xmlErrorGetLineNo(const void *id, int clear)
1164 struct _xml_id *xid = (struct _xml_id *)id;
1165 struct _root_id *rid;
1167 if (xid->name) rid = xid->root;
1168 else rid = (struct _root_id *)xid;
1174 struct _xml_error *err = rid->info;
1175 char *ps = rid->start;
1176 char *pe = err->pos;
1182 new = memchr(ps, '\n', pe-ps);
1191 if (clear) err->err_no = 0;
1199 xmlErrorGetString(const void *id, int clear)
1205 struct _xml_id *xid = (struct _xml_id *)id;
1206 struct _root_id *rid;
1208 if (xid->name) rid = xid->root;
1209 else rid = (struct _root_id *)xid;
1215 struct _xml_error *err = rid->info;
1216 if (XML_NO_ERROR <= err->err_no && err->err_no < XML_MAX_ERROR)
1218 ret = (char *)__xml_error_str[err->err_no];
1222 ret = "incorrect error number.";
1225 if (clear) err->err_no = 0;
1233 /* -------------------------------------------------------------------------- */
1235 #ifndef XML_NONVALIDATING
1236 static const char *__xml_error_str[XML_MAX_ERROR] =
1239 "unable to allocate enough memory.",
1240 "unable to open file for reading.",
1241 "buffer too small to hold all data, truncating.",
1242 "incorrect comment section.",
1243 "bad information block.",
1244 "unexpected end of section.",
1245 "incompatible opening tag for element.",
1246 "missing or invalid closing tag for element.",
1247 "missing or invalid opening quote for attribute.",
1248 "missing or invalid closing quote for attribute."
1253 __xmlNodeCopy(const char *start, size_t *len, const char **path)
1255 char *node, *p, *ret = 0;
1259 slen = strlen(*path);
1260 node = (char *)*path;
1261 p = __xmlNodeGetPath(start, &rlen, &node, &slen);
1264 ret = malloc(rlen+1);
1267 memcpy(ret, p, rlen);
1268 *(ret+rlen+1) = '\0';
1272 xmlErrorSet(0, 0, XML_OUT_OF_MEMORY);
1285 __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen)
1298 if (*plen > *len) return 0;
1301 if (*node == '/') node++;
1308 slen = strlen(node);
1309 path = strchr(node, '/');
1311 if (!path) plen = slen;
1312 else plen = path++ - node;
1315 ret = __xmlNodeGet(start, len, &node, &plen, &num);
1318 plen = slen - (path - *name);
1319 ret = __xmlNodeGetPath(ret, len, &path, &plen);
1332 __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1334 char *new, *cur, *ne, *ret = 0;
1335 char *element, *start_tag=0;
1336 size_t restlen, elementlen;
1347 assert(nodenum != 0);
1352 *name = (char *)start;
1353 *len = XML_UNEXPECTED_EOF;
1360 cur = (char *)start;
1363 while ((new = memchr(cur, '<', restlen)) != 0)
1365 if (*(new+1) == '/') /* cascading closing tag found */
1377 new = __xmlCommentSkip(cur, restlen);
1382 *len = XML_INVALID_COMMENT;
1389 else if (*cur == '?')
1391 new = __xmlInfoProcess(cur, restlen);
1396 *len = XML_INVALID_INFO_BLOCK;
1407 new = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1410 retlen = elementlen;
1414 start_tag = element;
1421 new = cur+elementlen;
1426 *len = XML_UNEXPECTED_EOF;
1432 if (*(new-1) == '/') /* e.g. <test/> */
1441 if ((restlen < 1) || (*new != '>'))
1445 *len = XML_ELEMENT_NO_CLOSING_TAG;
1449 restlen -= new+1-cur;
1454 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1456 new = memchr(cur, '<', restlen);
1461 *len = XML_ELEMENT_NO_CLOSING_TAG;
1467 if (*(cur+1) != '/') /* new node found */
1470 size_t slen = restlen;
1474 new = __xmlNodeGet(cur, &slen, &node, &nlen, &pos);
1477 if (slen == restlen)
1481 *len = XML_UNEXPECTED_EOF;
1484 else new = cur + slen;
1490 new = memchr(cur, '<', restlen);
1495 *len = XML_ELEMENT_NO_CLOSING_TAG;
1503 if (*(cur+1) == '/') /* closing tag found */
1505 if (!strncasecmp(new+2, element, elementlen))
1514 else /* report error */
1518 *len = XML_ELEMENT_NO_OPENING_TAG;
1525 new = memchr(cur, '>', restlen);
1530 *len = XML_ELEMENT_NO_CLOSING_TAG;
1545 if ((ret == 0) && (start_tag == 0) && (*rlen > 1))
1550 *len = XML_NO_ERROR; /* element not found */
1562 __xmlCommentSkip(const char *start, size_t len)
1566 cur = (char *)start;
1569 if (memcmp(cur, "!--", 3) == 0)
1571 if (len < 6) return 0; /* <!-- --> */
1577 new = memchr(cur, '-', len);
1581 if ((len > 3) && (memcmp(new, "-->", 3) == 0))
1591 while (new && (len > 2));
1598 __xmlInfoProcess(const char *start, size_t len)
1602 cur = (char *)start;
1607 if (len < 3) return 0; /* <? ?> */
1611 new = memchr(cur, '?', len);
1612 if (!new || *(new+1) != '>') return 0;
1621 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1623 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1624 char **needle, size_t *needlelen)
1628 if (haystack && needle && needlelen && (*needlelen > 0)
1629 && (*haystacklen >= *needlelen))
1631 char *hs = (char *)haystack;
1637 /* search for everything */
1638 if ((*ns == '*') && (*needlelen == 1))
1640 char *he = hs + *haystacklen;
1642 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1643 *needle = (char *)haystack;
1644 *needlelen = hs - haystack;
1645 while ((hs < he) && (*hs != '>')) hs++;
1650 size_t nlen = *needlelen;
1651 char *he = hs + *haystacklen;
1653 for (i=0; i<nlen; i++)
1655 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1656 if (isspace(*hs) || (*hs == '>')) break;
1663 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1664 *needle = (char *)haystack;
1665 *needlelen = hs - haystack;
1669 int found = (isspace(*hs) || (*hs == '>'));
1671 *needle = (char *)haystack;
1672 *needlelen = hs - haystack;
1674 while ((hs < he) && (*hs != '>')) hs++;
1676 if (!found) *needlelen = hs - haystack;
1681 *haystacklen -= hs - haystack;
1687 #ifndef XML_NONVALIDATING
1689 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1691 struct _xml_id *xid = (struct _xml_id *)id;
1692 struct _root_id *rid;
1696 if (xid->name) rid = xid->root;
1697 else rid = (struct _root_id *)xid;
1702 rid->info = malloc(sizeof(struct _xml_error));
1707 struct _xml_error *err = rid->info;
1709 err->pos = (char *)pos;
1710 err->err_no = err_no;
1717 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1721 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1727 f = (HANDLE)_get_osfhandle(fd);
1728 if (!f) return NULL;
1730 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1731 if (!m) return NULL;
1733 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1750 simple_unmmap(SIMPLE_UNMMAP *un)
1752 UnmapViewOfFile(un->p);