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>
61 #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 if (rid->info) free(rid->info);
233 xmlNodeGet(const void *id, const char *path)
235 struct _xml_id *xid = (struct _xml_id *)id;
236 struct _xml_id *xsid = 0;
246 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
249 xsid = malloc(sizeof(struct _xml_id));
254 xsid->name_len = slen;
256 #ifndef XML_NONVALIDATING
258 xsid->root = xid->root;
260 xsid->root = (struct _root_id *)xid;
265 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
270 xmlErrorSet(xid, node, len);
277 xmlNodeCopy(const void *id, const char *path)
279 struct _xml_id *xid = (struct _xml_id *)id;
280 struct _xml_id *xsid = 0;
281 char *ptr, *node, *p;
287 ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
290 xsid = malloc(sizeof(struct _xml_id) + len);
293 p = (char *)xsid + sizeof(struct _xml_id);
297 xsid->name_len = slen;
299 #ifndef XML_NONVALIDATING
301 xsid->root = xid->root;
303 xsid->root = (struct _root_id *)xid;
306 memcpy(xsid->start, ptr, len);
310 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
315 xmlErrorSet(xid, node, len);
322 xmlNodeGetName(const void *id)
324 struct _xml_id *xid = (struct _xml_id *)id;
334 memcpy(ret, xid->name, len);
339 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
346 xmlNodeCopyName(const void *id, char *buf, size_t buflen)
348 struct _xml_id *xid = (struct _xml_id *)id;
354 slen = xid->name_len;
358 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
360 memcpy(buf, xid->name, slen);
367 xmlNodeGetNum(const void *id, const char *path)
369 struct _xml_id *xid = (struct _xml_id *)id;
377 char *nodename, *pathname;
381 nodename = (char *)path;
382 if (*path == '/') nodename++;
383 slen = strlen(nodename);
385 pathname = strchr(nodename, '/');
392 slen -= pathname-nodename;
394 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
395 if (p == 0 && slen == 0)
397 xmlErrorSet(xid, node, len);
408 char *ret, *node = nodename;
409 ret = __xmlNodeGet(p, &len, &node, &slen, &num);
410 if (ret == 0 && slen == 0)
412 xmlErrorSet(xid, node, len);
422 xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
424 struct _xml_id *xpid = (struct _xml_id *)pid;
425 struct _xml_id *xid = (struct _xml_id *)id;
432 assert(element != 0);
435 slen = strlen(element);
436 node = (char *)element;
437 ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
443 xid->name_len = slen;
448 xmlErrorSet(xpid, node, len);
455 xmlGetString(const void *id)
457 struct _xml_id *xid = (struct _xml_id *)id;
469 __xmlPrepareData(&ps, &len);
477 memcpy(str, ps, len);
482 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
491 xmlCopyString(const void *id, char *buffer, size_t buflen)
493 struct _xml_id *xid = (struct _xml_id *)id;
508 __xmlPrepareData(&p, &len);
515 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
517 memcpy(buffer, p, len);
527 xmlCompareString(const void *id, const char *s)
529 struct _xml_id *xid = (struct _xml_id *)id;
535 if (xid->len && (strlen(s) > 0))
542 __xmlPrepareData(&ps, &len);
543 ret = strncasecmp(ps, s, len+1);
550 xmlNodeGetString(const void *id, const char *path)
552 struct _xml_id *xid = (struct _xml_id *)id;
560 char *p, *node = (char *)path;
561 size_t slen = strlen(node);
562 size_t len = xid->len;
565 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
568 __xmlPrepareData(&p, &len);
578 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
583 xmlErrorSet(xid, node, len);
591 xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
593 struct _xml_id *xid = (struct _xml_id *)id;
604 char *p, *node = (char *)path;
605 size_t slen = strlen(node);
606 size_t len = xid->len;
608 p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
611 __xmlPrepareData(&p, &len);
617 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
620 memcpy(buffer, p, len);
621 *(buffer+len) = '\0';
627 xmlErrorSet(xid, node, len);
635 xmlNodeCompareString(const void *id, const char *path, const char *s)
637 struct _xml_id *xid = (struct _xml_id *)id;
644 if (xid->len && (strlen(s) > 0))
646 char *node, *str, *ps, *pe;
652 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
656 __xmlPrepareData(&ps, &len);
657 ret = strncasecmp(ps, s, len);
661 xmlErrorSet(xid, node, len);
669 xmlGetInt(const void *id)
671 struct _xml_id *xid = (struct _xml_id *)id;
678 char *end = xid->start + xid->len;
679 li = strtol(xid->start, &end, 10);
686 xmlNodeGetInt(const void *id, const char *path)
688 struct _xml_id *xid = (struct _xml_id *)id;
702 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
706 li = strtol(str, &end, 10);
710 xmlErrorSet(xid, node, len);
718 xmlGetDouble(const void *id)
720 struct _xml_id *xid = (struct _xml_id *)id;
727 char *end = xid->start + xid->len;
728 d = strtod(xid->start, &end);
735 xmlNodeGetDouble(const void *id, const char *path)
737 struct _xml_id *xid = (struct _xml_id *)id;
751 str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
755 d = strtod(str, &end);
759 xmlErrorSet(xid, node, len);
767 xmlMarkId(const void *id)
769 struct _xml_id *xmid = 0;
773 xmid = malloc(sizeof(struct _xml_id));
776 struct _root_id *xrid = (struct _root_id *)id;
780 xmid->start = xrid->start;
781 xmid->len = xrid->len;
783 #ifndef XML_NONVALIDATING
789 memcpy(xmid, id, sizeof(struct _xml_id));
794 xmlErrorSet(id, 0, XML_OUT_OF_MEMORY);
801 xmlAttributeGetDouble(const void *id, const char *name)
803 struct _xml_id *xid = (struct _xml_id *)id;
811 size_t slen = strlen(name);
814 assert(xid->start > xid->name);
816 ps = xid->name + xid->name_len + 1;
820 while ((ps<pe) && isspace(*ps)) ps++;
821 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
824 if ((ps<pe) && (*ps == '='))
829 if (*ps == '"' || *ps == '\'') ps++;
832 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
837 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
840 ret = strtod(start, &ps);
844 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
850 while ((ps<pe) && !isspace(*ps)) ps++;
857 while ((ps<pe) && !isspace(*ps)) ps++;
865 xmlAttributeGetInt(const void *id, const char *name)
867 struct _xml_id *xid = (struct _xml_id *)id;
875 size_t slen = strlen(name);
878 assert(xid->start > xid->name);
880 ps = xid->name + xid->name_len + 1;
884 while ((ps<pe) && isspace(*ps)) ps++;
885 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
888 if ((ps<pe) && (*ps == '='))
893 if (*ps == '"' || *ps == '\'') ps++;
896 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
901 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
904 ret = strtol(start, &ps, 10);
908 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
914 while ((ps<pe) && isspace(*ps)) ps++;
921 while ((ps<pe) && !isspace(*ps)) ps++;
929 xmlAttributeGetString(const void *id, const char *name)
931 struct _xml_id *xid = (struct _xml_id *)id;
939 size_t slen = strlen(name);
942 assert(xid->start > xid->name);
944 ps = xid->name + xid->name_len + 1;
948 while ((ps<pe) && isspace(*ps)) ps++;
949 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
952 if ((ps<pe) && (*ps == '='))
957 if (*ps == '"' || *ps == '\'') ps++;
960 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
965 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
968 ret = malloc(ps-start);
971 memcpy(ret, start, (ps-start));
972 *(ret+(ps-start)) = '\0';
976 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
981 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
987 while ((ps<pe) && !isspace(*ps)) ps++;
995 while ((ps<pe) && !isspace(*ps)) ps++;
1003 xmlAttributeCopyString(const void *id, const char *name,
1004 char *buffer, size_t buflen)
1006 struct _xml_id *xid = (struct _xml_id *)id;
1011 assert(buffer != 0);
1016 size_t slen = strlen(name);
1019 assert(xid->start > xid->name);
1022 ps = xid->name + xid->name_len + 1;
1023 pe = xid->start - 1;
1026 while ((ps<pe) && isspace(*ps)) ps++;
1027 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1030 if ((ps<pe) && (*ps == '='))
1035 if (*ps == '"' || *ps == '\'') ps++;
1038 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1043 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1046 size_t restlen = ps-start;
1047 if (restlen >= buflen)
1050 xmlErrorSet(xid, ps, XML_TRUNCATE_RESULT);
1053 memcpy(buffer, start, restlen);
1054 *(buffer+restlen) = 0;
1059 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1065 while ((ps<pe) && isspace(*ps)) ps++;
1072 while ((ps<pe) && !isspace(*ps)) ps++;
1080 xmlAttributeCompareString(const void *id, const char *name, const char *s)
1082 struct _xml_id *xid = (struct _xml_id *)id;
1089 if (xid->name_len && strlen(s))
1091 size_t slen = strlen(name);
1094 assert(xid->start > xid->name);
1096 ps = xid->name + xid->name_len + 1;
1097 pe = xid->start - 1;
1100 while ((ps<pe) && isspace(*ps)) ps++;
1101 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1104 if ((ps<pe) && (*ps == '='))
1109 if (*ps == '"' || *ps == '\'') ps++;
1112 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1117 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1120 ret = strncasecmp(start, s, ps-start);
1124 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1130 while ((ps<pe) && !isspace(*ps)) ps++;
1137 while ((ps<pe) && !isspace(*ps)) ps++;
1145 #ifndef XML_NONVALIDATING
1147 xmlErrorGetNo(const void *id, int clear)
1153 struct _xml_id *xid = (struct _xml_id *)id;
1154 struct _root_id *rid;
1156 if (xid->name) rid = xid->root;
1157 else rid = (struct _root_id *)xid;
1163 struct _xml_error *err = rid->info;
1166 if (clear) err->err_no = 0;
1174 xmlErrorGetLineNo(const void *id, int clear)
1180 struct _xml_id *xid = (struct _xml_id *)id;
1181 struct _root_id *rid;
1183 if (xid->name) rid = xid->root;
1184 else rid = (struct _root_id *)xid;
1190 struct _xml_error *err = rid->info;
1191 char *ps = rid->start;
1192 char *pe = err->pos;
1198 new = memchr(ps, '\n', pe-ps);
1204 if (clear) err->err_no = 0;
1212 xmlErrorGetColumnNo(const void *id, int clear)
1218 struct _xml_id *xid = (struct _xml_id *)id;
1219 struct _root_id *rid;
1221 if (xid->name) rid = xid->root;
1222 else rid = (struct _root_id *)xid;
1228 struct _xml_error *err = rid->info;
1229 char *ps = rid->start;
1230 char *pe = err->pos;
1235 new = memchr(ps, '\n', pe-ps);
1236 new = memchr(ps, '\n', pe-ps);
1243 if (clear) err->err_no = 0;
1251 xmlErrorGetString(const void *id, int clear)
1257 struct _xml_id *xid = (struct _xml_id *)id;
1258 struct _root_id *rid;
1260 if (xid->name) rid = xid->root;
1261 else rid = (struct _root_id *)xid;
1267 struct _xml_error *err = rid->info;
1268 if (XML_NO_ERROR <= err->err_no && err->err_no < XML_MAX_ERROR)
1270 ret = (char *)__xml_error_str[err->err_no];
1274 ret = "incorrect error number.";
1277 if (clear) err->err_no = 0;
1285 /* -------------------------------------------------------------------------- */
1287 #ifndef XML_NONVALIDATING
1288 static const char *__xml_error_str[XML_MAX_ERROR] =
1291 "unable to allocate enough memory.",
1292 "unable to open file for reading.",
1293 "requested node name is invalid.",
1294 "unexpected end of section.",
1295 "buffer too small to hold all data, truncating.",
1296 "incorrect comment section.",
1297 "bad information block.",
1298 "incompatible opening tag for element.",
1299 "missing or invalid closing tag for element.",
1300 "missing or invalid opening quote for attribute.",
1301 "missing or invalid closing quote for attribute."
1306 __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *nlen)
1319 if (*nlen > *len) return 0;
1322 if (*path == '/') path++;
1325 size_t num, blocklen, pathlen, nodelen;
1329 pathlen = strlen(path);
1330 path = strchr(node, '/');
1332 if (!path) nodelen = pathlen;
1333 else nodelen = path++ - node;
1337 ret = __xmlNodeGet(start, &blocklen, &node, &nodelen, &num);
1342 ret = __xmlNodeGetPath(ret, &blocklen, &path, &pathlen);
1365 __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1367 char *cdata, *open_element = *name;
1368 char *element, *start_tag=0;
1369 char *new, *cur, *ne, *ret = 0;
1370 size_t restlen, elementlen;
1371 size_t open_len = *rlen;
1372 size_t return_len = 0;
1379 assert(nodenum != 0);
1381 if (open_len == 0 || *name == 0)
1382 SET_ERROR_AND_RETURN((char *)start, XML_INVALID_NODE_NAME);
1384 cdata = (char *)start;
1386 SET_ERROR_AND_RETURN((char *)start, XML_UNEXPECTED_EOF);
1391 cur = (char *)start;
1394 /* search for an opening tag */
1395 while ((new = memchr(cur, '<', restlen)) != 0)
1397 size_t len_remaining;
1400 if (*(new+1) == '/') /* end of section */
1410 if (*cur == '!') /* comment */
1413 size_t blocklen = restlen;
1414 new = __xmlProcessCDATA(&start, &blocklen);
1415 if (!new && start && open_len) /* CDATA */
1416 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1422 else if (*cur == '?') /* info block */
1424 new = __xmlInfoProcess(cur, restlen);
1426 SET_ERROR_AND_RETURN(cur, XML_INVALID_INFO_BLOCK);
1434 * get element name and a pointer to after the opening tag
1438 len_remaining = restlen;
1439 new = rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1440 if (rptr) /* requested element was found */
1442 return_len = elementlen;
1446 open_len = elementlen;
1447 start_tag = element;
1451 else /* different element name was foud */
1453 new = cur + (len_remaining - restlen);
1455 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1460 if (*(new-2) == '/') /* e.g. <test/> */
1467 open_element = start_tag;
1476 * get the next xml tag
1478 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1480 new = memchr(cur, '<', restlen);
1482 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1487 if (*cur == '!') /* comment, CDATA */
1490 size_t blocklen = restlen;
1491 new = __xmlProcessCDATA(&start, &blocklen);
1492 if (new && start && open_len) /* CDATA */
1497 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1503 * look for the closing tag of the cascading block
1505 new = memchr(cur, '<', restlen);
1507 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1514 if (*cur == '/') /* closing tag of leaf node found */
1516 if (!strncasecmp(new+1, element, elementlen))
1518 if (*(new+elementlen+1) != '>')
1519 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1526 open_element = start_tag;
1527 cdata = (char *)start;
1530 else /* report error */
1531 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1536 new = memchr(cur, '>', restlen);
1538 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1545 /* no leaf node, continue */
1546 if (*cur != '/') /* cascading tag found */
1549 size_t slen = restlen+1; /* due to cur-1 below*/
1554 * recursively walk the xml tree from here
1556 new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos);
1559 if (nlen == 0) /* error upstream */
1567 if (slen == restlen)
1568 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1574 else restlen -= slen;
1577 * look for the closing tag of the cascading block
1580 new = memchr(cur, '<', restlen);
1582 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1589 if (*cur == '/') /* closing tag found */
1591 if (!strncasecmp(new+1, element, elementlen))
1593 if (*(new+elementlen+1) != '>')
1594 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1601 open_element = start_tag;
1602 cdata = (char *)start;
1605 else /* report error */
1606 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1611 new = memchr(cur, '>', restlen);
1613 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1619 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1628 *len = XML_NO_ERROR; /* element not found, no real error */
1633 *name = open_element;
1641 __xmlProcessCDATA(char **start, size_t *len)
1644 size_t restlen = *len;
1647 if ((restlen > 6) && (*(cur+1) == '-')) /* comment */
1649 new = __xmlCommentSkip(cur, restlen);
1658 if (restlen < 12) return 0; /* ![CDATA[ ]]> */
1663 if (memcmp(cur, "![CDATA[", 8) == 0)
1670 new = memchr(cur, ']', restlen);
1673 if ((restlen > 3) && (memcmp(new, "]]>", 3) == 0))
1675 *len = new-1 - *start;
1688 while (new && (restlen > 2));
1695 __xmlCommentSkip(const char *start, size_t len)
1699 if (len < 7) return 0; /* !-- --> */
1701 cur = (char *)start;
1704 if (memcmp(cur, "!--", 3) == 0)
1710 new = memchr(cur, '-', len);
1714 if ((len >= 3) && (memcmp(new, "-->", 3) == 0))
1725 while (new && (len > 2));
1732 __xmlInfoProcess(const char *start, size_t len)
1736 cur = (char *)start;
1741 if (len < 3) return 0; /* <? ?> */
1745 new = memchr(cur, '?', len);
1746 if (!new || *(new+1) != '>') return 0;
1756 __xmlPrepareData(char **start, size_t *blocklen)
1758 size_t len = *blocklen;
1759 char *pe, *ps = *start;
1762 while ((ps<pe) && isspace(*ps)) ps++;
1763 while ((pe>ps) && isspace(*pe)) pe--;
1766 /* CDATA or comment */
1767 if ((len >= 2) && !strncmp(ps, "<!", 2))
1770 size_t blocklen = len-1;
1771 if (blocklen >= 6) /* !-- --> */
1773 char *new = __xmlProcessCDATA(&start, &len);
1779 while ((ps<pe) && isspace(*ps)) ps++;
1780 while ((pe>ps) && isspace(*pe)) pe--;
1790 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1792 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1793 char **needle, size_t *needlelen)
1797 if (haystack && needle && needlelen && (*needlelen > 0)
1798 && (*haystacklen >= *needlelen))
1800 char *hs = (char *)haystack;
1806 /* search for everything */
1807 if ((*ns == '*') && (*needlelen == 1))
1809 char *he = hs + *haystacklen;
1811 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1812 if (*(hs-1) == '/') hs--;
1814 *needle = (char *)haystack;
1815 *needlelen = hs - haystack;
1817 ns = memchr(hs, '>', he-hs);
1825 size_t nlen = *needlelen;
1826 char *he = hs + *haystacklen;
1828 for (i=0; i<nlen; i++)
1830 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1831 if (isspace(*hs) || (*hs == '/') || (*hs == '>')) break;
1838 *needle = (char *)haystack;
1839 *needlelen = hs - haystack;
1841 ns = memchr(hs, '>', he-hs);
1847 else /* not found */
1849 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1850 if (*(hs-1) == '/') hs--;
1852 *needle = (char *)haystack;
1853 *needlelen = hs - haystack;
1855 ns = memchr(hs, '>', he-hs);
1861 *haystacklen -= hs - haystack;
1867 #ifndef XML_NONVALIDATING
1869 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1871 struct _xml_id *xid = (struct _xml_id *)id;
1872 struct _root_id *rid;
1876 if (xid->name) rid = xid->root;
1877 else rid = (struct _root_id *)xid;
1882 rid->info = malloc(sizeof(struct _xml_error));
1887 struct _xml_error *err = rid->info;
1889 err->pos = (char *)pos;
1890 err->err_no = err_no;
1897 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1901 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1907 f = (HANDLE)_get_osfhandle(fd);
1908 if (!f) return (void *)-1;
1910 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1911 if (!m) return (void *)-1;
1913 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1930 simple_unmmap(SIMPLE_UNMMAP *un)
1932 UnmapViewOfFile(un->p);