1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-10-26 00:37:43 +03:00

Convert xmlIO.c to the new input and output buffers

Relatively mechanical changes, this also led to a couple of fixes
upon review of the I/O code on buffer usage.
This commit is contained in:
Daniel Veillard
2012-07-16 14:22:54 +08:00
parent 768eb3b82d
commit a6a6e70c47

166
xmlIO.c
View File

@@ -96,6 +96,9 @@
#endif #endif
#include <libxml/globals.h> #include <libxml/globals.h>
#include "buf.h"
#include "enc.h"
/* #define VERBOSE_FAILURE */ /* #define VERBOSE_FAILURE */
/* #define DEBUG_EXTERNAL_ENTITIES */ /* #define DEBUG_EXTERNAL_ENTITIES */
/* #define DEBUG_INPUT */ /* #define DEBUG_INPUT */
@@ -2036,8 +2039,8 @@ xmlIOHTTPCloseWrite( void * context, const char * http_mthd ) {
/* Pull the data out of the memory output buffer */ /* Pull the data out of the memory output buffer */
xmlOutputBufferPtr dctxt = ctxt->doc_buff; xmlOutputBufferPtr dctxt = ctxt->doc_buff;
http_content = (char *)dctxt->buffer->content; http_content = (char *) xmlBufContent(dctxt->buffer);
content_lgth = dctxt->buffer->use; content_lgth = xmlBufUse(dctxt->buffer);
} }
if ( http_content == NULL ) { if ( http_content == NULL ) {
@@ -2404,15 +2407,15 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
return(NULL); return(NULL);
} }
memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer)); memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
ret->buffer = xmlBufferCreateSize(2 * xmlDefaultBufferSize); ret->buffer = xmlBufCreateSize(2 * xmlDefaultBufferSize);
if (ret->buffer == NULL) { if (ret->buffer == NULL) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
} }
ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT; xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
ret->encoder = xmlGetCharEncodingHandler(enc); ret->encoder = xmlGetCharEncodingHandler(enc);
if (ret->encoder != NULL) if (ret->encoder != NULL)
ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize); ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
else else
ret->raw = NULL; ret->raw = NULL;
ret->readcallback = NULL; ret->readcallback = NULL;
@@ -2443,19 +2446,19 @@ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
return(NULL); return(NULL);
} }
memset(ret, 0, (size_t) sizeof(xmlOutputBuffer)); memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
ret->buffer = xmlBufferCreate(); ret->buffer = xmlBufCreate();
if (ret->buffer == NULL) { if (ret->buffer == NULL) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
} }
/* try to avoid a performance problem with Windows realloc() */ /* try to avoid a performance problem with Windows realloc() */
if (ret->buffer->alloc == XML_BUFFER_ALLOC_EXACT) if (xmlBufGetAllocationScheme(ret->buffer) == XML_BUFFER_ALLOC_EXACT)
ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT; xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_DOUBLEIT);
ret->encoder = encoder; ret->encoder = encoder;
if (encoder != NULL) { if (encoder != NULL) {
ret->conv = xmlBufferCreateSize(4000); ret->conv = xmlBufCreateSize(4000);
if (ret->conv == NULL) { if (ret->conv == NULL) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
@@ -2464,7 +2467,7 @@ xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
/* /*
* This call is designed to initiate the encoder state * This call is designed to initiate the encoder state
*/ */
xmlCharEncOutFunc(encoder, ret->conv, NULL); xmlCharEncOutput(ret, 1);
} else } else
ret->conv = NULL; ret->conv = NULL;
ret->writecallback = NULL; ret->writecallback = NULL;
@@ -2493,7 +2496,7 @@ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
return(NULL); return(NULL);
} }
memset(ret, 0, (size_t) sizeof(xmlOutputBuffer)); memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
ret->buffer = xmlBufferCreate(); ret->buffer = xmlBufCreate();
if (ret->buffer == NULL) { if (ret->buffer == NULL) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
@@ -2502,15 +2505,12 @@ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
/* /*
* For conversion buffers we use the special IO handling * For conversion buffers we use the special IO handling
* We don't do that from the exported API to avoid confusing
* user's code.
*/ */
ret->buffer->alloc = XML_BUFFER_ALLOC_IO; xmlBufSetAllocationScheme(ret->buffer, XML_BUFFER_ALLOC_IO);
ret->buffer->contentIO = ret->buffer->content;
ret->encoder = encoder; ret->encoder = encoder;
if (encoder != NULL) { if (encoder != NULL) {
ret->conv = xmlBufferCreateSize(4000); ret->conv = xmlBufCreateSize(4000);
if (ret->conv == NULL) { if (ret->conv == NULL) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
@@ -2519,7 +2519,7 @@ xmlAllocOutputBufferInternal(xmlCharEncodingHandlerPtr encoder) {
/* /*
* This call is designed to initiate the encoder state * This call is designed to initiate the encoder state
*/ */
xmlCharEncOutFunc(encoder, ret->conv, NULL); xmlCharEncOutput(ret, 1);
} else } else
ret->conv = NULL; ret->conv = NULL;
ret->writecallback = NULL; ret->writecallback = NULL;
@@ -2543,7 +2543,7 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
if (in == NULL) return; if (in == NULL) return;
if (in->raw) { if (in->raw) {
xmlBufferFree(in->raw); xmlBufFree(in->raw);
in->raw = NULL; in->raw = NULL;
} }
if (in->encoder != NULL) { if (in->encoder != NULL) {
@@ -2553,7 +2553,7 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
in->closecallback(in->context); in->closecallback(in->context);
} }
if (in->buffer != NULL) { if (in->buffer != NULL) {
xmlBufferFree(in->buffer); xmlBufFree(in->buffer);
in->buffer = NULL; in->buffer = NULL;
} }
@@ -2585,14 +2585,14 @@ xmlOutputBufferClose(xmlOutputBufferPtr out)
} }
written = out->written; written = out->written;
if (out->conv) { if (out->conv) {
xmlBufferFree(out->conv); xmlBufFree(out->conv);
out->conv = NULL; out->conv = NULL;
} }
if (out->encoder != NULL) { if (out->encoder != NULL) {
xmlCharEncCloseFunc(out->encoder); xmlCharEncCloseFunc(out->encoder);
} }
if (out->buffer != NULL) { if (out->buffer != NULL) {
xmlBufferFree(out->buffer); xmlBufFree(out->buffer);
out->buffer = NULL; out->buffer = NULL;
} }
@@ -2974,7 +2974,7 @@ xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) {
ret->context = (void *) mem; ret->context = (void *) mem;
ret->readcallback = (xmlInputReadCallback) xmlNop; ret->readcallback = (xmlInputReadCallback) xmlNop;
ret->closecallback = NULL; ret->closecallback = NULL;
errcode = xmlBufferAdd(ret->buffer, (const xmlChar *) mem, size); errcode = xmlBufAdd(ret->buffer, (const xmlChar *) mem, size);
if (errcode != 0) { if (errcode != 0) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
@@ -3011,14 +3011,14 @@ xmlParserInputBufferCreateStatic(const char *mem, int size,
return(NULL); return(NULL);
} }
memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer)); memset(ret, 0, (size_t) sizeof(xmlParserInputBuffer));
ret->buffer = xmlBufferCreateStatic((void *)mem, (size_t) size); ret->buffer = xmlBufCreateStatic((void *)mem, (size_t) size);
if (ret->buffer == NULL) { if (ret->buffer == NULL) {
xmlFree(ret); xmlFree(ret);
return(NULL); return(NULL);
} }
ret->encoder = xmlGetCharEncodingHandler(enc); ret->encoder = xmlGetCharEncodingHandler(enc);
if (ret->encoder != NULL) if (ret->encoder != NULL)
ret->raw = xmlBufferCreateSize(2 * xmlDefaultBufferSize); ret->raw = xmlBufCreateSize(2 * xmlDefaultBufferSize);
else else
ret->raw = NULL; ret->raw = NULL;
ret->compressed = -1; ret->compressed = -1;
@@ -3187,26 +3187,26 @@ xmlParserInputBufferPush(xmlParserInputBufferPtr in,
* Store the data in the incoming raw buffer * Store the data in the incoming raw buffer
*/ */
if (in->raw == NULL) { if (in->raw == NULL) {
in->raw = xmlBufferCreate(); in->raw = xmlBufCreate();
} }
ret = xmlBufferAdd(in->raw, (const xmlChar *) buf, len); ret = xmlBufAdd(in->raw, (const xmlChar *) buf, len);
if (ret != 0) if (ret != 0)
return(-1); return(-1);
/* /*
* convert as much as possible to the parser reading buffer. * convert as much as possible to the parser reading buffer.
*/ */
use = in->raw->use; use = xmlBufUse(in->raw);
nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); nbchars = xmlCharEncInput(in);
if (nbchars < 0) { if (nbchars < 0) {
xmlIOErr(XML_IO_ENCODER, NULL); xmlIOErr(XML_IO_ENCODER, NULL);
in->error = XML_IO_ENCODER; in->error = XML_IO_ENCODER;
return(-1); return(-1);
} }
in->rawconsumed += (use - in->raw->use); in->rawconsumed += (use - xmlBufUse(in->raw));
} else { } else {
nbchars = len; nbchars = len;
ret = xmlBufferAdd(in->buffer, (xmlChar *) buf, nbchars); ret = xmlBufAdd(in->buffer, (xmlChar *) buf, nbchars);
if (ret != 0) if (ret != 0)
return(-1); return(-1);
} }
@@ -3251,29 +3251,23 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
char *buffer = NULL; char *buffer = NULL;
int res = 0; int res = 0;
int nbchars = 0; int nbchars = 0;
int buffree;
unsigned int needSize;
if ((in == NULL) || (in->error)) return(-1); if ((in == NULL) || (in->error)) return(-1);
if ((len <= MINLEN) && (len != 4)) if ((len <= MINLEN) && (len != 4))
len = MINLEN; len = MINLEN;
buffree = in->buffer->size - in->buffer->use; if (xmlBufAvail(in->buffer) <= 0) {
if (buffree <= 0) {
xmlIOErr(XML_IO_BUFFER_FULL, NULL); xmlIOErr(XML_IO_BUFFER_FULL, NULL);
in->error = XML_IO_BUFFER_FULL; in->error = XML_IO_BUFFER_FULL;
return(-1); return(-1);
} }
needSize = in->buffer->use + len + 1; if (xmlBufGrow(in->buffer, len + 1) < 0) {
if (needSize > in->buffer->size){
if (!xmlBufferResize(in->buffer, needSize)){
xmlIOErrMemory("growing input buffer"); xmlIOErrMemory("growing input buffer");
in->error = XML_ERR_NO_MEMORY; in->error = XML_ERR_NO_MEMORY;
return(-1); return(-1);
} }
} buffer = (char *)xmlBufEnd(in->buffer);
buffer = (char *)&in->buffer->content[in->buffer->use];
/* /*
* Call the read method for this I/O type. * Call the read method for this I/O type.
@@ -3298,32 +3292,31 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
* Store the data in the incoming raw buffer * Store the data in the incoming raw buffer
*/ */
if (in->raw == NULL) { if (in->raw == NULL) {
in->raw = xmlBufferCreate(); in->raw = xmlBufCreate();
} }
res = xmlBufferAdd(in->raw, (const xmlChar *) buffer, len); res = xmlBufAdd(in->raw, (const xmlChar *) buffer, len);
if (res != 0) if (res != 0)
return(-1); return(-1);
/* /*
* convert as much as possible to the parser reading buffer. * convert as much as possible to the parser reading buffer.
*/ */
use = in->raw->use; use = xmlBufUse(in->raw);
nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw); nbchars = xmlCharEncInput(in);
if (nbchars < 0) { if (nbchars < 0) {
xmlIOErr(XML_IO_ENCODER, NULL); xmlIOErr(XML_IO_ENCODER, NULL);
in->error = XML_IO_ENCODER; in->error = XML_IO_ENCODER;
return(-1); return(-1);
} }
in->rawconsumed += (use - in->raw->use); in->rawconsumed += (use - xmlBufUse(in->raw));
} else { } else {
nbchars = len; nbchars = len;
in->buffer->use += nbchars; xmlBufAddLen(in->buffer, nbchars);
buffer[nbchars] = 0;
} }
#ifdef DEBUG_INPUT #ifdef DEBUG_INPUT
xmlGenericError(xmlGenericErrorContext, xmlGenericError(xmlGenericErrorContext,
"I/O: read %d chars, buffer %d/%d\n", "I/O: read %d chars, buffer %d\n",
nbchars, in->buffer->use, in->buffer->size); nbchars, xmlBufUse(in->buffer));
#endif #endif
return(nbchars); return(nbchars);
} }
@@ -3345,8 +3338,7 @@ xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
if ((in == NULL) || (in->error)) return(-1); if ((in == NULL) || (in->error)) return(-1);
if (in->readcallback != NULL) if (in->readcallback != NULL)
return(xmlParserInputBufferGrow(in, len)); return(xmlParserInputBufferGrow(in, len));
else if ((in->buffer != NULL) && else if (xmlBufGetAllocationScheme(in->buffer) == XML_BUFFER_ALLOC_IMMUTABLE)
(in->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE))
return(0); return(0);
else else
return(-1); return(-1);
@@ -3391,30 +3383,30 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
* Store the data in the incoming raw buffer * Store the data in the incoming raw buffer
*/ */
if (out->conv == NULL) { if (out->conv == NULL) {
out->conv = xmlBufferCreate(); out->conv = xmlBufCreate();
} }
ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk); ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
if (ret != 0) if (ret != 0)
return(-1); return(-1);
if ((out->buffer->use < MINLEN) && (chunk == len)) if ((xmlBufUse(out->buffer) < MINLEN) && (chunk == len))
goto done; goto done;
/* /*
* convert as much as possible to the parser reading buffer. * convert as much as possible to the parser reading buffer.
*/ */
ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); ret = xmlCharEncOutput(out, 0);
if ((ret < 0) && (ret != -3)) { if ((ret < 0) && (ret != -3)) {
xmlIOErr(XML_IO_ENCODER, NULL); xmlIOErr(XML_IO_ENCODER, NULL);
out->error = XML_IO_ENCODER; out->error = XML_IO_ENCODER;
return(-1); return(-1);
} }
nbchars = out->conv->use; nbchars = xmlBufUse(out->conv);
} else { } else {
ret = xmlBufferAdd(out->buffer, (const xmlChar *) buf, chunk); ret = xmlBufAdd(out->buffer, (const xmlChar *) buf, chunk);
if (ret != 0) if (ret != 0)
return(-1); return(-1);
nbchars = out->buffer->use; nbchars = xmlBufUse(out->buffer);
} }
buf += chunk; buf += chunk;
len -= chunk; len -= chunk;
@@ -3428,14 +3420,14 @@ xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
*/ */
if (out->encoder != NULL) { if (out->encoder != NULL) {
ret = out->writecallback(out->context, ret = out->writecallback(out->context,
(const char *)out->conv->content, nbchars); (const char *)xmlBufContent(out->conv), nbchars);
if (ret >= 0) if (ret >= 0)
xmlBufferShrink(out->conv, ret); xmlBufShrink(out->conv, ret);
} else { } else {
ret = out->writecallback(out->context, ret = out->writecallback(out->context,
(const char *)out->buffer->content, nbchars); (const char *)xmlBufContent(out->buffer), nbchars);
if (ret >= 0) if (ret >= 0)
xmlBufferShrink(out->buffer, ret); xmlBufShrink(out->buffer, ret);
} }
if (ret < 0) { if (ret < 0) {
xmlIOErr(XML_IO_WRITE, NULL); xmlIOErr(XML_IO_WRITE, NULL);
@@ -3543,7 +3535,8 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
if ((out == NULL) || (out->error) || (str == NULL) || if ((out == NULL) || (out->error) || (str == NULL) ||
(out->buffer == NULL) || (out->buffer == NULL) ||
(out->buffer->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) return(-1); (xmlBufGetAllocationScheme(out->buffer) == XML_BUFFER_ALLOC_IMMUTABLE))
return(-1);
len = strlen((const char *)str); len = strlen((const char *)str);
if (len < 0) return(0); if (len < 0) return(0);
if (out->error) return(-1); if (out->error) return(-1);
@@ -3556,14 +3549,14 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
* how many bytes to consume and how many bytes to store. * how many bytes to consume and how many bytes to store.
*/ */
cons = len; cons = len;
chunk = (out->buffer->size - out->buffer->use) - 1; chunk = xmlBufAvail(out->buffer) - 1;
/* /*
* make sure we have enough room to save first, if this is * make sure we have enough room to save first, if this is
* not the case force a flush, but make sure we stay in the loop * not the case force a flush, but make sure we stay in the loop
*/ */
if (chunk < 40) { if (chunk < 40) {
if (xmlBufferGrow(out->buffer, out->buffer->size + 100) < 0) if (xmlBufGrow(out->buffer, 100) < 0)
return(-1); return(-1);
oldwritten = -1; oldwritten = -1;
continue; continue;
@@ -3577,36 +3570,33 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
* Store the data in the incoming raw buffer * Store the data in the incoming raw buffer
*/ */
if (out->conv == NULL) { if (out->conv == NULL) {
out->conv = xmlBufferCreate(); out->conv = xmlBufCreate();
} }
ret = escaping(out->buffer->content + out->buffer->use , ret = escaping(xmlBufEnd(out->buffer) ,
&chunk, str, &cons); &chunk, str, &cons);
if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
return(-1); return(-1);
out->buffer->use += chunk; xmlBufAddLen(out->buffer, chunk);
out->buffer->content[out->buffer->use] = 0;
if ((out->buffer->use < MINLEN) && (cons == len)) if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len))
goto done; goto done;
/* /*
* convert as much as possible to the output buffer. * convert as much as possible to the output buffer.
*/ */
ret = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); ret = xmlCharEncOutput(out, 0);
if ((ret < 0) && (ret != -3)) { if ((ret < 0) && (ret != -3)) {
xmlIOErr(XML_IO_ENCODER, NULL); xmlIOErr(XML_IO_ENCODER, NULL);
out->error = XML_IO_ENCODER; out->error = XML_IO_ENCODER;
return(-1); return(-1);
} }
nbchars = out->conv->use; nbchars = xmlBufUse(out->conv);
} else { } else {
ret = escaping(out->buffer->content + out->buffer->use , ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
&chunk, str, &cons);
if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */ if ((ret < 0) || (chunk == 0)) /* chunk==0 => nothing done */
return(-1); return(-1);
out->buffer->use += chunk; xmlBufAddLen(out->buffer, chunk);
out->buffer->content[out->buffer->use] = 0; nbchars = xmlBufUse(out->buffer);
nbchars = out->buffer->use;
} }
str += cons; str += cons;
len -= cons; len -= cons;
@@ -3620,14 +3610,14 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
*/ */
if (out->encoder != NULL) { if (out->encoder != NULL) {
ret = out->writecallback(out->context, ret = out->writecallback(out->context,
(const char *)out->conv->content, nbchars); (const char *)xmlBufContent(out->conv), nbchars);
if (ret >= 0) if (ret >= 0)
xmlBufferShrink(out->conv, ret); xmlBufShrink(out->conv, ret);
} else { } else {
ret = out->writecallback(out->context, ret = out->writecallback(out->context,
(const char *)out->buffer->content, nbchars); (const char *)xmlBufContent(out->buffer), nbchars);
if (ret >= 0) if (ret >= 0)
xmlBufferShrink(out->buffer, ret); xmlBufShrink(out->buffer, ret);
} }
if (ret < 0) { if (ret < 0) {
xmlIOErr(XML_IO_WRITE, NULL); xmlIOErr(XML_IO_WRITE, NULL);
@@ -3635,8 +3625,8 @@ xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
return(ret); return(ret);
} }
out->written += ret; out->written += ret;
} else if (out->buffer->size - out->buffer->use < MINLEN) { } else if (xmlBufAvail(out->buffer) < MINLEN) {
xmlBufferResize(out->buffer, out->buffer->size + MINLEN); xmlBufGrow(out->buffer, MINLEN);
} }
written += nbchars; written += nbchars;
} while ((len > 0) && (oldwritten != written)); } while ((len > 0) && (oldwritten != written));
@@ -3696,7 +3686,7 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) {
/* /*
* convert as much as possible to the parser reading buffer. * convert as much as possible to the parser reading buffer.
*/ */
nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer); nbchars = xmlCharEncOutput(out, 0);
if (nbchars < 0) { if (nbchars < 0) {
xmlIOErr(XML_IO_ENCODER, NULL); xmlIOErr(XML_IO_ENCODER, NULL);
out->error = XML_IO_ENCODER; out->error = XML_IO_ENCODER;
@@ -3710,14 +3700,16 @@ xmlOutputBufferFlush(xmlOutputBufferPtr out) {
if ((out->conv != NULL) && (out->encoder != NULL) && if ((out->conv != NULL) && (out->encoder != NULL) &&
(out->writecallback != NULL)) { (out->writecallback != NULL)) {
ret = out->writecallback(out->context, ret = out->writecallback(out->context,
(const char *)out->conv->content, out->conv->use); (const char *)xmlBufContent(out->conv),
xmlBufUse(out->conv));
if (ret >= 0) if (ret >= 0)
xmlBufferShrink(out->conv, ret); xmlBufShrink(out->conv, ret);
} else if (out->writecallback != NULL) { } else if (out->writecallback != NULL) {
ret = out->writecallback(out->context, ret = out->writecallback(out->context,
(const char *)out->buffer->content, out->buffer->use); (const char *)xmlBufContent(out->buffer),
xmlBufUse(out->buffer));
if (ret >= 0) if (ret >= 0)
xmlBufferShrink(out->buffer, ret); xmlBufShrink(out->buffer, ret);
} }
if (ret < 0) { if (ret < 0) {
xmlIOErr(XML_IO_FLUSH, NULL); xmlIOErr(XML_IO_FLUSH, NULL);