diff --git a/HTMLparser.c b/HTMLparser.c index 15cf91bb..b9a257bd 100644 --- a/HTMLparser.c +++ b/HTMLparser.c @@ -2243,45 +2243,6 @@ htmlEncodeEntities(unsigned char* out, int *outlen, return(0); } -/************************************************************************ - * * - * Commodity functions to handle streams * - * * - ************************************************************************/ - -#ifdef LIBXML_PUSH_ENABLED -/** - * htmlNewInputStream: - * @ctxt: an HTML parser context - * - * Create a new input stream structure - * Returns the new input stream or NULL - */ -static htmlParserInputPtr -htmlNewInputStream(htmlParserCtxtPtr ctxt) { - htmlParserInputPtr input; - - input = (xmlParserInputPtr) xmlMalloc(sizeof(htmlParserInput)); - if (input == NULL) { - htmlErrMemory(ctxt); - return(NULL); - } - memset(input, 0, sizeof(htmlParserInput)); - input->filename = NULL; - input->base = NULL; - input->cur = NULL; - input->buf = NULL; - input->line = 1; - input->col = 1; - input->buf = NULL; - input->free = NULL; - input->version = NULL; - input->consumed = 0; - return(input); -} -#endif - - /************************************************************************ * * * Commodity functions, cleanup needed ? * @@ -3272,12 +3233,11 @@ htmlParseExternalID(htmlParserCtxtPtr ctxt, xmlChar **publicID) { } /** - * xmlParsePI: - * @ctxt: an XML parser context + * htmlParsePI: + * @ctxt: an HTML parser context * - * parse an XML Processing Instruction. - * - * [16] PI ::= '' Char*)))? '?>' + * Parse an XML Processing Instruction. HTML5 doesn't allow processing + * instructions, so this will be removed at some point. */ static void htmlParsePI(htmlParserCtxtPtr ctxt) { @@ -3388,9 +3348,7 @@ done: * htmlParseComment: * @ctxt: an HTML parser context * - * Parse an XML (SGML) comment - * - * [15] Comment ::= '' + * Parse an HTML comment */ static void htmlParseComment(htmlParserCtxtPtr ctxt) { @@ -4781,19 +4739,17 @@ __htmlParseContent(void *ctxt) { * htmlParseDocument: * @ctxt: an HTML parser context * - * parse an HTML document (and build a tree if using the standard SAX - * interface). + * Parse an HTML document and invoke the SAX handlers. This is useful + * if you're only interested in custom SAX callbacks. If you want a + * document tree, use htmlCtxtParseDocument. * - * Returns 0, -1 in case of error. the parser context is augmented - * as a result of the parsing. + * Returns 0, -1 in case of error. */ int htmlParseDocument(htmlParserCtxtPtr ctxt) { xmlDtdPtr dtd; - xmlInitParser(); - if ((ctxt == NULL) || (ctxt->input == NULL)) return(-1); @@ -5007,7 +4963,19 @@ htmlFreeParserCtxt(htmlParserCtxtPtr ctxt) /** * htmlNewParserCtxt: * - * Allocate and initialize a new parser context. + * Allocate and initialize a new HTML parser context. + * + * This can be used to parse HTML documents into DOM trees with + * functions like xmlCtxtReadFile or xmlCtxtReadMemory. + * + * See htmlCtxtUseOptions for parser options. + * + * See xmlCtxtSetErrorHandler for advanced error handling. + * + * See xmlNewInputURL, xmlNewInputMemory, xmlNewInputIO and similar + * functions for advanced input control. + * + * See htmlNewSAXParserCtxt for custom SAX parsers. * * Returns the htmlParserCtxtPtr or NULL in case of allocation error */ @@ -5023,8 +4991,14 @@ htmlNewParserCtxt(void) * @sax: SAX handler * @userData: user data * - * Allocate and initialize a new SAX parser context. If userData is NULL, - * the parser context will be passed as user data. + * Allocate and initialize a new HTML SAX parser context. If userData + * is NULL, the parser context will be passed as user data. + * + * Available since 2.11.0. If you want support older versions, + * it's best to invoke htmlNewParserCtxt and set ctxt->sax with + * struct assignment. + * + * Also see htmlNewParserCtxt. * * Returns the htmlParserCtxtPtr or NULL in case of allocation error */ @@ -5034,6 +5008,8 @@ htmlNewSAXParserCtxt(const htmlSAXHandler *sax, void *userData) { xmlParserCtxtPtr ctxt; + xmlInitParser(); + ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt)); if (ctxt == NULL) return(NULL); @@ -5045,68 +5021,65 @@ htmlNewSAXParserCtxt(const htmlSAXHandler *sax, void *userData) return(ctxt); } -/** - * htmlCreateMemoryParserCtxt: - * @buffer: a pointer to a char array - * @size: the size of the array - * - * Create a parser context for an HTML in-memory document. The input buffer - * must not contain a terminating null byte. - * - * Returns the new parser context or NULL - */ -htmlParserCtxtPtr -htmlCreateMemoryParserCtxt(const char *buffer, int size) { +static htmlParserCtxtPtr +htmlCreateMemoryParserCtxtInternal(const char *url, + const char *buffer, size_t size, + const char *encoding) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; if (buffer == NULL) return(NULL); - if (size <= 0) - return(NULL); ctxt = htmlNewParserCtxt(); if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); - if (buf == NULL) { + input = xmlNewInputMemory(ctxt, url, buffer, size, encoding, 0); + if (input == NULL) { xmlFreeParserCtxt(ctxt); return(NULL); } - input = xmlNewInputStream(ctxt); - if (input == NULL) { - xmlFreeParserInputBuffer(buf); - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(buf->buffer, input); - inputPush(ctxt, input); + return(ctxt); } +/** + * htmlCreateMemoryParserCtxt: + * @buffer: a pointer to a char array + * @size: the size of the array + * + * DEPRECATED: Use htmlNewParserCtxt and htmlCtxtReadMemory. + * + * Create a parser context for an HTML in-memory document. The input + * buffer must not contain any terminating null bytes. + * + * Returns the new parser context or NULL + */ +htmlParserCtxtPtr +htmlCreateMemoryParserCtxt(const char *buffer, int size) { + if (size <= 0) + return(NULL); + + return(htmlCreateMemoryParserCtxtInternal(NULL, buffer, size, NULL)); +} + /** * htmlCreateDocParserCtxt: * @str: a pointer to an array of xmlChar - * @encoding: optional encoding + * @encoding: encoding (optional) * * Create a parser context for a null-terminated string. * - * A non-NULL encoding overrides encoding declarations in the document. - * * Returns the new parser context or NULL if a memory allocation failed. */ static htmlParserCtxtPtr -htmlCreateDocParserCtxt(const xmlChar *str, const char *encoding) { +htmlCreateDocParserCtxt(const xmlChar *str, const char *url, + const char *encoding) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; if (str == NULL) return(NULL); @@ -5115,28 +5088,14 @@ htmlCreateDocParserCtxt(const xmlChar *str, const char *encoding) { if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateString(str); - if (buf == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input = xmlNewInputStream(ctxt); + input = xmlNewInputString(ctxt, url, (const char *) str, encoding, 0); if (input == NULL) { - xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); return(NULL); } - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(buf->buffer, input); - inputPush(ctxt, input); - if (encoding != NULL) - xmlSwitchEncodingName(ctxt, encoding); - return(ctxt); } @@ -5784,13 +5743,23 @@ done: /** * htmlParseChunk: * @ctxt: an HTML parser context - * @chunk: an char array - * @size: the size in byte of the chunk + * @chunk: chunk of memory + * @size: size of chunk in bytes * @terminate: last chunk indicator * - * Parse a Chunk of memory + * Parse a chunk of memory in push parser mode. * - * Returns zero if no error, the xmlParserErrors otherwise. + * Assumes that the parser context was initialized with + * htmlCreatePushParserCtxt. + * + * The last chunk, which will often be empty, must be marked with + * the @terminate flag. With the default SAX callbacks, the resulting + * document will be available in ctxt->myDoc. This pointer will not + * be freed by the library. + * + * If the document isn't well-formed, ctxt->myDoc is set to NULL. + * + * Returns an xmlParserErrors code (0 on success). */ int htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, @@ -5832,72 +5801,37 @@ htmlParseChunk(htmlParserCtxtPtr ctxt, const char *chunk, int size, /** * htmlCreatePushParserCtxt: - * @sax: a SAX handler - * @user_data: The user data returned on SAX callbacks - * @chunk: a pointer to an array of chars + * @sax: a SAX handler (optional) + * @user_data: The user data returned on SAX callbacks (optional) + * @chunk: a pointer to an array of chars (optional) * @size: number of chars in the array - * @filename: an optional file name or URI - * @enc: an optional encoding + * @filename: only used for error reporting (optional) + * @enc: encoding (deprecated, pass XML_CHAR_ENCODING_NONE) * - * Create a parser context for using the HTML parser in push mode - * The value of @filename is used for fetching external entities - * and error/warning reports. + * Create a parser context for using the HTML parser in push mode. * - * Returns the new parser context or NULL + * Returns the new parser context or NULL if a memory allocation + * failed. */ htmlParserCtxtPtr htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data, const char *chunk, int size, const char *filename, xmlCharEncoding enc) { htmlParserCtxtPtr ctxt; - htmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; - - xmlInitParser(); - - buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); - if (buf == NULL) return(NULL); + htmlParserInputPtr input; + const char *encoding; ctxt = htmlNewSAXParserCtxt(sax, user_data); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(buf); + if (ctxt == NULL) + return(NULL); + + encoding = xmlGetCharEncodingName(enc); + input = xmlNewInputPush(ctxt, filename, chunk, size, encoding); + if (input == NULL) { + htmlFreeParserCtxt(ctxt); return(NULL); } - inputStream = htmlNewInputStream(ctxt); - if (inputStream == NULL) { - xmlFreeParserCtxt(ctxt); - xmlFreeParserInputBuffer(buf); - return(NULL); - } - - inputStream->flags |= XML_INPUT_PROGRESSIVE; - - if (filename == NULL) - inputStream->filename = NULL; - else - inputStream->filename = (char *) - xmlCanonicPath((const xmlChar *) filename); - inputStream->buf = buf; - xmlBufResetInput(buf->buffer, inputStream); - - inputPush(ctxt, inputStream); - - if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && - (ctxt->input->buf != NULL)) { - size_t pos = ctxt->input->cur - ctxt->input->base; - int res; - - res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); - if (res < 0) { - htmlParseErr(ctxt, ctxt->input->buf->error, - "xmlParserInputBufferPush failed\n", NULL, NULL); - xmlHaltParser(ctxt); - } - } - - if (enc != XML_CHAR_ENCODING_NONE) - xmlSwitchEncoding(ctxt, enc); + inputPush(ctxt, input); return(ctxt); } @@ -5926,25 +5860,20 @@ htmlSAXParseDoc(const xmlChar *cur, const char *encoding, htmlDocPtr ret; htmlParserCtxtPtr ctxt; - xmlInitParser(); + if (cur == NULL) + return(NULL); - if (cur == NULL) return(NULL); + ctxt = htmlCreateDocParserCtxt(cur, NULL, encoding); + if (ctxt == NULL) + return(NULL); - - ctxt = htmlCreateDocParserCtxt(cur, encoding); - if (ctxt == NULL) return(NULL); if (sax != NULL) { - if (ctxt->sax != NULL) xmlFree (ctxt->sax); - ctxt->sax = sax; + *ctxt->sax = *sax; ctxt->userData = userData; } htmlParseDocument(ctxt); ret = ctxt->myDoc; - if (sax != NULL) { - ctxt->sax = NULL; - ctxt->userData = NULL; - } htmlFreeParserCtxt(ctxt); return(ret); @@ -5953,9 +5882,13 @@ htmlSAXParseDoc(const xmlChar *cur, const char *encoding, /** * htmlParseDoc: * @cur: a pointer to an array of xmlChar - * @encoding: a free form C string describing the HTML document encoding, or NULL + * @encoding: the encoding (optional) * - * parse an HTML in-memory document and build a tree. + * DEPRECATED: Use htmlReadDoc. + * + * Parse an HTML in-memory document and build a tree. + * + * This function uses deprecated global parser options. * * Returns the resulting document tree */ @@ -5971,6 +5904,8 @@ htmlParseDoc(const xmlChar *cur, const char *encoding) { * @filename: the filename * @encoding: optional encoding * + * DEPRECATED: Use htmlNewParserCtxt and htmlCtxtReadFile. + * * Create a parser context to read from a file. * * A non-NULL encoding overrides encoding declarations in the document. @@ -5984,8 +5919,7 @@ htmlParserCtxtPtr htmlCreateFileParserCtxt(const char *filename, const char *encoding) { htmlParserCtxtPtr ctxt; - htmlParserInputPtr inputStream; - char *canonicFilename; + htmlParserInputPtr input; if (filename == NULL) return(NULL); @@ -5994,23 +5928,13 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding) if (ctxt == NULL) { return(NULL); } - canonicFilename = (char *) xmlCanonicPath((const xmlChar *) filename); - if (canonicFilename == NULL) { + + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + if (input == NULL) { xmlFreeParserCtxt(ctxt); return(NULL); } - - inputStream = xmlLoadExternalEntity(canonicFilename, NULL, ctxt); - xmlFree(canonicFilename); - if (inputStream == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - inputPush(ctxt, inputStream); - - if (encoding != NULL) - xmlSwitchEncodingName(ctxt, encoding); + inputPush(ctxt, input); return(ctxt); } @@ -6018,7 +5942,7 @@ htmlCreateFileParserCtxt(const char *filename, const char *encoding) /** * htmlSAXParseFile: * @filename: the filename - * @encoding: a free form C string describing the HTML document encoding, or NULL + * @encoding: encoding (optional) * @sax: the SAX handler block * @userData: if using SAX, this pointer will be provided on callbacks. * @@ -6040,8 +5964,6 @@ htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr s htmlParserCtxtPtr ctxt; htmlSAXHandlerPtr oldsax = NULL; - xmlInitParser(); - ctxt = htmlCreateFileParserCtxt(filename, encoding); if (ctxt == NULL) return(NULL); if (sax != NULL) { @@ -6065,10 +5987,11 @@ htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr s /** * htmlParseFile: * @filename: the filename - * @encoding: a free form C string describing the HTML document encoding, or NULL + * @encoding: encoding (optional) * - * parse an HTML file and build a tree. Automatic support for ZLIB/Compress - * compressed document is provided by default if found at compile-time. + * Parse an HTML file and build a tree. + * + * See xmlNewInputURL for details. * * Returns the resulting document tree */ @@ -6239,7 +6162,6 @@ htmlCtxtReset(htmlParserCtxtPtr ctxt) if (ctxt == NULL) return; - xmlInitParser(); dict = ctxt->dict; while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */ @@ -6389,262 +6311,293 @@ htmlCtxtUseOptions(htmlParserCtxtPtr ctxt, int options) } /** - * htmlDoRead: + * htmlCtxtParseDocument: * @ctxt: an HTML parser context - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) - * @reuse: keep the context for reuse * - * Common front-end for the htmlRead functions + * Parse an HTML document and return the resulting document tree. * * Returns the resulting document tree or NULL */ -static htmlDocPtr -htmlDoRead(htmlParserCtxtPtr ctxt, const char *URL, const char *encoding, - int options, int reuse) +htmlDocPtr +htmlCtxtParseDocument(htmlParserCtxtPtr ctxt) { htmlDocPtr ret; - htmlCtxtUseOptions(ctxt, options); ctxt->html = 1; - if (encoding != NULL) - xmlSwitchEncodingName(ctxt, encoding); - if ((URL != NULL) && (ctxt->input != NULL) && - (ctxt->input->filename == NULL)) - ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); htmlParseDocument(ctxt); - if (ctxt->errNo == XML_ERR_NO_MEMORY) { + + if (ctxt->errNo != XML_ERR_NO_MEMORY) { + ret = ctxt->myDoc; + } else { + ret = NULL; xmlFreeDoc(ctxt->myDoc); - ctxt->myDoc = NULL; } - ret = ctxt->myDoc; ctxt->myDoc = NULL; - if (!reuse) { - if ((ctxt->dictNames) && - (ret != NULL) && - (ret->dict == ctxt->dict)) - ctxt->dict = NULL; - xmlFreeParserCtxt(ctxt); - } - return (ret); + + return(ret); } /** * htmlReadDoc: - * @cur: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @str: a pointer to a zero terminated string + * @url: only used for error reporting (optoinal) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions * - * parse an XML in-memory document and build a tree. + * Convenience function to parse an HTML document from a zero-terminated + * string. * - * Returns the resulting document tree + * See htmlCtxtReadDoc for details. + * + * Returns the resulting document tree. */ htmlDocPtr -htmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options) +htmlReadDoc(const xmlChar *str, const char *url, const char *encoding, + int options) { htmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + htmlDocPtr doc; - if (cur == NULL) - return (NULL); - - xmlInitParser(); - ctxt = htmlCreateDocParserCtxt(cur, NULL); + ctxt = htmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputString(ctxt, url, (const char *) str, encoding, + XML_INPUT_BUF_STATIC); + if (input == NULL) { + htmlFreeParserCtxt(ctxt); + return(NULL); + } + inputPush(ctxt, input); + + doc = htmlCtxtParseDocument(ctxt); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadFile: * @filename: a file or URL - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions * - * parse an XML file from the filesystem or the network. + * Convenience function to parse an HTML file from the filesystem, + * the network or a global user-defined resource loader. * - * Returns the resulting document tree + * See htmlCtxtReadFile for details. + * + * Returns the resulting document tree. */ htmlDocPtr htmlReadFile(const char *filename, const char *encoding, int options) { htmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + htmlDocPtr doc; - xmlInitParser(); - ctxt = htmlCreateFileParserCtxt(filename, encoding); + ctxt = htmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (htmlDoRead(ctxt, NULL, NULL, options, 0)); + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + if (input == NULL) { + htmlFreeParserCtxt(ctxt); + return(NULL); + } + inputPush(ctxt, input); + + doc = htmlCtxtParseDocument(ctxt); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadMemory: * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document + * @url: only used for error reporting (optional) * @encoding: the document encoding, or NULL * @options: a combination of htmlParserOption(s) * - * Parse an HTML in-memory document and build a tree. The input buffer must - * not contain a terminating null byte. + * Convenience function to parse an HTML document from memory. + * The input buffer must not contain any terminating null bytes. + * + * See htmlCtxtReadMemory for details. * * Returns the resulting document tree */ htmlDocPtr -htmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options) +htmlReadMemory(const char *buffer, int size, const char *url, + const char *encoding, int options) { htmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + htmlDocPtr doc; - xmlInitParser(); - ctxt = htmlCreateMemoryParserCtxt(buffer, size); + if (size < 0) + return(NULL); + + ctxt = htmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputMemory(ctxt, url, buffer, size, encoding, + XML_INPUT_BUF_STATIC); + if (input == NULL) { + htmlFreeParserCtxt(ctxt); + return(NULL); + } + inputPush(ctxt, input); + + doc = htmlCtxtParseDocument(ctxt); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadFd: * @fd: an open file descriptor - * @URL: the base URL to use for the document + * @url: only used for error reporting (optional) * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @options: a combination of htmlParserOptions + * + * Convenience function to parse an HTML document from a + * file descriptor. * - * parse an HTML from a file descriptor and build a tree. * NOTE that the file descriptor will not be closed when the - * reader is closed or reset. + * context is freed or reset. + * + * See htmlCtxtReadFd for details. * * Returns the resulting document tree */ htmlDocPtr -htmlReadFd(int fd, const char *URL, const char *encoding, int options) +htmlReadFd(int fd, const char *url, const char *encoding, int options) { htmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - htmlParserInputPtr stream; + xmlParserInputPtr input; + htmlDocPtr doc; - if (fd < 0) - return (NULL); - - xmlInitParser(); - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); - if (input == NULL) - return (NULL); - input->closecallback = NULL; ctxt = htmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); + if (ctxt == NULL) + return(NULL); + + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputFd(ctxt, url, fd, encoding, 0); + if (input == NULL) { htmlFreeParserCtxt(ctxt); - return (NULL); + return(NULL); } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + input->buf->closecallback = NULL; + inputPush(ctxt, input); + + doc = htmlCtxtParseDocument(ctxt); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlReadIO: * @ioread: an I/O read function - * @ioclose: an I/O close function + * @ioclose: an I/O close function (optional) * @ioctx: an I/O handler - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @url: only used for error reporting (optional) + * @encoding: the document encoding (optional) * @options: a combination of htmlParserOption(s) * - * parse an HTML document from I/O functions and source and build a tree. + * Convenience function to parse an HTML document from I/O functions + * and context. + * + * See htmlCtxtReadIO for details. * * Returns the resulting document tree */ htmlDocPtr htmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, - void *ioctx, const char *URL, const char *encoding, int options) + void *ioctx, const char *url, const char *encoding, int options) { htmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; + htmlDocPtr doc; - if (ioread == NULL) + ctxt = htmlNewParserCtxt(); + if (ctxt == NULL) return (NULL); - xmlInitParser(); - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); + htmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputIO(ctxt, url, ioread, ioclose, ioctx, encoding, 0); if (input == NULL) { if (ioclose != NULL) ioclose(ioctx); - return (NULL); + htmlFreeParserCtxt(ctxt); + return(NULL); } - ctxt = htmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - xmlFreeParserCtxt(ctxt); - return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 0)); + inputPush(ctxt, input); + + doc = htmlCtxtParseDocument(ctxt); + + htmlFreeParserCtxt(ctxt); + return(doc); } /** * htmlCtxtReadDoc: * @ctxt: an HTML parser context * @str: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @URL: only used for error reporting (optional) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions * - * parse an XML in-memory document and build a tree. - * This reuses the existing @ctxt parser context + * Parse an HTML in-memory document and build a tree. + * + * See htmlCtxtUseOptions for details. * * Returns the resulting document tree */ htmlDocPtr htmlCtxtReadDoc(htmlParserCtxtPtr ctxt, const xmlChar *str, - const char *URL, const char *encoding, int options) + const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; if (ctxt == NULL) return (NULL); - if (str == NULL) - return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateString(str); - if (input == NULL) { + input = xmlNewInputString(ctxt, URL, (const char *) str, encoding, 0); + if (input == NULL) return(NULL); - } + inputPush(ctxt, input); - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } - - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + return(htmlCtxtParseDocument(ctxt)); } /** * htmlCtxtReadFile: * @ctxt: an HTML parser context * @filename: a file or URL - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @encoding: the document encoding (optional) + * @options: a combination of htmlParserOptions * - * parse an XML file from the filesystem or the network. - * This reuses the existing @ctxt parser context + * Parse an HTML file from the filesystem, the network or a + * user-defined resource loader. + * + * See xmlNewInputURL and htmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -6652,22 +6605,20 @@ htmlDocPtr htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename, const char *encoding, int options) { - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (filename == NULL) - return (NULL); if (ctxt == NULL) return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - stream = xmlLoadExternalEntity(filename, NULL, ctxt); - if (stream == NULL) { + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + if (input == NULL) return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, NULL, encoding, options, 1)); + inputPush(ctxt, input); + + return(htmlCtxtParseDocument(ctxt)); } /** @@ -6675,13 +6626,14 @@ htmlCtxtReadFile(htmlParserCtxtPtr ctxt, const char *filename, * @ctxt: an HTML parser context * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @URL: only used for error reporting (optional) + * @encoding: the document encoding (optinal) + * @options: a combination of htmlParserOptions * * Parse an HTML in-memory document and build a tree. The input buffer must - * not contain a terminating null byte. - * This reuses the existing @ctxt parser context + * not contain any terminating null bytes. + * + * See htmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -6689,44 +6641,37 @@ htmlDocPtr htmlCtxtReadMemory(htmlParserCtxtPtr ctxt, const char *buffer, int size, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ctxt == NULL) + if ((ctxt == NULL) || (size < 0)) return (NULL); - if (buffer == NULL) - return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateStatic(buffer, size, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - htmlErrMemory(ctxt); + input = xmlNewInputMemory(ctxt, URL, buffer, size, encoding, + XML_INPUT_BUF_STATIC); + if (input == NULL) return(NULL); - } + inputPush(ctxt, input); - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } - - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + return(htmlCtxtParseDocument(ctxt)); } /** * htmlCtxtReadFd: * @ctxt: an HTML parser context * @fd: an open file descriptor - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of htmlParserOption(s) + * @URL: only used for error reporting (optional) + * @encoding: the document encoding (optinal) + * @options: a combination of htmlParserOptions * - * parse an XML from a file descriptor and build a tree. - * This reuses the existing @ctxt parser context + * Parse an HTML from a file descriptor and build a tree. + * + * See htmlCtxtUseOptions for details. + * + * NOTE that the file descriptor will not be closed when the + * context is freed or reset. * * Returns the resulting document tree */ @@ -6734,29 +6679,21 @@ htmlDocPtr htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (fd < 0) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + input = xmlNewInputFd(ctxt, URL, fd, encoding, 0); if (input == NULL) return (NULL); - input->closecallback = NULL; - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + input->buf->closecallback = NULL; + inputPush(ctxt, input); + + return(htmlCtxtParseDocument(ctxt)); } /** @@ -6769,8 +6706,9 @@ htmlCtxtReadFd(htmlParserCtxtPtr ctxt, int fd, * @encoding: the document encoding, or NULL * @options: a combination of htmlParserOption(s) * - * parse an HTML document from I/O functions and source and build a tree. - * This reuses the existing @ctxt parser context + * Parse an HTML document from I/O functions and source and build a tree. + * + * See xmlNewInputIO and htmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -6780,31 +6718,23 @@ htmlCtxtReadIO(htmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ioread == NULL) - return (NULL); if (ctxt == NULL) return (NULL); - xmlInitParser(); htmlCtxtReset(ctxt); + htmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); + input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0); if (input == NULL) { if (ioclose != NULL) ioclose(ioctx); return (NULL); } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (htmlDoRead(ctxt, URL, encoding, options, 1)); + inputPush(ctxt, input); + + return(htmlCtxtParseDocument(ctxt)); } #endif /* LIBXML_HTML_ENABLED */ diff --git a/include/libxml/HTMLparser.h b/include/libxml/HTMLparser.h index 0e97425a..47c7598d 100644 --- a/include/libxml/HTMLparser.h +++ b/include/libxml/HTMLparser.h @@ -246,6 +246,8 @@ XMLPUBFUN htmlDocPtr const char *URL, const char *encoding, int options); +XMLPUBFUN htmlDocPtr + htmlCtxtParseDocument (htmlParserCtxtPtr ctxt); XMLPUBFUN htmlDocPtr htmlCtxtReadDoc (xmlParserCtxtPtr ctxt, const xmlChar *cur, diff --git a/include/libxml/parser.h b/include/libxml/parser.h index eeac3bfe..e271733f 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -1309,6 +1309,8 @@ XMLPUBFUN xmlDocPtr const char *URL, const char *encoding, int options); +XMLPUBFUN xmlDocPtr + xmlCtxtParseDocument (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlDocPtr xmlCtxtReadDoc (xmlParserCtxtPtr ctxt, const xmlChar *cur, @@ -1342,6 +1344,46 @@ XMLPUBFUN xmlDocPtr const char *encoding, int options); +/** + * New input API (2.9.13) + */ + +#define XML_INPUT_BUF_STATIC (1u << 1) +#define XML_INPUT_BUF_ZERO_TERMINATED (1u << 2) + +XMLPUBFUN xmlParserInputPtr + xmlNewInputURL (xmlParserCtxtPtr ctxt, + const char *url, + const char *publicId, + const char *encoding, + int flags); +XMLPUBFUN xmlParserInputPtr + xmlNewInputMemory (xmlParserCtxtPtr ctxt, + const char *filename, + const void *mem, size_t size, + const char *encoding, + int flags); +XMLPUBFUN xmlParserInputPtr + xmlNewInputString (xmlParserCtxtPtr ctxt, + const char *filename, + const char *str, + const char *encoding, + int flags); +XMLPUBFUN xmlParserInputPtr + xmlNewInputFd (xmlParserCtxtPtr ctxt, + const char *filename, + int fd, + const char *encoding, + int flags); +XMLPUBFUN xmlParserInputPtr + xmlNewInputIO (xmlParserCtxtPtr ctxt, + const char *url, + xmlInputReadCallback ioRead, + xmlInputCloseCallback ioClose, + void *ioCtxt, + const char *encoding, + int flags); + /* * Library wide options */ diff --git a/include/private/io.h b/include/private/io.h index 375052aa..01c2cedf 100644 --- a/include/private/io.h +++ b/include/private/io.h @@ -17,8 +17,12 @@ xmlNoNetExists(const char *filename); XML_HIDDEN int xmlParserInputBufferCreateFilenameSafe(const char *URI, xmlCharEncoding enc, xmlParserInputBufferPtr *out); + XML_HIDDEN xmlParserInputBufferPtr -xmlParserInputBufferCreateString(const xmlChar *str); +xmlNewInputBufferString(const char *str, int flags); +XML_HIDDEN xmlParserInputBufferPtr +xmlNewInputBufferMemory(const void *mem, size_t size, int flags, + xmlCharEncoding enc); #ifdef LIBXML_OUTPUT_ENABLED XML_HIDDEN xmlOutputBufferPtr diff --git a/include/private/parser.h b/include/private/parser.h index 43f11892..10e65101 100644 --- a/include/private/parser.h +++ b/include/private/parser.h @@ -83,4 +83,8 @@ xmlParserNsUpdateSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix, XML_HIDDEN void * xmlParserNsLookupSax(xmlParserCtxtPtr ctxt, const xmlChar *prefix); +XML_HIDDEN xmlParserInputPtr +xmlNewInputPush(xmlParserCtxtPtr ctxt, const char *url, + const char *chunk, int size, const char *encoding); + #endif /* XML_PARSER_H_PRIVATE__ */ diff --git a/parser.c b/parser.c index 2dae4e96..466af837 100644 --- a/parser.c +++ b/parser.c @@ -199,10 +199,6 @@ static const char* const xmlW3CPIs[] = { static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str); -static int -xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, - const char *encoding); - static xmlParserErrors xmlCtxtParseEntity(xmlParserCtxtPtr oldctxt, xmlEntityPtr ent); @@ -2315,8 +2311,11 @@ xmlPopInput(xmlParserCtxtPtr ctxt) { * @ctxt: an XML parser context * @input: an XML parser input fragment (entity, XML fragment ...). * - * xmlPushInput: switch to a new input stream which is stacked on top - * of the previous one(s). + * Push an input stream onto the stack. + * + * This makes the parser use an input returned from advanced functions + * like xmlNewInputURL or xmlNewInputMemory. + * * Returns -1 in case of error or the index in the input stack */ int @@ -10461,21 +10460,15 @@ xmlFinishDocument(xmlParserCtxtPtr ctxt) { * xmlParseDocument: * @ctxt: an XML parser context * - * parse an XML document (and build a tree if using the standard SAX - * interface). + * Parse an XML document and invoke the SAX handlers. This is useful + * if you're only interested in custom SAX callbacks. If you want a + * document tree, use xmlCtxtParseDocument. * - * [1] document ::= prolog element Misc* - * - * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? - * - * Returns 0, -1 in case of error. the parser context is augmented - * as a result of the parsing. + * Returns 0, -1 in case of error. */ int xmlParseDocument(xmlParserCtxtPtr ctxt) { - xmlInitParser(); - if ((ctxt == NULL) || (ctxt->input == NULL)) return(-1); @@ -11480,25 +11473,36 @@ encoding_error: /** * xmlParseChunk: * @ctxt: an XML parser context - * @chunk: an char array - * @size: the size in byte of the chunk + * @chunk: chunk of memory + * @size: size of chunk in bytes * @terminate: last chunk indicator * - * Parse a Chunk of memory + * Parse a chunk of memory in push parser mode. * - * Returns zero if no error, the xmlParserErrors otherwise. + * Assumes that the parser context was initialized with + * xmlCreatePushParserCtxt. + * + * The last chunk, which will often be empty, must be marked with + * the @terminate flag. With the default SAX callbacks, the resulting + * document will be available in ctxt->myDoc. This pointer will not + * be freed by the library. + * + * If the document isn't well-formed, ctxt->myDoc is set to NULL. + * The push parser doesn't support recovery mode. + * + * Returns an xmlParserErrors code (0 on success). */ int xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, int terminate) { int end_in_lf = 0; - if (ctxt == NULL) - return(XML_ERR_INTERNAL_ERROR); + if ((ctxt == NULL) || (size < 0)) + return(XML_ERR_ARGUMENT); if (ctxt->disableSAX != 0) return(ctxt->errNo); if (ctxt->input == NULL) - return(-1); + return(XML_ERR_INTERNAL_ERROR); ctxt->input->flags |= XML_INPUT_PROGRESSIVE; if (ctxt->instate == XML_PARSER_START) @@ -11592,77 +11596,41 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size, /** * xmlCreatePushParserCtxt: - * @sax: a SAX handler - * @user_data: The user data returned on SAX callbacks - * @chunk: a pointer to an array of chars - * @size: number of chars in the array - * @filename: an optional file name or URI + * @sax: a SAX handler (optional) + * @user_data: user data for SAX callbacks (optional) + * @chunk: initial chunk (optional, deprecated) + * @size: size of initial chunk in bytes + * @filename: file name or URI (optional) * * Create a parser context for using the XML parser in push mode. - * If @buffer and @size are non-NULL, the data is used to detect - * the encoding. The remaining characters will be parsed so they - * don't need to be fed in again through xmlParseChunk. - * To allow content encoding detection, @size should be >= 4 - * The value of @filename is used for fetching external entities - * and error/warning reports. + * See xmlParseChunk. * - * Returns the new parser context or NULL + * Passing an initial chunk is useless and deprecated. + * + * @filename is used as base URI to fetch external entities and for + * error reports. + * + * Returns the new parser context or NULL in case of error. */ xmlParserCtxtPtr xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, const char *chunk, int size, const char *filename) { xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; - - buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); - if (buf == NULL) return(NULL); + xmlParserInputPtr input; ctxt = xmlNewSAXParserCtxt(sax, user_data); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(buf); + if (ctxt == NULL) return(NULL); - } + ctxt->dictNames = 1; - inputStream = xmlNewInputStream(ctxt); - if (inputStream == NULL) { + input = xmlNewInputPush(ctxt, filename, chunk, size, NULL); + if (input == NULL) { xmlFreeParserCtxt(ctxt); - xmlFreeParserInputBuffer(buf); return(NULL); } - - inputStream->flags |= XML_INPUT_PROGRESSIVE; - - if (filename == NULL) - inputStream->filename = NULL; - else { - inputStream->filename = (char *) - xmlCanonicPath((const xmlChar *) filename); - if (inputStream->filename == NULL) { - xmlFreeInputStream(inputStream); - xmlFreeParserCtxt(ctxt); - xmlFreeParserInputBuffer(buf); - return(NULL); - } - } - inputStream->buf = buf; - xmlBufResetInput(inputStream->buf->buffer, inputStream); - inputPush(ctxt, inputStream); - - if ((size != 0) && (chunk != NULL) && - (ctxt->input != NULL) && (ctxt->input->buf != NULL)) { - size_t pos = ctxt->input->cur - ctxt->input->base; - int res; - - res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); - if (res < 0) { - xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); - xmlHaltParser(ctxt); - } - } + inputPush(ctxt, input); return(ctxt); } @@ -11685,12 +11653,14 @@ xmlStopParser(xmlParserCtxtPtr ctxt) { /** * xmlCreateIOParserCtxt: - * @sax: a SAX handler - * @user_data: The user data returned on SAX callbacks + * @sax: a SAX handler (optional) + * @user_data: user data for SAX callbacks (optional) * @ioread: an I/O read function - * @ioclose: an I/O close function + * @ioclose: an I/O close function (optional) * @ioctx: an I/O handler - * @enc: the charset encoding if known + * @enc: the charset encoding if known (deprecated) + * + * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadIO. * * Create a parser context for using the XML parser with an existing * I/O stream @@ -11699,41 +11669,26 @@ xmlStopParser(xmlParserCtxtPtr ctxt) { */ xmlParserCtxtPtr xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data, - xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, - void *ioctx, xmlCharEncoding enc) { + xmlInputReadCallback ioread, + xmlInputCloseCallback ioclose, + void *ioctx, xmlCharEncoding enc) { xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; + xmlParserInputPtr input; + const char *encoding; - if (ioread == NULL) return(NULL); + ctxt = xmlNewSAXParserCtxt(sax, user_data); + if (ctxt == NULL) + return(NULL); - buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); - if (buf == NULL) { + encoding = xmlGetCharEncodingName(enc); + input = xmlNewInputIO(ctxt, NULL, ioread, ioclose, ioctx, encoding, 0); + if (input == NULL) { + xmlFreeParserCtxt(ctxt); if (ioclose != NULL) ioclose(ioctx); return (NULL); } - - ctxt = xmlNewSAXParserCtxt(sax, user_data); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(buf); - return(NULL); - } - - inputStream = xmlNewIOInputStream(ctxt, buf, enc); - if (inputStream == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - inputPush(ctxt, inputStream); - - if (enc != XML_CHAR_ENCODING_NONE) { - if (xmlSwitchEncoding(ctxt, enc) < 0) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - } + inputPush(ctxt, input); return(ctxt); } @@ -12409,7 +12364,7 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, if (doc->encoding != NULL) xmlSwitchEncodingName(ctxt, (const char *) doc->encoding); - xmlCtxtUseOptionsInternal(ctxt, options, NULL); + xmlCtxtUseOptions(ctxt, options); xmlDetectSAX2(ctxt); ctxt->myDoc = doc; /* parsing in context, i.e. as within existing content */ @@ -12519,19 +12474,18 @@ xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen, * @user_data: The user data returned on SAX callbacks (possibly NULL) * @depth: Used for loop detection, use 0 * @string: the input string in UTF8 or ISO-Latin (zero terminated) - * @lst: the return value for the set of parsed nodes + * @list: the return value for the set of parsed nodes * @recover: return nodes even if the data is broken (use 0) * - * * Parse a well-balanced chunk of an XML document - * called by the parser + * * The allowed sequence for the Well Balanced Chunk is the one defined by * the content production in the XML grammar: * * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)* * - * Returns 0 if the chunk is well balanced, -1 in case of args problem and - * the parser error code otherwise + * Returns 0 if the chunk is well balanced, or thehe parser error code + * otherwise. * * In case recover is set to 1, the nodelist will not be empty even if * the parsed chunk is not well balanced, assuming the parsing succeeded to @@ -12548,10 +12502,13 @@ xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, if (list != NULL) *list = NULL; - ctxt = xmlNewSAXParserCtxt(sax, user_data); - if ((ctxt == NULL) || (string == NULL)) + if (string == NULL) return(XML_ERR_ARGUMENT); + ctxt = xmlNewSAXParserCtxt(sax, user_data); + if (ctxt == NULL) + return(XML_ERR_NO_MEMORY); + xmlDetectSAX2(ctxt); ctxt->depth = depth; @@ -12598,23 +12555,24 @@ xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) { return(NULL); } if (sax != NULL) { - if (ctxt->sax != NULL) - xmlFree(ctxt->sax); - ctxt->sax = sax; + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } ctxt->userData = NULL; } xmlParseExtParsedEnt(ctxt); - if (ctxt->wellFormed) + if (ctxt->wellFormed) { ret = ctxt->myDoc; - else { + } else { ret = NULL; xmlFreeDoc(ctxt->myDoc); - ctxt->myDoc = NULL; } - if (sax != NULL) - ctxt->sax = NULL; + xmlFreeParserCtxt(ctxt); return(ret); @@ -12645,6 +12603,8 @@ xmlParseEntity(const char *filename) { * @ID: the entity PUBLIC ID * @base: a possible base for the target URI * + * DEPRECATED: Use xmlNewInputURL. + * * Create a parser context for an external entity * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. @@ -12655,7 +12615,7 @@ xmlParserCtxtPtr xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, const xmlChar *base) { xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; + xmlParserInputPtr input; xmlChar *uri = NULL; ctxt = xmlNewParserCtxt(); @@ -12669,11 +12629,11 @@ xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, URL = uri; } - inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); - if (inputStream == NULL) + input = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt); + if (input == NULL) goto error; - if (inputPush(ctxt, inputStream) < 0) + if (inputPush(ctxt, input) < 0) goto error; xmlFree(uri); @@ -12696,6 +12656,8 @@ error: * @filename: the filename or URL * @options: a combination of xmlParserOption * + * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile. + * * Create a parser context for a file or URL content. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time and for file accesses @@ -12706,23 +12668,21 @@ xmlParserCtxtPtr xmlCreateURLParserCtxt(const char *filename, int options) { xmlParserCtxtPtr ctxt; - xmlParserInputPtr inputStream; + xmlParserInputPtr input; ctxt = xmlNewParserCtxt(); if (ctxt == NULL) return(NULL); - if (options) - xmlCtxtUseOptionsInternal(ctxt, options, NULL); + xmlCtxtUseOptions(ctxt, options); ctxt->linenumbers = 1; - inputStream = xmlLoadExternalEntity(filename, NULL, ctxt); - if (inputStream == NULL) { + input = xmlLoadExternalEntity(filename, NULL, ctxt); + if (input == NULL) { xmlFreeParserCtxt(ctxt); return(NULL); } - - inputPush(ctxt, inputStream); + inputPush(ctxt, input); return(ctxt); } @@ -12731,6 +12691,8 @@ xmlCreateURLParserCtxt(const char *filename, int options) * xmlCreateFileParserCtxt: * @filename: the filename * + * DEPRECATED: Use xmlNewParserCtxt and xmlCtxtReadFile. + * * Create a parser context for a file content. * Automatic support for ZLIB/Compress compressed document is provided * by default if found at compile-time. @@ -12771,16 +12733,17 @@ xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename, xmlDocPtr ret; xmlParserCtxtPtr ctxt; - xmlInitParser(); - ctxt = xmlCreateFileParserCtxt(filename); if (ctxt == NULL) { return(NULL); } if (sax != NULL) { - if (ctxt->sax != NULL) - xmlFree(ctxt->sax); - ctxt->sax = sax; + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } } xmlDetectSAX2(ctxt); if (data!=NULL) { @@ -12789,24 +12752,8 @@ xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename, ctxt->recovery = recovery; - xmlParseDocument(ctxt); + ret = xmlCtxtParseDocument(ctxt); - if ((ctxt->wellFormed) || recovery) { - ret = ctxt->myDoc; - if ((ret != NULL) && (ctxt->input->buf != NULL)) { - if (ctxt->input->buf->compressed > 0) - ret->compression = 9; - else - ret->compression = ctxt->input->buf->compressed; - } - } - else { - ret = NULL; - xmlFreeDoc(ctxt->myDoc); - ctxt->myDoc = NULL; - } - if (sax != NULL) - ctxt->sax = NULL; xmlFreeParserCtxt(ctxt); return(ret); @@ -12914,15 +12861,9 @@ xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer, xmlClearParserCtxt(ctxt); - input = xmlNewInputStream(ctxt); + input = xmlNewInputString(ctxt, filename, (const char *) buffer, NULL, 0); if (input == NULL) return; - - if (filename != NULL) - input->filename = (char *) xmlCanonicPath((const xmlChar *)filename); - input->base = buffer; - input->cur = buffer; - input->end = &buffer[xmlStrlen(buffer)]; inputPush(ctxt, input); } @@ -12948,9 +12889,12 @@ xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data, ctxt = xmlCreateFileParserCtxt(filename); if (ctxt == NULL) return -1; if (sax != NULL) { - if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) - xmlFree(ctxt->sax); - ctxt->sax = sax; + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } ctxt->userData = user_data; } xmlDetectSAX2(ctxt); @@ -12995,35 +12939,21 @@ xmlParserCtxtPtr xmlCreateMemoryParserCtxt(const char *buffer, int size) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; - if (buffer == NULL) - return(NULL); - if (size <= 0) + if (size < 0) return(NULL); ctxt = xmlNewParserCtxt(); if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); - if (buf == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input = xmlNewInputStream(ctxt); + input = xmlNewInputMemory(ctxt, NULL, buffer, size, NULL, 0); if (input == NULL) { - xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); return(NULL); } - - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(input->buf->buffer, input); - inputPush(ctxt, input); + return(ctxt); } @@ -13055,14 +12985,15 @@ xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer, xmlDocPtr ret; xmlParserCtxtPtr ctxt; - xmlInitParser(); - ctxt = xmlCreateMemoryParserCtxt(buffer, size); if (ctxt == NULL) return(NULL); if (sax != NULL) { - if (ctxt->sax != NULL) - xmlFree(ctxt->sax); - ctxt->sax = sax; + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } } xmlDetectSAX2(ctxt); if (data!=NULL) { @@ -13071,16 +13002,8 @@ xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer, ctxt->recovery = recovery; - xmlParseDocument(ctxt); + ret = xmlCtxtParseDocument(ctxt); - if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc; - else { - ret = NULL; - xmlFreeDoc(ctxt->myDoc); - ctxt->myDoc = NULL; - } - if (sax != NULL) - ctxt->sax = NULL; xmlFreeParserCtxt(ctxt); return(ret); @@ -13160,14 +13083,15 @@ int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data, int ret = 0; xmlParserCtxtPtr ctxt; - xmlInitParser(); - ctxt = xmlCreateMemoryParserCtxt(buffer, size); if (ctxt == NULL) return -1; if (sax != NULL) { - if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler) - xmlFree(ctxt->sax); - ctxt->sax = sax; + if (sax->initialized == XML_SAX2_MAGIC) { + *ctxt->sax = *sax; + } else { + memset(ctxt->sax, 0, sizeof(*ctxt->sax)); + memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1)); + } ctxt->userData = user_data; } xmlDetectSAX2(ctxt); @@ -13204,33 +13128,18 @@ xmlParserCtxtPtr xmlCreateDocParserCtxt(const xmlChar *str) { xmlParserCtxtPtr ctxt; xmlParserInputPtr input; - xmlParserInputBufferPtr buf; - - if (str == NULL) - return(NULL); ctxt = xmlNewParserCtxt(); if (ctxt == NULL) return(NULL); - buf = xmlParserInputBufferCreateString(str); - if (buf == NULL) { - xmlFreeParserCtxt(ctxt); - return(NULL); - } - - input = xmlNewInputStream(ctxt); + input = xmlNewInputString(ctxt, NULL, (const char *) str, NULL, 0); if (input == NULL) { - xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctxt); return(NULL); } - - input->filename = NULL; - input->buf = buf; - xmlBufResetInput(input->buf->buffer, input); - inputPush(ctxt, input); + return(ctxt); } @@ -13433,81 +13342,38 @@ int xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk, int size, const char *filename, const char *encoding) { - xmlParserInputPtr inputStream; - xmlParserInputBufferPtr buf; + xmlParserInputPtr input; if (ctxt == NULL) return(1); - buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); - if (buf == NULL) - return(1); - - if (ctxt == NULL) { - xmlFreeParserInputBuffer(buf); - return(1); - } - xmlCtxtReset(ctxt); - inputStream = xmlNewInputStream(ctxt); - if (inputStream == NULL) { - xmlFreeParserInputBuffer(buf); + input = xmlNewInputPush(ctxt, filename, chunk, size, encoding); + if (input == NULL) return(1); - } - - if (filename == NULL) - inputStream->filename = NULL; - else - inputStream->filename = (char *) - xmlCanonicPath((const xmlChar *) filename); - inputStream->buf = buf; - xmlBufResetInput(buf->buffer, inputStream); - - inputPush(ctxt, inputStream); - - if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) && - (ctxt->input->buf != NULL)) { - size_t pos = ctxt->input->cur - ctxt->input->base; - int res; - - res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk); - xmlBufUpdateInput(ctxt->input->buf->buffer, ctxt->input, pos); - if (res < 0) { - xmlCtxtErrIO(ctxt, ctxt->input->buf->error, NULL); - xmlHaltParser(ctxt); - return(1); - } - } - - if (encoding != NULL) - xmlSwitchEncodingName(ctxt, encoding); + inputPush(ctxt, input); return(0); } /** - * xmlCtxtUseOptionsInternal: + * xmlCtxtUseOptions: * @ctxt: an XML parser context * @options: a combination of xmlParserOption - * @encoding: the user provided encoding to use * * Applies the options to the parser context * * Returns 0 in case of success, the set of unknown or unimplemented options * in case of error. */ -static int -xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding) +int +xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options) { if (ctxt == NULL) return(-1); - if (encoding != NULL) { - if (ctxt->encoding != NULL) - xmlFree((xmlChar *) ctxt->encoding); - ctxt->encoding = xmlStrdup((const xmlChar *) encoding); - } + if (options & XML_PARSE_RECOVER) { ctxt->recovery = 1; options -= XML_PARSE_RECOVER; @@ -13622,22 +13488,6 @@ xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encodi return (options); } -/** - * xmlCtxtUseOptions: - * @ctxt: an XML parser context - * @options: a combination of xmlParserOption - * - * Applies the options to the parser context - * - * Returns 0 in case of success, the set of unknown or unimplemented options - * in case of error. - */ -int -xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options) -{ - return(xmlCtxtUseOptionsInternal(ctxt, options, NULL)); -} - /** * xmlCtxtSetMaxAmplification: * @ctxt: an XML parser context @@ -13658,87 +13508,84 @@ xmlCtxtSetMaxAmplification(xmlParserCtxtPtr ctxt, unsigned maxAmpl) } /** - * xmlDoRead: + * xmlCtxtParseDocument: * @ctxt: an XML parser context - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL - * @options: a combination of xmlParserOption - * @reuse: keep the context for reuse * - * Common front-end for the xmlRead functions + * Parse an XML document and return the resulting document tree. * * Returns the resulting document tree or NULL */ -static xmlDocPtr -xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding, - int options, int reuse) +xmlDocPtr +xmlCtxtParseDocument(xmlParserCtxtPtr ctxt) { xmlDocPtr ret = NULL; - xmlCtxtUseOptionsInternal(ctxt, options, encoding); - if (encoding != NULL) - xmlSwitchEncodingName(ctxt, encoding); - if ((URL != NULL) && (ctxt->input != NULL) && - (ctxt->input->filename == NULL)) { - ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); - if (ctxt->input->filename == NULL) { - xmlErrMemory(ctxt); - goto error; - } - } xmlParseDocument(ctxt); + if ((ctxt->wellFormed) || ((ctxt->recovery) && (ctxt->errNo != XML_ERR_NO_MEMORY))) { ret = ctxt->myDoc; } else { ret = NULL; - if (ctxt->myDoc != NULL) { - xmlFreeDoc(ctxt->myDoc); - } + xmlFreeDoc(ctxt->myDoc); } ctxt->myDoc = NULL; -error: - if (!reuse) { - xmlFreeParserCtxt(ctxt); - } - - return (ret); + return(ret); } /** * xmlReadDoc: * @cur: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML in-memory document and build a tree. + * Convenience function to parse an XML document from a + * zero-terminated string. + * + * See xmlCtxtReadDoc for details. * * Returns the resulting document tree */ xmlDocPtr -xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options) +xmlReadDoc(const xmlChar *cur, const char *URL, const char *encoding, + int options) { xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlDocPtr doc; - if (cur == NULL) - return (NULL); - xmlInitParser(); - - ctxt = xmlCreateDocParserCtxt(cur); + ctxt = xmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputString(ctxt, URL, (const char *) cur, encoding, + XML_INPUT_BUF_STATIC); + if (input == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + inputPush(ctxt, input); + + doc = xmlCtxtParseDocument(ctxt); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadFile: * @filename: a file or URL - * @encoding: the document encoding, or NULL + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML file from the filesystem or the network. + * Convenience function to parse an XML file from the filesystem, + * the network or a global user-define resource loader. + * + * See xmlCtxtReadFile for details. * * Returns the resulting document tree */ @@ -13746,49 +13593,87 @@ xmlDocPtr xmlReadFile(const char *filename, const char *encoding, int options) { xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlDocPtr doc; - xmlInitParser(); - ctxt = xmlCreateURLParserCtxt(filename, options); + ctxt = xmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (xmlDoRead(ctxt, NULL, encoding, options, 0)); + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + if (input == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + inputPush(ctxt, input); + + doc = xmlCtxtParseDocument(ctxt); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadMemory: * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @url: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * * Parse an XML in-memory document and build a tree. The input buffer must * not contain a terminating null byte. * + * See xmlCtxtReadMemory for details. + * * Returns the resulting document tree */ xmlDocPtr -xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options) +xmlReadMemory(const char *buffer, int size, const char *url, + const char *encoding, int options) { xmlParserCtxtPtr ctxt; + xmlParserInputPtr input; + xmlDocPtr doc; - xmlInitParser(); - ctxt = xmlCreateMemoryParserCtxt(buffer, size); + if (size < 0) + return(NULL); + + ctxt = xmlNewParserCtxt(); if (ctxt == NULL) - return (NULL); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputMemory(ctxt, url, buffer, size, encoding, + XML_INPUT_BUF_STATIC); + if (input == NULL) { + xmlFreeParserCtxt(ctxt); + return(NULL); + } + inputPush(ctxt, input); + + doc = xmlCtxtParseDocument(ctxt); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadFd: * @fd: an open file descriptor - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML from a file descriptor and build a tree. + * Parse an XML from a file descriptor and build a tree. + * + * See xmlCtxtReadFd for details. + * * NOTE that the file descriptor will not be closed when the - * reader is closed or reset. + * context is freed or reset. * * Returns the resulting document tree */ @@ -13796,42 +13681,41 @@ xmlDocPtr xmlReadFd(int fd, const char *URL, const char *encoding, int options) { xmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; + xmlDocPtr doc; - if (fd < 0) - return (NULL); - xmlInitParser(); - - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); - if (input == NULL) - return (NULL); - input->closecallback = NULL; ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); + if (ctxt == NULL) + return(NULL); + + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputFd(ctxt, URL, fd, encoding, 0); + if (input == NULL) { xmlFreeParserCtxt(ctxt); - return (NULL); + return(NULL); } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + input->buf->closecallback = NULL; + inputPush(ctxt, input); + + doc = xmlCtxtParseDocument(ctxt); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlReadIO: * @ioread: an I/O read function - * @ioclose: an I/O close function + * @ioclose: an I/O close function (optional) * @ioctx: an I/O handler - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML document from I/O functions and source and build a tree. + * Parse an XML document from I/O functions and context and build a tree. + * + * See xmlCtxtReadIO for details. * * Returns the resulting document tree */ @@ -13840,45 +13724,44 @@ xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options) { xmlParserCtxtPtr ctxt; - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; + xmlDocPtr doc; - if (ioread == NULL) - return (NULL); - xmlInitParser(); + ctxt = xmlNewParserCtxt(); + if (ctxt == NULL) + return(NULL); - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); + xmlCtxtUseOptions(ctxt, options); + + input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0); if (input == NULL) { + xmlFreeParserCtxt(ctxt); if (ioclose != NULL) ioclose(ioctx); return (NULL); } - ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - xmlFreeParserCtxt(ctxt); - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 0)); + inputPush(ctxt, input); + + doc = xmlCtxtParseDocument(ctxt); + + xmlFreeParserCtxt(ctxt); + return(doc); } /** * xmlCtxtReadDoc: * @ctxt: an XML parser context * @str: a pointer to a zero terminated string - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML in-memory document and build a tree. - * This reuses the existing @ctxt parser context + * Parse an XML in-memory document and build a tree. + * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -13886,41 +13769,34 @@ xmlDocPtr xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar *str, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; if (ctxt == NULL) - return (NULL); - if (str == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateString(str); - if (input == NULL) { + input = xmlNewInputString(ctxt, URL, (const char *) str, encoding, + XML_INPUT_BUF_STATIC); + if (input == NULL) return(NULL); - } + inputPush(ctxt, input); - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } - - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + return(xmlCtxtParseDocument(ctxt)); } /** * xmlCtxtReadFile: * @ctxt: an XML parser context * @filename: a file or URL - * @encoding: the document encoding, or NULL + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML file from the filesystem or the network. - * This reuses the existing @ctxt parser context + * Parse an XML file from the filesystem, the network or a user-defined + * resource loader. + * + * See xmlNewInputURL and xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -13928,22 +13804,20 @@ xmlDocPtr xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename, const char *encoding, int options) { - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (filename == NULL) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - stream = xmlLoadExternalEntity(filename, NULL, ctxt); - if (stream == NULL) { - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, NULL, encoding, options, 1)); + input = xmlNewInputURL(ctxt, filename, NULL, encoding, 0); + if (input == NULL) + return(NULL); + inputPush(ctxt, input); + + return(xmlCtxtParseDocument(ctxt)); } /** @@ -13951,13 +13825,17 @@ xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename, * @ctxt: an XML parser context * @buffer: a pointer to a char array * @size: the size of the array - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * * Parse an XML in-memory document and build a tree. The input buffer must * not contain a terminating null byte. - * This reuses the existing @ctxt parser context + * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -13965,46 +13843,40 @@ xmlDocPtr xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ctxt == NULL) - return (NULL); - if (buffer == NULL) - return (NULL); - xmlInitParser(); + if ((ctxt == NULL) || (size < 0)) + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateStatic(buffer, size, - XML_CHAR_ENCODING_NONE); - if (input == NULL) { - xmlErrMemory(ctxt); + input = xmlNewInputMemory(ctxt, URL, buffer, size, encoding, + XML_INPUT_BUF_STATIC); + if (input == NULL) return(NULL); - } + inputPush(ctxt, input); - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return(NULL); - } - - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + return(xmlCtxtParseDocument(ctxt)); } /** * xmlCtxtReadFd: * @ctxt: an XML parser context * @fd: an open file descriptor - * @URL: the base URL to use for the document - * @encoding: the document encoding, or NULL + * @URL: base URL (optional) + * @encoding: the document encoding (optional) * @options: a combination of xmlParserOption * - * parse an XML from a file descriptor and build a tree. - * This reuses the existing @ctxt parser context + * Parse an XML document from a file descriptor and build a tree. + * * NOTE that the file descriptor will not be closed when the - * reader is closed or reset. + * context is freed or reset. + * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. * * Returns the resulting document tree */ @@ -14012,29 +13884,21 @@ xmlDocPtr xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (fd < 0) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + input = xmlNewInputFd(ctxt, URL, fd, encoding, 0); if (input == NULL) return (NULL); - input->closecallback = NULL; - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + input->buf->closecallback = NULL; + inputPush(ctxt, input); + + return(xmlCtxtParseDocument(ctxt)); } /** @@ -14050,6 +13914,11 @@ xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd, * parse an XML document from I/O functions and source and build a tree. * This reuses the existing @ctxt parser context * + * @URL is used as base to resolve external entities and for error + * reporting. + * + * See xmlCtxtUseOptions for details. + * * Returns the resulting document tree */ xmlDocPtr @@ -14058,30 +13927,22 @@ xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, const char *URL, const char *encoding, int options) { - xmlParserInputBufferPtr input; - xmlParserInputPtr stream; + xmlParserInputPtr input; - if (ioread == NULL) - return (NULL); if (ctxt == NULL) - return (NULL); - xmlInitParser(); + return(NULL); xmlCtxtReset(ctxt); + xmlCtxtUseOptions(ctxt, options); - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, - XML_CHAR_ENCODING_NONE); + input = xmlNewInputIO(ctxt, URL, ioread, ioclose, ioctx, encoding, 0); if (input == NULL) { if (ioclose != NULL) ioclose(ioctx); return (NULL); } - stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (NULL); - } - inputPush(ctxt, stream); - return (xmlDoRead(ctxt, URL, encoding, options, 1)); + inputPush(ctxt, input); + + return(xmlCtxtParseDocument(ctxt)); } diff --git a/parserInternals.c b/parserInternals.c index 0a915c32..cc37770d 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -309,23 +309,6 @@ xmlCtxtErr(xmlParserCtxtPtr ctxt, xmlNodePtr node, xmlErrorDomain domain, va_end(ap); } -/** - * xmlErrInternal: - * @ctxt: an XML parser context - * @msg: the error message - * @str: error information - * - * Handle an internal error - */ -static void LIBXML_ATTR_FORMAT(2,0) -xmlErrInternal(xmlParserCtxtPtr ctxt, const char *msg, const xmlChar * str) -{ - if (ctxt == NULL) - return; - xmlCtxtErr(ctxt, NULL, XML_FROM_PARSER, XML_ERR_INTERNAL_ERROR, - XML_ERR_FATAL, str, NULL, NULL, 0, msg, str); -} - /** * xmlFatalErr: * @ctxt: an XML parser context @@ -1084,6 +1067,32 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) return(ret); } +/** + * xmlSwitchEncodingName: + * @ctxt: the parser context, only for error reporting + * @input: the input strea, + * @encoding: the encoding name + * + * Returns 0 in case of success, -1 otherwise + */ +static int +xmlSwitchInputEncodingName(xmlParserCtxtPtr ctxt, xmlParserInputPtr input, + const char *encoding) { + xmlCharEncodingHandlerPtr handler; + int res; + + if (encoding == NULL) + return(-1); + + res = xmlOpenCharEncodingHandler(encoding, &handler); + if (res != 0) { + xmlFatalErr(ctxt, res, encoding); + return(-1); + } + + return(xmlSwitchInputEncoding(ctxt, input, handler)); +} + /** * xmlSwitchEncodingName: * @ctxt: the parser context @@ -1101,24 +1110,12 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc) */ int xmlSwitchEncodingName(xmlParserCtxtPtr ctxt, const char *encoding) { - xmlCharEncodingHandlerPtr handler; - int res; - - if (encoding == NULL) - return(-1); - - res = xmlOpenCharEncodingHandler(encoding, &handler); - if (res != 0) { - xmlFatalErr(ctxt, res, encoding); - return(-1); - } - - return(xmlSwitchInputEncoding(ctxt, ctxt->input, handler)); + return(xmlSwitchInputEncodingName(ctxt, ctxt->input, encoding)); } /** * xmlSwitchInputEncoding: - * @ctxt: the parser context + * @ctxt: the parser context, only for error reporting * @input: the input stream * @handler: the encoding handler * @@ -1467,36 +1464,341 @@ xmlNewInputStream(xmlParserCtxtPtr ctxt) { return(input); } +/** + * xmlNewInputURL: + * @ctxt: parser context + * @url: filename or URL + * @publicId: publid ID from doctype (optional) + * @encoding: character encoding (optional) + * @flags: unused, pass 0 + * + * Creates a new parser input from the filesystem, the network or + * a user-defined resource loader. + * + * @url is a filename or URL. If if contains the substring "://", + * it is assumed to be a Legacy Extended IRI. Otherwise, it is + * treated as a filesystem path. + * + * @publicId is an optional XML public ID, typically from a doctype + * declaration. It is used for catalog lookups. + * + * If @encoding is specified, it will override any encodings found + * in XML declarations, text declarations, BOMs, etc. Pass NULL + * for auto-detection. + * + * The following resource loaders will be called if they were + * registered (in order of precedence): + * + * - the global external entity loader set with + * xmlSetExternalEntityLoader + * - the per-thread xmlParserInputBufferCreateFilenameFunc set with + * xmlParserInputBufferCreateFilenameDefault + * - the default loader which will return + * - the result from a matching global input callback set with + * xmlRegisterInputCallbacks + * - a HTTP resource if support is compiled in. + * - a file opened from the filesystem, with automatic detection + * of compressed files if support is compiled in. + * + * The returned input should be push onto the input stack with + * xmlPushInput. + * + * This function should not be invoked from user-defined resource + * loaders to avoid infinite loops. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputURL(xmlParserCtxtPtr ctxt, const char *url, const char *publicId, + const char *encoding, int flags ATTRIBUTE_UNUSED) { + xmlParserInputPtr input; + + if ((ctxt == NULL) || (url == NULL)) + return(NULL); + + input = xmlLoadExternalEntity(url, publicId, ctxt); + if (input == NULL) + return(NULL); + + if (encoding != NULL) + xmlSwitchInputEncodingName(ctxt, input, encoding); + + return(input); +} + +/** + * xmlNewInputInternal: + * @ctxt: parser context + * @buf: parser input buffer + * @filename: filename or URL + * @encoding: character encoding (optional) + * + * Internal helper function. + * + * Returns a new parser input. + */ +static xmlParserInputPtr +xmlNewInputInternal(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr buf, + const char *filename, const char *encoding) { + xmlParserInputPtr input; + + input = xmlNewInputStream(ctxt); + if (input == NULL) { + xmlFreeParserInputBuffer(buf); + return(NULL); + } + + input->buf = buf; + xmlBufResetInput(input->buf->buffer, input); + + if (filename != NULL) { + input->filename = xmlMemStrdup(filename); + if (input->filename == NULL) { + xmlCtxtErrMemory(ctxt); + xmlFreeInputStream(input); + return(NULL); + } + } + + if (encoding != NULL) { + if (xmlSwitchInputEncodingName(ctxt, input, encoding) < 0) { + xmlFreeInputStream(input); + return(NULL); + } + } + + return(input); +} + +/** + * xmlNewInputMemory: + * @ctxt: parser context + * @url: base URL (optional) + * @mem: pointer to char array + * @size: size of array + * @encoding: character encoding (optional) + * @flags: optimization hints + * + * Creates a new parser input to read from a memory area. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * If the XML_INPUT_BUF_STATIC flag is set, the memory area must + * stay unchanged until parsing has finished. This can avoid + * temporary copies. + * + * If the XML_INPUT_BUF_ZERO_TERMINATED flag is set, the memory + * area must contain a zero byte after the buffer at position @size. + * This can avoid temporary copies. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputMemory(xmlParserCtxtPtr ctxt, const char *url, + const void *mem, size_t size, + const char *encoding, int flags) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (mem == NULL)) + return(NULL); + + buf = xmlNewInputBufferMemory(mem, size, flags, XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputString: + * @ctxt: parser context + * @url: base URL (optional) + * @str: zero-terminated string + * @encoding: character encoding (optional) + * @flags: optimization hints + * + * Creates a new parser input to read from a zero-terminated string. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * If the XML_INPUT_BUF_STATIC flag is set, the string must + * stay unchanged until parsing has finished. This can avoid + * temporary copies. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputString(xmlParserCtxtPtr ctxt, const char *url, + const char *str, const char *encoding, int flags) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (str == NULL)) + return(NULL); + + buf = xmlNewInputBufferString(str, flags); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputFd: + * @ctxt: parser context + * @url: base URL (optional) + * @fd: file descriptor + * @encoding: character encoding (optional) + * @flags: unused, pass 0 + * + * Creates a new parser input to read from a zero-terminated string. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * @fd is closed after parsing has finished. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputFd(xmlParserCtxtPtr ctxt, const char *url, + int fd, const char *encoding, int flags ATTRIBUTE_UNUSED) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (fd < 0)) + return(NULL); + + buf = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputIO: + * @ctxt: parser context + * @url: base URL (optional) + * @ioRead: read callback + * @ioClose: close callback (optional) + * @ioCtxt: IO context + * @encoding: character encoding (optional) + * @flags: unused, pass 0 + * + * Creates a new parser input to read from input callbacks and + * cintext. + * + * @url is used as base to resolve external entities and for + * error reporting. + * + * @ioRead is called to read new data into a provided buffer. + * It must return the number of bytes written into the buffer + * ot a negative xmlParserErrors code on failure. + * + * @ioClose is called after parsing has finished. + * + * @ioCtxt is an opaque pointer passed to the callbacks. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputIO(xmlParserCtxtPtr ctxt, const char *url, + xmlInputReadCallback ioRead, xmlInputCloseCallback ioClose, + void *ioCtxt, + const char *encoding, int flags ATTRIBUTE_UNUSED) { + xmlParserInputBufferPtr buf; + + if ((ctxt == NULL) || (ioRead == NULL)) + return(NULL); + + buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + buf->context = ioCtxt; + buf->readcallback = ioRead; + buf->closecallback = ioClose; + + return(xmlNewInputInternal(ctxt, buf, url, encoding)); +} + +/** + * xmlNewInputPush: + * @ctxt: parser context + * @url: base URL (optional) + * @chunk: pointer to char array + * @size: size of array + * @encoding: character encoding (optional) + * + * Creates a new parser input for a push parser. + * + * Returns a new parser input. + */ +xmlParserInputPtr +xmlNewInputPush(xmlParserCtxtPtr ctxt, const char *url, + const char *chunk, int size, const char *encoding) { + xmlParserInputBufferPtr buf; + xmlParserInputPtr input; + + buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); + if (buf == NULL) { + xmlCtxtErrMemory(ctxt); + return(NULL); + } + + input = xmlNewInputInternal(ctxt, buf, url, encoding); + if (input == NULL) + return(NULL); + + input->flags |= XML_INPUT_PROGRESSIVE; + + if ((size > 0) && (chunk != NULL)) { + int res; + + res = xmlParserInputBufferPush(input->buf, size, chunk); + xmlBufResetInput(input->buf->buffer, input); + if (res < 0) { + xmlCtxtErrIO(ctxt, input->buf->error, NULL); + xmlFreeInputStream(input); + return(NULL); + } + } + + return(input); +} + /** * xmlNewIOInputStream: * @ctxt: an XML parser context * @input: an I/O Input * @enc: the charset encoding if known * + * DEPRECATED: Use xmlNewInputURL, xmlNewInputMemory, etc. + * * Create a new input stream structure encapsulating the @input into * a stream suitable for the parser. * * Returns the new input stream or NULL */ xmlParserInputPtr -xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input, +xmlNewIOInputStream(xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr buf, xmlCharEncoding enc) { - xmlParserInputPtr inputStream; + const char *encoding; - if (input == NULL) return(NULL); - inputStream = xmlNewInputStream(ctxt); - if (inputStream == NULL) { - return(NULL); - } - inputStream->filename = NULL; - inputStream->buf = input; - xmlBufResetInput(inputStream->buf->buffer, inputStream); + if (buf == NULL) + return(NULL); - if (enc != XML_CHAR_ENCODING_NONE) { - xmlSwitchEncoding(ctxt, enc); - } - - return(inputStream); + encoding = xmlGetCharEncodingName(enc); + return(xmlNewInputInternal(ctxt, buf, NULL, encoding)); } /** @@ -1518,14 +1820,20 @@ xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) { return(NULL); if (ent->content != NULL) { - input = xmlNewStringInputStream(ctxt, ent->content); + input = xmlNewInputString(ctxt, NULL, (const char *) ent->content, + NULL, XML_INPUT_BUF_STATIC); } else if (ent->URI != NULL) { input = xmlLoadExternalEntity((char *) ent->URI, (char *) ent->ExternalID, ctxt); } else { - input = xmlNewStringInputStream(ctxt, ""); + input = xmlNewInputMemory(ctxt, NULL, "", 0, NULL, + XML_INPUT_BUF_STATIC | + XML_INPUT_BUF_ZERO_TERMINATED); } + if (input == NULL) + return(NULL); + input->entity = ent; return(input); @@ -1536,35 +1844,18 @@ xmlNewEntityInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr ent) { * @ctxt: an XML parser context * @buffer: an memory buffer * + * DEPRECATED: Use xmlNewInputString. + * * Create a new input stream based on a memory buffer. + * * Returns the new input stream */ xmlParserInputPtr xmlNewStringInputStream(xmlParserCtxtPtr ctxt, const xmlChar *buffer) { - xmlParserInputPtr input; - xmlParserInputBufferPtr buf; - - if (buffer == NULL) { - xmlErrInternal(ctxt, "xmlNewStringInputStream string = NULL\n", - NULL); - return(NULL); - } - buf = xmlParserInputBufferCreateString(buffer); - if (buf == NULL) { - xmlCtxtErrMemory(ctxt); - return(NULL); - } - input = xmlNewInputStream(ctxt); - if (input == NULL) { - xmlCtxtErrMemory(ctxt); - xmlFreeParserInputBuffer(buf); - return(NULL); - } - input->buf = buf; - xmlBufResetInput(input->buf->buffer, input); - return(input); + return(xmlNewInputString(ctxt, NULL, (const char *) buffer, NULL, 0)); } + /**************************************************************** * * * External entities loading * @@ -1716,6 +2007,8 @@ xmlCheckHTTPInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr ret) { * @ctxt: an XML parser context * @filename: the filename to use as entity * + * DEPRECATED: Use xmlNewInputURL. + * * Create a new input stream based on a file or an URL. * * Returns the new input stream or NULL in case of error @@ -1891,8 +2184,7 @@ xmlGetExternalEntityLoader(void) { * @ID: the Public ID for the entity to load * @ctxt: the context in which the entity is called or NULL * - * Load an external entity, note that the use of this function for - * unparsed entities may generate problems + * DEPRECATED: Use xmlNewInputURL. * * Returns the xmlParserInputPtr or NULL */ @@ -1942,8 +2234,6 @@ xmlInitSAXParserCtxt(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax, if (ctxt == NULL) return(-1); - xmlInitParser(); - if (ctxt->dict == NULL) ctxt->dict = xmlDictCreate(); if (ctxt->dict == NULL) @@ -2210,6 +2500,10 @@ xmlNewParserCtxt(void) * Allocate and initialize a new SAX parser context. If userData is NULL, * the parser context will be passed as user data. * + * Available since 2.11.0. If you want support older versions, + * it's best to invoke xmlNewParserCtxt and set ctxt->sax with + * struct assignment. + * * Returns the xmlParserCtxtPtr or NULL if memory allocation failed. */ @@ -2218,6 +2512,8 @@ xmlNewSAXParserCtxt(const xmlSAXHandler *sax, void *userData) { xmlParserCtxtPtr ctxt; + xmlInitParser(); + ctxt = (xmlParserCtxtPtr) xmlMalloc(sizeof(xmlParserCtxt)); if (ctxt == NULL) return(NULL); diff --git a/xmlIO.c b/xmlIO.c index 2a89f449..8bd79c5e 100644 --- a/xmlIO.c +++ b/xmlIO.c @@ -1913,12 +1913,55 @@ static int xmlMemClose(void *vctxt) { xmlMemIOCtxt *ctxt = vctxt; - if (ctxt->mem != 0) + if (ctxt->mem != NULL) xmlFree(ctxt->mem); xmlFree(ctxt); return(0); } +xmlParserInputBufferPtr +xmlNewInputBufferMemory(const void *mem, size_t size, int flags, + xmlCharEncoding enc) { + xmlParserInputBufferPtr ret; + xmlMemIOCtxt *ctxt; + char *copy = NULL; + + if ((flags & XML_INPUT_BUF_STATIC) == 0) { + if (size + 1 == 0) + return(NULL); + copy = xmlMalloc(size + 1); + if (copy == NULL) + return(NULL); + memcpy(copy, mem, size); + copy[size] = 0; + + mem = copy; + } + + ret = xmlAllocParserInputBuffer(enc); + if (ret == NULL) { + xmlFree(copy); + return(NULL); + } + + ctxt = xmlMalloc(sizeof(*ctxt)); + if (ctxt == NULL) { + xmlFreeParserInputBuffer(ret); + xmlFree(copy); + return(NULL); + } + + ctxt->mem = copy; + ctxt->cur = mem; + ctxt->size = size; + + ret->context = ctxt; + ret->readcallback = xmlMemRead; + ret->closecallback = xmlMemClose; + + return(ret); +} + /** * xmlParserInputBufferCreateMem: * @mem: the memory input @@ -1940,27 +1983,10 @@ xmlMemClose(void *vctxt) { */ xmlParserInputBufferPtr xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { - xmlParserInputBufferPtr buf; - xmlMemIOCtxt *ctxt; - char *copy; - - if ((size < 0) || (mem == NULL)) + if ((mem == NULL) || (size < 0)) return(NULL); - copy = (char *) xmlStrndup((const xmlChar *) mem, size); - if (copy == NULL) - return(NULL); - - buf = xmlParserInputBufferCreateStatic(copy, size, enc); - if (buf == NULL) { - xmlFree(copy); - return(NULL); - } - - ctxt = buf->context; - ctxt->mem = copy; - - return(buf); + return(xmlNewInputBufferMemory(mem, size, 0, enc)); } /** @@ -1984,40 +2010,20 @@ xmlParserInputBufferCreateMem(const char *mem, int size, xmlCharEncoding enc) { xmlParserInputBufferPtr xmlParserInputBufferCreateStatic(const char *mem, int size, xmlCharEncoding enc) { - xmlParserInputBufferPtr ret; - xmlMemIOCtxt *ctxt; - - if ((size < 0) || (mem == NULL)) + if ((mem == NULL) || (size < 0)) return(NULL); - ret = xmlAllocParserInputBuffer(enc); - if (ret == NULL) - return(NULL); - - ctxt = xmlMalloc(sizeof(*ctxt)); - if (ctxt == NULL) { - xmlFreeParserInputBuffer(ret); - return(NULL); - } - ctxt->mem = NULL; - ctxt->cur = mem; - ctxt->size = size; - - ret->context = ctxt; - ret->readcallback = xmlMemRead; - ret->closecallback = xmlMemClose; - - return(ret); + return(xmlNewInputBufferMemory(mem, size, XML_INPUT_BUF_STATIC, enc)); } typedef struct { - const xmlChar *str; + const char *str; } xmlStringIOCtxt; static int xmlStringRead(void *vctxt, char *buf, int size) { xmlStringIOCtxt *ctxt = vctxt; - const xmlChar *zero; + const char *zero; size_t len; zero = memchr(ctxt->str, 0, size); @@ -2035,21 +2041,14 @@ xmlStringClose(void *vctxt) { return(0); } -/** - * xmlParserInputBufferCreateString: - * @str: a null-terminated string - * - * Create a buffered parser input for the progressive parsing for the input - * from a null-terminated C string. - * - * Returns the new parser input or NULL - */ xmlParserInputBufferPtr -xmlParserInputBufferCreateString(const xmlChar *str) { +xmlNewInputBufferString(const char *str, int flags) { xmlParserInputBufferPtr ret; xmlStringIOCtxt *ctxt; - if (str == NULL) return(NULL); + if ((flags & XML_INPUT_BUF_STATIC) == 0) + return(xmlNewInputBufferMemory(str, strlen(str), flags, + XML_CHAR_ENCODING_NONE)); ret = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE); if (ret == NULL) @@ -2060,6 +2059,7 @@ xmlParserInputBufferCreateString(const xmlChar *str) { xmlFreeParserInputBuffer(ret); return(NULL); } + ctxt->str = str; ret->context = ctxt; diff --git a/xmllint.c b/xmllint.c index 0a1baa67..bc8c2851 100644 --- a/xmllint.c +++ b/xmllint.c @@ -1776,7 +1776,6 @@ static void streamFile(char *filename) { int fd = -1; struct stat info; const char *base = NULL; - xmlParserInputBufferPtr input = NULL; if (memory) { if (stat(filename, &info) < 0) @@ -1928,7 +1927,6 @@ static void streamFile(char *filename) { #endif #ifdef HAVE_MMAP if (memory) { - xmlFreeParserInputBuffer(input); munmap((char *) base, info.st_size); close(fd); }