1
0
Fork 0

* add xmlInitBuffer() for processing of a preallocated buffer

* add xmlErrorGetColumnNo to get the column number of the syntax error
  * pass an error at a higher level to lower levels
  * detect a number of extra syntax errors
This commit is contained in:
ehofman 2009-04-27 16:54:46 +00:00 committed by Tim Moore
parent 1f40ee2366
commit 228c7aaaa0
5 changed files with 165 additions and 59 deletions

View file

@ -1,3 +1,10 @@
27-04-2009
* add xmlInitBuffer() for processing of a preallocated buffer
* add xmlErrorGetColumnNo to get the column number of the syntax error
* pass an error at a higher level to lower levels
* detect a number of extra syntax errors
* fix a buffer overflow
26-04-2009 26-04-2009
* add support for comments inside xml-tags, e.g.: <test><!-- --></test> * add support for comments inside xml-tags, e.g.: <test><!-- --></test>

View file

@ -47,22 +47,23 @@ Overview of the available functions:
# id = xmlOpen("/tmp/file.xml"); # id = xmlOpen("/tmp/file.xml");
# xmlClose(id); # xmlClose(id);
# #
void *xmlOpen(const char *); void *xmlOpen(const char *filename);
void xmlClose(const void *); void *xmlInitBuffer(const char *buffer, size_t size);
void xmlClose(void *xid);
# #
# Get the Id of a node at the specified path # Get the Id of a node at the specified path
# e.g. # e.g.
# xnid = xmlNodeGet(id, "/path/to/specified/node"); # xnid = xmlNodeGet(id, "/path/to/specified/node");
# #
void *xmlNodeGet(const void *, const char *); void *xmlNodeGet(const void *xid, const char *path);
void *xmlNodeCopy(void *, const char *); void *xmlNodeCopy(const void *xid, const char *path);
# #
# Functions to walk the node tree and process them one by one. # Functions to walk the node tree and process them one by one.
# e.g. # e.g.
# xmid = xmlMarkId(id); # xmid = xmlMarkId(id);
# num = xmlNodeGetNum(xmid); # num = xmlNodeGetNum(xmid, "node");
# for (i=0; i<num; i++) { # for (i=0; i<num; i++) {
# if (xmlNodeGetPos(id, xmid, "element", i) != 0) { # if (xmlNodeGetPos(id, xmid, "element", i) != 0) {
# if ((s = xmlGetString(xmid)) != 0) { # if ((s = xmlGetString(xmid)) != 0) {
@ -73,15 +74,15 @@ void *xmlNodeCopy(void *, const char *);
# } # }
# free(xmid); # free(xmid);
# #
void *xmlMarkId(void *); void *xmlMarkId(const void *xid);
unsigned int xmlNodeGetNum(void *, const char *); unsigned int xmlNodeGetNum(const void *xid, const char *path);
void *xmlNodeGetPos(const void *, void *, const char *, int); void *xmlNodeGetPos(const void *pid, void *xid, const char *element, int pos);
# #
# Get the name of the current node # Get the name of the current node
# #
char *xmlNodeGetName(void *); char *xmlNodeGetName(const void *xid);
size_t xmlNodeCopyName(void *, const char *, size_t); size_t xmlNodeCopyName(const void *xid, const char *buffer, size_t size);
# #
# These functions work on the current node. # These functions work on the current node.
@ -92,11 +93,11 @@ size_t xmlNodeCopyName(void *, const char *, size_t);
# xnid = xmlNodeGet(id, "/path/to/specified/node"); # xnid = xmlNodeGet(id, "/path/to/specified/node");
# if (xmlCompareString(xnid, "value") == 0) printf("We have a match!\n"); # if (xmlCompareString(xnid, "value") == 0) printf("We have a match!\n");
# #
long int xmlGetInt(void *); long int xmlGetInt(const void *xid);
double xmlGetDouble(void *); double xmlGetDouble(const void *xid);
char *xmlGetString(void *); char *xmlGetString(const void *xid);
size_t xmlCopyString(void *, char *, const size_t); size_t xmlCopyString(const void *xid, char *buffer, const size_t size);
int xmlCompareString(const void *, const char *); int xmlCompareString(const void *xid, const char *str);
# #
# These functions work on a specified node path # These functions work on a specified node path
@ -106,11 +107,12 @@ int xmlCompareString(const void *, const char *);
# xnid = xmlNodeGet(id, "/path/to"); # xnid = xmlNodeGet(id, "/path/to");
# i = xmlNodeGetInt(xnid, "node"); # i = xmlNodeGetInt(xnid, "node");
# #
long int xmlNodeGetInt(void *, const char *); long int xmlNodeGetInt(const void *xid, const char *path);
double xmlNodeGetDouble(void *, const char *); double xmlNodeGetDouble(const void *xid, const char *path);
char *xmlNodeGetString(void *, const char *); char *xmlNodeGetString(const void *xid, const char *path);
size_t xmlNodeCopyString(void *, const char *, char *, const size_t); size_t xmlNodeCopyString(const void *xid, const char *path,
int xmlNodeCompareString(const void *, const char *, const char *); char *buffer, const size_t size);
int xmlNodeCompareString(const void *xid, const char *path, const char *str);
# #
# These functions work on a specified atribute # These functions work on a specified atribute
@ -118,15 +120,17 @@ int xmlNodeCompareString(const void *, const char *, const char *);
# i = xmlAttributeGetInt(id, "n"); # i = xmlAttributeGetInt(id, "n");
# #
# or # or
# s = xmlNodeGetString(id, "type"); # s = xmlAttributeGetString(id, "type");
# if (s) printf("node is of type '%s'\n", s); # if (s) printf("node is of type '%s'\n", s);
# free(s); # free(s);
# #
long int xmlAttributeGetInt(const void *, const char *); long int xmlAttributeGetInt(const void *xid, const char *attr);
double xmlAttributeGetDouble(const void *, const char *); double xmlAttributeGetDouble(const void *xid, const char *attr);
char *xmlAttributeGetString(const void *, const char *); char *xmlAttributeGetString(const void *xid, const char *attr);
size_t xmlAttributeCopyString(const void *, const char *, const char *, size_t); size_t xmlAttributeCopyString(const void *xid, const char *attr,
int xmlAttributeCompareString(const void *, const char *, const char *); const char *buffer, size_t size);
int xmlAttributeCompareString(const void *xid, const char *attr,
const char *str);
# #
# Error detection and reporting functions # Error detection and reporting functions
@ -136,6 +140,7 @@ int xmlAttributeCompareString(const void *, const char *, const char *);
# int err = xmlErrorGetNo(id, 1); /* clear last error */ # int err = xmlErrorGetNo(id, 1); /* clear last error */
# if (err) printf("Error #%i at line %u: '%s'\n", err, err_lineno, err_str); # if (err) printf("Error #%i at line %u: '%s'\n", err, err_lineno, err_str);
# #
int xmlErrorGetNo(const void *, int); int xmlErrorGetNo(const void *xid, int clear);
size_t xmlErrorGetLineNo(const void *, int); size_t xmlErrorGetLineNo(const void *xid, int clear);
const char *xmlErrorGetString(const void *, int); size_t xmlErrorGetColumnNo(const void *xid, int clear);
const char *xmlErrorGetString(const void *xid, int clear);

View file

@ -46,16 +46,16 @@ typedef struct
#endif #endif
#include <stdlib.h> /* free, malloc */ #include <stdlib.h> /* free, malloc */
#include <string.h> #include <string.h>
#ifndef _MSC_VER
#include <strings.h> /* strncasecmp */
#else
# define strncasecmp strnicmp
#endif
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#ifndef _MSC_VER
# include <strings.h> /* strncasecmp */
#else
# define strncasecmp strnicmp
#endif
#ifndef XML_NONVALIDATING #ifndef XML_NONVALIDATING
#include "xml.h" #include "xml.h"
@ -172,6 +172,25 @@ xmlOpen(const char *filename)
return (void *)rid; return (void *)rid;
} }
void *
xmlInitBuffer(const char *buffer, size_t size)
{
struct _root_id *rid = 0;
if (buffer && (size>0))
{
rid->fd = 0;
rid->start = (char *)buffer;
rid->len = size;
rid->name = 0;
#ifndef XML_NONVALIDATING
rid->info = 0;
#endif
}
return (void *)rid;
}
void void
xmlClose(void *id) xmlClose(void *id)
{ {
@ -180,8 +199,11 @@ xmlClose(void *id)
assert(rid != 0); assert(rid != 0);
assert(rid->name == 0); assert(rid->name == 0);
munmap(rid->start, rid->len); if (rid->fd)
close(rid->fd); {
munmap(rid->start, rid->len);
close(rid->fd);
}
if (rid->info) free(rid->info); if (rid->info) free(rid->info);
free(rid); free(rid);
@ -1183,12 +1205,9 @@ xmlErrorGetLineNo(const void *id, int clear)
while (ps<pe) while (ps<pe)
{ {
new = memchr(ps, '\n', pe-ps); new = memchr(ps, '\n', pe-ps);
if (new) if (new) ret++;
{ else break;
ps = new; ps = new+1;
ret++;
}
ps++;
} }
if (clear) err->err_no = 0; if (clear) err->err_no = 0;
@ -1198,6 +1217,45 @@ xmlErrorGetLineNo(const void *id, int clear)
return ret; return ret;
} }
size_t
xmlErrorGetColumnNo(const void *id, int clear)
{
size_t ret = 0;
if (id)
{
struct _xml_id *xid = (struct _xml_id *)id;
struct _root_id *rid;
if (xid->name) rid = xid->root;
else rid = (struct _root_id *)xid;
assert(rid != 0);
if (rid->info)
{
struct _xml_error *err = rid->info;
char *ps = rid->start;
char *pe = err->pos;
char *new;
while (ps<pe)
{
new = memchr(ps, '\n', pe-ps);
new = memchr(ps, '\n', pe-ps);
if (new) ret++;
else break;
ps = new+1;
}
ret = pe-ps;
if (clear) err->err_no = 0;
}
}
return ret;
}
const char * const char *
xmlErrorGetString(const void *id, int clear) xmlErrorGetString(const void *id, int clear)
{ {
@ -1334,8 +1392,8 @@ __xmlNodeGetPath(const char *start, size_t *len, char **name, size_t *plen)
char * char *
__xmlNodeGet(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 *element, *open, *start_tag=0;
char *new, *cur, *ne, *ret = 0; char *new, *cur, *ne, *ret = 0;
char *element, *start_tag=0;
size_t restlen, elementlen; size_t restlen, elementlen;
size_t return_len = 0; size_t return_len = 0;
int found, num; int found, num;
@ -1412,6 +1470,7 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
/* /*
* get element name and a pointer to after the opening tag * get element name and a pointer to after the opening tag
*/ */
open = cur;
element = *name; element = *name;
elementlen = *rlen; elementlen = *rlen;
len_remaining = restlen; len_remaining = restlen;
@ -1514,6 +1573,14 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos); new = __xmlNodeGet(cur-1, &slen, &node, &nlen, &pos);
if (!new) if (!new)
{ {
if (nlen == 0) /* error upstream */
{
*rlen = nlen;
*name = node;
*len = slen;
return 0;
}
if (slen == restlen) if (slen == restlen)
{ {
*rlen = 0; *rlen = 0;
@ -1557,24 +1624,31 @@ __xmlNodeGet(const char *start, size_t *len, char **name, size_t *rlen, size_t *
if (found == num) if (found == num)
{ {
if (start_tag) if (start_tag)
{ {
*len = new-ret-1; *len = new-ret-1;
*name = start_tag; *name = start_tag;
} }
else /* report error */ else /* report error */
{ {
*rlen = 0; *rlen = 0;
*name = new; *name = new;
*len = XML_ELEMENT_NO_OPENING_TAG; *len = XML_ELEMENT_NO_OPENING_TAG;
return 0; return 0;
} }
} }
found++; found++;
} }
/* else proper closing tag not yet found, continue. */ #ifndef XML_NONVALIDATING
/* TODO: could be a bad match to the opening tag though */ /* strcmp is a heavy operation when not required */
/* like: <test></teft> */ else if (strncmp(open, new+1, elementlen))
{
*rlen = 0;
*name = new+1;
*len = XML_ELEMENT_NO_CLOSING_TAG;
return 0;
}
#endif
new = memchr(cur, '>', restlen); new = memchr(cur, '>', restlen);
if (!new) if (!new)

View file

@ -52,6 +52,16 @@ enum
*/ */
void *xmlOpen(const char *); void *xmlOpen(const char *);
/**
* Process a section of XML code in a preallocated buffer.
* The buffer may not be free'd until xmlClose has been called.
*
* @param buffer pointer to the buffer
* @param size size of the buffer
* @return XML-id which is used for further processing
*/
void *xmlInitBuffer(const char *, size_t);
/** /**
* Close the XML file after which no further processing is possible. * Close the XML file after which no further processing is possible.
* *
@ -329,6 +339,15 @@ int xmlErrorGetNo(const void *, int);
*/ */
size_t xmlErrorGetLineNo(const void *, int); size_t xmlErrorGetLineNo(const void *, int);
/**
* Get the column number of the last detected syntax error in the xml file.
*
* @param xid XML-id
* @param clear clear the error state if non zero
* @return the line number of the detected syntax error.
*/
size_t xmlErrorGetColumnNo(const void *, int);
/** /**
* Get a string that explains the last error. * Get a string that explains the last error.
* *

View file

@ -323,8 +323,9 @@ void grep_file(unsigned num)
if (r) if (r)
{ {
size_t n = xmlErrorGetLineNo(xrid, 0); size_t n = xmlErrorGetLineNo(xrid, 0);
size_t c = xmlErrorGetColumnNo(xrid, 0);
char *s = xmlErrorGetString(xrid, 1); /* clear the error */ char *s = xmlErrorGetString(xrid, 1); /* clear the error */
printf("%s: at line %u: '%s'\n",_filenames[num], n, s); printf("%s: at line %u, column %u: '%s'\n",_filenames[num], n,c, s);
} }
free(xrid); free(xrid);