+16-04-2008
+ * Rename xmlGetNode functions to xmlNodeGet for better consistancy
+ * likewise for xmlCopyNode en xmlCompareNode
+ * add xmlAttributeGetDouble, xmlAttributeGetInt, xmlAttributeGetString
+ xmlAttributeCopyString and xmlAttributeCompareString functions
+ * fix some small bugs and problems along the way
+ * add support for filtering on attribute value in xmlgrep
+
21-07-2008
* change a number of function parameters to const where appropriate
* fix a problem where the wrong node-name length was returned
for a particular node. this is required for cases where a node with a
particular name is located deeper in a node with the same name;
for example -r /configuration/device/reference/device would fail in the
- previous version
+ previous verion
* rename xmlGetElement to xmlGetNodeNum and add the possibility to request
the nth node with this name
* rename xmlGetNumElements to xmlGetNumNodes
06-07-2008
* reorganize the code to be able to skip comment sections
* depreciate __xmlFindNextElement and use __xmlGetNode instead
- * xmlGetNextElement now returns char* instead of void* for future use
+ * xmlGetNextElement now returns char* instead of void* for furute use
* add preliminary support for wildcards in the search path ('*' and '?')
01-07-2008
To achieve these goals the mmap function is used to map the configuration file
to a memory region. The only places where memory is allocated is when creating
-a new XML-id, when requesting a string from a node, when requesting the node
+a new XML-id, when requesting a string from a node, when requestiong the node
name or when a request is made to copy a node into a new memory region.
Using this library should be pretty simple for most tasks; just open a file,
void *xid;
xid = xmlOpen("/tmp/file.xml");
- xpos = xmlGetNodeDouble(xid, "/configuration/x-pos");
- ypos = xmlGetNodeDouble(xid, "/configuration/y-pos");
- zpos = xmlGetNodeDouble(xid, "/configuration/z-pos");
+ xpos = xmlNodeGetDouble(xid, "/configuration/x-pos");
+ ypos = xmlNodeGetDouble(xid, "/configuration/y-pos");
+ zpos = xmlNodeGetDouble(xid, "/configuration/z-pos");
xmlClose(xid);
}
While it is certainly possible to access every node directly by calling the
-xmlGetNode(Int/Double/String) functions, when more than one node need to be
+xmlNodeGet(Int/Double/String) functions, when more than one node need to be
gathered from a parent node it is advised to get the id of the parent node
and work from there since the XML-id holds the boundaries of the (parent)node
which limits the searching area resulting in improved searching speed.
void *xnid;
char *s;
- xnid = xmlGetNode(id, "/configuration/setup/");
- version = xmlGetNodeDouble(xnid, "version");
- s = xmlGetNodeString(xnid, "author");
+ xnid = xmlNodeGet(id, "/configuration/setup/");
+ version = xmlNodeGetDouble(xnid, "version");
+ s = xmlNodeGetString(xnid, "author");
if (s) author = s;
free(s);
free(xnid);
#
# Get the Id of a node at the specified path
# e.g.
-# xnid = xmlGetNode(id, "/path/to/specified/node");
+# xnid = xmlNodeGet(id, "/path/to/specified/node");
#
-void *xmlGetNode(const void *, const char *);
-void *xmlCopyNode(void *, const char *);
+void *xmlNodeGet(const void *, const char *);
+void *xmlNodeCopy(void *, const char *);
#
# Functions to walk the node tree and process them one by one.
# e.g.
# xmid = xmlMarkId(id);
-# num = xmlGetNumNodes(xmid);
+# num = xmlNodeGetNum(xmid);
# for (i=0; i<num; i++) {
-# if (xmlGetNodeNum(id, xmid, "element", i) != 0) {
+# if (xmlNodeGetPos(id, xmid, "element", i) != 0) {
# if ((s = xmlGetString(xmid)) != 0) {
# printf("%s\n", s);
# free(s);
# free(xmid);
#
void *xmlMarkId(void *);
-unsigned int xmlGetNumNodes(void *, const char *);
-void *xmlGetNodeNum(const void *, void *, const char *, int);
+unsigned int xmlNodeGetNum(void *, const char *);
+void *xmlNodeGetPos(const void *, void *, const char *, int);
#
# Get the name of the current node
#
-char *xmlGetNodeName(void *);
-size_t xmlCopyNodeName(void *, const char *, size_t);
+char *xmlNodeGetName(void *);
+size_t xmlNodeCopyName(void *, const char *, size_t);
#
# These functions work on the current node.
# e.g.
-# xnid = xmlGetNode(id, "/path/to/last/node");
+# xnid = xmlNodeGet(id, "/path/to/last/node");
# i = xmlGetInt(xnid);
# or
-# xnid = xmlGetNode(id, "/path/to/specified/node");
+# xnid = xmlNodeGet(id, "/path/to/specified/node");
# if (xmlCompareString(xnid, "value") == 0) printf("We have a match!\n");
#
long int xmlGetInt(void *);
#
# These functions work on a specified node path
# e.g.
-# d = xmlGetNodeDouble(id, "/path/to/node");
+# d = xmlNodeGetDouble(id, "/path/to/node");
# or
-# xnid = xmlGetNode(id, "/path/to");
-# i = xmlGetNodeInt(xnid, "node");
+# xnid = xmlNodeGet(id, "/path/to");
+# i = xmlNodeGetInt(xnid, "node");
#
-long int xmlGetNodeInt(void *, const char *);
-double xmlGetNodeDouble(void *, const char *);
-char *xmlGetNodeString(void *, const char *);
-size_t xmlCopyNodeString(void *, const char *, char *, const size_t);
-int xmlCompareNodeString(const void *, const char *, const char *);
+long int xmlNodeGetInt(void *, const char *);
+double xmlNodeGetDouble(void *, const char *);
+char *xmlNodeGetString(void *, const char *);
+size_t xmlNodeCopyString(void *, const char *, char *, const size_t);
+int xmlNodeCompareString(const void *, const char *, const char *);
+
+#
+# These functions work on a specified atribute
+# e.g.
+# i = xmlAttributeGetInt(id, "n");
+#
+# or
+# s = xmlNodeGetString(id, "type");
+# if (s) printf("node is of type '%s'\n", s);
+# free(s);
+#
+long int xmlAttributeGetInt(const void *, const char *);
+double xmlAttributeGetDouble(const void *, const char *);
+char *xmlAttributeGetString(const void *, const char *);
+size_t xmlAttributeCopyString(const void *, const char *, const char *, size_t);
+int xmlAttributeCompareString(const void *, const char *, const char *);
/*
* map 'filename' and return a pointer to it.
*/
-void *simple_mmap(int, unsigned int, SIMPLE_UNMMAP *);
-void simple_unmmap(SIMPLE_UNMMAP *);
+static void *simple_mmap(int, size_t, SIMPLE_UNMMAP *);
+static 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)
#include <ctype.h>
#include <string.h>
#include <strings.h> /* strncasecmp */
+#ifndef NDEBUG
#include <stdio.h>
-#include <stdlib.h>
+#endif
struct _xml_id
{
- char *name;
- char *start;
size_t len;
+ char *start;
+ char *name;
union {
+ size_t name_len;
int fd;
- size_t len;
} node;
};
-static char *__xmlCopyNode(const char *, size_t, const char *);
-static char *__xmlGetNodePath(const char *, size_t *, char **, size_t *);
-static char *__xmlGetNode(const char *, size_t *, char **, size_t *, size_t *);
-static char *__xmlSkipComment(const char *, size_t);
-static char *__xmlSkipInfo(const char *, size_t);
+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 *__xmlCommentSkip(const char *, size_t);
+static char *__xmlInfoSkip(const char *, size_t);
-static void *__xml_memmem(const char *, size_t, const char *, size_t);
static void *__xml_memncasecmp(const char *, size_t *, char **, size_t *);
#define PRINT(a, b, c) { \
}
void *
-xmlGetNode(const void *id, const char *path)
+xmlNodeGet(const void *id, const char *path)
{
struct _xml_id *xsid = 0;
node = (char *)path;
len = xid->len;
slen = strlen(path);
- ptr = __xmlGetNodePath(xid->start, &len, &node, &slen);
+ ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
if (ptr)
{
xsid = malloc(sizeof(struct _xml_id));
{
xsid->len = len;
xsid->start = ptr;
- xsid->node.len = slen;
+ xsid->node.name_len = slen;
xsid->name = node;
}
}
}
void *
-xmlCopyNode(const void *id, const char *path)
+xmlNodeCopy(const void *id, const char *path)
{
struct _xml_id *xsid = 0;
node = (char *)path;
len = xid->len;
slen = strlen(path);
- ptr = __xmlGetNodePath(xid->start, &len, &node, &slen);
+ ptr = __xmlNodeGetPath(xid->start, &len, &node, &slen);
if (ptr)
{
xsid = malloc(sizeof(struct _xml_id) + len);
xsid->len = len;
xsid->start = p;
- xsid->node.len = slen;
+ xsid->node.name_len = slen;
xsid->name = node;
memcpy(xsid->start, ptr, len);
}
char *
-xmlGetNodeName(const void *id)
+xmlNodeGetName(const void *id)
{
struct _xml_id *xid = (struct _xml_id *)id;
size_t len;
char *ret;
- len = xid->node.len;
+ len = xid->node.name_len;
ret = malloc(len+1);
if (ret)
{
}
size_t
-xmlCopyNodeName(const void *id, char *buf, size_t len)
+xmlNodeCopyName(const void *id, char *buf, size_t len)
{
struct _xml_id *xid = (struct _xml_id *)id;
size_t slen = 0;
if (buf)
{
slen = len-1;
- if (slen > xid->node.len) slen = xid->node.len;
+ if (slen > xid->node.name_len) slen = xid->node.name_len;
memcpy(buf, xid->name, slen);
*(buf + slen) = 0;
}
}
unsigned int
-xmlGetNumNodes(const void *id, const char *path)
+xmlNodeGetNum(const void *id, const char *path)
{
struct _xml_id *xid = (struct _xml_id *)id;
size_t num = 0;
pathname++;
slen -= pathname-nodename;
node = pathname;
- p = __xmlGetNodePath(xid->start, &len, &node, &slen);
+ p = __xmlNodeGetPath(xid->start, &len, &node, &slen);
}
else
{
if (p)
{
char *node = nodename;
- __xmlGetNode(p, &len, &node, &slen, &num);
+ __xmlNodeGet(p, &len, &node, &slen, &num);
}
}
}
void *
-xmlGetNodeNum(const void *pid, void *id, const char *element, size_t num)
+xmlNodeGetPos(const void *pid, void *id, const char *element, size_t num)
{
void *ret = 0;
len = xpid->len;
slen = strlen(element);
node = (char *)element;
- ptr = __xmlGetNode(xpid->start, &len, &node, &slen, &num);
+ ptr = __xmlNodeGet(xpid->start, &len, &node, &slen, &num);
if (ptr)
{
xid->len = len;
xid->start = ptr;
xid->name = node;
- xid->node.len = slen;
+ xid->node.name_len = slen;
ret = xid;
}
}
}
size_t
-xmlCopyString(const void *id, char *buf, size_t len)
+xmlCopyString(const void *id, char *buffer, size_t buflen)
{
struct _xml_id *xid = (struct _xml_id *)id;
- size_t nlen = 0;
+ size_t ret = 0;
- if (xid && xid->len && buf && len)
+ if (xid && xid->len && buffer && buflen)
{
char *ps, *pe, *pend;
- int slen;
+ size_t slen, nlen;
- nlen = len-1;
+ *buffer = '\0';
+ nlen = buflen-1;
ps = xid->start;
slen = xid->len;
pend = ps+slen;
if (nlen)
{
- memcpy(buf, ps, nlen);
- *(buf+nlen) = 0;
+ if (nlen >= buflen) nlen = buflen-1;
+ memcpy(buffer, ps, nlen);
+ *(buffer+nlen) = 0;
+ ret = nlen;
}
}
- return nlen;
+ return ret;
}
int
}
char *
-xmlGetNodeString(const void *id, const char *path)
+xmlNodeGetString(const 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);
+ str = __xmlNodeCopy(xid->start, xid->len, path);
if (str)
{
char *ps, *pe, *pend;
}
size_t
-xmlCopyNodeString(const void *id, const char *path, char *buffer, size_t buflen)
+xmlNodeCopyString(const void *id, const char *path, char *buffer, size_t buflen)
{
struct _xml_id *xid = (struct _xml_id *)id;
- size_t len = 0;
+ size_t ret = 0;
if (xid && xid->len && path && buffer && buflen)
{
char *str, *node;
- size_t slen;
+ size_t slen, nlen;
*buffer = '\0';
- len = xid->len;
+ nlen = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlGetNodePath(xid->start, &len, &node, &slen);
+ str = __xmlNodeGetPath(xid->start, &nlen, &node, &slen);
if (str)
{
char *ps, *pe;
ps = str;
- pe = ps+len-1;
+ pe = ps+nlen-1;
while ((ps<pe) && isspace(*ps)) ps++;
while ((pe>ps) && isspace(*pe)) pe--;
- len = (pe-ps)+1;
- if (len >= buflen) len = buflen-1;
+ nlen = (pe-ps)+1;
+ if (nlen >= buflen) nlen = buflen-1;
- memcpy(buffer, ps, len);
- str = buffer + len;
- *str = '\0';
+ memcpy(buffer, ps, nlen);
+ *(buffer + nlen) = '\0';
+ ret = nlen;
}
}
- return len;
+ return ret;
}
int
-xmlCompareNodeString(const void *id, const char *path, const char *s)
+xmlNodeCompareString(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 *node, *str, *ps, *pe;
- size_t len, slen, i;
+ size_t len, slen;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlGetNodePath(xid->start, &len, &node, &slen);
+ str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
if (str)
{
ps = str;
}
long int
-xmlGetNodeInt(const void *id, const char *path)
+xmlNodeGetInt(const void *id, const char *path)
{
struct _xml_id *xid = (struct _xml_id *)id;
long int li = 0;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlGetNodePath(xid->start, &len, &node, &slen);
+ str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
if (str)
{
char *end = str+len;
}
double
-xmlGetNodeDouble(const void *id, const char *path)
+xmlNodeGetDouble(const void *id, const char *path)
{
struct _xml_id *xid = (struct _xml_id *)id;
double d = 0.0;
len = xid->len;
slen = strlen(path);
node = (char *)path;
- str = __xmlGetNodePath(xid->start, &len, &node, &slen);
+ str = __xmlNodeGetPath(xid->start, &len, &node, &slen);
if (str)
{
char *end = str+len;
return (void *)xmid;
}
+double
+xmlAttributeGetDouble(const void *id, const char *name)
+{
+ struct _xml_id *xid = (struct _xml_id *)id;
+ double ret = 0.0;
+
+ if (xid && xid->start && xid->len && xid->node.name_len)
+ {
+ char *p, *end, *new = 0;
+
+ assert(xid->start > xid->name);
+
+ p = xid->name + xid->node.name_len;
+ end = xid->start-1;
+
+ while ((p<end) && isspace(*p)) p++;
+ while (p<end)
+ {
+ size_t elementlen = strlen(name);
+ size_t restlen = end-p;
+ char *element = (char *)name;
+
+ new = __xml_memncasecmp(p, &restlen, &element, &elementlen);
+ if (new)
+ {
+ restlen = end-p;
+ new = memchr(p, '=', restlen);
+ if (new)
+ {
+ new++;
+ if (*new == '"') new++;
+ restlen -= (new-p);
+ end = new+restlen;
+ ret = strtod(new, &end);
+ }
+ break;
+ }
+
+ while ((p<end) && !isspace(*p)) p++;
+ if (p<end)
+ while ((p<end) && isspace(*p)) p++;
+ }
+ }
+
+ return ret;
+}
+
+long int
+xmlAttributeGetInt(const void *id, const char *name)
+{
+ struct _xml_id *xid = (struct _xml_id *)id;
+ long int ret = 0;
+
+ if (xid && xid->start && xid->len && xid->node.name_len)
+ {
+ char *p, *end, *new = 0;
+
+ assert(xid->start > xid->name);
+
+ p = xid->name + xid->node.name_len;
+ end = xid->start-1;
+
+ while ((p<end) && isspace(*p)) p++;
+ while (p<end)
+ {
+ size_t elementlen = strlen(name);
+ size_t restlen = end-p;
+ char *element = (char *)name;
+
+ new = __xml_memncasecmp(p, &restlen, &element, &elementlen);
+ if (new)
+ {
+ restlen = end-p;
+ new = memchr(p, '=', restlen);
+ if (new)
+ {
+ new++;
+ if (*new == '"') new++;
+ restlen -= (new-p);
+ end = new+restlen;
+ ret = strtol(new, &end, 10);
+ }
+ break;
+ }
+
+ while ((p<end) && !isspace(*p)) p++;
+ if (p<end)
+ while ((p<end) && isspace(*p)) p++;
+ }
+ }
+
+ return ret;
+}
+
+char *
+xmlAttributeGetString(const void *id, const char *name)
+{
+ struct _xml_id *xid = (struct _xml_id *)id;
+ char *ret = 0;
+
+ if (xid && xid->start && xid->len && xid->node.name_len)
+ {
+ char *p, *end, *new = 0;
+
+ assert(xid->start > xid->name);
+
+ p = xid->name + xid->node.name_len;
+ end = xid->start-1;
+
+ while ((p<end) && isspace(*p)) p++;
+ while (p<end)
+ {
+ size_t elementlen = strlen(name);
+ size_t restlen = end-p;
+ char *element = (char *)name;
+
+ new = __xml_memncasecmp(p, &restlen, &element, &elementlen);
+ if (new)
+ {
+ restlen = end-p;
+ new = memchr(p, '=', restlen);
+ if (new)
+ {
+ new++;
+ if (*new == '"') new++;
+ p = new;
+ while ((p<end) && (*p != '"') && (*p != ' ')) p++;
+ if (p<end)
+ {
+ ret = calloc(1, p-new);
+ memcpy(ret, new, (p-new));
+ }
+ }
+ break;
+ }
+
+ while ((p<end) && !isspace(*p)) p++;
+ if (p<end)
+ while ((p<end) && isspace(*p)) p++;
+ }
+ }
+
+ return ret;
+}
+
+size_t
+xmlAttributeCopyString(const void *id, const char *name,
+ char *buffer, size_t buflen)
+{
+ struct _xml_id *xid = (struct _xml_id *)id;
+ size_t ret = 0;
+
+ if (xid && xid->start && xid->len && xid->node.name_len
+ && buffer && buflen)
+ {
+ char *ps, *pe;
+
+ *buffer = '\0';
+ ps = xid->name + xid->node.name_len + 1;
+ pe = xid->start - 1;
+
+ assert((int)(pe-ps) > 0);
+
+ while ((ps<pe) && isspace(*ps)) ps++;
+ while (ps<pe)
+ {
+ size_t slen = strlen(name);
+ size_t restlen = pe-ps;
+
+ if ((restlen >= slen) && (strncasecmp(ps, name, slen) == 0))
+ {
+ char *new;
+
+ restlen = pe-ps;
+ new = memchr(ps, '=', restlen);
+ if (new)
+ {
+ new++;
+ if (*new == '"') new++;
+ ps = new;
+ while ((ps<pe) && (*ps != '"') && (*ps != ' ')) ps++;
+ if (ps<pe)
+ {
+ restlen = ps-new;
+ if (restlen >= buflen) restlen = buflen-1;
+ memcpy(buffer, new, restlen);
+ *(buffer+restlen) = 0;
+ ret = restlen;
+ }
+ }
+ break;
+ }
+
+ while ((ps<pe) && !isspace(*ps)) ps++;
+ if (ps<pe)
+ while ((ps<pe) && isspace(*ps)) ps++;
+ }
+ }
+
+ return ret;
+}
+
+int
+xmlAttributeCompareString(const void *id, const char *name, const char *s)
+{
+ struct _xml_id *xid = (struct _xml_id *)id;
+ int ret = -1;
+
+ if (xid && xid->start && xid->len && xid->node.name_len
+ && s && strlen(s))
+ {
+ char *ps, *pe;
+
+ ps = xid->name + xid->node.name_len + 1;
+ pe = xid->start - 1;
+
+ assert((int)(pe-ps) > 0);
+
+ while ((ps<pe) && isspace(*ps)) ps++;
+ while (ps<pe)
+ {
+ size_t slen = strlen(name);
+ size_t restlen = pe-ps;
+
+ if ((restlen >= slen) && (strncasecmp(ps, name, slen) == 0))
+ {
+ char *new;
+
+ restlen = pe-ps;
+ new = memchr(ps, '=', restlen);
+ if (new)
+ {
+ new++;
+ if (*new == '"') new++;
+ ps = new;
+ while ((ps<pe) && (*ps != '"') && (*ps != ' ')) ps++;
+ if (ps<pe)
+ {
+ int alen = ps-new;
+ ret = strncasecmp(new, s, alen);
+ }
+ }
+ break;
+ }
+
+ while ((ps<pe) && !isspace(*ps)) ps++;
+ if (ps<pe)
+ while ((ps<pe) && isspace(*ps)) ps++;
+ }
+ }
+
+ return ret;
+}
+
+
/* -------------------------------------------------------------------------- */
static char *
-__xmlCopyNode(const char *start, size_t len, const char *path)
+__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 = __xmlGetNodePath(start, &rlen, &node, &slen);
+ p = __xmlNodeGetPath(start, &rlen, &node, &slen);
if (p && rlen)
{
ret = calloc(1, rlen+1);
}
char *
-__xmlGetNodePath(const char *start, size_t *len, char **name, size_t *plen)
+__xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen)
{
char *node;
char *ret = 0;
else plen = path++ - node;
num = 0;
- ret = __xmlGetNode(start, len, &node, &plen, &num);
+ ret = __xmlNodeGet(start, len, &node, &plen, &num);
if (ret && path)
{
plen = slen - (path - *name);
- ret = __xmlGetNodePath(ret, len, &path, &plen);
+ ret = __xmlNodeGetPath(ret, len, &path, &plen);
}
*name = path;
}
char *
-__xmlGetNode(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
+__xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *nodenum)
{
char *new, *cur, *ne, *ret = 0;
+ char *element, *start_tag=0;
size_t restlen, elementlen;
size_t retlen = 0;
int found, num;
- char *element;
assert (start != 0);
assert (len != 0);
if (*cur == '!')
{
- new = __xmlSkipComment(cur, restlen);
+ new = __xmlCommentSkip(cur, restlen);
if (!new) return 0;
restlen -= new-cur;
cur = new;
}
else if (*cur == '?')
{
- new = __xmlSkipInfo(cur, restlen);
+ new = __xmlInfoSkip(cur, restlen);
if (!new) return 0;
restlen -= new-cur;
if (new)
{
retlen = elementlen;
- if (found == num ) ret = new+1;
+ if (found == num )
+ {
+ ret = new+1;
+ start_tag = element;
+ }
+ else start_tag = 0;
}
else
{
size_t nlen = 1;
size_t pos = -1;
- new = __xmlGetNode(cur, &slen, &node, &nlen, &pos);
+ new = __xmlNodeGet(cur, &slen, &node, &nlen, &pos);
if (!new)
{
if (slen == restlen) return 0;
{
if (!strncasecmp(new+2, element, elementlen))
{
- if (found == num) *len = new-ret;
- *name = element;
+ if (found == num)
+ {
+ assert(start_tag != 0);
+ *len = new-ret;
+ *name = start_tag;
+ }
found++;
}
}
char *
-__xmlSkipComment(const char *start, size_t len)
+__xmlCommentSkip(const char *start, size_t len)
{
char *cur, *new;
}
char *
-__xmlSkipInfo(const char *start, size_t len)
+__xmlInfoSkip(const char *start, size_t len)
{
char *cur, *new;
}
-void *
-__xml_memmem(const char *haystack, size_t haystacklen,
- const char *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;
-}
-
-
#define NOCASECMP(a,b) ( ((a)^(b)) & 0xdf )
void *
__xml_memncasecmp(const char *haystack, size_t *haystacklen,
*/
void *
-simple_mmap(int fd, unsigned int length, SIMPLE_UNMMAP *un)
+simple_mmap(int fd, size_t length, SIMPLE_UNMMAP *un)
{
HANDLE f;
HANDLE m;
return NULL;
}
- if (n) *n = GetFileSize(f, NULL);
-
if (un)
{
un->m = m;
#define __XML_CONFIG 1
/**
- * Open an XML file for processing
+ * Open an XML file for processing.
*
* @param fname path to the file
* @return XML-id which is used for further processing
void *xmlOpen(const char *);
/**
- * Close the XML file after which no further processing is possible
+ * Close the XML file after which no further processing is possible.
*
* @param xid XML-id
*/
/**
* Locate a subsection of the xml tree for further processing.
* This adds processing speed since the reuired nodes will only be searched
- * in the subsection
+ * in the subsection.
*
* The memory allocated for the XML-subsection-id has to be freed by the
- * calling process
+ * calling process.
*
* @param xid XML-id
* @param node path to the node containing the subsection
* @return XML-subsection-id for further processing
*/
-void *xmlGetNode(const void *, const char *);
+void *xmlNodeGet(const void *, const char *);
/**
* Copy a subsection of the xml tree for further processing.
* This is useful when it's required to process a section of the XML code
* after the file has been closed. The drawback is the added memory
- * requirements
+ * requirements.
*
* The memory allocated for the XML-subsection-id has to be freed by the
* calling process.
* @param node path to the node containing the subsection
* @return XML-subsection-id for further processing
*/
-void *xmlCopyNode(const void *, const char *);
+void *xmlNodeCopy(const void *, const char *);
/**
* Return the name of this node.
- * The returned string has to be freed by the calling process
+ * The returned string has to be freed by the calling process.
*
* @param xid XML-id
* @return a newly alocated string containing the node name
*/
-char *xmlGetNodeName(const void *);
+char *xmlNodeGetName(const void *);
/**
- * Copy the name of this node in a pre-allocated buffer
+ * Copy the name of this node in a pre-allocated buffer.
*
* @param xid XML-id
* @param buffer the buffer to copy the string to
* @param buflen length of the destination buffer
* @return the length of the node name
*/
-size_t xmlCopyNodeName(const void *, char *, size_t);
+size_t xmlNodeCopyName(const void *, char *, size_t);
+
+/**
+ * Create a marker XML-id that starts out with the same settings as the
+ * refference XML-id.
+ *
+ * Marker id's are required when xmlNodeGetNum() and xmlNodeGetPos() are used
+ * to walk a number of nodes. The xmlNodeGetPos function adjusts the contents
+ * of the provided XML-id to keep track of it's position within the xml section.
+ * The returned XML-id is limited to the boundaries of the requested XML tag
+ * and has to be freed by the calling process.
+ *
+ * @param xid reference XML-id
+ * @return a copy of the reference XML-id
+ */
+void *xmlMarkId(const void *);
/**
- * Get the number of nodes with the same name from a specified xml path
+ * Get the number of nodes with the same name from a specified xml path.
*
* @param xid XML-id
* @param path path to the xml node
* @return the number count of the nodename
*/
-unsigned int xmlGetNumNodes(const void *, const char *);
+unsigned int xmlNodeGetNum(const void *, const char *);
/**
* Get the nth occurrence of node in the parent node.
- * The return value should neevr be altered or freed by the caller
+ * The return value should never be altered or freed by the caller.
*
* @param pid XML-id of the parent node of this node
* @param xid XML-id
* @param num specify which occurence to return
* @return XML-subsection-id for further processing or NULL if unsuccessful
*/
-void *xmlGetNodeNum(const void *, void *, const char *, int);
+void *xmlNodeGetPos(const void *, void *, const char *, int);
/**
* Get a string of characters from the current node.
- * The returned string has to be freed by the calling process
+ * The returned string has to be freed by the calling process.
*
* @param xid XML-id
* @return a newly alocated string containing the contents of the node
* Get a string of characters from the current node.
* This function has the advantage of not allocating its own return buffer,
* keeping the memory management to an absolute minimum but the disadvantage
- * is that it's unreliable in multithread environments
+ * is that it's unreliable in multithread environments.
*
* @param xid XML-id
* @param buffer the buffer to copy the string to
/**
* Compare the value of this node to a reference string.
- * Comparing is done in a case insensitive way
+ * Comparing is done in a case insensitive way.
*
* @param xid XML-id
* @param str the string to compare to
/**
* Get a string of characters from a specified xml path.
- * The returned string has to be freed by the calling process
+ * The returned string has to be freed by the calling process.
*
* @param xid XML-id
* @param path path to the xml node
* @return a newly alocated string containing the contents of the node
*/
-char *xmlGetNodeString(const void *, const char *);
+char *xmlNodeGetString(const void *, const char *);
/**
* Get a string of characters from a specified xml path.
* This function has the advantage of not allocating its own return buffer,
* keeping the memory management to an absolute minimum but the disadvantage
- * is that it's unreliable in multithread environments
+ * is that it's unreliable in multithread environments.
*
* @param xid XML-id
* @param path path to the xml node
* @param buflen length of the destination buffer
* @return the length of the string
*/
-size_t xmlCopyNodeString(const void *, const char *, char *, size_t);
+size_t xmlNodeCopyString(const void *, const char *, char *, size_t);
/**
* Compare the value of a node to a reference string.
- * Comparing is done in a case insensitive way
+ * Comparing is done in a case insensitive way.
*
* @param xid XML-id
* @param path path to the xml node to compare to
* of the node is found, respectively, to be less than, to match, or be greater
* than str
*/
-int xmlCompareNodeString(const void *, const char *, const char *);
+int xmlNodeCompareString(const void *, const char *, const char *);
+/**
+ * Get a string of characters from a named attribute.
+ * The returned string has to be freed by the calling process.
+ *
+ * @param xid XML-id
+ * @param name name of the attribute to acquire
+ * @return the contents of the node converted to an integer value
+ */
+char *xmlAttributeGetString(const void *, const char *);
/**
- * Get the integer value from the current node
+ * Get a string of characters from a named attribute.
+ * This function has the advantage of not allocating its own return buffer,
+ * keeping the memory management to an absolute minimum but the disadvantage
+ * is that it's unreliable in multithread environments.
+ *
+ * @param xid XML-id
+ * @param name name of the attribute to acquire.
+ * @param buffer the buffer to copy the string to
+ * @param buflen length of the destination buffer
+ * @return the length of the string
+size_t xmlAttributeCopyString(const void *, const char *, const char *, size_t);
+
+/**
+ * Compare the value of an attribute to a reference string.
+ * Comparing is done in a case insensitive way.
+ *
+ * @param xid XML-id
+ * @param name name of the attribute to acquire.
+ * @param str the string to compare to
+ * @return an integer less than, equal to, ro greater than zero if the value
+ * of the node is found, respectively, to be less than, to match, or be greater
+ * than str
+int xmlAttributeCompareString(const void *, const char *, const char *);
+
+
+/**
+ * Get the integer value from the current node/
*
* @param xid XML-id
* @return the contents of the node converted to an integer value
long int xmlGetInt(const void *);
/**
- * Get an integer value from a specified xml path
+ * Get an integer value from a specified xml path.
*
* @param xid XML-id
* @param path path to the xml node
* @return the contents of the node converted to an integer value
*/
-long int xmlGetNodeInt(const void *, const char *);
+long int xmlNodeGetInt(const void *, const char *);
+
+/**
+ * Get the integer value from the named attribute.
+ *
+ * @param xid XML-id
+ * @param name name of the attribute to acquire
+ * @return the contents of the node converted to an integer value
+ */
+long int xmlAttributeGetInt(const void *, const char *);
/**
- * Get the double value from the curent node
+ * Get the double value from the curent node/
*
* @param xid XML-id
* @return the contents of the node converted to a double value
double xmlGetDouble(const void *);
/**
- * Get a double value from a specified xml path
+ * Get a double value from a specified xml path/
*
* @param xid XML-id
* @param path path to the xml node
* @return the contents of the node converted to a double value
*/
-double xmlGetNodeDouble(const void *, const char *);
+double xmlNodeGetDouble(const void *, const char *);
/**
- * Create a marker XML-id that starts out with the same settings as the
- * refference XML-id.
- * The returned XML-id has to be freed by the calling process
+ * Get the double value from the named attribute.
*
- * @param xid reference XML-id
- * @return a copy of the reference XML-id
+ * @param xid XML-id
+ * @param name name of the attribute to acquire
+ * @return the contents of the node converted to an integer value
*/
-void *xmlMarkId(const void *);
+double xmlAttributeGetDouble(const void *, const char *);
#endif /* __XML_CONFIG */
#include <stdio.h>
-#include <strings.h>
-#include <stdlib.h>
+
+#define _GNU_SOURCE
#include <string.h>
+#include <strings.h>
+#include <assert.h>
#include "xml.h"
static char *_value = 0;
static char *_root = 0;
static char *_print = 0;
+static char *_attribute = 0;
static int print_filenames = 0;
static void free_and_exit(int i);
printf("usage: xmlgrep [options] [file ...]\n\n");
printf("Options:\n");
printf("\t-h\t\tshow this help message\n");
+ printf("\t-a <string>\tprint this attribute as the output\n");
printf("\t-e <id>\t\tshow sections that contain this element\n");
printf("\t-p <id>\t\tprint this element as the output\n");
printf("\t-r <path>\tspecify the XML search root\n");
- printf("\t-v <string>\tshow sections where one of the elements has this ");
- printf("value\n\n");
+ printf("\t-v <string>\tfilter sections that contain this vale\n\n");
printf(" To print the contents of the 'type' element of the XML section ");
- printf("that begins\n at '/printer/output' one would use the following ");
- printf("syntax:\n\n\txmlgrep -r /printer/output -p type sample.xml\n\n");
+ printf("that begins\n at '/printer/output' use the following command:\n\n");
+ printf("\txmlgrep -r /printer/output -p type sample.xml\n\n");
+ printf(" To filter 'output' elements under '/printer' that have attribute");
+ printf(" 'n' set to '1'\n use the following command:\n\n");
+ printf("\txmlgrep -r /printer -p output -a n -v 1 sample.xml\n\n");
printf(" To filter out sections that contain the 'driver' element with ");
- printf("'generic' as\n it's value one would issue the following command:");
+ printf("'generic' as\n it's value use the following command:");
printf("\n\n\txmlgrep -r /printer/output -e driver -v generic sample.xml");
printf("\n\n");
free_and_exit(0);
}
void
-free_and_exit(int i)
+free_and_exit(int ret)
{
if (_root && _root != _static_root) free(_root);
if (_element && _element != _static_element) free(_element);
if (_value) free(_value);
if (_print) free(_print);
+ if (_attribute) free(_attribute);
if (_filenames)
{
+ unsigned int i;
for (i=0; i < _fcount; i++)
{
if (_filenames[i])
free(_filenames);
}
- exit(i);
+ exit(ret);
}
int
parse_option(char **args, int n, int max)
{
char *opt, *arg = 0;
- int sz;
+ unsigned int alen = 0;
+ unsigned int olen;
opt = args[n];
- if (opt[0] == '-' && opt[1] == '-')
+ if (strncmp(opt, "--", 2) == 0)
opt++;
if ((arg = strchr(opt, '=')) != NULL)
#endif
}
- sz = strlen(opt);
- if (strncmp(opt, "-help", sz) == 0)
+ olen = strlen(opt);
+ if (strncmp(opt, "-help", olen) == 0)
{
show_help();
}
- else if (strncmp(opt, "-root", sz) == 0)
+ else if (strncmp(opt, "-root", olen) == 0)
+ {
+ if (arg == 0) SHOW_NOVAL(opt);
+ alen = strlen(arg)+1;
+ _root = malloc(alen);
+ memcpy(_root, arg, alen);
+ return 2;
+ }
+ else if (strncmp(opt, "-element", olen) == 0)
{
if (arg == 0) SHOW_NOVAL(opt);
- _root = strdup(arg);
+ alen = strlen(arg)+1;
+ _element = malloc(alen);
+ memcpy(_element, arg, alen);
return 2;
}
- else if (strncmp(opt, "-element", sz) == 0)
+ else if (strncmp(opt, "-value", olen) == 0)
{
if (arg == 0) SHOW_NOVAL(opt);
- _element = strdup(arg);
+ alen = strlen(arg)+1;
+ _value = malloc(alen);
+ memcpy(_value, arg, alen);
return 2;
}
- else if (strncmp(opt, "-value", sz) == 0)
+ else if (strncmp(opt, "-print", olen) == 0)
{
if (arg == 0) SHOW_NOVAL(opt);
- _value = strdup(arg);
+ alen = strlen(arg)+1;
+ _print = malloc(alen);
+ memcpy(_print, arg, alen);
return 2;
}
- else if (strncmp(opt, "-print", sz) == 0)
+ else if (strncmp(opt, "-attribute", olen) == 0)
{
if (arg == 0) SHOW_NOVAL(opt);
- _print = strdup(arg);
+ alen = strlen(arg)+1;
+ _attribute = malloc(alen);
+ memcpy(_attribute, arg, alen);
return 2;
}
- else if (strncmp(opt, "-list-filenames", sz) == 0)
+ else if (strncmp(opt, "-list-filenames", olen) == 0)
{ /* undocumented test argument */
print_filenames = 1;
return 1;
_filenames = ptr;
}
- _filenames[pos] = strdup(opt);
+ alen = strlen(opt)+1;
+ _filenames[pos] = malloc(alen);
+ memcpy(_filenames[pos], opt, alen);
}
return 1;
void *xmid = xmlMarkId(xid);
if (xmid && _print)
{
- no_elements = xmlGetNumNodes(xid, _print);
+ no_elements = xmlNodeGetNum(xid, _print);
for (i=0; i<no_elements; i++)
{
- if (xmlGetNodeNum(xid, xmid, _print, i) != 0)
+ if (xmlNodeGetPos(xid, xmid, _print, i) != 0)
{
- char value[64];
+ char value[1024];
- xmlCopyString(xmid, (char *)&value, 64);
- printf("%s: <%s>%s</%s>\n",
- _filenames[num], _print, value, _print);
+ xmlCopyString(xmid, (char *)&value, 1024);
+ if (_value && _attribute)
+ {
+ if (!xmlAttributeCompareString(xmid, _attribute, _value))
+ {
+ printf("%s: <%s %s=\"%s\">%s</%s>\n",
+ _filenames[num], _print, _attribute, _value,
+ value, _print);
+ }
+ }
+ else
+ {
+ printf("%s: <%s>%s</%s>\n",
+ _filenames[num], _print, value, _print);
+ }
}
}
free(xmid);
}
else if (xmid && _value)
{
- no_elements = xmlGetNumNodes(xmid, _element);
+ no_elements = xmlNodeGetNum(xmid, _element);
for (i=0; i<no_elements; i++)
{
- if (xmlGetNodeNum(xid, xmid, _element, i) != 0)
+ if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
{
char nodename[64];
- xmlCopyNodeName(xmid, (char *)&nodename, 64);
+ xmlNodeCopyName(xmid, (char *)&nodename, 64);
if (xmlCompareString(xmid, _value) == 0)
{
printf("%s: <%s>%s</%s>\n",
{
char parentname[64];
- xmlCopyNodeName(xid, (char *)&parentname, 64);
+ xmlNodeCopyName(xid, (char *)&parentname, 64);
- no_elements = xmlGetNumNodes(xmid, _element);
+ no_elements = xmlNodeGetNum(xmid, _element);
for (i=0; i<no_elements; i++)
{
- if (xmlGetNodeNum(xid, xmid, _element, i) != 0)
+ if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
{
char nodename[64];
- xmlCopyNodeName(xmid, (char *)&nodename, 64);
+ xmlNodeCopyName(xmid, (char *)&nodename, 64);
if (strncasecmp((char *)&nodename, _element, 64) == 0)
{
char value[64];
xmid = xmlMarkId(xid);
if (xmid)
{
- if (next) *next++ = 0;
+ if (next)
+ {
+ *next++ = 0;
+ }
- no_elements = xmlGetNumNodes(xid, elem);
+ no_elements = xmlNodeGetNum(xid, elem);
for (i=0; i<no_elements; i++)
{
- if (xmlGetNodeNum(xid, xmid, elem, i) != 0)
+ if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
walk_the_tree(num, xmid, next);
}
- if (next) *--next = '/';
+ if (next)
+ {
+ *--next = '/';
+ }
free(xmid);
}
int
main (int argc, char **argv)
{
- int i;
+ unsigned int i;
if (argc == 1)
show_help();