*/
#ifdef WIN32
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
# include <io.h>
-typedef struct
-{
- HANDLE m;
- void *p;
-} SIMPLE_UNMMAP;
-
#else /* !WIN32 */
# include <sys/mman.h>
# include <unistd.h>
# include <stdio.h>
#endif
#include <stdlib.h> /* free, malloc */
-#include <string.h>
+#include <malloc.h>
+#include <string.h> /* memcmp */
#ifndef _MSC_VER
#include <strings.h> /* strncasecmp */
#else
#include <assert.h>
#include <ctype.h>
-#ifndef XML_NONVALIDATING
#include "xml.h"
+#ifndef XML_NONVALIDATING
static const char *__xml_error_str[XML_MAX_ERROR];
-struct _xml_error
-{
- char *pos;
- int err_no;
-};
-
static void __xmlErrorSet(const void *, const char *, unsigned int);
# define xmlErrorSet(a, b, c) __xmlErrorSet(a, b, c)
-#else /* !XML_NONVALIDATING */
-# define xmlErrorSet(a, b, c)
-#endif
-/*
- * It is required for both the rood node and the normal xml nodes to both
- * have 'char *name' defined as the first entry. The code tests whether
- * name == 0 to detect the root node.
- */
-struct _root_id
-{
- char *name;
- char *start;
- size_t len;
- int fd;
-#ifndef XML_NONVALIDATING
- struct _xml_error *info;
-#endif
-# ifdef WIN32
- SIMPLE_UNMMAP un;
+# ifndef NDEBUG
+# define PRINT_INFO(a) \
+ assert((a) < XML_MAX_ERROR); \
+ printf("at line %i: %s\n", __LINE__, __xml_error_str[(a)])
+# else
+# define PRINT_INFO(a)
# endif
-};
-struct _xml_id
-{
- char *name;
- char *start;
- size_t len;
- size_t name_len;
-#ifndef XML_NONVALIDATING
- struct _root_id *root;
+# define SET_ERROR_AND_RETURN(a, b) \
+ { *rlen = 0; *name = (a); *len = (b); PRINT_INFO(b); return 0; }
+
+#else /* !XML_NONVALIDATING */
+# define xmlErrorSet(a, b, c)
+# define SET_ERROR_AND_RETURN(a, b) return 0;
#endif
-};
-static char *__xmlNodeCopy(const char *, size_t *, const char **);
-static char *__xmlNodeGetPath(const char *, size_t *, char **, size_t *);
-static char *__xmlNodeGet(const char *, size_t *, char **, size_t *, size_t *);
+static char *__xmlNodeGetPath(void **, const char *, size_t *, char **, size_t *);
+static char *__xmlNodeGet(void *, const char *, size_t *, char **, size_t *, size_t *);
+static char *__xmlProcessCDATA(char **, size_t *);
static char *__xmlCommentSkip(const char *, size_t);
static char *__xmlInfoProcess(const char *, size_t);
static void *__xml_memncasecmp(const char *, size_t *, char **, size_t *);
+static void __xmlPrepareData(char **, size_t *);
#ifdef WIN32
/*
#ifndef NDEBUG
# define PRINT(a, b, c) { \
- if (a) { \
- size_t q, len = c; \
- if (b < c) len = b; \
+ size_t l1 = (b), l2 = (c); \
+ char *s = (a); \
+ if (s) { \
+ size_t q, len = l2; \
+ if (l1 < l2) len = l1; \
if (len < 50000) { \
printf("(%i) '", len); \
- for (q=0; q<len; q++) printf("%c", ((char *)(a))[q]); \
+ for (q=0; q<len; q++) printf("%c", s[q]); \
printf("'\n"); \
} else printf("Length (%u) seems too large at line %i\n",len, __LINE__); \
} else printf("NULL pointer at line %i\n", __LINE__); \
if (filename)
{
int fd = open(filename, O_RDONLY);
- if (fd > 0)
+ if (fd >= 0)
{
- rid = malloc(sizeof(struct _root_id));
- if (rid)
- {
- struct stat statbuf;
- void *mm;
+ struct stat statbuf;
+ void *mm;
- fstat(fd, &statbuf);
- mm = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0L);
- if (mm != (void *)-1)
+ fstat(fd, &statbuf);
+ mm = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0L);
+ if (mm != (void *)-1)
+ {
+ rid = calloc(1, sizeof(struct _root_id));
+ if (rid)
{
+ size_t blen = statbuf.st_size;
+#ifdef XML_USE_NODECACHE
+ size_t num = 0, nlen = 1;
+ char *n = "*";
+
+ rid->node = cacheInit();
+ __xmlNodeGet(rid->node, mm, &blen, &n, &nlen, &num);
+#endif
rid->fd = fd;
rid->start = mm;
- rid->len = statbuf.st_size;
- rid->name = 0;
-#ifndef XML_NONVALIDATING
- rid->info = 0;
-#endif
+ rid->len = blen;
}
}
}
if (buffer && (size > 0))
{
- rid = malloc(sizeof(struct _root_id));
+ rid = calloc(1, sizeof(struct _root_id));
if (rid)
{
- rid->fd = -1;
+#ifdef XML_USE_NODECACHE
+ size_t num = 0, nlen = 1;
+ size_t blen = size;
+ char *n = "*";
+
+ rid->node = cacheInit();
+ __xmlNodeGet(rid->node, buffer, &blen, &n, &nlen, &num);
+#endif
+ rid->fd = -1;
rid->start = (char *)buffer;
rid->len = size;
- rid->name = 0;
-#ifndef XML_NONVALIDATING
- rid->info = 0;
-#endif
}
}
close(rid->fd);
}
+#ifdef XML_USE_NODECACHE
+ if (rid->node) cacheFree(rid->node);
+#endif
+#ifndef XML_NONVALIDATING
if (rid->info) free(rid->info);
+#endif
free(rid);
id = 0;
}
struct _xml_id *xsid = 0;
size_t len, slen;
char *ptr, *node;
+ void *nc, *nnc;
assert(id != 0);
assert(path != 0);
node = (char *)path;
len = xid->len;
slen = strlen(path);
- ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+
+ nnc = nc = cacheNodeGet(xid);
+ ptr = __xmlNodeGetPath(&nnc, xid->start, &len, &node, &slen);
if (ptr)
{
xsid = malloc(sizeof(struct _xml_id));
if (xsid)
{
- xsid->len = len;
- xsid->start = ptr;
- xsid->name_len = slen;
xsid->name = node;
+ xsid->name_len = slen;
+ xsid->start = ptr;
+ xsid->len = len;
+#ifdef XML_USE_NODECACHE
+ xsid->node = nnc;
+#endif
#ifndef XML_NONVALIDATING
if (xid->name)
xsid->root = xid->root;
struct _xml_id *xsid = 0;
char *ptr, *node, *p;
size_t slen, len;
+ void *nc, *nnc;
node = (char *)path;
len = xid->len;
slen = strlen(path);
- ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+
+ nnc = nc = cacheNodeGet(xid);
+ ptr = __xmlNodeGetPath(&nnc, xid->start, &len, &node, &slen);
if (ptr)
{
xsid = malloc(sizeof(struct _xml_id) + len);
xsid->start = p;
xsid->name_len = slen;
xsid->name = node;
+#ifdef XML_USE_NODECACHE
+ xsid->node = nc;
+#endif
#ifndef XML_NONVALIDATING
if (xid->name)
xsid->root = xid->root;
{
char *nodename, *pathname;
size_t len, slen;
+ void *nc;
char *p;
nodename = (char *)path;
if (*path == '/') nodename++;
slen = strlen(nodename);
+ nc = cacheNodeGet(xid);
pathname = strchr(nodename, '/');
if (pathname)
{
pathname++;
slen -= pathname-nodename;
node = pathname;
- p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ p = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (p == 0 && slen == 0)
{
xmlErrorSet(xid, node, len);
if (p)
{
char *ret, *node = nodename;
- ret = __xmlNodeGet(p, &len, &node, &slen, &num);
+#ifndef XML_USE_NODECACHE
+ ret = __xmlNodeGet(nc, p, &len, &node, &slen, &num);
+#else
+ ret = __xmlNodeGetFromCache(&nc, p, &len, &node, &slen, &num);
+#endif
if (ret == 0 && slen == 0)
{
xmlErrorSet(xid, node, len);
size_t len, slen;
char *ptr, *node;
void *ret = 0;
+ void *nc;
assert(xpid != 0);
assert(xid != 0);
len = xpid->len;
slen = strlen(element);
node = (char *)element;
- ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
+ nc = cacheNodeGet(xpid);
+#ifndef XML_USE_NODECACHE
+ ptr = __xmlNodeGet(nc, xpid->start, &len, &node, &slen, &num);
+#else
+ ptr = __xmlNodeGetFromCache(&nc, xpid->start, &len, &node, &slen, &num);
+#endif
if (ptr)
{
xid->len = len;
xid->start = ptr;
xid->name = node;
xid->name_len = slen;
+#ifdef XML_USE_NODECACHE
+ /* unused for the cache but tested at the start of this function */
+ if (len == 0) xid->len = 1;
+ xid->node = nc;
+#endif
ret = xid;
}
else if (slen == 0)
if (xid->len)
{
- char *ps, *pe, *pend;
- int nlen;
+ size_t len;
+ char *ps;
ps = xid->start;
- nlen = xid->len;
- pend = ps+nlen;
- pe = pend;
-
- while ((ps<pe) && isspace(*ps)) ps++;
- while ((pe>ps) && isspace(*pe)) pe--;
- nlen = (pe-ps);
- if (nlen)
+ len = xid->len-1;
+ __xmlPrepareData(&ps, &len);
+ if (len)
{
- str = malloc(nlen+1);
+ len++;
+ str = malloc(len+1);
if (str)
{
- memcpy(str, ps, nlen);
- *(str+nlen) = 0;
+ memcpy(str, ps, len);
+ *(str+len) = 0;
}
else
{
assert(buffer != 0);
assert(buflen > 0);
+ *buffer = '\0';
if (xid->len)
{
- char *ps, *pe, *pend;
- size_t slen, nlen;
+ size_t len;
+ char *ps;
- *buffer = '\0';
- nlen = buflen-1;
ps = xid->start;
- slen = xid->len;
- pend = ps+slen;
- pe = pend;
-
- while ((ps<pe) && isspace(*ps)) ps++;
- while ((pe>ps) && isspace(*pe)) pe--;
- nlen = (pe-ps);
- if (nlen > slen) nlen = slen;
-
- if (nlen)
+ len = xid->len;
+ __xmlPrepareData(&ps, &len);
+ if (len)
{
- if (nlen >= buflen)
+ if (len >= buflen)
{
- nlen = buflen-1;
+ len = buflen-1;
xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
}
- memcpy(buffer, ps, nlen);
- *(buffer+nlen) = 0;
- ret = nlen;
+ memcpy(buffer, ps, len);
+ *(buffer+len) = 0;
}
+ ret = len;
}
return ret;
if (xid->len && (strlen(s) > 0))
{
- char *ps, *pe;
+ size_t len;
+ char *ps;
ps = xid->start;
- pe = ps + xid->len;
- pe--;
-
- while ((ps<pe) && isspace(*ps)) ps++;
- while ((pe>ps) && isspace(*pe)) pe--;
- pe++;
-
- ret = strncasecmp(ps, s, pe-ps);
+ len = xid->len;
+ __xmlPrepareData(&ps, &len);
+ ret = strncasecmp(ps, s, len);
}
return ret;
if (xid->len)
{
+ char *ptr, *node = (char *)path;
+ size_t slen = strlen(node);
size_t len = xid->len;
- char *node = (char *)path;
+ void *nc;
- str = __xmlNodeCopy(xid->start, &len, &path);
- if (str)
+ nc = cacheNodeGet(xid);
+ ptr = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
+ if (ptr && len)
{
- char *ps, *pe, *pend;
- int slen;
-
- ps = str;
- slen = strlen(str);
- pend = ps+slen;
- pe = pend-1;
-
- while ((ps<pe) && isspace(*ps)) ps++;
- while ((pe>ps) && isspace(*pe)) pe--;
-
- *++pe = 0;
- slen = (pe-ps);
- if (slen && (ps>str)) memmove(str, ps, slen);
- else if (!slen) *str = 0;
+ __xmlPrepareData(&ptr, &len);
+ str = malloc(len+1);
+ if (str)
+ {
+ memcpy(str, ptr, len);
+ *(str+len) = '\0';
+ }
+ else
+ {
+ xmlErrorSet(xid, 0, XML_OUT_OF_MEMORY);
+ }
}
else
{
assert(buffer != 0);
assert(buflen > 0);
+ *buffer = '\0';
if (xid->len)
{
- char *str, *node;
- size_t slen, nlen;
+ char *p, *node = (char *)path;
+ size_t slen = strlen(node);
+ size_t len = xid->len;
+ void *nc;
- *buffer = '\0';
- nlen = xid->len;
- slen = strlen(path);
- node = (char *)path;
- str = __xmlNodeGetPath(xid->start, &nlen, &node, &slen);
- if (str)
+ nc = cacheNodeGet(xid);
+ p = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
+ if (p)
{
- char *ps, *pe;
-
- ps = str;
- pe = ps+nlen-1;
-
- while ((ps<pe) && isspace(*ps)) ps++;
- while ((pe>ps) && isspace(*pe)) pe--;
-
- nlen = (pe-ps)+1;
- if (nlen >= buflen)
+ __xmlPrepareData(&p, &len);
+ if (len)
{
- nlen = buflen-1;
- xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
- }
+ if (len >= buflen)
+ {
+ len = buflen-1;
+ xmlErrorSet(xid, 0, XML_TRUNCATE_RESULT);
+ }
- memcpy(buffer, ps, nlen);
- *(buffer + nlen) = '\0';
- ret = nlen;
+ memcpy(buffer, p, len);
+ *(buffer+len) = '\0';
+ }
+ ret = len;
}
else if (slen == 0)
{
- xmlErrorSet(xid, node, nlen);
+ xmlErrorSet(xid, node, len);
}
}
{
char *node, *str, *ps, *pe;
size_t len, slen;
+ void *nc;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ nc = cacheNodeGet(xid);
+ str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (str)
{
ps = str;
- pe = ps + len;
- pe--;
-
- while ((ps<pe) && isspace(*ps)) ps++;
- while ((pe>ps) && isspace(*pe)) pe--;
- pe++;
-
- ret = strncasecmp(ps, s, pe-ps);
+ __xmlPrepareData(&ps, &len);
+ ret = strncasecmp(ps, s, len);
}
else if (slen == 0)
{
{
size_t len, slen;
char *str, *node;
+ void *nc;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ nc = cacheNodeGet(xid);
+ str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (str)
{
char *end = str+len;
{
size_t len, slen;
char *str, *node;
+ void *nc;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
+ nc = cacheNodeGet(xid);
+ str = __xmlNodeGetPath(&nc, xid->start, &len, &node, &slen);
if (str)
{
char *end = str+len;
if (xrid->name == 0)
{
xmid->name = "";
+ xmid->name_len = 0;
xmid->start = xrid->start;
xmid->len = xrid->len;
- xmid->name_len = 0;
+#ifdef XML_USE_NODECACHE
+ xmid->node = xrid->node;
+#endif
#ifndef XML_NONVALIDATING
xmid->root = xrid;
#endif
return ret;
}
+
+#else
+
+int
+xmlErrorGetNo(const void *id, int clear)
+{
+ return XML_NO_ERROR;
+}
+
+size_t
+xmlErrorGetLineNo(const void *id, int clear)
+{
+ return 0;
+}
+
+size_t
+xmlErrorGetColumnNo(const void *id, int clear)
+{
+ return 0;
+}
+
+const char *
+xmlErrorGetString(const void *id, int clear)
+{
+ return "error detection was not enabled at compile time: no error.";
+}
+
#endif
/* -------------------------------------------------------------------------- */
"no error.",
"unable to allocate enough memory.",
"unable to open file for reading.",
+ "requested node name is invalid.",
+ "unexpected end of section.",
"buffer too small to hold all data, truncating.",
"incorrect comment section.",
"bad information block.",
- "unexpected end of section.",
"incompatible opening tag for element.",
"missing or invalid closing tag for element.",
"missing or invalid opening quote for attribute.",
#endif
char *
-__xmlNodeCopy(const char *start, size_t *len, const char **path)
-{
- char *node, *p, *ret = 0;
- size_t rlen, slen;
-
- rlen = *len;
- slen = strlen(*path);
- node = (char *)*path;
- p = __xmlNodeGetPath(start, &rlen, &node, &slen);
- if (p && rlen)
- {
- ret = malloc(rlen+1);
- if (ret)
- {
- memcpy(ret, p, rlen);
- *(ret+rlen) = '\0';
- }
- else
- {
- xmlErrorSet(0, 0, XML_OUT_OF_MEMORY);
- }
- }
- else if (slen == 0)
- {
- *path = node;
- *len = rlen;
- }
-
- return ret;
-}
-
-char *
-__xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen)
+__xmlNodeGetPath(void **nc, const char *start, size_t *len, char **name, size_t *nlen)
{
- char *node;
+ char *path;
char *ret = 0;
assert(start != 0);
assert(len != 0);
- assert(*len != 0);
assert(name != 0);
assert(*name != 0);
- assert(plen != 0);
- assert(*plen != 0);
-
- if (*plen > *len) return 0;
+ assert(nlen != 0);
- node = *name;
- if (*node == '/') node++;
- if (*node != 0)
+ path = *name;
+ if (*path == '/') path++;
+ if (*path != '\0')
{
- size_t plen, slen;
- char *path;
- size_t num;
+ size_t num, blocklen, pathlen, nodelen;
+ char *node;
- slen = strlen(node);
+ node = path;
+ pathlen = strlen(path);
path = strchr(node, '/');
- if (!path) plen = slen;
- else plen = path++ - node;
+ if (!path) nodelen = pathlen;
+ else nodelen = path++ - node;
num = 0;
- ret = __xmlNodeGet(start, len, &node, &plen, &num);
- if (ret && path)
+ blocklen = *len;
+
+#ifndef XML_USE_NODECACHE
+ ret = __xmlNodeGet(nc, start, &blocklen, &node, &nodelen, &num);
+#else
+ ret = __xmlNodeGetFromCache(nc, start, &blocklen, &node, &nodelen, &num);
+#endif
+ if (ret)
{
- plen = slen - (path - *name);
- ret = __xmlNodeGetPath(ret, len, &path, &plen);
- *name = path;
+ if (path)
+ {
+ ret = __xmlNodeGetPath(nc, ret, &blocklen, &path, &pathlen);
+ *name = path;
+ *len = blocklen;
+ *nlen = pathlen;
+ }
+ else
+ {
+ *name = node;
+ *nlen = nodelen;
+ *len = blocklen;
+ }
}
- else if (plen == 0)
+ else
{
- *name = node;
+ *len = 0;
+ *nlen = 0;
}
}
}
char *
-__xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
+__xmlNodeGet(void *nc, const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
{
- char *open_element = *name;
+ char *cdata, *open_element = *name;
char *element, *start_tag=0;
char *new, *cur, *ne, *ret = 0;
size_t restlen, elementlen;
size_t open_len = *rlen;
size_t return_len = 0;
int found, num;
+ void *nnc = 0;
assert(start != 0);
assert(len != 0);
- assert(*len != 0);
assert(name != 0);
- assert(*name != 0);
assert(rlen != 0);
- assert(*rlen != 0);
assert(nodenum != 0);
+ if (open_len == 0 || *name == 0)
+ SET_ERROR_AND_RETURN((char *)start, XML_INVALID_NODE_NAME);
+
+ cdata = (char *)start;
if (*rlen > *len)
- {
- *rlen = 0;
- *name = (char *)start;
- *len = XML_UNEXPECTED_EOF;
- return 0;
- }
+ SET_ERROR_AND_RETURN((char *)start, XML_UNEXPECTED_EOF);
found = 0;
num = *nodenum;
cur = (char *)start;
ne = cur + restlen;
+#ifdef XML_USE_NODECACHE
+ cacheInitLevel(nc);
+#endif
+
/* search for an opening tag */
while ((new = memchr(cur, '<', restlen)) != 0)
{
if (*(new+1) == '/') /* end of section */
{
- *len -= restlen-1;
+ *len -= restlen;
break;
}
if (*cur == '!') /* comment */
{
- new = __xmlCommentSkip(cur, restlen);
- if (!new)
- {
- *rlen = 0;
- *name = cur;
- *len = XML_INVALID_COMMENT;
- return 0;
- }
+ char *start = cur;
+ size_t blocklen = restlen;
+ new = __xmlProcessCDATA(&start, &blocklen);
+ if (!new && start && open_len) /* CDATA */
+ SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
+
restlen -= new-cur;
cur = new;
continue;
{
new = __xmlInfoProcess(cur, restlen);
if (!new)
- {
- *rlen = 0;
- *name = cur;
- *len = XML_INVALID_INFO_BLOCK;
- return 0;
- }
+ SET_ERROR_AND_RETURN(cur, XML_INVALID_INFO_BLOCK);
restlen -= new-cur;
cur = new;
element = *name;
elementlen = *rlen;
len_remaining = restlen;
- new = rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
+ rptr = __xml_memncasecmp(cur, &restlen, &element, &elementlen);
if (rptr) /* requested element was found */
{
+ new = rptr;
return_len = elementlen;
if (found == num)
{
{
new = cur + (len_remaining - restlen);
if (new >= ne)
- {
- *rlen = 0;
- *name = cur;
- *len = XML_UNEXPECTED_EOF;
- return 0;
- }
+ SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
+
element = *name;
}
+#ifdef XML_USE_NODECACHE
+ nnc = cacheNodeNew(nc);
+#endif
+
if (*(new-2) == '/') /* e.g. <test/> */
{
cur = new;
if (rptr)
{
+#ifdef XML_USE_NODECACHE
+ cacheDataSet(nnc, element, elementlen, rptr, 0);
+#endif
if (found == num)
{
open_element = start_tag;
cur = new;
new = memchr(cur, '<', restlen);
if (!new)
- {
- *rlen = 0;
- *name = cur;
- *len = XML_ELEMENT_NO_CLOSING_TAG;
- return 0;
- }
+ SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
new++;
restlen -= new-cur;
cur = new;
- if (*cur == '!') /* comment */
+ if (*cur == '!') /* comment, CDATA */
{
- new = __xmlCommentSkip(cur, restlen);
- if (!new)
+ char *start = cur;
+ size_t blocklen = restlen;
+ new = __xmlProcessCDATA(&start, &blocklen);
+ if (new && start && open_len) /* CDATA */
{
- *rlen = 0;
- *name = cur;
- *len = XML_INVALID_COMMENT;
- return 0;
+ cdata = ret;
}
+ else if (!new)
+ SET_ERROR_AND_RETURN(cur, XML_INVALID_COMMENT);
+
restlen -= new-cur;
cur = new;
*/
new = memchr(cur, '<', restlen);
if (!new)
+ SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
+
+ new++;
+ restlen -= new-cur;
+ cur = new;
+ }
+
+ if (*cur == '/') /* closing tag of leaf node found */
+ {
+ if (!strncasecmp(new+1, element, elementlen))
{
- *rlen = 0;
- *name = cur;
- *len = XML_ELEMENT_NO_CLOSING_TAG;
- return 0;
+#ifdef XML_USE_NODECACHE
+ cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
+#endif
+ if (*(new+elementlen+1) != '>')
+ SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
+
+ if (found == num)
+ {
+ if (start_tag)
+ {
+ *len = new-ret-1;
+ open_element = start_tag;
+ cdata = (char *)start;
+ start_tag = 0;
+ }
+ else /* report error */
+ SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
+ }
+ found++;
}
- new++;
+
+ new = memchr(cur, '>', restlen);
+ if (!new)
+ SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
+
restlen -= new-cur;
cur = new;
+ continue;
}
+ /* no leaf node, continue */
if (*cur != '/') /* cascading tag found */
{
char *node = "*";
- size_t slen = restlen+1;
+ size_t slen = restlen+1; /* due to cur-1 below*/
size_t nlen = 1;
size_t pos = -1;
/*
* recursively walk the xml tree from here
*/
- new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos);
+ new = __xmlNodeGet(nnc, cur-1, &slen, &node, &nlen, &pos);
if (!new)
{
if (nlen == 0) /* error upstream */
}
if (slen == restlen)
- {
- *rlen = 0;
- *name = cur;
- *len = XML_UNEXPECTED_EOF;
- return 0;
- }
- else new = cur + slen;
- }
+ SET_ERROR_AND_RETURN(cur, XML_UNEXPECTED_EOF);
- restlen -= slen;
- cur = new;
+ slen--;
+ new = cur + slen;
+ restlen -= slen;
+ }
+ else restlen -= slen;
/*
* look for the closing tag of the cascading block
*/
+ cur = new;
new = memchr(cur, '<', restlen);
if (!new)
- {
- *rlen = 0;
- *name = cur;
- *len = XML_ELEMENT_NO_CLOSING_TAG;
- return 0;
- }
+ SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
+
new++;
restlen -= new-cur;
cur = new;
if (!strncasecmp(new+1, element, elementlen))
{
if (*(new+elementlen+1) != '>')
- {
- *rlen = 0;
- *name = new+1;
- *len = XML_ELEMENT_NO_CLOSING_TAG;
- return 0;
- }
+ SET_ERROR_AND_RETURN(new+1, XML_ELEMENT_NO_CLOSING_TAG);
+#ifdef XML_USE_NODECACHE
+ cacheDataSet(nnc, element, elementlen, rptr, new-rptr-1);
+#endif
if (found == num)
{
if (start_tag)
{
*len = new-ret-1;
open_element = start_tag;
+ cdata = (char *)start;
+ start_tag = 0;
}
else /* report error */
- {
- *rlen = 0;
- *name = new;
- *len = XML_ELEMENT_NO_OPENING_TAG;
- return 0;
- }
+ SET_ERROR_AND_RETURN(new, XML_ELEMENT_NO_OPENING_TAG);
}
found++;
}
new = memchr(cur, '>', restlen);
if (!new)
- {
- *rlen = 0;
- *name = cur;
- *len = XML_ELEMENT_NO_CLOSING_TAG;
- return 0;
- }
+ SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
restlen -= new-cur;
cur = new;
}
else
- {
- *rlen = 0;
- *name = cur;
- *len = XML_ELEMENT_NO_CLOSING_TAG;
- return 0;
- }
- }
+ SET_ERROR_AND_RETURN(cur, XML_ELEMENT_NO_CLOSING_TAG);
+
+ } /* while */
if (found == 0)
{
return ret;
}
+char *
+__xmlProcessCDATA(char **start, size_t *len)
+{
+ char *cur, *new;
+ size_t restlen = *len;
+
+ cur = *start;
+ if ((restlen > 6) && (*(cur+1) == '-')) /* comment */
+ {
+ new = __xmlCommentSkip(cur, restlen);
+ if (new)
+ {
+ *start = new;
+ *len = 0;
+ }
+ return new;
+ }
+
+ if (restlen < 12) return 0; /* ![CDATA[ ]]> */
+
+ cur = *start;
+ new = 0;
+
+ if (memcmp(cur, "![CDATA[", 8) == 0)
+ {
+ *start = cur+8;
+ cur += 8;
+ restlen -= 8;
+ do
+ {
+ new = memchr(cur, ']', restlen);
+ if (new)
+ {
+ if ((restlen > 3) && (memcmp(new, "]]>", 3) == 0))
+ {
+ *len = new-1 - *start;
+ restlen -= 3;
+ new += 3;
+ break;
+ }
+ cur = new+1;
+ }
+ else
+ {
+ *len = 0;
+ break;
+ }
+ }
+ while (new && (restlen > 2));
+ }
+
+ return new;
+}
+
char *
__xmlCommentSkip(const char *start, size_t len)
{
char *cur, *new;
+ if (len < 7) return 0; /* !-- --> */
+
cur = (char *)start;
new = 0;
if (memcmp(cur, "!--", 3) == 0)
{
- if (len < 6) return 0; /* <!-- --> */
-
cur += 3;
len -= 3;
do
new = memchr(cur, '-', len);
if (new)
{
- len -= new - cur;
- if ((len > 3) && (memcmp(new, "-->", 3) == 0))
+ len -= new-cur;
+ if ((len >= 3) && (memcmp(new, "-->", 3) == 0))
{
new += 3;
- len -= 3;
+ /* len -= 3; */
break;
}
cur = new+1;
+ len -= cur-new;
}
else break;
}
}
+static void
+__xmlPrepareData(char **start, size_t *blocklen)
+{
+ size_t len = *blocklen;
+ char *pe, *ps = *start;
+
+ if (len > 1)
+ {
+ pe = ps + len-1;
+ while ((ps<pe) && isspace(*ps)) ps++;
+ while ((pe>ps) && isspace(*pe)) pe--;
+ len = (pe-ps)+1;
+ }
+ else if (isspace(*(ps+1))) len--;
+
+ /* CDATA or comment */
+ if ((len >= 2) && !strncmp(ps, "<!", 2))
+ {
+ char *start = ps+1;
+ size_t blocklen = len-1;
+ if (blocklen >= 6) /* !-- --> */
+ {
+ char *new = __xmlProcessCDATA(&start, &len);
+ if (new)
+ {
+ ps = start;
+ pe = ps + len;
+
+ while ((ps<pe) && isspace(*ps)) ps++;
+ while ((pe>ps) && isspace(*pe)) pe--;
+ len = (pe-ps);
+ }
+ }
+ }
+
+ *start = ps;
+ *blocklen = len;
+}
+
#define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
void *
__xml_memncasecmp(const char *haystack, size_t *haystacklen,