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 */
49 #include <string.h> /* memcmp */
51 #include <strings.h> /* strncasecmp */
53 # define strncasecmp strnicmp
57 #include <sys/types.h>
63 #ifndef XML_NONVALIDATING
64 static const char *__xml_error_str[XML_MAX_ERROR];
72 static void __xmlErrorSet(const void *, const char *, unsigned int);
73 # define xmlErrorSet(a, b, c) __xmlErrorSet(a, b, c)
76 # define PRINT_INFO(a) \
77 assert((a) < XML_MAX_ERROR); \
78 printf("at line %i: %s\n", __LINE__, __xml_error_str[(a)])
80 # define PRINT_INFO(a)
83 # define SET_ERROR_AND_RETURN(a, b) \
84 { *rlen = 0; *name = (a); *len = (b); PRINT_INFO(b); return 0; }
86 #else /* !XML_NONVALIDATING */
87 # define xmlErrorSet(a, b, c)
88 # define SET_ERROR_AND_RETURN(a, b) return 0;
92 * It is required for both the rood node and the normal xml nodes to both
93 * have 'char *name' defined as the first entry. The code tests whether
94 * name == 0 to detect the root node.
102 #ifndef XML_NONVALIDATING
103 struct _xml_error *info;
116 #ifndef XML_NONVALIDATING
117 struct _root_id *root;
121 static char *__xmlNodeGetPath(const char *, size_t *, char **, size_t *);
122 static char *__xmlNodeGet(const char *, size_t *, char **, size_t *, size_t *);
123 static char *__xmlProcessCDATA(char **, size_t *);
124 static char *__xmlCommentSkip(const char *, size_t);
125 static char *__xmlInfoProcess(const char *, size_t);
127 static void *__xml_memncasecmp(const char *, size_t *, char **, size_t *);
128 static void __xmlPrepareData(char **, size_t *);
132 * map 'filename' and return a pointer to it.
134 static void *simple_mmap(int, size_t, SIMPLE_UNMMAP *);
135 static void simple_unmmap(SIMPLE_UNMMAP *);
137 # define mmap(a,b,c,d,e,f) simple_mmap((e), (b), &rid->un)
138 # define munmap(a,b) simple_unmmap(&rid->un)
142 # define PRINT(a, b, c) { \
145 if (b < c) len = b; \
147 printf("(%i) '", len); \
148 for (q=0; q<len; q++) printf("%c", ((char *)(a))[q]); \
150 } else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
151 } else printf("NULL pointer at line %i\n", __LINE__); \
156 xmlOpen(const char *filename)
158 struct _root_id *rid = 0;
162 int fd = open(filename, O_RDONLY);
169 mm = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0L);
170 if (mm != (void *)-1)
172 rid = malloc(sizeof(struct _root_id));
177 rid->len = statbuf.st_size;
179 #ifndef XML_NONVALIDATING
191 xmlInitBuffer(const char *buffer, size_t size)
193 struct _root_id *rid = 0;
195 if (buffer && (size > 0))
197 rid = malloc(sizeof(struct _root_id));
201 rid->start = (char *)buffer;
204 #ifndef XML_NONVALIDATING
216 struct _root_id *rid = (struct _root_id *)id;
219 assert(rid->name == 0);
223 munmap(rid->start, rid->len);
227 #ifndef XML_NONVALIDATING
228 if (rid->info) free(rid->info);
235 xmlNodeGet(const void *id, const char *path)
237 struct _xml_id *xid = (struct _xml_id *)id;
238 struct _xml_id *xsid = 0;
248 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
251 xsid = malloc(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;
267 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
272 xmlErrorSet(xid, node, len);
279 xmlNodeCopy(const void *id, const char *path)
281 struct _xml_id *xid = (struct _xml_id *)id;
282 struct _xml_id *xsid = 0;
283 char *ptr, *node, *p;
289 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
292 xsid = malloc(sizeof(struct _xml_id) + len);
295 p = (char *)xsid + sizeof(struct _xml_id);
299 xsid->name_len = slen;
301 #ifndef XML_NONVALIDATING
303 xsid->root = xid->root;
305 xsid->root = (struct _root_id *)xid;
308 memcpy(xsid->start, ptr, len);
312 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
317 xmlErrorSet(xid, node, len);
324 xmlNodeGetName(const void *id)
326 struct _xml_id *xid = (struct _xml_id *)id;
336 memcpy(ret, xid->name, len);
341 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
348 xmlNodeCopyName(const void *id, char *buf, size_t buflen)
350 struct _xml_id *xid = (struct _xml_id *)id;
356 slen = xid->name_len;
360 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
362 memcpy(buf, xid->name, slen);
369 xmlNodeGetNum(const void *id, const char *path)
371 struct _xml_id *xid = (struct _xml_id *)id;
379 char *nodename, *pathname;
383 nodename = (char *)path;
384 if (*path == '/') nodename++;
385 slen = strlen(nodename);
387 pathname = strchr(nodename, '/');
394 slen -= pathname-nodename;
396 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
397 if (p == 0 && slen == 0)
399 xmlErrorSet(xid, node, len);
410 char *ret, *node = nodename;
411 ret = __xmlNodeGet(p, &len, &node, &slen, &num);
412 if (ret == 0 && slen == 0)
414 xmlErrorSet(xid, node, len);
424 xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
426 struct _xml_id *xpid = (struct _xml_id *)pid;
427 struct _xml_id *xid = (struct _xml_id *)id;
434 assert(element != 0);
437 slen = strlen(element);
438 node = (char *)element;
439 ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
445 xid->name_len = slen;
450 xmlErrorSet(xpid, node, len);
457 xmlGetString(const void *id)
459 struct _xml_id *xid = (struct _xml_id *)id;
471 __xmlPrepareData(&ps, &len);
479 memcpy(str, ps, len);
484 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
493 xmlCopyString(const void *id, char *buffer, size_t buflen)
495 struct _xml_id *xid = (struct _xml_id *)id;
510 __xmlPrepareData(&p, &len);
517 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
519 memcpy(buffer, p, len);
529 xmlCompareString(const void *id, const char *s)
531 struct _xml_id *xid = (struct _xml_id *)id;
537 if (xid->len && (strlen(s) > 0))
544 __xmlPrepareData(&ps, &len);
545 ret = strncasecmp(ps, s, len+1);
552 xmlNodeGetString(const void *id, const char *path)
554 struct _xml_id *xid = (struct _xml_id *)id;
562 char *p, *node = (char *)path;
563 size_t slen = strlen(node);
564 size_t len = xid->len;
567 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
570 __xmlPrepareData(&p, &len);
580 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
585 xmlErrorSet(xid, node, len);
593 xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
595 struct _xml_id *xid = (struct _xml_id *)id;
606 char *p, *node = (char *)path;
607 size_t slen = strlen(node);
608 size_t len = xid->len;
610 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
613 __xmlPrepareData(&p, &len);
619 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
622 memcpy(buffer, p, len);
623 *(buffer+len) = '\0';
629 xmlErrorSet(xid, node, len);
637 xmlNodeCompareString(const void *id, const char *path, const char *s)
639 struct _xml_id *xid = (struct _xml_id *)id;
646 if (xid->len && (strlen(s) > 0))
648 char *node, *str, *ps, *pe;
654 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
658 __xmlPrepareData(&ps, &len);
659 ret = strncasecmp(ps, s, len);
663 xmlErrorSet(xid, node, len);
671 xmlGetInt(const void *id)
673 struct _xml_id *xid = (struct _xml_id *)id;
680 char *end = xid->start + xid->len;
681 li = strtol(xid->start, &end, 10);
688 xmlNodeGetInt(const void *id, const char *path)
690 struct _xml_id *xid = (struct _xml_id *)id;
704 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
708 li = strtol(str, &end, 10);
712 xmlErrorSet(xid, node, len);
720 xmlGetDouble(const void *id)
722 struct _xml_id *xid = (struct _xml_id *)id;
729 char *end = xid->start + xid->len;
730 d = strtod(xid->start, &end);
737 xmlNodeGetDouble(const void *id, const char *path)
739 struct _xml_id *xid = (struct _xml_id *)id;
753 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
757 d = strtod(str, &end);
761 xmlErrorSet(xid, node, len);
769 xmlMarkId(const void *id)
771 struct _xml_id *xmid = 0;
775 xmid = malloc(sizeof(struct _xml_id));
778 struct _root_id *xrid = (struct _root_id *)id;
782 xmid->start = xrid->start;
783 xmid->len = xrid->len;
785 #ifndef XML_NONVALIDATING
791 memcpy(xmid, id, sizeof(struct _xml_id));
796 xmlErrorSet(id, 0, XML_OUT_OF_MEMORY);
803 xmlAttributeGetDouble(const void *id, const char *name)
805 struct _xml_id *xid = (struct _xml_id *)id;
813 size_t slen = strlen(name);
816 assert(xid->start > xid->name);
818 ps = xid->name + xid->name_len + 1;
822 while ((ps<pe) && isspace(*ps)) ps++;
823 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
826 if ((ps<pe) && (*ps == '='))
831 if (*ps == '"' || *ps == '\'') ps++;
834 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
839 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
842 ret = strtod(start, &ps);
846 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
852 while ((ps<pe) && !isspace(*ps)) ps++;
859 while ((ps<pe) && !isspace(*ps)) ps++;
867 xmlAttributeGetInt(const void *id, const char *name)
869 struct _xml_id *xid = (struct _xml_id *)id;
877 size_t slen = strlen(name);
880 assert(xid->start > xid->name);
882 ps = xid->name + xid->name_len + 1;
886 while ((ps<pe) && isspace(*ps)) ps++;
887 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
890 if ((ps<pe) && (*ps == '='))
895 if (*ps == '"' || *ps == '\'') ps++;
898 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
903 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
906 ret = strtol(start, &ps, 10);
910 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
916 while ((ps<pe) && isspace(*ps)) ps++;
923 while ((ps<pe) && !isspace(*ps)) ps++;
931 xmlAttributeGetString(const void *id, const char *name)
933 struct _xml_id *xid = (struct _xml_id *)id;
941 size_t slen = strlen(name);
944 assert(xid->start > xid->name);
946 ps = xid->name + xid->name_len + 1;
950 while ((ps<pe) && isspace(*ps)) ps++;
951 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
954 if ((ps<pe) && (*ps == '='))
959 if (*ps == '"' || *ps == '\'') ps++;
962 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
967 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
970 ret = malloc(ps-start);
973 memcpy(ret, start, (ps-start));
974 *(ret+(ps-start)) = '\0';
978 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
983 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
989 while ((ps<pe) && !isspace(*ps)) ps++;
997 while ((ps<pe) && !isspace(*ps)) ps++;
1005 xmlAttributeCopyString(const void *id, const char *name,
1006 char *buffer, size_t buflen)
1008 struct _xml_id *xid = (struct _xml_id *)id;
1013 assert(buffer != 0);
1018 size_t slen = strlen(name);
1021 assert(xid->start > xid->name);
1024 ps = xid->name + xid->name_len + 1;
1025 pe = xid->start - 1;
1028 while ((ps<pe) && isspace(*ps)) ps++;
1029 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1032 if ((ps<pe) && (*ps == '='))
1037 if (*ps == '"' || *ps == '\'') ps++;
1040 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1045 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1048 size_t restlen = ps-start;
1049 if (restlen >= buflen)
1052 xmlErrorSet(xid, ps, XML_TRUNCATE_RESULT);
1055 memcpy(buffer, start, restlen);
1056 *(buffer+restlen) = 0;
1061 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1067 while ((ps<pe) && isspace(*ps)) ps++;
1074 while ((ps<pe) && !isspace(*ps)) ps++;
1082 xmlAttributeCompareString(const void *id, const char *name, const char *s)
1084 struct _xml_id *xid = (struct _xml_id *)id;
1091 if (xid->name_len && strlen(s))
1093 size_t slen = strlen(name);
1096 assert(xid->start > xid->name);
1098 ps = xid->name + xid->name_len + 1;
1099 pe = xid->start - 1;
1102 while ((ps<pe) && isspace(*ps)) ps++;
1103 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1106 if ((ps<pe) && (*ps == '='))
1111 if (*ps == '"' || *ps == '\'') ps++;
1114 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1119 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1122 ret = strncasecmp(start, s, ps-start);
1126 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1132 while ((ps<pe) && !isspace(*ps)) ps++;
1139 while ((ps<pe) && !isspace(*ps)) ps++;
1147 #ifndef XML_NONVALIDATING
1149 xmlErrorGetNo(const void *id, int clear)
1155 struct _xml_id *xid = (struct _xml_id *)id;
1156 struct _root_id *rid;
1158 if (xid->name) rid = xid->root;
1159 else rid = (struct _root_id *)xid;
1165 struct _xml_error *err = rid->info;
1168 if (clear) err->err_no = 0;
1176 xmlErrorGetLineNo(const void *id, int clear)
1182 struct _xml_id *xid = (struct _xml_id *)id;
1183 struct _root_id *rid;
1185 if (xid->name) rid = xid->root;
1186 else rid = (struct _root_id *)xid;
1192 struct _xml_error *err = rid->info;
1193 char *ps = rid->start;
1194 char *pe = err->pos;
1200 new = memchr(ps, '\n', pe-ps);
1206 if (clear) err->err_no = 0;
1214 xmlErrorGetColumnNo(const void *id, int clear)
1220 struct _xml_id *xid = (struct _xml_id *)id;
1221 struct _root_id *rid;
1223 if (xid->name) rid = xid->root;
1224 else rid = (struct _root_id *)xid;
1230 struct _xml_error *err = rid->info;
1231 char *ps = rid->start;
1232 char *pe = err->pos;
1237 new = memchr(ps, '\n', pe-ps);
1238 new = memchr(ps, '\n', pe-ps);
1245 if (clear) err->err_no = 0;
1253 xmlErrorGetString(const void *id, int clear)
1259 struct _xml_id *xid = (struct _xml_id *)id;
1260 struct _root_id *rid;
1262 if (xid->name) rid = xid->root;
1263 else rid = (struct _root_id *)xid;
1269 struct _xml_error *err = rid->info;
1270 if (XML_NO_ERROR <= err->err_no && err->err_no < XML_MAX_ERROR)
1272 ret = (char *)__xml_error_str[err->err_no];
1276 ret = "incorrect error number.";
1279 if (clear) err->err_no = 0;
1289 xmlErrorGetNo(const void *id, int clear)
1291 return XML_NO_ERROR;
1295 xmlErrorGetLineNo(const void *id, int clear)
1301 xmlErrorGetColumnNo(const void *id, int clear)
1307 xmlErrorGetString(const void *id, int clear)
1309 return "error detection was not enabled at compile time: no error.";
1314 /* -------------------------------------------------------------------------- */
1316 #ifndef XML_NONVALIDATING
1317 static const char *__xml_error_str[XML_MAX_ERROR] =
1320 "unable to allocate enough memory.",
1321 "unable to open file for reading.",
1322 "requested node name is invalid.",
1323 "unexpected end of section.",
1324 "buffer too small to hold all data, truncating.",
1325 "incorrect comment section.",
1326 "bad information block.",
1327 "incompatible opening tag for element.",
1328 "missing or invalid closing tag for element.",
1329 "missing or invalid opening quote for attribute.",
1330 "missing or invalid closing quote for attribute."
1335 __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *nlen)
1348 if (*nlen > *len) return 0;
1351 if (*path == '/') path++;
1354 size_t num, blocklen, pathlen, nodelen;
1358 pathlen = strlen(path);
1359 path = strchr(node, '/');
1361 if (!path) nodelen = pathlen;
1362 else nodelen = path++ - node;
1366 ret = __xmlNodeGet(start, &blocklen, &node, &nodelen, &num);
1371 ret = __xmlNodeGetPath(ret, &blocklen, &path, &pathlen);
1394 __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1396 char *cdata, *open_element = *name;
1397 char *element, *start_tag=0;
1398 char *new, *cur, *ne, *ret = 0;
1399 size_t restlen, elementlen;
1400 size_t open_len = *rlen;
1401 size_t return_len = 0;
1408 assert(nodenum != 0);
1410 if (open_len == 0 || *name == 0)
1411 SET_ERROR_AND_RETURN((char *)start, XML_INVALID_NODE_NAME);
1413 cdata = (char *)start;
1415 SET_ERROR_AND_RETURN((char *)start, XML_UNEXPECTED_EOF);
1420 cur = (char *)start;
1423 /* search for an opening tag */
1424 while ((new = memchr(cur, '<', restlen)) != 0)
1426 size_t len_remaining;
1429 if (*(new+1) == '/') /* end of section */
1439 if (*cur == '!') /* comment */
1442 size_t blocklen = restlen;
1443 new = __xmlProcessCDATA(&start, &blocklen);
1444 if (!new && start && open_len) /* CDATA */
1445 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1451 else if (*cur == '?') /* info block */
1453 new = __xmlInfoProcess(cur, restlen);
1455 SET_ERROR_AND_RETURN(cur, XML_INVALID_INFO_BLOCK);
1463 * get element name and a pointer to after the opening tag
1467 len_remaining = restlen;
1468 new = rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1469 if (rptr) /* requested element was found */
1471 return_len = elementlen;
1475 open_len = elementlen;
1476 start_tag = element;
1480 else /* different element name was foud */
1482 new = cur + (len_remaining - restlen);
1484 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1489 if (*(new-2) == '/') /* e.g. <test/> */
1496 open_element = start_tag;
1505 * get the next xml tag
1507 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1509 new = memchr(cur, '<', restlen);
1511 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1516 if (*cur == '!') /* comment, CDATA */
1519 size_t blocklen = restlen;
1520 new = __xmlProcessCDATA(&start, &blocklen);
1521 if (new && start && open_len) /* CDATA */
1526 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1532 * look for the closing tag of the cascading block
1534 new = memchr(cur, '<', restlen);
1536 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1543 if (*cur == '/') /* closing tag of leaf node found */
1545 if (!strncasecmp(new+1, element, elementlen))
1547 if (*(new+elementlen+1) != '>')
1548 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1555 open_element = start_tag;
1556 cdata = (char *)start;
1559 else /* report error */
1560 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1565 new = memchr(cur, '>', restlen);
1567 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1574 /* no leaf node, continue */
1575 if (*cur != '/') /* cascading tag found */
1578 size_t slen = restlen+1; /* due to cur-1 below*/
1583 * recursively walk the xml tree from here
1585 new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos);
1588 if (nlen == 0) /* error upstream */
1596 if (slen == restlen)
1597 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1603 else restlen -= slen;
1606 * look for the closing tag of the cascading block
1609 new = memchr(cur, '<', restlen);
1611 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1618 if (*cur == '/') /* closing tag found */
1620 if (!strncasecmp(new+1, element, elementlen))
1622 if (*(new+elementlen+1) != '>')
1623 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1630 open_element = start_tag;
1631 cdata = (char *)start;
1634 else /* report error */
1635 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1640 new = memchr(cur, '>', restlen);
1642 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1648 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1657 *len = XML_NO_ERROR; /* element not found, no real error */
1662 *name = open_element;
1670 __xmlProcessCDATA(char **start, size_t *len)
1673 size_t restlen = *len;
1676 if ((restlen > 6) && (*(cur+1) == '-')) /* comment */
1678 new = __xmlCommentSkip(cur, restlen);
1687 if (restlen < 12) return 0; /* ![CDATA[ ]]> */
1692 if (memcmp(cur, "![CDATA[", 8) == 0)
1699 new = memchr(cur, ']', restlen);
1702 if ((restlen > 3) && (memcmp(new, "]]>", 3) == 0))
1704 *len = new-1 - *start;
1717 while (new && (restlen > 2));
1724 __xmlCommentSkip(const char *start, size_t len)
1728 if (len < 7) return 0; /* !-- --> */
1730 cur = (char *)start;
1733 if (memcmp(cur, "!--", 3) == 0)
1739 new = memchr(cur, '-', len);
1743 if ((len >= 3) && (memcmp(new, "-->", 3) == 0))
1754 while (new && (len > 2));
1761 __xmlInfoProcess(const char *start, size_t len)
1765 cur = (char *)start;
1770 if (len < 3) return 0; /* <? ?> */
1774 new = memchr(cur, '?', len);
1775 if (!new || *(new+1) != '>') return 0;
1785 __xmlPrepareData(char **start, size_t *blocklen)
1787 size_t len = *blocklen;
1788 char *pe, *ps = *start;
1791 while ((ps<pe) && isspace(*ps)) ps++;
1792 while ((pe>ps) && isspace(*pe)) pe--;
1795 /* CDATA or comment */
1796 if ((len >= 2) && !strncmp(ps, "<!", 2))
1799 size_t blocklen = len-1;
1800 if (blocklen >= 6) /* !-- --> */
1802 char *new = __xmlProcessCDATA(&start, &len);
1808 while ((ps<pe) && isspace(*ps)) ps++;
1809 while ((pe>ps) && isspace(*pe)) pe--;
1819 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1821 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1822 char **needle, size_t *needlelen)
1826 if (haystack && needle && needlelen && (*needlelen > 0)
1827 && (*haystacklen >= *needlelen))
1829 char *hs = (char *)haystack;
1835 /* search for everything */
1836 if ((*ns == '*') && (*needlelen == 1))
1838 char *he = hs + *haystacklen;
1840 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1841 if (*(hs-1) == '/') hs--;
1843 *needle = (char *)haystack;
1844 *needlelen = hs - haystack;
1846 ns = memchr(hs, '>', he-hs);
1854 size_t nlen = *needlelen;
1855 char *he = hs + *haystacklen;
1857 for (i=0; i<nlen; i++)
1859 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1860 if (isspace(*hs) || (*hs == '/') || (*hs == '>')) break;
1867 *needle = (char *)haystack;
1868 *needlelen = hs - haystack;
1870 ns = memchr(hs, '>', he-hs);
1876 else /* not found */
1878 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1879 if (*(hs-1) == '/') hs--;
1881 *needle = (char *)haystack;
1882 *needlelen = hs - haystack;
1884 ns = memchr(hs, '>', he-hs);
1890 *haystacklen -= hs - haystack;
1896 #ifndef XML_NONVALIDATING
1898 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1900 struct _xml_id *xid = (struct _xml_id *)id;
1901 struct _root_id *rid;
1905 if (xid->name) rid = xid->root;
1906 else rid = (struct _root_id *)xid;
1911 rid->info = malloc(sizeof(struct _xml_error));
1916 struct _xml_error *err = rid->info;
1918 err->pos = (char *)pos;
1919 err->err_no = err_no;
1926 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1930 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1936 f = (HANDLE)_get_osfhandle(fd);
1937 if (!f) return (void *)-1;
1939 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1940 if (!m) return (void *)-1;
1942 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1959 simple_unmmap(SIMPLE_UNMMAP *un)
1961 UnmapViewOfFile(un->p);