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.
32 # include <sys/mman.h>
39 #include <stdlib.h> /* free, malloc */
41 #include <string.h> /* memcmp */
43 #include <strings.h> /* strncasecmp */
45 # define strncasecmp strnicmp
49 #include <sys/types.h>
55 #ifndef XML_NONVALIDATING
56 static const char *__xml_error_str[XML_MAX_ERROR];
58 static void __xmlErrorSet(const void *, const char *, unsigned int);
59 # define xmlErrorSet(a, b, c) __xmlErrorSet(a, b, c)
62 # define PRINT_INFO(a) \
63 assert((a) < XML_MAX_ERROR); \
64 printf("at line %i: %s\n", __LINE__, __xml_error_str[(a)])
66 # define PRINT_INFO(a)
69 # define SET_ERROR_AND_RETURN(a, b) \
70 { *rlen = 0; *name = (a); *len = (b); PRINT_INFO(b); return 0; }
72 #else /* !XML_NONVALIDATING */
73 # define xmlErrorSet(a, b, c)
74 # define SET_ERROR_AND_RETURN(a, b) return 0;
77 static char *__xmlNodeGetPath(void **, const char *, size_t *, char **, size_t *);
78 static char *__xmlNodeGet(void *, const char *, size_t *, char **, size_t *, size_t *);
79 static char *__xmlProcessCDATA(char **, size_t *);
80 static char *__xmlCommentSkip(const char *, size_t);
81 static char *__xmlInfoProcess(const char *, size_t);
83 static void *__xml_memncasecmp(const char *, size_t *, char **, size_t *);
84 static void __xmlPrepareData(char **, size_t *);
88 * map 'filename' and return a pointer to it.
90 static void *simple_mmap(int, size_t, SIMPLE_UNMMAP *);
91 static void simple_unmmap(SIMPLE_UNMMAP *);
93 # define mmap(a,b,c,d,e,f) simple_mmap((e), (b), &rid->un)
94 # define munmap(a,b) simple_unmmap(&rid->un)
98 # define PRINT(a, b, c) { \
99 size_t l1 = (b), l2 = (c); \
102 size_t q, len = l2; \
103 if (l1 < l2) len = l1; \
105 printf("(%i) '", len); \
106 for (q=0; q<len; q++) printf("%c", s[q]); \
108 } else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
109 } else printf("NULL pointer at line %i\n", __LINE__); \
114 xmlOpen(const char *filename)
116 struct _root_id *rid = 0;
120 int fd = open(filename, O_RDONLY);
127 mm = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0L);
128 if (mm != (void *)-1)
130 rid = calloc(1, sizeof(struct _root_id));
133 size_t blen = statbuf.st_size;
134 #ifdef XML_USE_NODECACHE
135 size_t num = 0, nlen = 1;
138 rid->node = cacheInit();
139 __xmlNodeGet(rid->node, mm, &blen, &n, &nlen, &num);
153 xmlInitBuffer(const char *buffer, size_t size)
155 struct _root_id *rid = 0;
157 if (buffer && (size > 0))
159 rid = calloc(1, sizeof(struct _root_id));
162 #ifdef XML_USE_NODECACHE
163 size_t num = 0, nlen = 1;
167 rid->node = cacheInit();
168 __xmlNodeGet(rid->node, buffer, &blen, &n, &nlen, &num);
171 rid->start = (char *)buffer;
182 struct _root_id *rid = (struct _root_id *)id;
185 assert(rid->name == 0);
189 munmap(rid->start, rid->len);
193 #ifdef XML_USE_NODECACHE
194 if (rid->node) cacheFree(rid->node);
196 #ifndef XML_NONVALIDATING
197 if (rid->info) free(rid->info);
204 xmlNodeGet(const void *id, const char *path)
206 struct _xml_id *xid = (struct _xml_id *)id;
207 struct _xml_id *xsid = 0;
219 nnc = nc = cacheNodeGet(xid);
220 ptr = __xmlNodeGetPath(&nnc, xid->start, &len, &node, &slen);
223 xsid = malloc(sizeof(struct _xml_id));
227 xsid->name_len = slen;
230 #ifdef XML_USE_NODECACHE
233 #ifndef XML_NONVALIDATING
235 xsid->root = xid->root;
237 xsid->root = (struct _root_id *)xid;
242 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
247 xmlErrorSet(xid, node, len);
254 xmlNodeCopy(const void *id, const char *path)
256 struct _xml_id *xid = (struct _xml_id *)id;
257 struct _xml_id *xsid = 0;
258 char *ptr, *node, *p;
266 nnc = nc = cacheNodeGet(xid);
267 ptr = __xmlNodeGetPath(&nnc, xid->start, &len, &node, &slen);
270 xsid = malloc(sizeof(struct _xml_id) + len);
273 p = (char *)xsid + sizeof(struct _xml_id);
277 xsid->name_len = slen;
279 #ifdef XML_USE_NODECACHE
282 #ifndef XML_NONVALIDATING
284 xsid->root = xid->root;
286 xsid->root = (struct _root_id *)xid;
289 memcpy(xsid->start, ptr, len);
293 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
298 xmlErrorSet(xid, node, len);
305 xmlNodeGetName(const void *id)
307 struct _xml_id *xid = (struct _xml_id *)id;
317 memcpy(ret, xid->name, len);
322 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
329 xmlNodeCopyName(const void *id, char *buf, size_t buflen)
331 struct _xml_id *xid = (struct _xml_id *)id;
337 slen = xid->name_len;
341 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
343 memcpy(buf, xid->name, slen);
350 xmlNodeGetNum(const void *id, const char *path)
352 struct _xml_id *xid = (struct _xml_id *)id;
360 char *nodename, *pathname;
365 nodename = (char *)path;
366 if (*path == '/') nodename++;
367 slen = strlen(nodename);
369 nc = cacheNodeGet(xid);
370 pathname = strchr(nodename, '/');
377 slen -= pathname-nodename;
379 p = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
380 if (p == 0 && slen == 0)
382 xmlErrorSet(xid, node, len);
393 char *ret, *node = nodename;
394 #ifndef XML_USE_NODECACHE
395 ret = __xmlNodeGet(nc, p, &len, &node, &slen, &num);
397 ret = __xmlNodeGetFromCache(&nc, p, &len, &node, &slen, &num);
399 if (ret == 0 && slen == 0)
401 xmlErrorSet(xid, node, len);
411 xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
413 struct _xml_id *xpid = (struct _xml_id *)pid;
414 struct _xml_id *xid = (struct _xml_id *)id;
422 assert(element != 0);
425 slen = strlen(element);
426 node = (char *)element;
427 nc = cacheNodeGet(xpid);
428 #ifndef XML_USE_NODECACHE
429 ptr = __xmlNodeGet(nc, xpid->start, &len, &node, &slen, &num);
431 ptr = __xmlNodeGetFromCache(&nc, xpid->start, &len, &node, &slen, &num);
438 xid->name_len = slen;
439 #ifdef XML_USE_NODECACHE
440 /* unused for the cache but tested at the start of this function */
441 if (len == 0) xid->len = 1;
448 xmlErrorSet(xpid, node, len);
455 xmlGetString(const void *id)
457 struct _xml_id *xid = (struct _xml_id *)id;
469 __xmlPrepareData(&ps, &len);
475 memcpy(str, ps, len);
480 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
489 xmlCopyString(const void *id, char *buffer, size_t buflen)
491 struct _xml_id *xid = (struct _xml_id *)id;
506 __xmlPrepareData(&ps, &len);
512 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
514 memcpy(buffer, ps, len);
524 xmlCompareString(const void *id, const char *s)
526 struct _xml_id *xid = (struct _xml_id *)id;
532 if (xid->len && (strlen(s) > 0))
539 __xmlPrepareData(&ps, &len);
540 ret = strncasecmp(ps, s, len);
547 xmlNodeGetString(const void *id, const char *path)
549 struct _xml_id *xid = (struct _xml_id *)id;
557 char *ptr, *node = (char *)path;
558 size_t slen = strlen(node);
559 size_t len = xid->len;
562 nc = cacheNodeGet(xid);
563 ptr = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
566 __xmlPrepareData(&ptr, &len);
570 memcpy(str, ptr, len);
575 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
580 xmlErrorSet(xid, node, len);
588 xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
590 struct _xml_id *xid = (struct _xml_id *)id;
601 char *p, *node = (char *)path;
602 size_t slen = strlen(node);
603 size_t len = xid->len;
606 nc = cacheNodeGet(xid);
607 p = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
610 __xmlPrepareData(&p, &len);
616 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
619 memcpy(buffer, p, len);
620 *(buffer+len) = '\0';
626 xmlErrorSet(xid, node, len);
634 xmlNodeCompareString(const void *id, const char *path, const char *s)
636 struct _xml_id *xid = (struct _xml_id *)id;
643 if (xid->len && (strlen(s) > 0))
645 char *node, *str, *ps, *pe;
652 nc = cacheNodeGet(xid);
653 str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
657 __xmlPrepareData(&ps, &len);
658 ret = strncasecmp(ps, s, len);
662 xmlErrorSet(xid, node, len);
670 xmlGetInt(const void *id)
672 struct _xml_id *xid = (struct _xml_id *)id;
679 char *end = xid->start + xid->len;
680 li = strtol(xid->start, &end, 10);
687 xmlNodeGetInt(const void *id, const char *path)
689 struct _xml_id *xid = (struct _xml_id *)id;
704 nc = cacheNodeGet(xid);
705 str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
709 li = strtol(str, &end, 10);
713 xmlErrorSet(xid, node, len);
721 xmlGetDouble(const void *id)
723 struct _xml_id *xid = (struct _xml_id *)id;
730 char *end = xid->start + xid->len;
731 d = strtod(xid->start, &end);
738 xmlNodeGetDouble(const void *id, const char *path)
740 struct _xml_id *xid = (struct _xml_id *)id;
755 nc = cacheNodeGet(xid);
756 str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
760 d = strtod(str, &end);
764 xmlErrorSet(xid, node, len);
772 xmlMarkId(const void *id)
774 struct _xml_id *xmid = 0;
778 xmid = malloc(sizeof(struct _xml_id));
781 struct _root_id *xrid = (struct _root_id *)id;
786 xmid->start = xrid->start;
787 xmid->len = xrid->len;
788 #ifdef XML_USE_NODECACHE
789 xmid->node = xrid->node;
791 #ifndef XML_NONVALIDATING
797 memcpy(xmid, id, sizeof(struct _xml_id));
802 xmlErrorSet(id, 0, XML_OUT_OF_MEMORY);
809 xmlAttributeGetDouble(const void *id, const char *name)
811 struct _xml_id *xid = (struct _xml_id *)id;
819 size_t slen = strlen(name);
822 assert(xid->start > xid->name);
824 ps = xid->name + xid->name_len + 1;
828 while ((ps<pe) && isspace(*ps)) ps++;
829 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
832 if ((ps<pe) && (*ps == '='))
837 if (*ps == '"' || *ps == '\'') ps++;
840 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
845 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
848 ret = strtod(start, &ps);
852 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
858 while ((ps<pe) && !isspace(*ps)) ps++;
865 while ((ps<pe) && !isspace(*ps)) ps++;
873 xmlAttributeGetInt(const void *id, const char *name)
875 struct _xml_id *xid = (struct _xml_id *)id;
883 size_t slen = strlen(name);
886 assert(xid->start > xid->name);
888 ps = xid->name + xid->name_len + 1;
892 while ((ps<pe) && isspace(*ps)) ps++;
893 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
896 if ((ps<pe) && (*ps == '='))
901 if (*ps == '"' || *ps == '\'') ps++;
904 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
909 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
912 ret = strtol(start, &ps, 10);
916 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
922 while ((ps<pe) && isspace(*ps)) ps++;
929 while ((ps<pe) && !isspace(*ps)) ps++;
937 xmlAttributeGetString(const void *id, const char *name)
939 struct _xml_id *xid = (struct _xml_id *)id;
947 size_t slen = strlen(name);
950 assert(xid->start > xid->name);
952 ps = xid->name + xid->name_len + 1;
956 while ((ps<pe) && isspace(*ps)) ps++;
957 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
960 if ((ps<pe) && (*ps == '='))
965 if (*ps == '"' || *ps == '\'') ps++;
968 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
973 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
976 ret = malloc(ps-start);
979 memcpy(ret, start, (ps-start));
980 *(ret+(ps-start)) = '\0';
984 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
989 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
995 while ((ps<pe) && !isspace(*ps)) ps++;
1003 while ((ps<pe) && !isspace(*ps)) ps++;
1011 xmlAttributeCopyString(const void *id, const char *name,
1012 char *buffer, size_t buflen)
1014 struct _xml_id *xid = (struct _xml_id *)id;
1019 assert(buffer != 0);
1024 size_t slen = strlen(name);
1027 assert(xid->start > xid->name);
1030 ps = xid->name + xid->name_len + 1;
1031 pe = xid->start - 1;
1034 while ((ps<pe) && isspace(*ps)) ps++;
1035 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1038 if ((ps<pe) && (*ps == '='))
1043 if (*ps == '"' || *ps == '\'') ps++;
1046 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1051 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1054 size_t restlen = ps-start;
1055 if (restlen >= buflen)
1058 xmlErrorSet(xid, ps, XML_TRUNCATE_RESULT);
1061 memcpy(buffer, start, restlen);
1062 *(buffer+restlen) = 0;
1067 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1073 while ((ps<pe) && isspace(*ps)) ps++;
1080 while ((ps<pe) && !isspace(*ps)) ps++;
1088 xmlAttributeCompareString(const void *id, const char *name, const char *s)
1090 struct _xml_id *xid = (struct _xml_id *)id;
1097 if (xid->name_len && strlen(s))
1099 size_t slen = strlen(name);
1102 assert(xid->start > xid->name);
1104 ps = xid->name + xid->name_len + 1;
1105 pe = xid->start - 1;
1108 while ((ps<pe) && isspace(*ps)) ps++;
1109 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1112 if ((ps<pe) && (*ps == '='))
1117 if (*ps == '"' || *ps == '\'') ps++;
1120 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1125 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1128 ret = strncasecmp(start, s, ps-start);
1132 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1138 while ((ps<pe) && !isspace(*ps)) ps++;
1145 while ((ps<pe) && !isspace(*ps)) ps++;
1153 #ifndef XML_NONVALIDATING
1155 xmlErrorGetNo(const void *id, int clear)
1161 struct _xml_id *xid = (struct _xml_id *)id;
1162 struct _root_id *rid;
1164 if (xid->name) rid = xid->root;
1165 else rid = (struct _root_id *)xid;
1171 struct _xml_error *err = rid->info;
1174 if (clear) err->err_no = 0;
1182 xmlErrorGetLineNo(const void *id, int clear)
1188 struct _xml_id *xid = (struct _xml_id *)id;
1189 struct _root_id *rid;
1191 if (xid->name) rid = xid->root;
1192 else rid = (struct _root_id *)xid;
1198 struct _xml_error *err = rid->info;
1199 char *ps = rid->start;
1200 char *pe = err->pos;
1206 new = memchr(ps, '\n', pe-ps);
1212 if (clear) err->err_no = 0;
1220 xmlErrorGetColumnNo(const void *id, int clear)
1226 struct _xml_id *xid = (struct _xml_id *)id;
1227 struct _root_id *rid;
1229 if (xid->name) rid = xid->root;
1230 else rid = (struct _root_id *)xid;
1236 struct _xml_error *err = rid->info;
1237 char *ps = rid->start;
1238 char *pe = err->pos;
1243 new = memchr(ps, '\n', pe-ps);
1244 new = memchr(ps, '\n', pe-ps);
1251 if (clear) err->err_no = 0;
1259 xmlErrorGetString(const void *id, int clear)
1265 struct _xml_id *xid = (struct _xml_id *)id;
1266 struct _root_id *rid;
1268 if (xid->name) rid = xid->root;
1269 else rid = (struct _root_id *)xid;
1275 struct _xml_error *err = rid->info;
1276 if (XML_NO_ERROR <= err->err_no && err->err_no < XML_MAX_ERROR)
1278 ret = (char *)__xml_error_str[err->err_no];
1282 ret = "incorrect error number.";
1285 if (clear) err->err_no = 0;
1295 xmlErrorGetNo(const void *id, int clear)
1297 return XML_NO_ERROR;
1301 xmlErrorGetLineNo(const void *id, int clear)
1307 xmlErrorGetColumnNo(const void *id, int clear)
1313 xmlErrorGetString(const void *id, int clear)
1315 return "error detection was not enabled at compile time: no error.";
1320 /* -------------------------------------------------------------------------- */
1322 #ifndef XML_NONVALIDATING
1323 static const char *__xml_error_str[XML_MAX_ERROR] =
1326 "unable to allocate enough memory.",
1327 "unable to open file for reading.",
1328 "requested node name is invalid.",
1329 "unexpected end of section.",
1330 "buffer too small to hold all data, truncating.",
1331 "incorrect comment section.",
1332 "bad information block.",
1333 "incompatible opening tag for element.",
1334 "missing or invalid closing tag for element.",
1335 "missing or invalid opening quote for attribute.",
1336 "missing or invalid closing quote for attribute."
1341 __xmlNodeGetPath(void **nc, const char *start, size_t *len, char **name, size_t *nlen)
1354 if (*nlen > *len) return 0;
1357 if (*path == '/') path++;
1360 size_t num, blocklen, pathlen, nodelen;
1364 pathlen = strlen(path);
1365 path = strchr(node, '/');
1367 if (!path) nodelen = pathlen;
1368 else nodelen = path++ - node;
1373 #ifndef XML_USE_NODECACHE
1374 ret = __xmlNodeGet(nc, start, &blocklen, &node, &nodelen, &num);
1376 ret = __xmlNodeGetFromCache(nc, start, &blocklen, &node, &nodelen, &num);
1382 ret = __xmlNodeGetPath(nc, ret, &blocklen, &path, &pathlen);
1405 __xmlNodeGet(void *nc, const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1407 char *cdata, *open_element = *name;
1408 char *element, *start_tag=0;
1409 char *new, *cur, *ne, *ret = 0;
1410 size_t restlen, elementlen;
1411 size_t open_len = *rlen;
1412 size_t return_len = 0;
1420 assert(nodenum != 0);
1422 if (open_len == 0 || *name == 0)
1423 SET_ERROR_AND_RETURN((char *)start, XML_INVALID_NODE_NAME);
1425 cdata = (char *)start;
1427 SET_ERROR_AND_RETURN((char *)start, XML_UNEXPECTED_EOF);
1432 cur = (char *)start;
1435 #ifdef XML_USE_NODECACHE
1439 /* search for an opening tag */
1440 while ((new = memchr(cur, '<', restlen)) != 0)
1442 size_t len_remaining;
1445 if (*(new+1) == '/') /* end of section */
1455 if (*cur == '!') /* comment */
1458 size_t blocklen = restlen;
1459 new = __xmlProcessCDATA(&start, &blocklen);
1460 if (!new && start && open_len) /* CDATA */
1461 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1467 else if (*cur == '?') /* info block */
1469 new = __xmlInfoProcess(cur, restlen);
1471 SET_ERROR_AND_RETURN(cur, XML_INVALID_INFO_BLOCK);
1479 * get element name and a pointer to after the opening tag
1483 len_remaining = restlen;
1484 rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1485 if (rptr) /* requested element was found */
1488 return_len = elementlen;
1492 open_len = elementlen;
1493 start_tag = element;
1497 else /* different element name was foud */
1499 new = cur + (len_remaining - restlen);
1501 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1506 #ifdef XML_USE_NODECACHE
1507 nnc = cacheNodeNew(nc);
1510 if (*(new-2) == '/') /* e.g. <test/> */
1515 #ifdef XML_USE_NODECACHE
1516 cacheDataSet(nnc, element, elementlen, rptr, 0);
1520 open_element = start_tag;
1529 * get the next xml tag
1531 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1533 new = memchr(cur, '<', restlen);
1535 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1540 if (*cur == '!') /* comment, CDATA */
1543 size_t blocklen = restlen;
1544 new = __xmlProcessCDATA(&start, &blocklen);
1545 if (new && start && open_len) /* CDATA */
1550 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1556 * look for the closing tag of the cascading block
1558 new = memchr(cur, '<', restlen);
1560 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1567 if (*cur == '/') /* closing tag of leaf node found */
1569 if (!strncasecmp(new+1, element, elementlen))
1571 #ifdef XML_USE_NODECACHE
1572 cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
1574 if (*(new+elementlen+1) != '>')
1575 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1582 open_element = start_tag;
1583 cdata = (char *)start;
1586 else /* report error */
1587 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1592 new = memchr(cur, '>', restlen);
1594 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1601 /* no leaf node, continue */
1602 if (*cur != '/') /* cascading tag found */
1605 size_t slen = restlen+1; /* due to cur-1 below*/
1610 * recursively walk the xml tree from here
1612 new = __xmlNodeGet(nnc, cur-1, &slen, &node, &nlen, &pos);
1615 if (nlen == 0) /* error upstream */
1623 if (slen == restlen)
1624 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1630 else restlen -= slen;
1633 * look for the closing tag of the cascading block
1636 new = memchr(cur, '<', restlen);
1638 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1645 if (*cur == '/') /* closing tag found */
1647 if (!strncasecmp(new+1, element, elementlen))
1649 if (*(new+elementlen+1) != '>')
1650 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1652 #ifdef XML_USE_NODECACHE
1653 cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
1660 open_element = start_tag;
1661 cdata = (char *)start;
1664 else /* report error */
1665 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1670 new = memchr(cur, '>', restlen);
1672 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1678 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1687 *len = XML_NO_ERROR; /* element not found, no real error */
1692 *name = open_element;
1700 __xmlProcessCDATA(char **start, size_t *len)
1703 size_t restlen = *len;
1706 if ((restlen > 6) && (*(cur+1) == '-')) /* comment */
1708 new = __xmlCommentSkip(cur, restlen);
1717 if (restlen < 12) return 0; /* ![CDATA[ ]]> */
1722 if (memcmp(cur, "![CDATA[", 8) == 0)
1729 new = memchr(cur, ']', restlen);
1732 if ((restlen > 3) && (memcmp(new, "]]>", 3) == 0))
1734 *len = new-1 - *start;
1747 while (new && (restlen > 2));
1754 __xmlCommentSkip(const char *start, size_t len)
1758 if (len < 7) return 0; /* !-- --> */
1760 cur = (char *)start;
1763 if (memcmp(cur, "!--", 3) == 0)
1769 new = memchr(cur, '-', len);
1773 if ((len >= 3) && (memcmp(new, "-->", 3) == 0))
1784 while (new && (len > 2));
1791 __xmlInfoProcess(const char *start, size_t len)
1795 cur = (char *)start;
1800 if (len < 3) return 0; /* <? ?> */
1804 new = memchr(cur, '?', len);
1805 if (!new || *(new+1) != '>') return 0;
1815 __xmlPrepareData(char **start, size_t *blocklen)
1817 size_t len = *blocklen;
1818 char *pe, *ps = *start;
1823 while ((ps<pe) && isspace(*ps)) ps++;
1824 while ((pe>ps) && isspace(*pe)) pe--;
1827 else if (isspace(*(ps+1))) len--;
1829 /* CDATA or comment */
1830 if ((len >= 2) && !strncmp(ps, "<!", 2))
1833 size_t blocklen = len-1;
1834 if (blocklen >= 6) /* !-- --> */
1836 char *new = __xmlProcessCDATA(&start, &len);
1842 while ((ps<pe) && isspace(*ps)) ps++;
1843 while ((pe>ps) && isspace(*pe)) pe--;
1853 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1855 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1856 char **needle, size_t *needlelen)
1860 if (haystack && needle && needlelen && (*needlelen > 0)
1861 && (*haystacklen >= *needlelen))
1863 char *hs = (char *)haystack;
1869 /* search for everything */
1870 if ((*ns == '*') && (*needlelen == 1))
1872 char *he = hs + *haystacklen;
1874 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1875 if (*(hs-1) == '/') hs--;
1877 *needle = (char *)haystack;
1878 *needlelen = hs - haystack;
1880 ns = memchr(hs, '>', he-hs);
1888 size_t nlen = *needlelen;
1889 char *he = hs + *haystacklen;
1891 for (i=0; i<nlen; i++)
1893 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1894 if (isspace(*hs) || (*hs == '/') || (*hs == '>')) break;
1901 *needle = (char *)haystack;
1902 *needlelen = hs - haystack;
1904 ns = memchr(hs, '>', he-hs);
1910 else /* not found */
1912 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1913 if (*(hs-1) == '/') hs--;
1915 *needle = (char *)haystack;
1916 *needlelen = hs - haystack;
1918 ns = memchr(hs, '>', he-hs);
1924 *haystacklen -= hs - haystack;
1930 #ifndef XML_NONVALIDATING
1932 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1934 struct _xml_id *xid = (struct _xml_id *)id;
1935 struct _root_id *rid;
1939 if (xid->name) rid = xid->root;
1940 else rid = (struct _root_id *)xid;
1945 rid->info = malloc(sizeof(struct _xml_error));
1950 struct _xml_error *err = rid->info;
1952 err->pos = (char *)pos;
1953 err->err_no = err_no;
1960 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1964 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1970 f = (HANDLE)_get_osfhandle(fd);
1971 if (!f) return (void *)-1;
1973 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1974 if (!m) return (void *)-1;
1976 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1993 simple_unmmap(SIMPLE_UNMMAP *un)
1995 UnmapViewOfFile(un->p);