more work on the xml reader interfaces. updated Igor's mail and the Web
* xmlreader.c include/libxml/xmlreader.h doc/libxml2-api.xml: more
work on the xml reader interfaces.
* AUTHORS MAINTAINERS doc/* win32/*: updated Igor's mail and the
Web page for the Windows binaries.
Daniel
diff --git a/xmlreader.c b/xmlreader.c
index 68632c6..254fd54 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -87,6 +87,7 @@
xmlNodePtr node; /* current node */
xmlNodePtr curnode;/* current attribute node */
int depth; /* depth of the current node */
+ xmlNodePtr faketext;/* fake xmlNs chld */
};
#ifdef DEBUG_READER
@@ -436,6 +437,62 @@
return(NULL);
}
+/**
+ * xmlTextReaderReadBase64:
+ * @reader: the xmlTextReaderPtr used
+ * @array: a byte array to store the content.
+ * @offset: the zero-based index into array where the method should
+ * begin to write.
+ * @len: the number of bytes to write.
+ *
+ * Reads and decodes the Base64 encoded contents of an element and
+ * stores the result in a byte buffer.
+ *
+ * Returns the number of bytes written to array, or zero if the current
+ * instance is not positioned on an element or -1 in case of error.
+ */
+int
+xmlTextReaderReadBase64(xmlTextReaderPtr reader, unsigned char *array,
+ int offset, int len) {
+ if ((reader == NULL) || (reader->ctxt == NULL))
+ return(-1);
+ if (reader->ctxt->wellFormed != 1)
+ return(-1);
+
+ if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
+ return(0);
+ TODO
+ return(0);
+}
+
+/**
+ * xmlTextReaderReadBinHex:
+ * @reader: the xmlTextReaderPtr used
+ * @array: a byte array to store the content.
+ * @offset: the zero-based index into array where the method should
+ * begin to write.
+ * @len: the number of bytes to write.
+ *
+ * Reads and decodes the BinHex encoded contents of an element and
+ * stores the result in a byte buffer.
+ *
+ * Returns the number of bytes written to array, or zero if the current
+ * instance is not positioned on an element or -1 in case of error.
+ */
+int
+xmlTextReaderReadBinHex(xmlTextReaderPtr reader, unsigned char *array,
+ int offset, int len) {
+ if ((reader == NULL) || (reader->ctxt == NULL))
+ return(-1);
+ if (reader->ctxt->wellFormed != 1)
+ return(-1);
+
+ if ((reader->node == NULL) || (reader->node->type == XML_ELEMENT_NODE))
+ return(0);
+ TODO
+ return(0);
+}
+
/************************************************************************
* *
* Constructor and destructors *
@@ -544,6 +601,9 @@
xmlFree(reader->sax);
if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT))
xmlFreeParserInputBuffer(reader->input);
+ if (reader->faketext != NULL) {
+ xmlFreeNode(reader->faketext);
+ }
xmlFree(reader);
}
@@ -1082,6 +1142,48 @@
return(0);
}
+/**
+ * xmlTextReaderReadAttributeValue:
+ * @reader: the xmlTextReaderPtr used
+ *
+ * Parses an attribute value into one or more Text and EntityReference nodes.
+ *
+ * Returns 1 in case of success, 0 if the reader was not positionned on an
+ * ttribute node or all the attribute values have been read, or -1
+ * in case of error.
+ */
+int
+xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader) {
+ if (reader == NULL)
+ return(-1);
+ if (reader->node == NULL)
+ return(-1);
+ if (reader->curnode == NULL)
+ return(0);
+ if (reader->curnode->type == XML_ATTRIBUTE_NODE) {
+ if (reader->curnode->children == NULL)
+ return(0);
+ reader->curnode = reader->curnode->children;
+ } else if (reader->curnode->type == XML_NAMESPACE_DECL) {
+ xmlNsPtr ns = (xmlNsPtr) reader->curnode;
+
+ if (reader->faketext == NULL) {
+ reader->faketext = xmlNewDocText(reader->node->doc,
+ ns->href);
+ } else {
+ if (reader->faketext->content != NULL)
+ xmlFree(reader->faketext->content);
+ reader->faketext->content = xmlStrdup(ns->href);
+ }
+ reader->curnode = reader->faketext;
+ } else {
+ if (reader->curnode->next == NULL)
+ return(0);
+ reader->curnode = reader->curnode->next;
+ }
+ return(1);
+}
+
/************************************************************************
* *
* Acces API to the current node *
@@ -1412,6 +1514,12 @@
if (reader->node == NULL)
return(0);
+ if (reader->curnode != NULL) {
+ if ((reader->curnode->type == XML_ATTRIBUTE_NODE) ||
+ (reader->curnode->type == XML_NAMESPACE_DECL))
+ return(reader->depth + 1);
+ return(reader->depth + 2);
+ }
return(reader->depth);
}
@@ -1589,3 +1697,272 @@
return(1);
}
+/************************************************************************
+ * *
+ * Extensions to the base APIs *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlTextReaderSetParserProp:
+ * @reader: the xmlTextReaderPtr used
+ * @prop: the xmlParserProperties to set
+ * @value: usually 0 or 1 to (de)activate it
+ *
+ * Change the parser processing behaviour by changing some of its internal
+ * properties. Note that some properties can only be changed before any
+ * read has been done.
+ *
+ * Returns 0 if the call was successful, or -1 in case of error
+ */
+int
+xmlTextReaderSetParserProp(xmlTextReaderPtr reader, int prop, int value) {
+ xmlParserProperties p = (xmlParserProperties) prop;
+ xmlParserCtxtPtr ctxt;
+
+ if ((reader == NULL) || (reader->ctxt == NULL))
+ return(-1);
+ ctxt = reader->ctxt;
+
+ switch (p) {
+ case XML_PARSER_LOADDTD:
+ if (value != 0) {
+ if (ctxt->loadsubset == 0) {
+ if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
+ return(-1);
+ ctxt->loadsubset = XML_DETECT_IDS;
+ }
+ } else {
+ ctxt->loadsubset = 0;
+ }
+ return(0);
+ case XML_PARSER_DEFAULTATTRS:
+ if (value != 0) {
+ ctxt->loadsubset |= XML_COMPLETE_ATTRS;
+ } else {
+ if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
+ ctxt->loadsubset -= XML_COMPLETE_ATTRS;
+ }
+ return(0);
+ case XML_PARSER_VALIDATE:
+ if (value != 0) {
+ ctxt->validate = 1;
+ } else {
+ ctxt->validate = 0;
+ }
+ return(0);
+ }
+ return(-1);
+}
+
+/**
+ * xmlTextReaderGetParserProp:
+ * @reader: the xmlTextReaderPtr used
+ * @prop: the xmlParserProperties to get
+ *
+ * Read the parser internal property.
+ *
+ * Returns the value, usually 0 or 1, or -1 in case of error.
+ */
+int
+xmlTextReaderGetParserProp(xmlTextReaderPtr reader, int prop) {
+ xmlParserProperties p = (xmlParserProperties) prop;
+ xmlParserCtxtPtr ctxt;
+
+ if ((reader == NULL) || (reader->ctxt == NULL))
+ return(-1);
+ ctxt = reader->ctxt;
+
+ switch (p) {
+ case XML_PARSER_LOADDTD:
+ if ((ctxt->loadsubset != 0) || (ctxt->validate != 0))
+ return(1);
+ return(0);
+ case XML_PARSER_DEFAULTATTRS:
+ if (ctxt->loadsubset & XML_COMPLETE_ATTRS)
+ return(1);
+ return(0);
+ case XML_PARSER_VALIDATE:
+ return(ctxt->validate);
+ }
+ return(-1);
+}
+
+/************************************************************************
+ * *
+ * Utilities *
+ * *
+ ************************************************************************/
+/**
+ * xmlBase64Decode:
+ * @in: the input buffer
+ * @inlen: the size of the input (in), the size read from it (out)
+ * @to: the output buffer
+ * @tolen: the size of the output (in), the size written to (out)
+ *
+ * Base64 decoder, reads from @in and save in @to
+ *
+ * Returns 0 if all the input was consumer, 1 if the Base64 end was reached,
+ * 2 if there wasn't enough space on the output or -1 in case of error.
+ */
+static int
+xmlBase64Decode(const unsigned char *in, unsigned long *inlen,
+ unsigned char *to, unsigned long *tolen) {
+ unsigned long incur; /* current index in in[] */
+ unsigned long inblk; /* last block index in in[] */
+ unsigned long outcur; /* current index in out[] */
+ unsigned long inmax; /* size of in[] */
+ unsigned long outmax; /* size of out[] */
+ unsigned char cur; /* the current value read from in[] */
+ unsigned char intmp[3], outtmp[4]; /* temporary buffers for the convert */
+ int nbintmp; /* number of byte in intmp[] */
+ int is_ignore; /* cur should be ignored */
+ int is_end = 0; /* the end of the base64 was found */
+ int retval = 1;
+ int i;
+
+ if ((in == NULL) || (inlen == NULL) || (to == NULL) || (tolen == NULL))
+ return(-1);
+
+ incur = 0;
+ inblk = 0;
+ outcur = 0;
+ inmax = *inlen;
+ outmax = *tolen;
+ nbintmp = 0;
+
+ while (1) {
+ if (incur >= inmax)
+ break;
+ cur = in[incur++];
+ is_ignore = 0;
+ if ((cur >= 'A') && (cur <= 'Z'))
+ cur = cur - 'A';
+ else if ((cur >= 'a') && (cur <= 'z'))
+ cur = cur - 'a' + 26;
+ else if ((cur >= '0') && (cur <= '9'))
+ cur = cur - '0' + 52;
+ else if (cur == '+')
+ cur = 62;
+ else if (cur == '/')
+ cur = 63;
+ else if (cur == '.')
+ cur = 0;
+ else if (cur == '=') /*no op , end of the base64 stream */
+ is_end = 1;
+ else {
+ is_ignore = 1;
+ if (nbintmp == 0)
+ inblk = incur;
+ }
+
+ if (!is_ignore) {
+ int nbouttmp = 3;
+ int is_break = 0;
+
+ if (is_end) {
+ if (nbintmp == 0)
+ break;
+ if ((nbintmp == 1) || (nbintmp == 2))
+ nbouttmp = 1;
+ else
+ nbouttmp = 2;
+ nbintmp = 3;
+ is_break = 1;
+ }
+ intmp[nbintmp++] = cur;
+ /*
+ * if intmp is full, push the 4byte sequence as a 3 byte
+ * sequence out
+ */
+ if (nbintmp == 4) {
+ nbintmp = 0;
+ outtmp[0] = (intmp[0] << 2) | ((intmp[1] & 0x30) >> 4);
+ outtmp[1] =
+ ((intmp[1] & 0x0F) << 4) | ((intmp[2] & 0x3C) >> 2);
+ outtmp[2] = ((intmp[2] & 0x03) << 6) | (intmp[3] & 0x3F);
+ if (outcur + 3 >= outmax) {
+ retval = 2;
+ break;
+ }
+
+ for (i = 0; i < nbouttmp; i++)
+ to[outcur++] = outtmp[i];
+ inblk = incur;
+ }
+
+ if (is_break) {
+ retval = 0;
+ break;
+ }
+ }
+ }
+
+ *tolen = outcur;
+ *inlen = inblk;
+ return (retval);
+}
+
+/*
+ * Test routine for the xmlBase64Decode function
+ */
+#if 0
+int main(int argc, char **argv) {
+ char *input = " VW4 gcGV0 \n aXQgdGVzdCAuCg== ";
+ char output[100];
+ char output2[100];
+ char output3[100];
+ unsigned long inlen = strlen(input);
+ unsigned long outlen = 100;
+ int ret;
+ unsigned long cons, tmp, tmp2, prod;
+
+ /*
+ * Direct
+ */
+ ret = xmlBase64Decode(input, &inlen, output, &outlen);
+
+ output[outlen] = 0;
+ printf("ret: %d, inlen: %ld , outlen: %ld, output: '%s'\n", ret, inlen, outlen, output);
+
+ /*
+ * output chunking
+ */
+ cons = 0;
+ prod = 0;
+ while (cons < inlen) {
+ tmp = 5;
+ tmp2 = inlen - cons;
+
+ printf("%ld %ld\n", cons, prod);
+ ret = xmlBase64Decode(&input[cons], &tmp2, &output2[prod], &tmp);
+ cons += tmp2;
+ prod += tmp;
+ printf("%ld %ld\n", cons, prod);
+ }
+ output2[outlen] = 0;
+ printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output2);
+
+ /*
+ * input chunking
+ */
+ cons = 0;
+ prod = 0;
+ while (cons < inlen) {
+ tmp = 100 - prod;
+ tmp2 = inlen - cons;
+ if (tmp2 > 5)
+ tmp2 = 5;
+
+ printf("%ld %ld\n", cons, prod);
+ ret = xmlBase64Decode(&input[cons], &tmp2, &output3[prod], &tmp);
+ cons += tmp2;
+ prod += tmp;
+ printf("%ld %ld\n", cons, prod);
+ }
+ output3[outlen] = 0;
+ printf("ret: %d, cons: %ld , prod: %ld, output: '%s'\n", ret, cons, prod, output3);
+ return(0);
+
+}
+#endif