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)
1353 if (*path == '/') path++;
1356 size_t num, blocklen, pathlen, nodelen;
1360 pathlen = strlen(path);
1361 path = strchr(node, '/');
1363 if (!path) nodelen = pathlen;
1364 else nodelen = path++ - node;
1369 #ifndef XML_USE_NODECACHE
1370 ret = __xmlNodeGet(nc, start, &blocklen, &node, &nodelen, &num);
1372 ret = __xmlNodeGetFromCache(nc, start, &blocklen, &node, &nodelen, &num);
1378 ret = __xmlNodeGetPath(nc, ret, &blocklen, &path, &pathlen);
1401 __xmlNodeGet(void *nc, const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
1403 char *cdata, *open_element = *name;
1404 char *element, *start_tag=0;
1405 char *new, *cur, *ne, *ret = 0;
1406 size_t restlen, elementlen;
1407 size_t open_len = *rlen;
1408 size_t return_len = 0;
1416 assert(nodenum != 0);
1418 if (open_len == 0 || *name == 0)
1419 SET_ERROR_AND_RETURN((char *)start, XML_INVALID_NODE_NAME);
1421 cdata = (char *)start;
1423 SET_ERROR_AND_RETURN((char *)start, XML_UNEXPECTED_EOF);
1428 cur = (char *)start;
1431 #ifdef XML_USE_NODECACHE
1435 /* search for an opening tag */
1436 while ((new = memchr(cur, '<', restlen)) != 0)
1438 size_t len_remaining;
1441 if (*(new+1) == '/') /* end of section */
1451 if (*cur == '!') /* comment */
1454 size_t blocklen = restlen;
1455 new = __xmlProcessCDATA(&start, &blocklen);
1456 if (!new && start && open_len) /* CDATA */
1457 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1463 else if (*cur == '?') /* info block */
1465 new = __xmlInfoProcess(cur, restlen);
1467 SET_ERROR_AND_RETURN(cur, XML_INVALID_INFO_BLOCK);
1475 * get element name and a pointer to after the opening tag
1479 len_remaining = restlen;
1480 rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
1481 if (rptr) /* requested element was found */
1484 return_len = elementlen;
1488 open_len = elementlen;
1489 start_tag = element;
1493 else /* different element name was foud */
1495 new = cur + (len_remaining - restlen);
1497 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1502 #ifdef XML_USE_NODECACHE
1503 nnc = cacheNodeNew(nc);
1506 if (*(new-2) == '/') /* e.g. <test/> */
1511 #ifdef XML_USE_NODECACHE
1512 cacheDataSet(nnc, element, elementlen, rptr, 0);
1516 open_element = start_tag;
1525 * get the next xml tag
1527 /* restlen -= new-cur; not necessary because of __xml_memncasecmp */
1529 new = memchr(cur, '<', restlen);
1531 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1536 if (*cur == '!') /* comment, CDATA */
1539 size_t blocklen = restlen;
1540 new = __xmlProcessCDATA(&start, &blocklen);
1541 if (new && start && open_len) /* CDATA */
1546 SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
1552 * look for the closing tag of the cascading block
1554 new = memchr(cur, '<', restlen);
1556 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1563 if (*cur == '/') /* closing tag of leaf node found */
1565 if (!strncasecmp(new+1, element, elementlen))
1567 #ifdef XML_USE_NODECACHE
1568 cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
1570 if (*(new+elementlen+1) != '>')
1571 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1578 open_element = start_tag;
1579 cdata = (char *)start;
1582 else /* report error */
1583 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1588 new = memchr(cur, '>', restlen);
1590 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1597 /* no leaf node, continue */
1598 if (*cur != '/') /* cascading tag found */
1601 size_t slen = restlen+1; /* due to cur-1 below*/
1606 * recursively walk the xml tree from here
1608 new = __xmlNodeGet(nnc, cur-1, &slen, &node, &nlen, &pos);
1611 if (nlen == 0) /* error upstream */
1619 if (slen == restlen)
1620 SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
1626 else restlen -= slen;
1629 * look for the closing tag of the cascading block
1632 new = memchr(cur, '<', restlen);
1634 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1641 if (*cur == '/') /* closing tag found */
1643 if (!strncasecmp(new+1, element, elementlen))
1645 if (*(new+elementlen+1) != '>')
1646 SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
1648 #ifdef XML_USE_NODECACHE
1649 cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
1656 open_element = start_tag;
1657 cdata = (char *)start;
1660 else /* report error */
1661 SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
1666 new = memchr(cur, '>', restlen);
1668 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1674 SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
1683 *len = XML_NO_ERROR; /* element not found, no real error */
1688 *name = open_element;
1696 __xmlProcessCDATA(char **start, size_t *len)
1699 size_t restlen = *len;
1702 if ((restlen > 6) && (*(cur+1) == '-')) /* comment */
1704 new = __xmlCommentSkip(cur, restlen);
1713 if (restlen < 12) return 0; /* ![CDATA[ ]]> */
1718 if (memcmp(cur, "![CDATA[", 8) == 0)
1725 new = memchr(cur, ']', restlen);
1728 if ((restlen > 3) && (memcmp(new, "]]>", 3) == 0))
1730 *len = new-1 - *start;
1743 while (new && (restlen > 2));
1750 __xmlCommentSkip(const char *start, size_t len)
1754 if (len < 7) return 0; /* !-- --> */
1756 cur = (char *)start;
1759 if (memcmp(cur, "!--", 3) == 0)
1765 new = memchr(cur, '-', len);
1769 if ((len >= 3) && (memcmp(new, "-->", 3) == 0))
1780 while (new && (len > 2));
1787 __xmlInfoProcess(const char *start, size_t len)
1791 cur = (char *)start;
1796 if (len < 3) return 0; /* <? ?> */
1800 new = memchr(cur, '?', len);
1801 if (!new || *(new+1) != '>') return 0;
1811 __xmlPrepareData(char **start, size_t *blocklen)
1813 size_t len = *blocklen;
1814 char *pe, *ps = *start;
1819 while ((ps<pe) && isspace(*ps)) ps++;
1820 while ((pe>ps) && isspace(*pe)) pe--;
1823 else if (isspace(*(ps+1))) len--;
1825 /* CDATA or comment */
1826 if ((len >= 2) && !strncmp(ps, "<!", 2))
1829 size_t blocklen = len-1;
1830 if (blocklen >= 6) /* !-- --> */
1832 char *new = __xmlProcessCDATA(&start, &len);
1838 while ((ps<pe) && isspace(*ps)) ps++;
1839 while ((pe>ps) && isspace(*pe)) pe--;
1849 #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
1851 __xml_memncasecmp(const char *haystack, size_t *haystacklen,
1852 char **needle, size_t *needlelen)
1856 if (haystack && needle && needlelen && (*needlelen > 0)
1857 && (*haystacklen >= *needlelen))
1859 char *hs = (char *)haystack;
1865 /* search for everything */
1866 if ((*ns == '*') && (*needlelen == 1))
1868 char *he = hs + *haystacklen;
1870 while ((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1871 if (*(hs-1) == '/') hs--;
1873 *needle = (char *)haystack;
1874 *needlelen = hs - haystack;
1876 ns = memchr(hs, '>', he-hs);
1884 size_t nlen = *needlelen;
1885 char *he = hs + *haystacklen;
1887 for (i=0; i<nlen; i++)
1889 if (NOCASECMP(*hs,*ns) && (*ns != '?')) break;
1890 if (isspace(*hs) || (*hs == '/') || (*hs == '>')) break;
1897 *needle = (char *)haystack;
1898 *needlelen = hs - haystack;
1900 ns = memchr(hs, '>', he-hs);
1906 else /* not found */
1908 while((hs < he) && !isspace(*hs) && (*hs != '>')) hs++;
1909 if (*(hs-1) == '/') hs--;
1911 *needle = (char *)haystack;
1912 *needlelen = hs - haystack;
1914 ns = memchr(hs, '>', he-hs);
1920 *haystacklen -= hs - haystack;
1926 #ifndef XML_NONVALIDATING
1928 __xmlErrorSet(const void *id, const char *pos, unsigned int err_no)
1930 struct _xml_id *xid = (struct _xml_id *)id;
1931 struct _root_id *rid;
1935 if (xid->name) rid = xid->root;
1936 else rid = (struct _root_id *)xid;
1941 rid->info = malloc(sizeof(struct _xml_error));
1946 struct _xml_error *err = rid->info;
1948 err->pos = (char *)pos;
1949 err->err_no = err_no;
1956 * https://mollyrocket.com/forums/viewtopic.php?p=2529
1960 simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
1966 f = (HANDLE)_get_osfhandle(fd);
1967 if (!f) return (void *)-1;
1969 m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
1970 if (!m) return (void *)-1;
1972 p = MapViewOfFile(m, FILE_MAP_READ, 0,0,0);
1989 simple_unmmap(SIMPLE_UNMMAP *un)
1991 UnmapViewOfFile(un->p);