1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-27 18:50:07 +03:00

parser: Add more parser context accessors

Fixes #763.
This commit is contained in:
Nick Wellnhofer 2025-03-08 22:07:15 +01:00
parent 5237d90fae
commit 5f0b1378d7
6 changed files with 344 additions and 23 deletions

View File

@ -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)

View File

@ -690,11 +690,16 @@
<exports symbol='xmlCtxtGetCatalogs' type='function'/>
<exports symbol='xmlCtxtGetDeclaredEncoding' type='function'/>
<exports symbol='xmlCtxtGetDict' type='function'/>
<exports symbol='xmlCtxtGetDocument' type='function'/>
<exports symbol='xmlCtxtGetOptions' type='function'/>
<exports symbol='xmlCtxtGetPrivate' type='function'/>
<exports symbol='xmlCtxtGetSaxHandler' type='function'/>
<exports symbol='xmlCtxtGetStandalone' type='function'/>
<exports symbol='xmlCtxtGetStatus' type='function'/>
<exports symbol='xmlCtxtGetValidCtxt' type='function'/>
<exports symbol='xmlCtxtGetVersion' type='function'/>
<exports symbol='xmlCtxtIsHtml' type='function'/>
<exports symbol='xmlCtxtIsStopped' type='function'/>
<exports symbol='xmlCtxtParseContent' type='function'/>
<exports symbol='xmlCtxtParseDocument' type='function'/>
<exports symbol='xmlCtxtParseDtd' type='function'/>
@ -713,6 +718,7 @@
<exports symbol='xmlCtxtSetOptions' type='function'/>
<exports symbol='xmlCtxtSetPrivate' type='function'/>
<exports symbol='xmlCtxtSetResourceLoader' type='function'/>
<exports symbol='xmlCtxtSetSaxHandler' type='function'/>
<exports symbol='xmlCtxtUseOptions' type='function'/>
<exports symbol='xmlCtxtValidateDocument' type='function'/>
<exports symbol='xmlCtxtValidateDtd' type='function'/>
@ -8451,6 +8457,11 @@ crash if you try to modify the tree)'/>
<return type='xmlDictPtr' info='the dictionary.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtGetDocument' file='parser' module='parserInternals'>
<info>Available since 2.14.0.</info>
<return type='xmlDocPtr' info='the parsed document or NULL if a fatal error occurred when parsing. The document must be freed by the caller. Resets the context&apos;s document to NULL.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtGetLastError' file='xmlerror' module='parserInternals'>
<info>Get the last parsing error registered.</info>
<return type='const xmlError *' info='NULL if no error occurred or a pointer to the error'/>
@ -8466,6 +8477,11 @@ crash if you try to modify the tree)'/>
<return type='void *' info='the private application data.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtGetSaxHandler' file='parser' module='parserInternals'>
<info>Available since 2.14.0.</info>
<return type='xmlSAXHandler *' info='the SAX handler struct. This is not a copy and must not be freed. Handlers can be updated.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtGetStandalone' file='parser' module='parser'>
<info>Available since 2.14.0.</info>
<return type='int' info='the value from the standalone document declaration.'/>
@ -8476,11 +8492,26 @@ crash if you try to modify the tree)'/>
<return type='int' info='a bitmask of XML_STATUS_* flags ORed together.'/>
<arg name='ctxt' type='xmlParserCtxt *' info='an XML parser context'/>
</function>
<function name='xmlCtxtGetValidCtxt' file='parser' module='parserInternals'>
<info>Available since 2.14.0.</info>
<return type='xmlValidCtxtPtr' info='the validation context.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtGetVersion' file='parser' module='parser'>
<info>Available since 2.14.0.</info>
<return type='const xmlChar *' info='the version from the XML declaration.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtIsHtml' file='parser' module='parserInternals'>
<info>Available since 2.14.0.</info>
<return type='int' info='1 if this is a HTML parser context, 0 otherwise.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtIsStopped' file='parser' module='parserInternals'>
<info>Available since 2.14.0.</info>
<return type='int' info='1 if the parser is stopped, 0 otherwise.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
</function>
<function name='xmlCtxtParseContent' file='parser' module='parser'>
<info>Parse a well-balanced chunk of XML matching the &apos;content&apos; production. Namespaces in scope of @node and entities of @node&apos;s document are recognized. When validating, the DTD of @node&apos;s document is used. Always consumes @input even in error case. Available since 2.14.0.</info>
<return type='xmlNodePtr' info='a node list or NULL in case of error.'/>
@ -8632,6 +8663,12 @@ crash if you try to modify the tree)'/>
<arg name='loader' type='xmlResourceLoader' info='callback'/>
<arg name='vctxt' type='void *' info='user data'/>
</function>
<function name='xmlCtxtSetSaxHandler' file='parser' module='parserInternals'>
<info>Available since 2.14.0. Set the SAX handler struct to a copy of @sax.</info>
<return type='int' info='0 on success or -1 if arguments are invalid or a memory allocation failed.'/>
<arg name='ctxt' type='xmlParserCtxtPtr' info='parser context'/>
<arg name='sax' type='const xmlSAXHandler *' info='SAX handler'/>
</function>
<function name='xmlCtxtUseOptions' file='parser' module='parser'>
<info>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</info>
<return type='int' info='0 in case of success, the set of unknown or unimplemented options in case of error.'/>

View File

@ -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 *

View File

@ -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)

View File

@ -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 *

171
testapi.c
View File

@ -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();