Synchronize with trunk r58457.
[reactos.git] / lib / 3rdparty / libxml2 / xmlreader.c
index 97c71ab..579e943 100644 (file)
@@ -44,6 +44,8 @@
 #include <libxml/pattern.h>
 #endif
 
+#include "buf.h"
+
 #define MAX_ERR_MSG_SIZE 64000
 
 /*
@@ -135,7 +137,7 @@ struct _xmlTextReader {
     int                                depth;  /* depth of the current node */
     xmlNodePtr                 faketext;/* fake xmlNs chld */
     int                                preserve;/* preserve the resulting document */
-    xmlBufferPtr               buffer; /* used to return const xmlChar * */
+    xmlBufPtr                  buffer; /* used to return const xmlChar * */
     xmlDictPtr                 dict;   /* the context dictionnary */
 
     /* entity stack when traversing entities content */
@@ -152,6 +154,7 @@ struct _xmlTextReader {
     /* Handling of RelaxNG validation */
     xmlRelaxNGPtr          rngSchemas; /* The Relax NG schemas */
     xmlRelaxNGValidCtxtPtr rngValidCtxt;/* The Relax NG validation context */
+    int                    rngPreserveCtxt; /* 1 if the context was provided by the user */
     int                    rngValidErrors;/* The number of errors detected */
     xmlNodePtr             rngFullNode;        /* the node if RNG not progressive */
     /* Handling of Schemas validation */
@@ -806,9 +809,10 @@ xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
  */
 static int
 xmlTextReaderPushData(xmlTextReaderPtr reader) {
-    xmlBufferPtr inbuf;
+    xmlBufPtr inbuf;
     int val, s;
     xmlTextReaderState oldstate;
+    int alloc;
 
     if ((reader->input == NULL) || (reader->input->buffer == NULL))
        return(-1);
@@ -816,17 +820,18 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
     oldstate = reader->state;
     reader->state = XML_TEXTREADER_NONE;
     inbuf = reader->input->buffer;
+    alloc = xmlBufGetAllocationScheme(inbuf);
 
     while (reader->state == XML_TEXTREADER_NONE) {
-       if (inbuf->use < reader->cur + CHUNK_SIZE) {
+       if (xmlBufUse(inbuf) < reader->cur + CHUNK_SIZE) {
            /*
             * Refill the buffer unless we are at the end of the stream
             */
            if (reader->mode != XML_TEXTREADER_MODE_EOF) {
                val = xmlParserInputBufferRead(reader->input, 4096);
                if ((val == 0) &&
-                   (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
-                   if (inbuf->use == reader->cur) {
+                   (alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
+                   if (xmlBufUse(inbuf) == reader->cur) {
                        reader->mode = XML_TEXTREADER_MODE_EOF;
                        reader->state = oldstate;
                    }
@@ -849,21 +854,23 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
         * parse by block of CHUNK_SIZE bytes, various tests show that
         * it's the best tradeoff at least on a 1.2GH Duron
         */
-       if (inbuf->use >= reader->cur + CHUNK_SIZE) {
+       if (xmlBufUse(inbuf) >= reader->cur + CHUNK_SIZE) {
            val = xmlParseChunk(reader->ctxt,
-                         (const char *) &inbuf->content[reader->cur],
-                         CHUNK_SIZE, 0);
+                 (const char *) xmlBufContent(inbuf) + reader->cur,
+                                CHUNK_SIZE, 0);
            reader->cur += CHUNK_SIZE;
-           if ((val != 0) || (reader->ctxt->wellFormed == 0))
-               return(-1);
+           if (val != 0)
+               reader->ctxt->wellFormed = 0;
+           if (reader->ctxt->wellFormed == 0)
+               break;
        } else {
-           s = inbuf->use - reader->cur;
+           s = xmlBufUse(inbuf) - reader->cur;
            val = xmlParseChunk(reader->ctxt,
-                         (const char *) &inbuf->content[reader->cur],
-                         s, 0);
+                (const char *) xmlBufContent(inbuf) + reader->cur,
+                               s, 0);
            reader->cur += s;
-           if ((val != 0) || (reader->ctxt->wellFormed == 0))
-               return(-1);
+           if (val != 0)
+               reader->ctxt->wellFormed = 0;
            break;
        }
     }
@@ -872,10 +879,10 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
      * Discard the consumed input when needed and possible
      */
     if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
-        if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
+        if (alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
            if ((reader->cur >= 4096) &&
-               (inbuf->use - reader->cur <= CHUNK_SIZE)) {
-               val = xmlBufferShrink(inbuf, reader->cur);
+               (xmlBufUse(inbuf) - reader->cur <= CHUNK_SIZE)) {
+               val = xmlBufShrink(inbuf, reader->cur);
                if (val >= 0) {
                    reader->cur -= val;
                }
@@ -889,17 +896,26 @@ xmlTextReaderPushData(xmlTextReaderPtr reader) {
      */
     else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
        if (reader->state != XML_TEXTREADER_DONE) {
-           s = inbuf->use - reader->cur;
+           s = xmlBufUse(inbuf) - reader->cur;
            val = xmlParseChunk(reader->ctxt,
-                   (const char *) &inbuf->content[reader->cur],
-                   s, 1);
-           reader->cur = inbuf->use;
+                (const char *) xmlBufContent(inbuf) + reader->cur,
+                               s, 1);
+           reader->cur = xmlBufUse(inbuf);
            reader->state  = XML_TEXTREADER_DONE;
-           if ((val != 0) || (reader->ctxt->wellFormed == 0))
-               return(-1);
+           if (val != 0) {
+               if (reader->ctxt->wellFormed)
+                   reader->ctxt->wellFormed = 0;
+               else
+                   return(-1);
+           }
        }
     }
     reader->state = oldstate;
+    if (reader->ctxt->wellFormed == 0) {
+       reader->mode = XML_TEXTREADER_MODE_EOF;
+        return(-1);
+    }
+
     return(0);
 }
 
@@ -1212,6 +1228,9 @@ xmlTextReaderCollectSiblings(xmlNodePtr node)
     xmlBufferPtr buffer;
     xmlChar *ret;
 
+    if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
+        return(NULL);
+
     buffer = xmlBufferCreate();
     if (buffer == NULL)
        return NULL;
@@ -1264,8 +1283,6 @@ xmlTextReaderRead(xmlTextReaderPtr reader) {
         return(xmlTextReaderReadTree(reader));
     if (reader->ctxt == NULL)
        return(-1);
-    if (reader->ctxt->wellFormed != 1)
-       return(-1);
 
 #ifdef DEBUG_READER
     fprintf(stderr, "\nREAD ");
@@ -1709,8 +1726,8 @@ xmlTextReaderReadInnerXml(xmlTextReaderPtr reader ATTRIBUTE_UNUSED)
  *
  * Reads the contents of the current node, including child nodes and markup.
  *
- * Returns a string containing the node and any XML content, or NULL if the 
- *         current node cannot be serialized. The string must be deallocated 
+ * Returns a string containing the node and any XML content, or NULL if the
+ *         current node cannot be serialized. The string must be deallocated
  *         by the caller.
  */
 xmlChar *
@@ -2055,7 +2072,7 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     ret->entMax = 0;
     ret->entNr = 0;
     ret->input = input;
-    ret->buffer = xmlBufferCreateSize(100);
+    ret->buffer = xmlBufCreateSize(100);
     if (ret->buffer == NULL) {
         xmlFree(ret);
         xmlGenericError(xmlGenericErrorContext,
@@ -2064,7 +2081,7 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     }
     ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler));
     if (ret->sax == NULL) {
-       xmlBufferFree(ret->buffer);
+       xmlBufFree(ret->buffer);
        xmlFree(ret);
         xmlGenericError(xmlGenericErrorContext,
                "xmlNewTextReader : malloc failed\n");
@@ -2097,12 +2114,13 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     ret->mode = XML_TEXTREADER_MODE_INITIAL;
     ret->node = NULL;
     ret->curnode = NULL;
-    if (ret->input->buffer->use < 4) {
+    if (xmlBufUse(ret->input->buffer) < 4) {
        xmlParserInputBufferRead(input, 4);
     }
-    if (ret->input->buffer->use >= 4) {
+    if (xmlBufUse(ret->input->buffer) >= 4) {
        ret->ctxt = xmlCreatePushParserCtxt(ret->sax, NULL,
-                       (const char *) ret->input->buffer->content, 4, URI);
+                            (const char *) xmlBufContent(ret->input->buffer),
+                                            4, URI);
        ret->base = 0;
        ret->cur = 4;
     } else {
@@ -2114,7 +2132,7 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) {
     if (ret->ctxt == NULL) {
         xmlGenericError(xmlGenericErrorContext,
                "xmlNewTextReader : malloc failed\n");
-       xmlBufferFree(ret->buffer);
+       xmlBufFree(ret->buffer);
        xmlFree(ret->sax);
        xmlFree(ret);
        return(NULL);
@@ -2187,7 +2205,8 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
        reader->rngSchemas = NULL;
     }
     if (reader->rngValidCtxt != NULL) {
-       xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
+       if (! reader->rngPreserveCtxt)
+           xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
        reader->rngValidCtxt = NULL;
     }
     if (reader->xsdPlug != NULL) {
@@ -2243,7 +2262,7 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
     if ((reader->input != NULL)  && (reader->allocs & XML_TEXTREADER_INPUT))
        xmlFreeParserInputBuffer(reader->input);
     if (reader->buffer != NULL)
-        xmlBufferFree(reader->buffer);
+        xmlBufFree(reader->buffer);
     if (reader->entTab != NULL)
        xmlFree(reader->entTab);
     if (reader->dict != NULL)
@@ -3591,16 +3610,17 @@ xmlTextReaderConstValue(xmlTextReaderPtr reader) {
                (attr->children->next == NULL))
                return(attr->children->content);
            else {
-               if (reader->buffer == NULL)
-                   reader->buffer = xmlBufferCreateSize(100);
                if (reader->buffer == NULL) {
-                   xmlGenericError(xmlGenericErrorContext,
-                                   "xmlTextReaderSetup : malloc failed\n");
-                   return (NULL);
-               }
-               reader->buffer->use = 0;
-               xmlNodeBufGetContent(reader->buffer, node);
-               return(reader->buffer->content);
+                   reader->buffer = xmlBufCreateSize(100);
+                    if (reader->buffer == NULL) {
+                        xmlGenericError(xmlGenericErrorContext,
+                                        "xmlTextReaderSetup : malloc failed\n");
+                        return (NULL);
+                    }
+                } else
+                    xmlBufEmpty(reader->buffer);
+               xmlBufGetNodeContent(reader->buffer, node);
+               return(xmlBufContent(reader->buffer));
            }
            break;
        }
@@ -4095,9 +4115,11 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
            reader->rngSchemas = NULL;
        }
         if (reader->rngValidCtxt != NULL) {
-           xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
+           if (! reader->rngPreserveCtxt)
+               xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
            reader->rngValidCtxt = NULL;
         }
+       reader->rngPreserveCtxt = 0;
        return(0);
     }
     if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
@@ -4107,9 +4129,11 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
        reader->rngSchemas = NULL;
     }
     if (reader->rngValidCtxt != NULL) {
-       xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
+       if (! reader->rngPreserveCtxt)
+           xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
        reader->rngValidCtxt = NULL;
     }
+    reader->rngPreserveCtxt = 0;
     reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(schema);
     if (reader->rngValidCtxt == NULL)
         return(-1);
@@ -4130,6 +4154,60 @@ xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema) {
     return(0);
 }
 
+/**
+ * xmlTextReaderLocator:
+ * @ctx: the xmlTextReaderPtr used
+ * @file: returned file information
+ * @line: returned line information
+ *
+ * Internal locator function for the readers
+ *
+ * Returns 0 in case the Schema validation could be (des)activated and
+ *         -1 in case of error.
+ */
+static int
+xmlTextReaderLocator(void *ctx, const char **file, unsigned long *line) {
+    xmlTextReaderPtr reader;
+
+    if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
+        return(-1);
+
+    if (file != NULL)
+        *file = NULL;
+    if (line != NULL)
+        *line = 0;
+
+    reader = (xmlTextReaderPtr) ctx;
+    if ((reader->ctxt != NULL) && (reader->ctxt->input != NULL)) {
+       if (file != NULL)
+           *file = reader->ctxt->input->filename;
+       if (line != NULL)
+           *line = reader->ctxt->input->line;
+       return(0);
+    }
+    if (reader->node != NULL) {
+        long res;
+       int ret = 0;
+
+       if (line != NULL) {
+           res = xmlGetLineNo(reader->node);
+           if (res > 0)
+               *line = (unsigned long) res;
+           else
+                ret = -1;
+       }
+        if (file != NULL) {
+           xmlDocPtr doc = reader->node->doc;
+           if ((doc != NULL) && (doc->URL != NULL))
+               *file = (const char *) doc->URL;
+           else
+                ret = -1;
+       }
+       return(ret);
+    }
+    return(-1);
+}
+
 /**
  * xmlTextReaderSetSchema:
  * @reader:  the xmlTextReaderPtr used
@@ -4197,6 +4275,10 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
        reader->xsdValidCtxt = NULL;
        return(-1);
     }
+    xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
+                                xmlTextReaderLocator,
+                               (void *) reader);
+
     if (reader->errorFunc != NULL) {
        xmlSchemaSetValidErrors(reader->xsdValidCtxt,
                        xmlTextReaderValidityErrorRelay,
@@ -4214,67 +4296,91 @@ xmlTextReaderSetSchema(xmlTextReaderPtr reader, xmlSchemaPtr schema) {
 }
 
 /**
- * xmlTextReaderRelaxNGValidate:
+ * xmlTextReaderRelaxNGValidateInternal:
  * @reader:  the xmlTextReaderPtr used
  * @rng:  the path to a RelaxNG schema or NULL
+ * @ctxt: the RelaxNG schema validation context or NULL
+ * @options: options (not yet used)
  *
  * Use RelaxNG to validate the document as it is processed.
  * Activation is only possible before the first Read().
- * if @rng is NULL, then RelaxNG validation is deactivated.
+ * If both @rng and @ctxt are NULL, then RelaxNG validation is deactivated.
  *
  * Returns 0 in case the RelaxNG validation could be (de)activated and
- *         -1 in case of error.
+ *        -1 in case of error.
  */
-int
-xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng) {
-    xmlRelaxNGParserCtxtPtr ctxt;
-
+static int
+xmlTextReaderRelaxNGValidateInternal(xmlTextReaderPtr reader,
+                                    const char *rng,
+                                    xmlRelaxNGValidCtxtPtr ctxt,
+                                    int options ATTRIBUTE_UNUSED)
+{
     if (reader == NULL)
-        return(-1);
+       return(-1);
 
-    if (rng == NULL) {
-        if (reader->rngValidCtxt != NULL) {
+    if ((rng != NULL) && (ctxt != NULL))
+       return (-1);
+
+    if (((rng != NULL) || (ctxt != NULL)) &&
+       ((reader->mode != XML_TEXTREADER_MODE_INITIAL) ||
+        (reader->ctxt == NULL)))
+       return(-1);
+
+    /* Cleanup previous validation stuff. */
+    if (reader->rngValidCtxt != NULL) {
+       if ( !reader->rngPreserveCtxt)
            xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
-           reader->rngValidCtxt = NULL;
-        }
-        if (reader->rngSchemas != NULL) {
-           xmlRelaxNGFree(reader->rngSchemas);
-           reader->rngSchemas = NULL;
-       }
-       return(0);
+       reader->rngValidCtxt = NULL;
     }
-    if (reader->mode != XML_TEXTREADER_MODE_INITIAL)
-       return(-1);
+    reader->rngPreserveCtxt = 0;
     if (reader->rngSchemas != NULL) {
        xmlRelaxNGFree(reader->rngSchemas);
        reader->rngSchemas = NULL;
     }
-    if (reader->rngValidCtxt != NULL) {
-       xmlRelaxNGFreeValidCtxt(reader->rngValidCtxt);
-       reader->rngValidCtxt = NULL;
-    }
-    ctxt = xmlRelaxNGNewParserCtxt(rng);
-    if (reader->errorFunc != NULL) {
-       xmlRelaxNGSetParserErrors(ctxt,
-                        xmlTextReaderValidityErrorRelay,
-                        xmlTextReaderValidityWarningRelay,
-                        reader);
-    }
-    if (reader->sErrorFunc != NULL) {
-       xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
-                       xmlTextReaderValidityStructuredRelay,
-                       reader);
+
+    if ((rng == NULL) && (ctxt == NULL)) {
+       /* We just want to deactivate the validation, so get out. */
+       return(0);
     }
-    reader->rngSchemas = xmlRelaxNGParse(ctxt);
-    xmlRelaxNGFreeParserCtxt(ctxt);
-    if (reader->rngSchemas == NULL)
-        return(-1);
-    reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
-    if (reader->rngValidCtxt == NULL) {
-       xmlRelaxNGFree(reader->rngSchemas);
-       reader->rngSchemas = NULL;
-        return(-1);
+
+
+    if (rng != NULL) {
+       xmlRelaxNGParserCtxtPtr pctxt;
+       /* Parse the schema and create validation environment. */
+
+       pctxt = xmlRelaxNGNewParserCtxt(rng);
+       if (reader->errorFunc != NULL) {
+           xmlRelaxNGSetParserErrors(pctxt,
+               xmlTextReaderValidityErrorRelay,
+               xmlTextReaderValidityWarningRelay,
+               reader);
+       }
+       if (reader->sErrorFunc != NULL) {
+           xmlRelaxNGSetValidStructuredErrors(reader->rngValidCtxt,
+               xmlTextReaderValidityStructuredRelay,
+               reader);
+       }
+       reader->rngSchemas = xmlRelaxNGParse(pctxt);
+       xmlRelaxNGFreeParserCtxt(pctxt);
+       if (reader->rngSchemas == NULL)
+           return(-1);
+       reader->rngValidCtxt = xmlRelaxNGNewValidCtxt(reader->rngSchemas);
+       if (reader->rngValidCtxt == NULL) {
+           xmlRelaxNGFree(reader->rngSchemas);
+           reader->rngSchemas = NULL;
+           return(-1);
+       }
+    } else {
+       /* Use the given validation context. */
+       reader->rngValidCtxt = ctxt;
+       reader->rngPreserveCtxt = 1;
     }
+    /*
+    * Redirect the validation context's error channels to use
+    * the reader channels.
+    * TODO: In case the user provides the validation context we
+    *  could make this redirection optional.
+    */
     if (reader->errorFunc != NULL) {
        xmlRelaxNGSetValidErrors(reader->rngValidCtxt,
                         xmlTextReaderValidityErrorRelay,
@@ -4387,6 +4493,9 @@ xmlTextReaderSchemaValidateInternal(xmlTextReaderPtr reader,
            return(-1);
        }
     }
+    xmlSchemaValidateSetLocator(reader->xsdValidCtxt,
+                                xmlTextReaderLocator,
+                               (void *) reader);
     /*
     * Redirect the validation context's error channels to use
     * the reader channels.
@@ -4447,6 +4556,46 @@ xmlTextReaderSchemaValidate(xmlTextReaderPtr reader, const char *xsd)
 {
     return(xmlTextReaderSchemaValidateInternal(reader, xsd, NULL, 0));
 }
+
+/**
+ * xmlTextReaderRelaxNGValidateCtxt:
+ * @reader:  the xmlTextReaderPtr used
+ * @ctxt: the RelaxNG schema validation context or NULL
+ * @options: options (not used yet)
+ *
+ * Use RelaxNG schema context to validate the document as it is processed.
+ * Activation is only possible before the first Read().
+ * If @ctxt is NULL, then RelaxNG schema validation is deactivated.
+ *
+ * Returns 0 in case the schemas validation could be (de)activated and
+ *         -1 in case of error.
+ */
+int
+xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader,
+                                xmlRelaxNGValidCtxtPtr ctxt,
+                                int options)
+{
+    return(xmlTextReaderRelaxNGValidateInternal(reader, NULL, ctxt, options));
+}
+
+/**
+ * xmlTextReaderRelaxNGValidate:
+ * @reader:  the xmlTextReaderPtr used
+ * @rng:  the path to a RelaxNG schema or NULL
+ *
+ * Use RelaxNG schema to validate the document as it is processed.
+ * Activation is only possible before the first Read().
+ * If @rng is NULL, then RelaxNG schema validation is deactivated.
+ *
+ * Returns 0 in case the schemas validation could be (de)activated and
+ *         -1 in case of error.
+ */
+int
+xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng)
+{
+    return(xmlTextReaderRelaxNGValidateInternal(reader, rng, NULL, 0));
+}
+
 #endif
 
 /**
@@ -4964,7 +5113,7 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
        reader->allocs |= XML_TEXTREADER_INPUT;
     }
     if (reader->buffer == NULL)
-        reader->buffer = xmlBufferCreateSize(100);
+        reader->buffer = xmlBufCreateSize(100);
     if (reader->buffer == NULL) {
         xmlGenericError(xmlGenericErrorContext,
                         "xmlTextReaderSetup : malloc failed\n");
@@ -5005,13 +5154,14 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
     reader->node = NULL;
     reader->curnode = NULL;
     if (input != NULL) {
-        if (reader->input->buffer->use < 4) {
+        if (xmlBufUse(reader->input->buffer) < 4) {
             xmlParserInputBufferRead(input, 4);
         }
         if (reader->ctxt == NULL) {
-            if (reader->input->buffer->use >= 4) {
+            if (xmlBufUse(reader->input->buffer) >= 4) {
                 reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL,
-                      (const char *) reader->input->buffer->content, 4, URL);
+                      (const char *) xmlBufContent(reader->input->buffer),
+                                      4, URL);
                 reader->base = 0;
                 reader->cur = 4;
             } else {
@@ -5040,10 +5190,7 @@ xmlTextReaderSetup(xmlTextReaderPtr reader,
                inputStream->filename = (char *)
                    xmlCanonicPath((const xmlChar *) URL);
            inputStream->buf = buf;
-           inputStream->base = inputStream->buf->buffer->content;
-           inputStream->cur = inputStream->buf->buffer->content;
-           inputStream->end =
-            &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
+            xmlBufResetInput(buf->buffer, inputStream);
 
            inputPush(reader->ctxt, inputStream);
            reader->cur = 0;
@@ -5331,8 +5478,11 @@ xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
 
     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
                                          XML_CHAR_ENCODING_NONE);
-    if (input == NULL)
+    if (input == NULL) {
+        if (ioclose != NULL)
+            ioclose(ioctx);
         return (NULL);
+    }
     reader = xmlNewTextReader(input, URL);
     if (reader == NULL) {
         xmlFreeParserInputBuffer(input);
@@ -5549,10 +5699,14 @@ xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread,
 
     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
                                          XML_CHAR_ENCODING_NONE);
-    if (input == NULL)
+    if (input == NULL) {
+        if (ioclose != NULL)
+            ioclose(ioctx);
         return (-1);
+    }
     return (xmlTextReaderSetup(reader, input, URL, encoding, options));
 }
+
 /************************************************************************
  *                                                                     *
  *                     Utilities                                       *