diff --git a/HTMLparser.c b/HTMLparser.c index 070c9c1d..02ab081e 100644 --- a/HTMLparser.c +++ b/HTMLparser.c @@ -5927,13 +5927,7 @@ htmlCtxtParseDocument(htmlParserCtxtPtr ctxt, xmlParserInputPtr input) ctxt->html = INSERT_INITIAL; htmlParseDocument(ctxt); - if (ctxt->errNo != XML_ERR_NO_MEMORY) { - ret = ctxt->myDoc; - } else { - ret = NULL; - xmlFreeDoc(ctxt->myDoc); - } - ctxt->myDoc = NULL; + ret = xmlCtxtGetDocument(ctxt); /* assert(ctxt->inputNr == 1); */ while (ctxt->inputNr > 0) diff --git a/doc/libxml2-api.xml b/doc/libxml2-api.xml index 58eee541..fb95c15d 100644 --- a/doc/libxml2-api.xml +++ b/doc/libxml2-api.xml @@ -690,11 +690,16 @@ + + + + + @@ -713,6 +718,7 @@ + @@ -8451,6 +8457,11 @@ crash if you try to modify the tree)'/> + + Available since 2.14.0. + + + Get the last parsing error registered. @@ -8466,6 +8477,11 @@ crash if you try to modify the tree)'/> + + Available since 2.14.0. + + + Available since 2.14.0. @@ -8476,11 +8492,26 @@ crash if you try to modify the tree)'/> + + Available since 2.14.0. + + + Available since 2.14.0. + + Available since 2.14.0. + + + + + Available since 2.14.0. + + + Parse a well-balanced chunk of XML matching the 'content' production. Namespaces in scope of @node and entities of @node's document are recognized. When validating, the DTD of @node's document is used. Always consumes @input even in error case. Available since 2.14.0. @@ -8632,6 +8663,12 @@ crash if you try to modify the tree)'/> + + Available since 2.14.0. Set the SAX handler struct to a copy of @sax. + + + + DEPRECATED: Use xmlCtxtSetOptions. Applies the options to the parser context. The following options are never cleared and can only be enabled: XML_PARSE_NOERROR XML_PARSE_NOWARNING XML_PARSE_NONET XML_PARSE_NSCLEAN XML_PARSE_NOCDATA XML_PARSE_COMPACT XML_PARSE_OLD10 XML_PARSE_HUGE XML_PARSE_OLDSAX XML_PARSE_IGNORE_ENC XML_PARSE_BIG_LINES diff --git a/include/libxml/parser.h b/include/libxml/parser.h index b5c74429..d78304cb 100644 --- a/include/libxml/parser.h +++ b/include/libxml/parser.h @@ -1405,6 +1405,19 @@ XMLPUBFUN xmlDictPtr XMLPUBFUN void xmlCtxtSetDict (xmlParserCtxtPtr ctxt, xmlDictPtr); +XMLPUBFUN xmlSAXHandler * + xmlCtxtGetSaxHandler (xmlParserCtxtPtr ctxt); +XMLPUBFUN int + xmlCtxtSetSaxHandler (xmlParserCtxtPtr ctxt, + const xmlSAXHandler *sax); +XMLPUBFUN xmlDocPtr + xmlCtxtGetDocument (xmlParserCtxtPtr ctxt); +XMLPUBFUN int + xmlCtxtIsHtml (xmlParserCtxtPtr ctxt); +XMLPUBFUN int + xmlCtxtIsStopped (xmlParserCtxtPtr ctxt); +XMLPUBFUN xmlValidCtxtPtr + xmlCtxtGetValidCtxt (xmlParserCtxtPtr ctxt); XMLPUBFUN const xmlChar * xmlCtxtGetVersion (xmlParserCtxtPtr ctxt); XMLPUBFUN const xmlChar * diff --git a/parser.c b/parser.c index 10f1d6a4..283539ac 100644 --- a/parser.c +++ b/parser.c @@ -13816,17 +13816,9 @@ xmlCtxtParseDocument(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) xmlParseDocument(ctxt); - if ((ctxt->wellFormed) || - ((ctxt->recovery) && (!xmlCtxtIsCatastrophicError(ctxt)))) { - ret = ctxt->myDoc; - } else { - if (ctxt->errNo == XML_ERR_OK) - xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, "unknown error\n"); - - ret = NULL; - xmlFreeDoc(ctxt->myDoc); - } - ctxt->myDoc = NULL; + ret = xmlCtxtGetDocument(ctxt); + if ((ret == NULL) && (ctxt->errNo == XML_ERR_OK)) + xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR, "unknown error\n"); /* assert(ctxt->inputNr == 1); */ while (ctxt->inputNr > 0) diff --git a/parserInternals.c b/parserInternals.c index effd566c..5c80694c 100644 --- a/parserInternals.c +++ b/parserInternals.c @@ -3162,6 +3162,130 @@ xmlCtxtSetDict(xmlParserCtxtPtr ctxt, xmlDictPtr dict) { ctxt->dict = dict; } +/** + * xmlCtxtGetSaxHandler: + * @ctxt: parser context + * + * Available since 2.14.0. + * + * Returns the SAX handler struct. This is not a copy and must not + * be freed. Handlers can be updated. + */ +xmlSAXHandler * +xmlCtxtGetSaxHandler(xmlParserCtxtPtr ctxt) { + if (ctxt == NULL) + return(NULL); + + return(ctxt->sax); +} + +/** + * xmlCtxtSetSaxHandler: + * @ctxt: parser context + * @sax: SAX handler + * + * Available since 2.14.0. + * + * Set the SAX handler struct to a copy of @sax. + * + * Returns 0 on success or -1 if arguments are invalid or a memory + * allocation failed. + */ +int +xmlCtxtSetSaxHandler(xmlParserCtxtPtr ctxt, const xmlSAXHandler *sax) { + xmlSAXHandler *copy; + + if ((ctxt == NULL) || (sax == NULL)) + return(-1); + + copy = xmlMalloc(sizeof(*copy)); + if (copy == NULL) + return(-1); + + memcpy(copy, sax, sizeof(*copy)); + ctxt->sax = copy; + + return(0); +} + +/** + * xmlCtxtGetDocument: + * @ctxt: parser context + * + * Available since 2.14.0. + * + * Returns the parsed document or NULL if a fatal error occurred when + * parsing. The document must be freed by the caller. Resets the + * context's document to NULL. + */ +xmlDocPtr +xmlCtxtGetDocument(xmlParserCtxtPtr ctxt) { + xmlDocPtr doc; + + if (ctxt == NULL) + return(NULL); + + if ((ctxt->wellFormed) || + (((ctxt->recovery) || (ctxt->html)) && + (!xmlCtxtIsCatastrophicError(ctxt)))) { + doc = ctxt->myDoc; + } else { + doc = NULL; + xmlFreeDoc(ctxt->myDoc); + } + ctxt->myDoc = NULL; + + return(doc); +} + +/** + * xmlCtxtIsHtml: + * @ctxt: parser context + * + * Available since 2.14.0. + * + * Returns 1 if this is a HTML parser context, 0 otherwise. + */ +int +xmlCtxtIsHtml(xmlParserCtxtPtr ctxt) { + if (ctxt == NULL) + return(0); + + return(ctxt->html ? 1 : 0); +} + +/** + * xmlCtxtIsStopped: + * @ctxt: parser context + * + * Available since 2.14.0. + * + * Returns 1 if the parser is stopped, 0 otherwise. + */ +int +xmlCtxtIsStopped(xmlParserCtxtPtr ctxt) { + if (ctxt == NULL) + return(0); + + return(PARSER_STOPPED(ctxt)); +} + +/** + * xmlCtxtGetValidCtxt: + * @ctxt: parser context + * + * Available since 2.14.0. + * + * Returns the validation context. + */ +xmlValidCtxtPtr +xmlCtxtGetValidCtxt(xmlParserCtxtPtr ctxt) { + if (ctxt == NULL) + return(NULL); + + return(&ctxt->vctxt); +} + /************************************************************************ * * * Handling of node information * diff --git a/testapi.c b/testapi.c index 4828da0c..72d82a77 100644 --- a/testapi.c +++ b/testapi.c @@ -11937,6 +11937,38 @@ test_xmlCtxtGetDeclaredEncoding(void) { } +static int +test_xmlCtxtGetDocument(void) { + int test_ret = 0; + + int mem_base; + xmlDocPtr ret_val; + xmlParserCtxtPtr ctxt; /* parser context */ + int n_ctxt; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + + ret_val = xmlCtxtGetDocument(ctxt); + desret_xmlDocPtr(ret_val); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCtxtGetDocument", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf("\n"); + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCtxtGetOptions(void) { int test_ret = 0; @@ -12001,6 +12033,16 @@ test_xmlCtxtGetPrivate(void) { } +static int +test_xmlCtxtGetSaxHandler(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlCtxtGetStandalone(void) { int test_ret = 0; @@ -12069,6 +12111,16 @@ test_xmlCtxtGetStatus(void) { } +static int +test_xmlCtxtGetValidCtxt(void) { + int test_ret = 0; + + + /* missing type support */ + return(test_ret); +} + + static int test_xmlCtxtGetVersion(void) { int test_ret = 0; @@ -12101,6 +12153,70 @@ test_xmlCtxtGetVersion(void) { } +static int +test_xmlCtxtIsHtml(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlParserCtxtPtr ctxt; /* parser context */ + int n_ctxt; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + + ret_val = xmlCtxtIsHtml(ctxt); + desret_int(ret_val); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCtxtIsHtml", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf("\n"); + } + } + function_tests++; + + return(test_ret); +} + + +static int +test_xmlCtxtIsStopped(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlParserCtxtPtr ctxt; /* parser context */ + int n_ctxt; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + + ret_val = xmlCtxtIsStopped(ctxt); + desret_int(ret_val); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCtxtIsStopped", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf("\n"); + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCtxtParseContent(void) { int test_ret = 0; @@ -12714,6 +12830,49 @@ test_xmlCtxtSetResourceLoader(void) { } +#define gen_nb_const_xmlSAXHandler_ptr 1 +#define gen_const_xmlSAXHandler_ptr(no, nr) NULL +#define des_const_xmlSAXHandler_ptr(no, val, nr) + +static int +test_xmlCtxtSetSaxHandler(void) { + int test_ret = 0; + + int mem_base; + int ret_val; + xmlParserCtxtPtr ctxt; /* parser context */ + int n_ctxt; + const xmlSAXHandler * sax; /* SAX handler */ + int n_sax; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlParserCtxtPtr;n_ctxt++) { + for (n_sax = 0;n_sax < gen_nb_const_xmlSAXHandler_ptr;n_sax++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlParserCtxtPtr(n_ctxt, 0); + sax = gen_const_xmlSAXHandler_ptr(n_sax, 1); + + ret_val = xmlCtxtSetSaxHandler(ctxt, sax); + desret_int(ret_val); + call_tests++; + des_xmlParserCtxtPtr(n_ctxt, ctxt, 0); + des_const_xmlSAXHandler_ptr(n_sax, sax, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlCtxtSetSaxHandler", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf(" %d", n_sax); + printf("\n"); + } + } + } + function_tests++; + + return(test_ret); +} + + static int test_xmlCtxtUseOptions(void) { int test_ret = 0; @@ -13415,10 +13574,6 @@ test_xmlNewParserCtxt(void) { } -#define gen_nb_const_xmlSAXHandler_ptr 1 -#define gen_const_xmlSAXHandler_ptr(no, nr) NULL -#define des_const_xmlSAXHandler_ptr(no, val, nr) - static int test_xmlNewSAXParserCtxt(void) { int test_ret = 0; @@ -15489,7 +15644,7 @@ static int test_parser(void) { int test_ret = 0; - if (quiet == 0) printf("Testing parser : 88 of 104 functions ...\n"); + if (quiet == 0) printf("Testing parser : 92 of 110 functions ...\n"); test_ret += test_xmlByteConsumed(); test_ret += test_xmlCleanupGlobals(); test_ret += test_xmlClearNodeInfoSeq(); @@ -15498,11 +15653,16 @@ test_parser(void) { test_ret += test_xmlCreatePushParserCtxt(); test_ret += test_xmlCtxtGetCatalogs(); test_ret += test_xmlCtxtGetDeclaredEncoding(); + test_ret += test_xmlCtxtGetDocument(); test_ret += test_xmlCtxtGetOptions(); test_ret += test_xmlCtxtGetPrivate(); + test_ret += test_xmlCtxtGetSaxHandler(); test_ret += test_xmlCtxtGetStandalone(); test_ret += test_xmlCtxtGetStatus(); + test_ret += test_xmlCtxtGetValidCtxt(); test_ret += test_xmlCtxtGetVersion(); + test_ret += test_xmlCtxtIsHtml(); + test_ret += test_xmlCtxtIsStopped(); test_ret += test_xmlCtxtParseContent(); test_ret += test_xmlCtxtParseDocument(); test_ret += test_xmlCtxtParseDtd(); @@ -15519,6 +15679,7 @@ test_parser(void) { test_ret += test_xmlCtxtSetOptions(); test_ret += test_xmlCtxtSetPrivate(); test_ret += test_xmlCtxtSetResourceLoader(); + test_ret += test_xmlCtxtSetSaxHandler(); test_ret += test_xmlCtxtUseOptions(); test_ret += test_xmlCtxtValidateDocument(); test_ret += test_xmlCtxtValidateDtd();