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);
476 memcpy(str, ps, len);
481 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
490 xmlCopyString(const void *id, char *buffer, size_t buflen)
492 struct _xml_id *xid = (struct _xml_id *)id;
507 __xmlPrepareData(&ps, &len);
513 xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
515 memcpy(buffer, ps, len);
525 xmlCompareString(const void *id, const char *s)
527 struct _xml_id *xid = (struct _xml_id *)id;
533 if (xid->len && (strlen(s) > 0))
540 __xmlPrepareData(&ps, &len);
541 ret = strncasecmp(ps, s, len);
548 xmlNodeGetString(const void *id, const char *path)
550 struct _xml_id *xid = (struct _xml_id *)id;
558 char *ptr, *node = (char *)path;
559 size_t slen = strlen(node);
560 size_t len = xid->len;
563 nc = cacheNodeGet(xid);
564 ptr = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
567 __xmlPrepareData(&ptr, &len);
571 memcpy(str, ptr, len);
576 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
581 xmlErrorSet(xid, node, len);
589 xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
591 struct _xml_id *xid = (struct _xml_id *)id;
602 char *p, *node = (char *)path;
603 size_t slen = strlen(node);
604 size_t len = xid->len;
607 nc = cacheNodeGet(xid);
608 p = __xmlNodeGetPath(&nc, 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;
653 nc = cacheNodeGet(xid);
654 str = __xmlNodeGetPath(&nc, 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;
705 nc = cacheNodeGet(xid);
706 str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
710 li = strtol(str, &end, 10);
714 xmlErrorSet(xid, node, len);
722 xmlGetDouble(const void *id)
724 struct _xml_id *xid = (struct _xml_id *)id;
731 char *end = xid->start + xid->len;
732 d = strtod(xid->start, &end);
739 xmlNodeGetDouble(const void *id, const char *path)
741 struct _xml_id *xid = (struct _xml_id *)id;
756 nc = cacheNodeGet(xid);
757 str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
761 d = strtod(str, &end);
765 xmlErrorSet(xid, node, len);
773 xmlMarkId(const void *id)
775 struct _xml_id *xmid = 0;
779 xmid = malloc(sizeof(struct _xml_id));
782 struct _root_id *xrid = (struct _root_id *)id;
787 xmid->start = xrid->start;
788 xmid->len = xrid->len;
789 #ifdef XML_USE_NODECACHE
790 xmid->node = xrid->node;
792 #ifndef XML_NONVALIDATING
798 memcpy(xmid, id, sizeof(struct _xml_id));
803 xmlErrorSet(id, 0, XML_OUT_OF_MEMORY);
810 xmlAttributeGetDouble(const void *id, const char *name)
812 struct _xml_id *xid = (struct _xml_id *)id;
820 size_t slen = strlen(name);
823 assert(xid->start > xid->name);
825 ps = xid->name + xid->name_len + 1;
829 while ((ps<pe) && isspace(*ps)) ps++;
830 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
833 if ((ps<pe) && (*ps == '='))
838 if (*ps == '"' || *ps == '\'') ps++;
841 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
846 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
849 ret = strtod(start, &ps);
853 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
859 while ((ps<pe) && !isspace(*ps)) ps++;
866 while ((ps<pe) && !isspace(*ps)) ps++;
874 xmlAttributeGetInt(const void *id, const char *name)
876 struct _xml_id *xid = (struct _xml_id *)id;
884 size_t slen = strlen(name);
887 assert(xid->start > xid->name);
889 ps = xid->name + xid->name_len + 1;
893 while ((ps<pe) && isspace(*ps)) ps++;
894 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
897 if ((ps<pe) && (*ps == '='))
902 if (*ps == '"' || *ps == '\'') ps++;
905 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
910 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
913 ret = strtol(start, &ps, 10);
917 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
923 while ((ps<pe) && isspace(*ps)) ps++;
930 while ((ps<pe) && !isspace(*ps)) ps++;
938 xmlAttributeGetString(const void *id, const char *name)
940 struct _xml_id *xid = (struct _xml_id *)id;
948 size_t slen = strlen(name);
951 assert(xid->start > xid->name);
953 ps = xid->name + xid->name_len + 1;
957 while ((ps<pe) && isspace(*ps)) ps++;
958 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
961 if ((ps<pe) && (*ps == '='))
966 if (*ps == '"' || *ps == '\'') ps++;
969 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
974 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
977 ret = malloc(ps-start);
980 memcpy(ret, start, (ps-start));
981 *(ret+(ps-start)) = '\0';
985 xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
990 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
996 while ((ps<pe) && !isspace(*ps)) ps++;
1004 while ((ps<pe) && !isspace(*ps)) ps++;
1012 xmlAttributeCopyString(const void *id, const char *name,
1013 char *buffer, size_t buflen)
1015 struct _xml_id *xid = (struct _xml_id *)id;
1020 assert(buffer != 0);
1025 size_t slen = strlen(name);
1028 assert(xid->start > xid->name);
1031 ps = xid->name + xid->name_len + 1;
1032 pe = xid->start - 1;
1035 while ((ps<pe) && isspace(*ps)) ps++;
1036 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1039 if ((ps<pe) && (*ps == '='))
1044 if (*ps == '"' || *ps == '\'') ps++;
1047 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1052 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1055 size_t restlen = ps-start;
1056 if (restlen >= buflen)
1059 xmlErrorSet(xid, ps, XML_TRUNCATE_RESULT);
1062 memcpy(buffer, start, restlen);
1063 *(buffer+restlen) = 0;
1068 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1074 while ((ps<pe) && isspace(*ps)) ps++;
1081 while ((ps<pe) && !isspace(*ps)) ps++;
1089 xmlAttributeCompareString(const void *id, const char *name, const char *s)
1091 struct _xml_id *xid = (struct _xml_id *)id;
1098 if (xid->name_len && strlen(s))
1100 size_t slen = strlen(name);
1103 assert(xid->start > xid->name);
1105 ps = xid->name + xid->name_len + 1;
1106 pe = xid->start - 1;
1109 while ((ps<pe) && isspace(*ps)) ps++;
1110 if (((size_t)(pe-ps) > slen) && (strncasecmp(ps, name, slen) == 0))
1113 if ((ps<pe) && (*ps == '='))
1118 if (*ps == '"' || *ps == '\'') ps++;
1121 xmlErrorSet(xid, ps, XML_ATTRIB_NO_OPENING_QUOTE);
1126 while ((ps<pe) && (*ps != '"') && (*ps != '\'')) ps++;
1129 ret = strncasecmp(start, s, ps-start);
1133 xmlErrorSet(xid, ps, XML_ATTRIB_NO_CLOSING_QUOTE);
1139 while ((ps<pe) && !isspace(*ps)) ps++;
1146 while ((ps<pe) && !isspace(*ps)) ps++;
1154 #ifndef XML_NONVALIDATING
1156 xmlErrorGetNo(const void *id, int clear)
1162 struct _xml_id *xid = (struct _xml_id *)id;
1163 struct _root_id *rid;
1165 if (xid->name) rid = xid->root;
1166 else rid = (struct _root_id *)xid;
1172 struct _xml_error *err = rid->info;
1175 if (clear) err->err_no = 0;
1183 xmlErrorGetLineNo(const void *id, int clear)
1189 struct _xml_id *xid = (struct _xml_id *)id;
1190 struct _root_id *rid;
1192 if (xid->name) rid = xid->root;
1193 else rid = (struct _root_id *)xid;
1199 struct _xml_error *err = rid->info;
1200 char *ps = rid->start;
1201 char *pe = err->pos;
1207 new = memchr(ps, '\n', pe-ps);
1213 if (clear) err->err_no = 0;
1221 xmlErrorGetColumnNo(const void *id, int clear)
1227 struct _xml_id *xid = (struct _xml_id *)id;
1228 struct _root_id *rid;
1230 if (xid->name) rid = xid->root;
1231 else rid = (struct _root_id *)xid;
1237 struct _xml_error *err = rid->info;
1238 char *ps = rid->start;
1239 char *pe = err->pos;
1244 new = memchr(ps, '\n', pe-ps);
1245 new = memchr(ps, '\n', pe-ps);
1252 if (clear) err->err_no = 0;
1260 xmlErrorGetString(const void *id, int clear)
1266 struct _xml_id *xid = (struct _xml_id *)id;
1267 struct _root_id *rid;
1269 if (xid->name) rid = xid->root;
1270 else rid = (struct _root_id *)xid;
1276 struct _xml_error *err = rid->info;
1277 if (XML_NO_ERROR <= err->err_no && err->err_no < XML_MAX_ERROR)
1279 ret = (char *)__xml_error_str[err->err_no];
1283 ret = "incorrect error number.";
1286 if (clear) err->err_no = 0;
1296 xmlErrorGetNo(const void *id, int clear)
1298 return XML_NO_ERROR;
1302 xmlErrorGetLineNo(const void *id, int clear)
1308 xmlErrorGetColumnNo(const void *id, int clear)
1314 xmlErrorGetString(const void *id, int clear)
1316 return "error detection was not enabled at compile time: no error.";
1321 /* -------------------------------------------------------------------------- */
1323 #ifndef XML_NONVALIDATING
1324 static const char *__xml_error_str[XML_MAX_ERROR] =
1327 "unable to allocate enough memory.",
1328 "unable to open file for reading.",
1329 "requested node name is invalid.",
1330 "unexpected end of section.",
1331 "buffer too small to hold all data, truncating.",
1332 "incorrect comment section.",
1333 "bad information block.",
1334 "incompatible opening tag for element.",
1335 "missing or invalid closing tag for element.",
1336 "missing or invalid opening quote for attribute.",
1337 "missing or invalid closing quote for attribute."
1342 __xmlNodeGetPath(void **nc, const char *start, size_t *len, char **name, size_t *nlen)
1354 if (*path == '/') path++;
1357 size_t num, blocklen, pathlen, nodelen;
1361 pathlen = strlen(path);
1362 path = strchr(node, '/');
1364 if (!path) nodelen = pathlen;
1365 else nodelen = path++ - node;
1370 #ifndef XML_USE_NODECACHE
1371 ret = __xmlNodeGet(nc, start, &blocklen, &node, &nodelen, &num);
1373 ret = __xmlNodeGetFromCache(nc, start, &blocklen, &node, &nodelen, &num);
1379 ret = __xmlNodeGetPath(nc, ret, &blocklen, &path, &pathlen);
1402 __xmlNodeGet(void *nc, const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1404 char *cdata, *open_element = *name;
1405 char *element, *start_tag=0;
1406 char *new, *cur, *ne, *ret = 0;
1407 size_t restlen, elementlen;
1408 size_t open_len = *rlen;
1409 size_t return_len = 0;
1417 assert(nodenum != 0);
1419 if (open_len == 0 || *name == 0)
1420 SET_ERROR_AND_RETURN((char *)start, XML_INVALID_NODE_NAME);
1422 cdata = (char *)start;
1424 SET_ERROR_AND_RETURN((char *)start, XML_UNEXPECTED_EOF);
1429 cur = (char *)start;
1432 #ifdef XML_USE_NODECACHE
1436 /* search for an opening tag */
1437 while ((new = memchr(cur, '<', restlen)) != 0)
1439 size_t len_remaining;
1442 if (*(new+1) == '/') /* end of section */
1452 if (*cur == '!') /* comment */
1455 size_t blocklen = restlen;
1456 new = __xmlProcessCDATA(&start, &blocklen);
1457 if (!new && start && open_len) /* CDATA */
1458 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1464 else if (*cur == '?') /* info block */
1466 new = __xmlInfoProcess(cur, restlen);
1468 SET_ERROR_AND_RETURN(cur, XML_INVALID_INFO_BLOCK);
1476 * get element name and a pointer to after the opening tag
1480 len_remaining = restlen;
1481 rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1482 if (rptr) /* requested element was found */
1485 return_len = elementlen;
1489 open_len = elementlen;
1490 start_tag = element;
1494 else /* different element name was foud */
1496 new = cur + (len_remaining - restlen);
1498 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1503 #ifdef XML_USE_NODECACHE
1504 nnc = cacheNodeNew(nc);
1507 if (*(new-2) == '/') /* e.g. <test/> */
1512 #ifdef XML_USE_NODECACHE
1513 cacheDataSet(nnc, element, elementlen, rptr, 0);
1517 open_element = start_tag;
1526 * get the next xml tag
1528 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1530 new = memchr(cur, '<', restlen);
1532 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1537 if (*cur == '!') /* comment, CDATA */
1540 size_t blocklen = restlen;
1541 new = __xmlProcessCDATA(&start, &blocklen);
1542 if (new && start && open_len) /* CDATA */
1547 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1553 * look for the closing tag of the cascading block
1555 new = memchr(cur, '<', restlen);
1557 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1564 if (*cur == '/') /* closing tag of leaf node found */
1566 if (!strncasecmp(new+1, element, elementlen))
1568 #ifdef XML_USE_NODECACHE
1569 cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
1571 if (*(new+elementlen+1) != '>')
1572 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1579 open_element = start_tag;
1580 cdata = (char *)start;
1583 else /* report error */
1584 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1589 new = memchr(cur, '>', restlen);
1591 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1598 /* no leaf node, continue */
1599 if (*cur != '/') /* cascading tag found */
1602 size_t slen = restlen+1; /* due to cur-1 below*/
1607 * recursively walk the xml tree from here
1609 new = __xmlNodeGet(nnc, cur-1, &slen, &node, &nlen, &pos);
1612 if (nlen == 0) /* error upstream */
1620 if (slen == restlen)
1621 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1627 else restlen -= slen;
1630 * look for the closing tag of the cascading block
1633 new = memchr(cur, '<', restlen);
1635 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1642 if (*cur == '/') /* closing tag found */
1644 if (!strncasecmp(new+1, element, elementlen))
1646 if (*(new+elementlen+1) != '>')
1647 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1649 #ifdef XML_USE_NODECACHE
1650 cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
1657 open_element = start_tag;
1658 cdata = (char *)start;
1661 else /* report error */
1662 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1667 new = memchr(cur, '>', restlen);
1669 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1675 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1684 *len = XML_NO_ERROR; /* element not found, no real error */
1689 *name = open_element;
1697 __xmlProcessCDATA(char **start, size_t *len)
1700 size_t restlen = *len;
1703 if ((restlen > 6) && (*(cur+1) == '-')) /* comment */
1705 new = __xmlCommentSkip(cur, restlen);
1714 if (restlen < 12) return 0; /* ![CDATA[ ]]> */
1719 if (memcmp(cur, "![CDATA[", 8) == 0)
1726 new = memchr(cur, ']', restlen);
1729 if ((restlen > 3) && (memcmp(new, "]]>", 3) == 0))
1731 *len = new-1 - *start;
1744 while (new && (restlen > 2));
1751 __xmlCommentSkip(const char *start, size_t len)
1755 if (len < 7) return 0; /* !-- --> */
1757 cur = (char *)start;
1760 if (memcmp(cur, "!--", 3) == 0)
1766 new = memchr(cur, '-', len);
1770 if ((len >= 3) && (memcmp(new, "-->", 3) == 0))
1781 while (new && (len > 2));
1788 __xmlInfoProcess(const char *start, size_t len)
1792 cur = (char *)start;
1797 if (len < 3) return 0; /* <? ?> */
1801 new = memchr(cur, '?', len);
1802 if (!new || *(new+1) != '>') return 0;
1812 __xmlPrepareData(char **start, size_t *blocklen)
1814 size_t len = *blocklen;
1815 char *pe, *ps = *start;
1820 while ((ps<pe) && isspace(*ps)) ps++;
1821 while ((pe>ps) && isspace(*pe)) pe--;
1824 else if (isspace(*(ps+1))) len--;
1826 /* CDATA or comment */
1827 if ((len >= 2) && !strncmp(ps, "<!", 2))
1830 size_t blocklen = len-1;
1831 if (blocklen >= 6) /* !-- --> */
1833 char *new = __xmlProcessCDATA(&start, &len);
1839 while ((ps<pe) && isspace(*ps)) ps++;
1840 while ((pe>ps) && isspace(*pe)) pe--;
1850 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1852 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1853 char **needle, size_t *needlelen)
1857 if (haystack && needle && needlelen && (*needlelen > 0)
1858 && (*haystacklen >= *needlelen))
1860 char *hs = (char *)haystack;
1866 /* search for everything */
1867 if ((*ns == '*') && (*needlelen == 1))
1869 char *he = hs + *haystacklen;
1871 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1872 if (*(hs-1) == '/') hs--;
1874 *needle = (char *)haystack;
1875 *needlelen = hs - haystack;
1877 ns = memchr(hs, '>', he-hs);
1885 size_t nlen = *needlelen;
1886 char *he = hs + *haystacklen;
1888 for (i=0; i<nlen; i++)
1890 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1891 if (isspace(*hs) || (*hs == '/') || (*hs == '>')) break;
1898 *needle = (char *)haystack;
1899 *needlelen = hs - haystack;
1901 ns = memchr(hs, '>', he-hs);
1907 else /* not found */
1909 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1910 if (*(hs-1) == '/') hs--;
1912 *needle = (char *)haystack;
1913 *needlelen = hs - haystack;
1915 ns = memchr(hs, '>', he-hs);
1921 *haystacklen -= hs - haystack;
1927 #ifndef XML_NONVALIDATING
1929 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1931 struct _xml_id *xid = (struct _xml_id *)id;
1932 struct _root_id *rid;
1936 if (xid->name) rid = xid->root;
1937 else rid = (struct _root_id *)xid;
1942 rid->info = malloc(sizeof(struct _xml_error));
1947 struct _xml_error *err = rid->info;
1949 err->pos = (char *)pos;
1950 err->err_no = err_no;
1957 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1961 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1967 f = (HANDLE)_get_osfhandle(fd);
1968 if (!f) return (void *)-1;
1970 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1971 if (!m) return (void *)-1;
1973 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1990 simple_unmmap(SIMPLE_UNMMAP *un)
1992 UnmapViewOfFile(un->p);