/* Copyright (c) 2007, 2008 by Adalin B.V. * Copyright (c) 2007, 2008 by Erik Hofman * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of (any of) the copyrightholder(s) nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include typedef struct { HANDLE m; void *p; } SIMPLE_UNMMAP; static SIMPLE_UNMMAP un; /* * map 'filename' and return a pointer to it. */ void *simple_mmap(int, unsigned int, SIMPLE_UNMMAP *); void simple_unmmap(SIMPLE_UNMMAP *); #define mmap(a,b,c,d,e,f) simple_mmap((e), (b), &un) #define munmap(a,b) simple_unmmap(&un) #else /* !WIN32 */ # include # include #endif #include #include #include #include #include #include #include struct _xml_id { char *start; size_t len; int fd; }; static char *__xmlCopyNode(char *, size_t, const char *); static char *__xmlGetNode(char *, size_t, const char *, size_t *); static void *__xml_memmem(const void *, size_t, const void *, size_t); static void *__xml_memncasecmp(void *, size_t, void **, size_t *); #define PRINT(a, b, c) { \ size_t q, len=(((b)>(c)) ? (c) : (b)); \ if (a) { \ printf("(%i) '", len); \ for (q=0; q 0) { id = malloc(sizeof(struct _xml_id)); if (id) { struct stat statbuf; fstat(fd, &statbuf); id->fd = fd; id->len = statbuf.st_size; id->start = mmap(0, id->len, PROT_READ, MAP_PRIVATE, fd, 0L); } } } return (void*)id; } void xmlClose(void *id) { if (id) { struct _xml_id *xid = (struct _xml_id *)id; munmap(xid->start, xid->len); close(xid->fd); free(id); id = 0; } } void * xmlCopyNode(void *id, char *path) { struct _xml_id *xsid = 0; if (id && path) { struct _xml_id *xid = (struct _xml_id *)id; char *ptr, *p; size_t rlen; rlen = strlen(path); ptr = __xmlGetNode(xid->start, xid->len, path, &rlen); if (ptr) { xsid = malloc(sizeof(struct _xml_id) + rlen); if (xsid) { p = (char *)xsid + sizeof(struct _xml_id); xsid->len = rlen; xsid->start = p; xsid->fd = 0; memcpy(xsid->start, ptr, rlen); } } } return (void *)xsid; } void * xmlGetNode(void *id, char *path) { struct _xml_id *xsid = 0; if (id && path) { struct _xml_id *xid = (struct _xml_id *)id; size_t rlen; char *ptr; rlen = strlen(path); ptr = __xmlGetNode(xid->start, xid->len, path, &rlen); if (ptr) { xsid = malloc(sizeof(struct _xml_id)); xsid->len = rlen; xsid->start = ptr; xsid->fd = 0; } } return (void *)xsid; } const char * xmlGetNextElement(const void *pid, void *id, char *path) { struct _xml_id *xpid = (struct _xml_id *)pid; const char *ret; if (id && path) { struct _xml_id *xid = (struct _xml_id *)id; size_t rlen, nlen; char *ptr; if (xid->len < xpid->len) xid->start += xid->len; nlen = xpid->len - (xid->start - xpid->start); rlen = strlen(path); ptr = __xmlGetNode(xid->start, nlen, path, &rlen); if (ptr) { xid->len = rlen; xid->start = ptr; ret = path; } else ret = 0; } else ret = 0; return ret; } int xmlCompareString(const void *id, const char *s) { struct _xml_id *xid = (struct _xml_id *)id; int ret = -1; if (xid && xid->len && s && (strlen(s) > 0)) { char *ps, *pe; ps = xid->start; pe = ps + xid->len; pe--; while ((psps) && isspace(*pe)) pe--; pe++; ret = strncasecmp(ps, s, pe-ps); } return ret; } int xmlCompareNodeString(const void *id, const char *path, const char *s) { struct _xml_id *xid = (struct _xml_id *)id; int ret = -1; if (xid && xid->len && path && s && (strlen(s) > 0)) { char *str, *ps, *pe; size_t rlen; rlen = strlen(path); str = __xmlGetNode(xid->start, xid->len, path, &rlen); ps = str; pe = ps + rlen; pe--; while ((psps) && isspace(*pe)) pe--; pe++; if (str) ret = strncasecmp(pe, s, pe-ps); } return ret; } char * xmlGetNodeString(void *id, const char *path) { struct _xml_id *xid = (struct _xml_id *)id; char *str = 0; if (xid && xid->len && path) { str = __xmlCopyNode(xid->start, xid->len, path); if (str) { char *ps, *pe, *pend; int slen; slen = strlen(str); ps = str; pend = ps+slen; pe = pend-1; while ((psps) && isspace(*pe)) pe--; *++pe = 0; slen = (pe-ps); if (slen && (ps>str)) memmove(str, ps, slen); else if (!slen) *str = 0; } } return str; } char * xmlGetString(void *id) { struct _xml_id *xid = (struct _xml_id *)id; char *str = 0; if (xid && xid->len) { str = malloc(xid->len+1); if (str) { char *ps, *pe, *pend; int slen; slen = xid->len; memcpy(str, xid->start, slen); ps = str; pend = ps+slen; pe = pend-1; *pend = 0; while ((psps) && isspace(*pe)) pe--; if (pestr) && slen) memmove(str, ps, slen+1); else if (!slen) *str = 0; } } return str; } unsigned int xmlCopyString(void *id, const char *path, char *buffer, unsigned int buflen) { struct _xml_id *xid = (struct _xml_id *)id; unsigned int rlen = 0; if (xid && xid->len && path && buffer && buflen) { char *str; *buffer = 0; rlen = strlen(path); str = __xmlGetNode(xid->start, xid->len, path, &rlen); if (str) { char *ps, *pe; ps = str; pe = ps+rlen-1; while ((psps) && isspace(*pe)) pe--; rlen = (pe-ps)+1; if (rlen >= buflen) rlen = buflen-1; memcpy(buffer, ps, rlen); str = buffer + rlen; *str = 0; } } return rlen; } long int xmlGetNodeInt(void *id, const char *path) { struct _xml_id *xid = (struct _xml_id *)id; long int li = 0; if (path && xid && xid->len) { unsigned int rlen; char *str; rlen = strlen(path); str = __xmlGetNode(xid->start, xid->len, path, &rlen); if (str) li = strtol(str, (char **)NULL, 10); } return li; } long int xmlGetInt(void *id) { struct _xml_id *xid = (struct _xml_id *)id; long int li = 0; if (xid && xid->len) li = strtol(xid->start, (char **)NULL, 10); return li; } double xmlGetNodeDouble(void *id, const char *path) { struct _xml_id *xid = (struct _xml_id *)id; double d = 0.0; if (path && xid && xid->len) { unsigned int rlen; char *str; rlen = strlen(path); str = __xmlGetNode(xid->start, xid->len, path, &rlen); if (str) d = strtod(str, (char **)NULL); } return d; } double xmlGetDouble(void *id) { struct _xml_id *xid = (struct _xml_id *)id; double d = 0.0; if (xid && xid->len) d = strtod(xid->start, (char **)NULL); return d; } unsigned int xmlGetNumElements(void *id, const char *path) { struct _xml_id *xid = (struct _xml_id *)id; unsigned ret = 0; if (xid && xid->len && path) { unsigned int clen; char *p, *pathname; char *nname; pathname = (char *)path; if (*path == '/') pathname++; nname = strrchr(pathname, '/'); if (nname) { clen = nname-pathname; p = __xmlGetNode(xid->start, xid->len, pathname, &clen); } else { nname = (char *)pathname; p = (char *)xid->start; clen = xid->len; } do { unsigned int slen = strlen(nname); p = __xmlGetNode(p, clen, nname, &slen); if (p) ret++; } while (p); } return ret; } void * xmlMarkId(void *id) { struct _xml_id *xmid = 0; if (id) { xmid = malloc(sizeof(struct _xml_id)); if (xmid) { memcpy(xmid, id, sizeof(struct _xml_id)); xmid->fd = 0; } } return (void *)xmid; } /* -------------------------------------------------------------------------- */ char * __xmlCopyNode(char *start, size_t len, const char *path) { char *p, *ret = 0; size_t rlen; rlen = strlen(path); p = __xmlGetNode(start, len, path, &rlen); if (p && rlen) { ret = calloc(1, rlen+1); memcpy(ret, p, rlen); } return ret; } char * __xmlGetNode(char *start, size_t len, const char *path, size_t *rlen) { char *ret = 0; if (len && rlen && *rlen) { size_t elem_len, newpath_len; char *newpath, *element; char last_node = 0; newpath_len = *rlen; element = (char *)path; if (*element == '/') { element++; /* skip the leading '/' character */ newpath_len--; } newpath = strchr(element, '/'); if (!newpath) { last_node = 1; elem_len = newpath_len; } else { elem_len = newpath++ - element; newpath_len -= (newpath - element); } if (elem_len) { char *p, *cur; size_t newlen; void *newelem; cur = p = start; do { len -= cur - p; p = memchr(cur, '<', len); if (p) { p++; if (p >= (cur+len)) return 0; len -= p - cur; cur = p; /* skip comments */ if (memcmp(cur, "!--", 3) == 0) { if (len < 6) return 0; cur += 3; len -= 3; do { p = memchr(cur, '-', len); if (p) { len -= p - cur; if ((len > 3) && (memcmp(cur, "-->", 3) == 0)) { p += 3; len -= 3; break; } cur = p+1; } else return 0; } while (p && (len > 2)); if (!p || (len < 2)) return 0; } else if (*cur == '?') { if (len < 3) return 0; cur++; len--; p = memchr(cur, '?', len); if (!p || *(p+1) != '>') return 0; p += 2; len -= (p - cur); } else { newlen = elem_len; newelem = element; cur = __xml_memncasecmp(p, len, &newelem, &newlen); if (cur) { break; } cur = p + elem_len; } } } while (p); if (cur && p) { len -= elem_len; p = cur; while ((*cur++ != '>') && (cur<(p+len))); len -= cur - p; if (last_node) { char *rptr = cur; do { if ((p = __xml_memmem(cur, len, "') break; } } while (p); if (p) { *rlen = p-rptr; ret = rptr; } } else { *rlen = newpath_len; ret = __xmlGetNode(cur, len, newpath, rlen); } } } } return ret; } #define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf ) void * __xml_memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { void *rptr = 0; if (haystack && needle && (needlelen > 0) && (haystacklen >= needlelen)) { char *ns, *hs, *ptr; hs = (char *)haystack; ns = (char *)needle; do { ptr = memchr(hs, *ns, haystacklen); if (ptr) { haystacklen -= (ptr - hs); if (haystacklen < needlelen) break; if (memcmp(ptr, needle, needlelen) == 0) { rptr = ptr; break; } hs = ptr+1; } else break; } while (haystacklen > needlelen); } return rptr; } void * __xml_memncasecmp(void *haystack, size_t haystacklen, void **needle, size_t *needlelen) { void *rptr = 0; if (haystack && needle && needlelen && (*needlelen > 0) && (haystacklen >= *needlelen)) { char *ns, *hs; size_t i; ns = (char *)*needle; hs = (char *)haystack; /* search for everything */ if ((*ns == '*') && (*needlelen == 1)) { char *he = hs + haystacklen; while ((hs < he) && (*hs != ' ') && (*hs != '>')) hs++; *needle = (void *)haystack; *needlelen = hs - (char *)haystack; rptr = hs; } else { size_t nlen = *needlelen; for (i=0; im = m; un->p = p; } return p; } void simple_unmmap(SIMPLE_UNMMAP *un) { UnmapViewOfFile(un->p); CloseHandle(un->m); } #endif