mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-29 11:41:22 +03:00
- Large resync between W3C and Gnome tree
- configure.in: 2.1.0 prerelease - example/Makefile.am example/gjobread.c tree.h: work on libxml1 libxml2 convergence. - nanoftp, nanohttp.c: fixed stalled connections probs - HTMLtree.c SAX.c : support for attribute without values in HTML for andersca - valid.c: Fixed most validation + namespace problems - HTMLparser.c: start document callback for andersca - debugXML.c xpath.c: lots of XPath fixups from Picdar Technology - parser.h, SAX.c: serious speed improvement for large CDATA blocks - encoding.[ch] xmlIO.[ch]: Improved seriously saving to different encoding - config.h.in parser.c xmllint.c: added xmlCheckVersion() and the LIBXML_TEST_VERSION macro Daniel
This commit is contained in:
627
xmlIO.c
627
xmlIO.c
@ -41,9 +41,9 @@
|
||||
#include <libxml/nanohttp.h>
|
||||
#include <libxml/nanoftp.h>
|
||||
|
||||
/* #define DEBUG_INPUT */
|
||||
/* #define VERBOSE_FAILURE */
|
||||
/* #define DEBUG_EXTERNAL_ENTITIES */
|
||||
/* #define DEBUG_INPUT */
|
||||
|
||||
#ifdef DEBUG_INPUT
|
||||
#define MINLEN 40
|
||||
@ -67,6 +67,22 @@ xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
|
||||
int xmlInputCallbackNr = 0;
|
||||
int xmlInputCallbackInitialized = 0;
|
||||
|
||||
/*
|
||||
* Output I/O callback sets
|
||||
*/
|
||||
typedef struct _xmlOutputCallback {
|
||||
xmlOutputMatchCallback matchcallback;
|
||||
xmlOutputOpenCallback opencallback;
|
||||
xmlOutputWriteCallback writecallback;
|
||||
xmlOutputCloseCallback closecallback;
|
||||
} xmlOutputCallback;
|
||||
|
||||
#define MAX_OUTPUT_CALLBACK 15
|
||||
|
||||
xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
|
||||
int xmlOutputCallbackNr = 0;
|
||||
int xmlOutputCallbackInitialized = 0;
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Standard I/O for file accesses *
|
||||
@ -123,11 +139,44 @@ xmlFdOpen (const char *filename) {
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFdOpenW:
|
||||
* @filename: the URI for matching
|
||||
*
|
||||
* input from file descriptor,
|
||||
* if @filename is "-" then the standard output is used
|
||||
*
|
||||
* Returns an I/O context or NULL in case of error
|
||||
*/
|
||||
void *
|
||||
xmlFdOpenW (const char *filename) {
|
||||
const char *path = NULL;
|
||||
int fd;
|
||||
|
||||
if (!strcmp(filename, "-")) {
|
||||
fd = 1;
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
if (!strncmp(filename, "file://localhost", 16))
|
||||
path = &filename[16];
|
||||
else if (!strncmp(filename, "file:///", 8))
|
||||
path = &filename[8];
|
||||
else if (filename[0] == '/')
|
||||
path = filename;
|
||||
if (path == NULL)
|
||||
return(NULL);
|
||||
|
||||
fd = open (filename, O_WRONLY);
|
||||
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFdRead:
|
||||
* @context: the I/O context
|
||||
* @buffer: where to drop data
|
||||
* @len: number of bytes to write
|
||||
* @len: number of bytes to read
|
||||
*
|
||||
* Read @len bytes to @buffer from the I/O channel.
|
||||
*
|
||||
@ -138,6 +187,21 @@ xmlFdRead (void * context, char * buffer, int len) {
|
||||
return(read((int) context, &buffer[0], len));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFdWrite:
|
||||
* @context: the I/O context
|
||||
* @buffer: where to get data
|
||||
* @len: number of bytes to write
|
||||
*
|
||||
* Write @len bytes from @buffer to the I/O channel.
|
||||
*
|
||||
* Returns the number of bytes written
|
||||
*/
|
||||
int
|
||||
xmlFdWrite (void * context, const char * buffer, int len) {
|
||||
return(write((int) context, &buffer[0], len));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFdClose:
|
||||
* @context: the I/O context
|
||||
@ -198,6 +262,38 @@ xmlFileOpen (const char *filename) {
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFileOpenW:
|
||||
* @filename: the URI for matching
|
||||
*
|
||||
* output to from FILE *,
|
||||
* if @filename is "-" then the standard output is used
|
||||
*
|
||||
* Returns an I/O context or NULL in case of error
|
||||
*/
|
||||
void *
|
||||
xmlFileOpenW (const char *filename) {
|
||||
const char *path = NULL;
|
||||
FILE *fd;
|
||||
|
||||
if (!strcmp(filename, "-")) {
|
||||
fd = stdout;
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
if (!strncmp(filename, "file://localhost", 16))
|
||||
path = &filename[16];
|
||||
else if (!strncmp(filename, "file:///", 8))
|
||||
path = &filename[8];
|
||||
else
|
||||
path = filename;
|
||||
if (path == NULL)
|
||||
return(NULL);
|
||||
|
||||
fd = fopen(path, "w");
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFileRead:
|
||||
* @context: the I/O context
|
||||
@ -213,6 +309,21 @@ xmlFileRead (void * context, char * buffer, int len) {
|
||||
return(fread(&buffer[0], 1, len, (FILE *) context));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFileWrite:
|
||||
* @context: the I/O context
|
||||
* @buffer: where to drop data
|
||||
* @len: number of bytes to write
|
||||
*
|
||||
* Write @len bytes from @buffer to the I/O channel.
|
||||
*
|
||||
* Returns the number of bytes written
|
||||
*/
|
||||
int
|
||||
xmlFileWrite (void * context, const char * buffer, int len) {
|
||||
return(fwrite(&buffer[0], 1, len, (FILE *) context));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFileClose:
|
||||
* @context: the I/O context
|
||||
@ -273,6 +384,39 @@ xmlGzfileOpen (const char *filename) {
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlGzfileOpenW:
|
||||
* @filename: the URI for matching
|
||||
* @compression: the compression factor (0 - 9 included)
|
||||
*
|
||||
* input from compressed file open
|
||||
* if @filename is " " then the standard input is used
|
||||
*
|
||||
* Returns an I/O context or NULL in case of error
|
||||
*/
|
||||
void *
|
||||
xmlGzfileOpenW (const char *filename, int compression) {
|
||||
const char *path = NULL;
|
||||
char mode[15];
|
||||
gzFile fd;
|
||||
|
||||
sprintf(mode, "w%d", compression);
|
||||
if (!strcmp(filename, "-")) {
|
||||
fd = gzdopen(1, mode);
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
if (!strncmp(filename, "file://localhost", 16))
|
||||
path = &filename[16];
|
||||
else if (!strncmp(filename, "file:///", 8))
|
||||
path = &filename[8];
|
||||
else
|
||||
path = filename;
|
||||
|
||||
fd = gzopen(filename, mode);
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlGzfileRead:
|
||||
* @context: the I/O context
|
||||
@ -288,6 +432,21 @@ xmlGzfileRead (void * context, char * buffer, int len) {
|
||||
return(gzread((gzFile) context, &buffer[0], len));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlGzfileWrite:
|
||||
* @context: the I/O context
|
||||
* @buffer: where to drop data
|
||||
* @len: number of bytes to write
|
||||
*
|
||||
* Write @len bytes from @buffer to the compressed I/O channel.
|
||||
*
|
||||
* Returns the number of bytes written
|
||||
*/
|
||||
int
|
||||
xmlGzfileWrite (void * context, const char * buffer, int len) {
|
||||
return(gzwrite((gzFile) context, (char *) &buffer[0], len));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlGzfileClose:
|
||||
* @context: the I/O context
|
||||
@ -448,6 +607,31 @@ xmlRegisterInputCallbacks(xmlInputMatchCallback match,
|
||||
return(xmlInputCallbackNr++);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlRegisterOutputCallbacks:
|
||||
* @match: the xmlOutputMatchCallback
|
||||
* @open: the xmlOutputOpenCallback
|
||||
* @write: the xmlOutputWriteCallback
|
||||
* @close: the xmlOutputCloseCallback
|
||||
*
|
||||
* Register a new set of I/O callback for handling output.
|
||||
*
|
||||
* Returns the registered handler number or -1 in case of error
|
||||
*/
|
||||
int
|
||||
xmlRegisterOutputCallbacks(xmlOutputMatchCallback match,
|
||||
xmlOutputOpenCallback open, xmlOutputWriteCallback write,
|
||||
xmlOutputCloseCallback close) {
|
||||
if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
|
||||
return(-1);
|
||||
}
|
||||
xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = match;
|
||||
xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = open;
|
||||
xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = write;
|
||||
xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = close;
|
||||
return(xmlOutputCallbackNr++);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlRegisterDefaultInputCallbacks:
|
||||
*
|
||||
@ -473,6 +657,39 @@ xmlRegisterDefaultInputCallbacks(void) {
|
||||
#endif /* LIBXML_FTP_ENABLED */
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlRegisterDefaultOutputCallbacks:
|
||||
*
|
||||
* Registers the default compiled-in I/O handlers.
|
||||
*/
|
||||
void
|
||||
xmlRegisterDefaultOutputCallbacks(void) {
|
||||
xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
|
||||
xmlFileWrite, xmlFileClose);
|
||||
/*********************************
|
||||
No way a-priori to distinguish between gzipped files from
|
||||
uncompressed ones except opening if existing then closing
|
||||
and saving with same compression ratio ... a pain.
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
|
||||
xmlGzfileWrite, xmlGzfileClose);
|
||||
#endif
|
||||
No HTTP PUT support yet, patches welcome
|
||||
|
||||
#ifdef LIBXML_HTTP_ENABLED
|
||||
xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
|
||||
xmlIOHTTPWrite, xmlIOHTTPClose);
|
||||
#endif
|
||||
|
||||
Nor FTP PUT ....
|
||||
#ifdef LIBXML_FTP_ENABLED
|
||||
xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
|
||||
xmlIOFTPWrite, xmlIOFTPClose);
|
||||
#endif
|
||||
**********************************/
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlAllocParserInputBuffer:
|
||||
* @enc: the charset encoding if known
|
||||
@ -509,6 +726,47 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlAllocOutputBuffer:
|
||||
* @encoder: the encoding converter or NULL
|
||||
*
|
||||
* Create a buffered parser output
|
||||
*
|
||||
* Returns the new parser output or NULL
|
||||
*/
|
||||
xmlOutputBufferPtr
|
||||
xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
|
||||
xmlOutputBufferPtr ret;
|
||||
|
||||
ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
|
||||
if (ret == NULL) {
|
||||
fprintf(stderr, "xmlAllocOutputBuffer : out of memory!\n");
|
||||
return(NULL);
|
||||
}
|
||||
memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
|
||||
ret->buffer = xmlBufferCreate();
|
||||
if (ret->buffer == NULL) {
|
||||
xmlFree(ret);
|
||||
return(NULL);
|
||||
}
|
||||
ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
|
||||
ret->encoder = encoder;
|
||||
if (encoder != NULL) {
|
||||
ret->conv = xmlBufferCreateSize(4000);
|
||||
/*
|
||||
* This call is designed to initiate the encoder state
|
||||
*/
|
||||
xmlCharEncOutFunc(encoder, ret->conv, NULL);
|
||||
} else
|
||||
ret->conv = NULL;
|
||||
ret->writecallback = NULL;
|
||||
ret->closecallback = NULL;
|
||||
ret->context = NULL;
|
||||
ret->written = 0;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlFreeParserInputBuffer:
|
||||
* @in: a buffered parser input
|
||||
@ -536,6 +794,43 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
|
||||
xmlFree(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferClose:
|
||||
* @out: a buffered output
|
||||
*
|
||||
* flushes and close the output I/O channel
|
||||
* and free up all the associated resources
|
||||
*
|
||||
* Returns the number of byte written or -1 in case of error.
|
||||
*/
|
||||
int
|
||||
xmlOutputBufferClose(xmlOutputBufferPtr out) {
|
||||
int written;
|
||||
|
||||
if (out == NULL)
|
||||
return(-1);
|
||||
xmlOutputBufferFlush(out);
|
||||
if (out->closecallback != NULL) {
|
||||
out->closecallback(out->context);
|
||||
}
|
||||
written = out->written;
|
||||
if (out->conv) {
|
||||
xmlBufferFree(out->conv);
|
||||
out->conv = NULL;
|
||||
}
|
||||
if (out->encoder != NULL) {
|
||||
xmlCharEncCloseFunc(out->encoder);
|
||||
}
|
||||
if (out->buffer != NULL) {
|
||||
xmlBufferFree(out->buffer);
|
||||
out->buffer = NULL;
|
||||
}
|
||||
|
||||
memset(out, 0xbe, (size_t) sizeof(xmlOutputBuffer));
|
||||
xmlFree(out);
|
||||
return(written);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlParserInputBufferCreateFilename:
|
||||
* @URI: a C string containing the URI or filename
|
||||
@ -591,6 +886,80 @@ xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferCreateFilename:
|
||||
* @URI: a C string containing the URI or filename
|
||||
* @encoder: the encoding converter or NULL
|
||||
* @compression: the compression ration (0 none, 9 max).
|
||||
*
|
||||
* Create a buffered output for the progressive saving of a file
|
||||
* If filename is "-' then we use stdout as the output.
|
||||
* Automatic support for ZLIB/Compress compressed document is provided
|
||||
* by default if found at compile-time.
|
||||
* TODO: currently if compression is set, the library only support
|
||||
* writing to a local file.
|
||||
*
|
||||
* Returns the new output or NULL
|
||||
*/
|
||||
xmlOutputBufferPtr
|
||||
xmlOutputBufferCreateFilename(const char *URI,
|
||||
xmlCharEncodingHandlerPtr encoder,
|
||||
int compression) {
|
||||
xmlOutputBufferPtr ret;
|
||||
int i;
|
||||
void *context = NULL;
|
||||
|
||||
if (xmlOutputCallbackInitialized == 0)
|
||||
xmlRegisterDefaultOutputCallbacks();
|
||||
|
||||
if (URI == NULL) return(NULL);
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
if ((compression > 0) && (compression <= 9)) {
|
||||
context = xmlGzfileOpenW(URI, compression);
|
||||
if (context != NULL) {
|
||||
ret = xmlAllocOutputBuffer(encoder);
|
||||
if (ret != NULL) {
|
||||
ret->context = context;
|
||||
ret->writecallback = xmlGzfileWrite;
|
||||
ret->closecallback = xmlGzfileClose;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Try to find one of the output accept method accepting taht scheme
|
||||
* Go in reverse to give precedence to user defined handlers.
|
||||
*/
|
||||
for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
|
||||
if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
|
||||
(xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
|
||||
context = xmlOutputCallbackTable[i].opencallback(URI);
|
||||
if (context != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (context == NULL) {
|
||||
#ifdef DEBUG_INPUT
|
||||
fprintf(stderr, "No output filter matching \"%s\"\n", URI);
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the Output buffer front-end.
|
||||
*/
|
||||
ret = xmlAllocOutputBuffer(encoder);
|
||||
if (ret != NULL) {
|
||||
ret->context = context;
|
||||
ret->writecallback = xmlOutputCallbackTable[i].writecallback;
|
||||
ret->closecallback = xmlOutputCallbackTable[i].closecallback;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlParserInputBufferCreateFile:
|
||||
* @file: a FILE*
|
||||
@ -620,6 +989,35 @@ xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferCreateFile:
|
||||
* @file: a FILE*
|
||||
* @encoder: the encoding converter or NULL
|
||||
*
|
||||
* Create a buffered output for the progressive saving to a FILE *
|
||||
* buffered C I/O
|
||||
*
|
||||
* Returns the new parser output or NULL
|
||||
*/
|
||||
xmlOutputBufferPtr
|
||||
xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
|
||||
xmlOutputBufferPtr ret;
|
||||
|
||||
if (xmlOutputCallbackInitialized == 0)
|
||||
xmlRegisterDefaultOutputCallbacks();
|
||||
|
||||
if (file == NULL) return(NULL);
|
||||
|
||||
ret = xmlAllocOutputBuffer(encoder);
|
||||
if (ret != NULL) {
|
||||
ret->context = file;
|
||||
ret->writecallback = xmlFileWrite;
|
||||
ret->closecallback = xmlFileClose;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlParserInputBufferCreateFd:
|
||||
* @fd: a file descriptor number
|
||||
@ -646,6 +1044,32 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferCreateFd:
|
||||
* @fd: a file descriptor number
|
||||
* @encoder: the encoding converter or NULL
|
||||
*
|
||||
* Create a buffered output for the progressive saving
|
||||
* to a file descriptor
|
||||
*
|
||||
* Returns the new parser output or NULL
|
||||
*/
|
||||
xmlOutputBufferPtr
|
||||
xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
|
||||
xmlOutputBufferPtr ret;
|
||||
|
||||
if (fd < 0) return(NULL);
|
||||
|
||||
ret = xmlAllocOutputBuffer(encoder);
|
||||
if (ret != NULL) {
|
||||
ret->context = (void *) fd;
|
||||
ret->writecallback = xmlFdWrite;
|
||||
ret->closecallback = xmlFdClose;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlParserInputBufferCreateIO:
|
||||
* @ioread: an I/O read function
|
||||
@ -654,7 +1078,7 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
|
||||
* @enc: the charset encoding if known
|
||||
*
|
||||
* Create a buffered parser input for the progressive parsing for the input
|
||||
* from a file descriptor
|
||||
* from an I/O handler
|
||||
*
|
||||
* Returns the new parser input or NULL
|
||||
*/
|
||||
@ -675,11 +1099,41 @@ xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferCreateIO:
|
||||
* @iowrite: an I/O write function
|
||||
* @ioclose: an I/O close function
|
||||
* @ioctx: an I/O handler
|
||||
* @enc: the charset encoding if known
|
||||
*
|
||||
* Create a buffered output for the progressive saving
|
||||
* to an I/O handler
|
||||
*
|
||||
* Returns the new parser output or NULL
|
||||
*/
|
||||
xmlOutputBufferPtr
|
||||
xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
|
||||
xmlOutputCloseCallback ioclose, void *ioctx,
|
||||
xmlCharEncodingHandlerPtr encoder) {
|
||||
xmlOutputBufferPtr ret;
|
||||
|
||||
if (iowrite == NULL) return(NULL);
|
||||
|
||||
ret = xmlAllocOutputBuffer(encoder);
|
||||
if (ret != NULL) {
|
||||
ret->context = (void *) ioctx;
|
||||
ret->writecallback = iowrite;
|
||||
ret->closecallback = ioclose;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlParserInputBufferPush:
|
||||
* @in: a buffered parser input
|
||||
* @buf: an char array
|
||||
* @len: the size in bytes of the array.
|
||||
* @buf: an char array
|
||||
*
|
||||
* Push the content of the arry in the input buffer
|
||||
* This routine handle the I18N transcoding to internal UTF-8
|
||||
@ -769,16 +1223,12 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
|
||||
xmlFree(buffer);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
xmlFree(buffer);
|
||||
return(0);
|
||||
}
|
||||
if (res < 0) {
|
||||
perror ("read error");
|
||||
xmlFree(buffer);
|
||||
return(-1);
|
||||
}
|
||||
len = res;
|
||||
if (in->encoder != NULL) {
|
||||
/*
|
||||
* Store the data in the incoming raw buffer
|
||||
@ -797,7 +1247,7 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
|
||||
return(-1);
|
||||
}
|
||||
} else {
|
||||
nbchars = res;
|
||||
nbchars = len;
|
||||
buffer[nbchars] = 0;
|
||||
xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
|
||||
}
|
||||
@ -827,7 +1277,162 @@ xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
|
||||
if (in->readcallback != NULL)
|
||||
return(xmlParserInputBufferGrow(in, len));
|
||||
else
|
||||
return(0);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferWrite:
|
||||
* @out: a buffered parser output
|
||||
* @len: the size in bytes of the array.
|
||||
* @buf: an char array
|
||||
*
|
||||
* Write the content of the array in the output I/O buffer
|
||||
* This routine handle the I18N transcoding from internal UTF-8
|
||||
* The buffer is lossless, i.e. will store in case of partial
|
||||
* or delayed writes.
|
||||
*
|
||||
* Returns the number of chars immediately written, or -1
|
||||
* in case of error.
|
||||
*/
|
||||
int
|
||||
xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
|
||||
int nbchars = 0, ret;
|
||||
|
||||
if (len < 0) return(0);
|
||||
|
||||
/*
|
||||
* first handle encoding stuff.
|
||||
*/
|
||||
if (out->encoder != NULL) {
|
||||
/*
|
||||
* Store the data in the incoming raw buffer
|
||||
*/
|
||||
if (out->conv == NULL) {
|
||||
out->conv = xmlBufferCreate();
|
||||
}
|
||||
xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
|
||||
|
||||
if (out->buffer->use < MINLEN)
|
||||
return(0);
|
||||
|
||||
/*
|
||||
* convert as much as possible to the parser reading buffer.
|
||||
*/
|
||||
nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
|
||||
if (nbchars < 0) {
|
||||
fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
|
||||
return(-1);
|
||||
}
|
||||
nbchars = out->conv->use;
|
||||
} else {
|
||||
xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
|
||||
nbchars = out->buffer->use;
|
||||
}
|
||||
if (nbchars < MINLEN)
|
||||
return(0);
|
||||
|
||||
/*
|
||||
* second write the stuff to the I/O channel
|
||||
*/
|
||||
if (out->encoder != NULL) {
|
||||
ret = out->writecallback(out->context,
|
||||
(const char *)out->conv->content, nbchars);
|
||||
if (ret >= 0)
|
||||
xmlBufferShrink(out->conv, nbchars);
|
||||
} else {
|
||||
ret = out->writecallback(out->context,
|
||||
(const char *)out->buffer->content, nbchars);
|
||||
if (ret >= 0)
|
||||
xmlBufferShrink(out->buffer, nbchars);
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "I/O: error %d writing %d bytes\n", ret, nbchars);
|
||||
return(ret);
|
||||
}
|
||||
out->written += ret;
|
||||
|
||||
#ifdef DEBUG_INPUT
|
||||
fprintf(stderr, "I/O: wrote %d chars\n", ret);
|
||||
#endif
|
||||
return(nbchars);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferWriteString:
|
||||
* @out: a buffered parser output
|
||||
* @str: a zero terminated C string
|
||||
*
|
||||
* Write the content of the string in the output I/O buffer
|
||||
* This routine handle the I18N transcoding from internal UTF-8
|
||||
* The buffer is lossless, i.e. will store in case of partial
|
||||
* or delayed writes.
|
||||
*
|
||||
* Returns the number of chars immediately written, or -1
|
||||
* in case of error.
|
||||
*/
|
||||
int
|
||||
xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
|
||||
int len;
|
||||
|
||||
if (str == NULL)
|
||||
return(-1);
|
||||
len = strlen(str);
|
||||
|
||||
if (len > 0)
|
||||
return(xmlOutputBufferWrite(out, len, str));
|
||||
return(len);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlOutputBufferFlush:
|
||||
* @out: a buffered output
|
||||
*
|
||||
* flushes the output I/O channel
|
||||
*
|
||||
* Returns the number of byte written or -1 in case of error.
|
||||
*/
|
||||
int
|
||||
xmlOutputBufferFlush(xmlOutputBufferPtr out) {
|
||||
int nbchars = 0, ret;
|
||||
|
||||
/*
|
||||
* first handle encoding stuff.
|
||||
*/
|
||||
if ((out->conv != NULL) && (out->encoder != NULL)) {
|
||||
/*
|
||||
* convert as much as possible to the parser reading buffer.
|
||||
*/
|
||||
nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
|
||||
if (nbchars < 0) {
|
||||
fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* second flush the stuff to the I/O channel
|
||||
*/
|
||||
if ((out->conv != NULL) && (out->encoder != NULL)) {
|
||||
ret = out->writecallback(out->context,
|
||||
(const char *)out->conv->content, out->conv->use);
|
||||
if (ret >= 0)
|
||||
xmlBufferShrink(out->conv, ret);
|
||||
} else {
|
||||
ret = out->writecallback(out->context,
|
||||
(const char *)out->buffer->content, out->buffer->use);
|
||||
if (ret >= 0)
|
||||
xmlBufferShrink(out->buffer, ret);
|
||||
}
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "I/O: error %d flushing %d bytes\n", ret, nbchars);
|
||||
return(ret);
|
||||
}
|
||||
out->written += ret;
|
||||
|
||||
#ifdef DEBUG_INPUT
|
||||
fprintf(stderr, "I/O: flushed %d chars\n", ret);
|
||||
#endif
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user