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>
48 #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;
310 if (slen > xid->name_len)
312 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 us too small to hold the result, truncating.",
1242 "incorrect comment section.",
1243 "bad information block.",
1244 "unexpected end of xml section (maybe a missing end tag?)",
1245 "element not found.",
1246 "incompatible opening tag for element.",
1247 "missing or invalid closing tag for element.",
1248 "missing or invalid opening quote for attribute.",
1249 "missing or invalid closing quote for attribute."
1254 __xmlNodeCopy(const char *start, size_t *len, const char **path)
1256 char *node, *p, *ret = 0;
1260 slen = strlen(*path);
1261 node = (char *)*path;
1262 p = __xmlNodeGetPath(start, &rlen, &node, &slen);
1265 ret = malloc(rlen+1);
1268 memcpy(ret, p, rlen);
1269 *(ret+rlen+1) = '\0';
1273 xmlErrorSet(0, 0, XML_OUT_OF_MEMORY);
1286 __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen)
1298 if ((*len == 0) || (*plen == 0) || (*plen > *len))
1302 if (*node == '/') node++;
1309 slen = strlen(node);
1310 path = strchr(node, '/');
1312 if (!path) plen = slen;
1313 else plen = path++ - node;
1318 ret = __xmlNodeGet(start, len, &node, &plen, &num);
1321 plen = slen - (path - *name);
1322 ret = __xmlNodeGetPath(ret, len, &path, &plen);
1336 __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1338 char *new, *cur, *ne, *ret = 0;
1339 char *element, *start_tag=0;
1340 size_t restlen, elementlen;
1351 assert(nodenum != 0);
1357 *len = XML_UNEXPECTED_EOF;
1364 cur = (char *)start;
1367 while ((new = memchr(cur, '<', restlen)) != 0)
1369 if (*(new+1) == '/') /* cascading closing tag found */
1381 new = __xmlCommentSkip(cur, restlen);
1386 *len = XML_INVALID_COMMENT;
1393 else if (*cur == '?')
1395 new = __xmlInfoProcess(cur, restlen);
1400 *len = XML_INVALID_INFO_BLOCK;
1411 new = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1414 retlen = elementlen;
1418 start_tag = element;
1425 new = cur+elementlen;
1430 *len = XML_UNEXPECTED_EOF;
1436 if (*(new-1) == '/') /* e.g. <test/> */
1445 if ((restlen < 1) || (*new != '>'))
1449 *len = XML_ELEMENT_NO_CLOSING_TAG;
1453 restlen -= new+1-cur;
1458 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1460 new = memchr(cur, '<', restlen);
1465 *len = XML_ELEMENT_NO_CLOSING_TAG;
1471 if (*(cur+1) != '/') /* new node found */
1474 size_t slen = restlen;
1478 new = __xmlNodeGet(cur, &slen, &node, &nlen, &pos);
1481 if (slen == restlen)
1485 *len = XML_UNEXPECTED_EOF;
1488 else new = cur + slen;
1494 new = memchr(cur, '<', restlen);
1499 *len = XML_ELEMENT_NO_CLOSING_TAG;
1507 if (*(cur+1) == '/') /* closing tag found */
1509 if (!strncasecmp(new+2, element, elementlen))
1518 else /* report error */
1522 *len = XML_ELEMENT_NO_OPENING_TAG;
1529 new = memchr(cur, '>', restlen);
1534 *len = XML_ELEMENT_NO_CLOSING_TAG;
1549 if ((ret == 0) && (start_tag == 0) && (*rlen > 1))
1554 *len = XML_ELEMENT_NOT_FOUND;
1566 __xmlCommentSkip(const char *start, size_t len)
1570 cur = (char *)start;
1573 if (memcmp(cur, "!--", 3) == 0)
1575 if (len < 6) return 0; /* <!-- --> */
1581 new = memchr(cur, '-', len);
1585 if ((len > 3) && (memcmp(new, "-->", 3) == 0))
1595 while (new && (len > 2));
1602 __xmlInfoProcess(const char *start, size_t len)
1606 cur = (char *)start;
1611 if (len < 3) return 0; /* <? ?> */
1615 new = memchr(cur, '?', len);
1616 if (!new || *(new+1) != '>') return 0;
1625 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1627 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1628 char **needle, size_t *needlelen)
1632 if (haystack && needle && needlelen && (*needlelen > 0)
1633 && (*haystacklen >= *needlelen))
1635 char *hs = (char *)haystack;
1641 /* search for everything */
1642 if ((*ns == '*') && (*needlelen == 1))
1644 char *he = hs + *haystacklen;
1646 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1647 *needle = (char *)haystack;
1648 *needlelen = hs - haystack;
1649 while ((hs < he) && (*hs != '>')) hs++;
1654 size_t nlen = *needlelen;
1655 char *he = hs + *haystacklen;
1657 for (i=0; i<nlen; i++)
1659 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1660 if (isspace(*hs) || (*hs == '>')) break;
1667 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1668 *needle = (char *)haystack;
1669 *needlelen = hs - haystack;
1673 int found = (isspace(*hs) || (*hs == '>'));
1675 *needle = (char *)haystack;
1676 *needlelen = hs - haystack;
1678 while ((hs < he) && (*hs != '>')) hs++;
1680 if (!found) *needlelen = hs - haystack;
1685 *haystacklen -= hs - haystack;
1691 #ifndef XML_NONVALIDATING
1693 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1695 struct _xml_id *xid = (struct _xml_id *)id;
1696 struct _root_id *rid;
1700 if (xid->name) rid = xid->root;
1701 else rid = (struct _root_id *)xid;
1706 rid->info = malloc(sizeof(struct _xml_error));
1711 struct _xml_error *err = rid->info;
1713 err->pos = (char *)pos;
1714 err->err_no = err_no;
1721 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1725 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1731 f = (HANDLE)_get_osfhandle(fd);
1732 if (!f) return NULL;
1734 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1735 if (!m) return NULL;
1737 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1754 simple_unmmap(SIMPLE_UNMMAP *un)
1756 UnmapViewOfFile(un->p);