1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-07-28 00:21:53 +03:00

adding repeated parsing and validating tests make the new DOM tree

* Makefile.am: adding repeated parsing and validating tests
* SAX2.c parser.c tree.c include/libxml/parser.h: make the new
  DOM tree building interfaces use the dictionary from the
  parsing context to build the element and attributes names
  as well as formatting spaces and short text nodes
* include/libxml/dict.h dict.c: added some reference counting
  for xmlDictPtr because they can be shared by documents and
  a parser context.
* xmlreader.c: a bit of cleanup, remove the specific tree freeing
  functions and use the standard ones now.
* xmllint.c: add --nodict
* python/libxml.c: fix a stupid bug so that ns() works on
  attribute nodes.
Daniel
This commit is contained in:
Daniel Veillard
2003-09-24 21:23:56 +00:00
parent 16fa96c5d0
commit e96a2a4bf0
11 changed files with 258 additions and 125 deletions

View File

@ -1,3 +1,19 @@
Wed Sep 24 23:17:59 CEST 2003 Daniel Veillard <daniel@veillard.com>
* Makefile.am: adding repeated parsing and validating tests
* SAX2.c parser.c tree.c include/libxml/parser.h: make the new
DOM tree building interfaces use the dictionary from the
parsing context to build the element and attributes names
as well as formatting spaces and short text nodes
* include/libxml/dict.h dict.c: added some reference counting
for xmlDictPtr because they can be shared by documents and
a parser context.
* xmlreader.c: a bit of cleanup, remove the specific tree freeing
functions and use the standard ones now.
* xmllint.c: add --nodict
* python/libxml.c: fix a stupid bug so that ns() works on
attribute nodes.
Tue Sep 23 23:07:45 CEST 2003 Daniel Veillard <daniel@veillard.com> Tue Sep 23 23:07:45 CEST 2003 Daniel Veillard <daniel@veillard.com>
* parser.c include/libxml/parser.h: adding a new set of * parser.c include/libxml/parser.h: adding a new set of

View File

@ -724,8 +724,10 @@ Timingtests: $(srcdir)/dba100000.xml
@echo "##" @echo "##"
@echo "## Timing tests to try to detect performance" @echo "## Timing tests to try to detect performance"
@echo "## as well a memory usage breakage when streaming" @echo "## as well a memory usage breakage when streaming"
@echo "## first when using the file interface" @echo "## 1/ using the file interface"
@echo "## then when using the memory interface" @echo "## 2/ using the memory interface"
@echo "## 3/ repeated DOM parsing"
@echo "## 4/ repeated DOM validation"
@echo "##" @echo "##"
-@(xmllint --stream --timing $(srcdir)/dba100000.xml; \ -@(xmllint --stream --timing $(srcdir)/dba100000.xml; \
MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\ MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\
@ -737,6 +739,16 @@ Timingtests: $(srcdir)/dba100000.xml
if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \ if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\ grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
exit 0) exit 0)
-@(xmllint --noout --timing --repeat $(srcdir)/test/valid/REC-xml-19980210.xml; \
MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\
if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
exit 0)
-@(xmllint --noout --timing --valid --repeat $(srcdir)/test/valid/REC-xml-19980210.xml; \
MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\
if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
exit 0)
C14Ntests : testC14N$(EXEEXT) C14Ntests : testC14N$(EXEEXT)
@echo "##" @echo "##"

47
SAX2.c
View File

@ -802,6 +802,8 @@ xmlSAX2StartDocument(void *ctx)
ctxt->disableSAX = 1; ctxt->disableSAX = 1;
return; return;
} }
if ((ctxt->dictNames) && (doc != NULL))
doc->dict = ctxt->dict;
} }
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) && if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
(ctxt->input != NULL) && (ctxt->input->filename != NULL)) { (ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
@ -1564,6 +1566,7 @@ xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
nodePop(ctxt); nodePop(ctxt);
} }
int nb_interned = 0;
/* /*
* xmlSAX2TextNode: * xmlSAX2TextNode:
* @ctxt: the parser context * @ctxt: the parser context
@ -1577,21 +1580,17 @@ xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
static xmlNodePtr static xmlNodePtr
xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) { xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
xmlNodePtr ret; xmlNodePtr ret;
const xmlChar *intern = NULL;
/*
* Allocate
*/
if (ctxt->freeElems != NULL) { if (ctxt->freeElems != NULL) {
ret = ctxt->freeElems; ret = ctxt->freeElems;
ctxt->freeElems = ret->next; ctxt->freeElems = ret->next;
ctxt->freeElemsNr--; ctxt->freeElemsNr--;
memset(ret, 0, sizeof(xmlNode));
ret->type = XML_TEXT_NODE;
ret->name = xmlStringText;
ret->content = xmlStrndup(str, len);
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
xmlRegisterNodeDefaultValue(ret);
} else { } else {
ret = xmlNewTextLen(str, len); ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
} }
if (ret == NULL) { if (ret == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
@ -1602,6 +1601,36 @@ xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
ctxt->disableSAX = 1; ctxt->disableSAX = 1;
return(NULL); return(NULL);
} }
/*
* intern the formatting blanks found between tags, or the
* very short strings
*/
if (ctxt->dictNames) {
xmlChar cur = str[len];
if ((len <= 3) && ((cur == '"') || (cur == '\'') || (cur == '<'))) {
intern = xmlDictLookup(ctxt->dict, str, len);
} else if (IS_BLANK(*str) && (len < 60) && (cur == '<')) {
int i;
for (i = 1;i < len;i++) {
if (!IS_BLANK(*str)) goto skip;
}
intern = xmlDictLookup(ctxt->dict, str, len);
}
}
skip:
memset(ret, 0, sizeof(xmlNode));
ret->type = XML_TEXT_NODE;
ret->name = xmlStringText;
if (intern == NULL)
ret->content = xmlStrndup(str, len);
else
ret->content = (xmlChar *) intern;
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
xmlRegisterNodeDefaultValue(ret);
return(ret); return(ret);
} }

25
dict.c
View File

@ -59,6 +59,8 @@ struct _xmlDictStrings {
* The entire dictionnary * The entire dictionnary
*/ */
struct _xmlDict { struct _xmlDict {
int ref_counter;
struct _xmlDictEntry *dict; struct _xmlDictEntry *dict;
int size; int size;
int nbElems; int nbElems;
@ -277,6 +279,8 @@ xmlDictCreate(void) {
dict = xmlMalloc(sizeof(xmlDict)); dict = xmlMalloc(sizeof(xmlDict));
if (dict) { if (dict) {
dict->ref_counter = 1;
dict->size = MIN_DICT_SIZE; dict->size = MIN_DICT_SIZE;
dict->nbElems = 0; dict->nbElems = 0;
dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry)); dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
@ -290,6 +294,21 @@ xmlDictCreate(void) {
return(NULL); return(NULL);
} }
/**
* xmlDictReference:
* @dict: the dictionnary
*
* Increment the reference counter of a dictionary
*
* Returns 0 in case of success and -1 in case of error
*/
int
xmlDictReference(xmlDictPtr dict) {
if (dict == NULL) return -1;
dict->ref_counter++;
return(0);
}
/** /**
* xmlDictGrow: * xmlDictGrow:
* @dict: the dictionnary * @dict: the dictionnary
@ -401,6 +420,11 @@ xmlDictFree(xmlDictPtr dict) {
if (dict == NULL) if (dict == NULL)
return; return;
/* decrement the counter, it may be shared by a parser and docs */
dict->ref_counter--;
if (dict->ref_counter > 0) return;
if (dict->dict) { if (dict->dict) {
for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) { for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
iter = &(dict->dict[i]); iter = &(dict->dict[i]);
@ -595,6 +619,7 @@ xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
} }
return(0); return(0);
} }
/** /**
* xmlDictSize: * xmlDictSize:
* @dict: the dictionnary * @dict: the dictionnary

View File

@ -37,6 +37,8 @@ typedef xmlDict *xmlDictPtr;
*/ */
XMLPUBFUN xmlDictPtr XMLCALL XMLPUBFUN xmlDictPtr XMLCALL
xmlDictCreate (void); xmlDictCreate (void);
XMLPUBFUN int XMLCALL
xmlDictReference(xmlDictPtr dict);
XMLPUBFUN void XMLCALL XMLPUBFUN void XMLCALL
xmlDictFree (xmlDictPtr dict); xmlDictFree (xmlDictPtr dict);

View File

@ -1044,7 +1044,8 @@ typedef enum {
XML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */ XML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */
XML_PARSE_SAX1 = 1<<9, /* use the SAX1 interface internally */ XML_PARSE_SAX1 = 1<<9, /* use the SAX1 interface internally */
XML_PARSE_XINCLUDE = 1<<10,/* Implement XInclude substitition */ XML_PARSE_XINCLUDE = 1<<10,/* Implement XInclude substitition */
XML_PARSE_NONET = 1<<11 /* Forbid network access */ XML_PARSE_NONET = 1<<11,/* Forbid network access */
XML_PARSE_NODICT = 1<<12 /* Do not reuse the context dictionnary */
} xmlParserOption; } xmlParserOption;
XMLPUBFUN void XMLCALL XMLPUBFUN void XMLCALL

View File

@ -11925,6 +11925,18 @@ xmlCleanupParser(void) {
* * * *
************************************************************************/ ************************************************************************/
/**
* DICT_FREE:
* @str: a string
*
* Free a string if it is not owned by the "dict" dictionnary in the
* current scope
*/
#define DICT_FREE(str) \
if ((str) && ((!dict) || \
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
xmlFree((char *)(str));
/** /**
* xmlCtxtReset: * xmlCtxtReset:
* @ctxt: an XML parser context * @ctxt: an XML parser context
@ -11935,6 +11947,7 @@ void
xmlCtxtReset(xmlParserCtxtPtr ctxt) xmlCtxtReset(xmlParserCtxtPtr ctxt)
{ {
xmlParserInputPtr input; xmlParserInputPtr input;
xmlDictPtr dict = ctxt->dict;
while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */ while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
xmlFreeInputStream(input); xmlFreeInputStream(input);
@ -11953,8 +11966,20 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
ctxt->nameNr = 0; ctxt->nameNr = 0;
ctxt->name = NULL; ctxt->name = NULL;
DICT_FREE(ctxt->version);
ctxt->version = NULL; ctxt->version = NULL;
DICT_FREE(ctxt->encoding);
ctxt->encoding = NULL; ctxt->encoding = NULL;
DICT_FREE(ctxt->directory);
ctxt->directory = NULL;
DICT_FREE(ctxt->extSubURI);
ctxt->extSubURI = NULL;
DICT_FREE(ctxt->extSubSystem);
ctxt->extSubSystem = NULL;
if (ctxt->myDoc != NULL)
xmlFreeDoc(ctxt->myDoc);
ctxt->myDoc = NULL;
ctxt->standalone = -1; ctxt->standalone = -1;
ctxt->hasExternalSubset = 0; ctxt->hasExternalSubset = 0;
ctxt->hasPErefs = 0; ctxt->hasPErefs = 0;
@ -11962,9 +11987,7 @@ xmlCtxtReset(xmlParserCtxtPtr ctxt)
ctxt->external = 0; ctxt->external = 0;
ctxt->instate = XML_PARSER_START; ctxt->instate = XML_PARSER_START;
ctxt->token = 0; ctxt->token = 0;
ctxt->directory = NULL;
ctxt->myDoc = NULL;
ctxt->wellFormed = 1; ctxt->wellFormed = 1;
ctxt->nsWellFormed = 1; ctxt->nsWellFormed = 1;
ctxt->valid = 1; ctxt->valid = 1;
@ -12064,6 +12087,12 @@ xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
ctxt->sax->initialized = 1; ctxt->sax->initialized = 1;
options -= XML_PARSE_SAX1; options -= XML_PARSE_SAX1;
} }
if (options & XML_PARSE_NODICT) {
ctxt->dictNames = 0;
options -= XML_PARSE_NODICT;
} else {
ctxt->dictNames = 1;
}
return (options); return (options);
} }
@ -12096,11 +12125,25 @@ xmlDoRead(xmlParserCtxtPtr ctxt, const char *encoding, int options, int reuse)
ret = ctxt->myDoc; ret = ctxt->myDoc;
else { else {
ret = NULL; ret = NULL;
xmlFreeDoc(ctxt->myDoc); if (ctxt->myDoc != NULL) {
ctxt->myDoc = NULL; ctxt->myDoc->dict = NULL;
xmlFreeDoc(ctxt->myDoc);
}
} }
if (!reuse) ctxt->myDoc = NULL;
if (!reuse) {
if ((ctxt->dictNames) &&
(ret != NULL) &&
(ret->dict == ctxt->dict))
ctxt->dict = NULL;
xmlFreeParserCtxt(ctxt); xmlFreeParserCtxt(ctxt);
} else {
/* Must duplicate the reference to the dictionary */
if ((ctxt->dictNames) &&
(ret != NULL) &&
(ret->dict == ctxt->dict))
xmlDictReference(ctxt->dict);
}
return (ret); return (ret);
} }

View File

@ -2288,7 +2288,9 @@ libxml_xmlNodeGetNs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
return (NULL); return (NULL);
node = (xmlNodePtr) PyxmlNode_Get(pyobj_node); node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) { if ((node == NULL) ||
((node->type != XML_ELEMENT_NODE) &&
(node->type != XML_ATTRIBUTE_NODE))) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
return (Py_None); return (Py_None);
} }

135
tree.c
View File

@ -913,6 +913,18 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
return(cur); return(cur);
} }
/**
* DICT_FREE:
* @str: a string
*
* Free a string if it is not owned by the "dict" dictionnary in the
* current scope
*/
#define DICT_FREE(str) \
if ((str) && ((!dict) || \
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
xmlFree((char *)(str));
/** /**
* xmlFreeDtd: * xmlFreeDtd:
* @cur: the DTD structure to free up * @cur: the DTD structure to free up
@ -921,13 +933,12 @@ xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name,
*/ */
void void
xmlFreeDtd(xmlDtdPtr cur) { xmlFreeDtd(xmlDtdPtr cur) {
xmlDictPtr dict = NULL;
if (cur == NULL) { if (cur == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlFreeDtd : DTD == NULL\n");
#endif
return; return;
} }
if (cur->doc != NULL) dict = cur->doc->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur); xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
@ -948,9 +959,9 @@ xmlFreeDtd(xmlDtdPtr cur) {
c = next; c = next;
} }
} }
if (cur->name != NULL) xmlFree((char *) cur->name); DICT_FREE(cur->name)
if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID); DICT_FREE(cur->SystemID)
if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID); DICT_FREE(cur->ExternalID)
/* TODO !!! */ /* TODO !!! */
if (cur->notations != NULL) if (cur->notations != NULL)
xmlFreeNotationTable((xmlNotationTablePtr) cur->notations); xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
@ -1019,6 +1030,7 @@ xmlNewDoc(const xmlChar *version) {
void void
xmlFreeDoc(xmlDocPtr cur) { xmlFreeDoc(xmlDocPtr cur) {
xmlDtdPtr extSubset, intSubset; xmlDtdPtr extSubset, intSubset;
xmlDictPtr dict = NULL;
if (cur == NULL) { if (cur == NULL) {
#ifdef DEBUG_TREE #ifdef DEBUG_TREE
@ -1027,6 +1039,7 @@ xmlFreeDoc(xmlDocPtr cur) {
#endif #endif
return; return;
} }
if (cur != NULL) dict = cur->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur); xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
@ -1054,13 +1067,14 @@ xmlFreeDoc(xmlDocPtr cur) {
} }
if (cur->children != NULL) xmlFreeNodeList(cur->children); if (cur->children != NULL) xmlFreeNodeList(cur->children);
if (cur->version != NULL) xmlFree((char *) cur->version);
if (cur->name != NULL) xmlFree((char *) cur->name);
if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs); if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
if (cur->URL != NULL) xmlFree((char *) cur->URL);
DICT_FREE(cur->version)
DICT_FREE(cur->name)
DICT_FREE(cur->encoding)
DICT_FREE(cur->URL)
xmlFree(cur); xmlFree(cur);
if (dict) xmlDictFree(dict);
} }
/** /**
@ -1915,13 +1929,7 @@ xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
void void
xmlFreePropList(xmlAttrPtr cur) { xmlFreePropList(xmlAttrPtr cur) {
xmlAttrPtr next; xmlAttrPtr next;
if (cur == NULL) { if (cur == NULL) return;
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlFreePropList : property == NULL\n");
#endif
return;
}
while (cur != NULL) { while (cur != NULL) {
next = cur->next; next = cur->next;
xmlFreeProp(cur); xmlFreeProp(cur);
@ -1937,13 +1945,10 @@ xmlFreePropList(xmlAttrPtr cur) {
*/ */
void void
xmlFreeProp(xmlAttrPtr cur) { xmlFreeProp(xmlAttrPtr cur) {
if (cur == NULL) { xmlDictPtr dict = NULL;
#ifdef DEBUG_TREE if (cur == NULL) return;
xmlGenericError(xmlGenericErrorContext,
"xmlFreeProp : property == NULL\n"); if (cur->doc != NULL) dict = cur->doc->dict;
#endif
return;
}
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur); xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
@ -1955,8 +1960,8 @@ xmlFreeProp(xmlAttrPtr cur) {
if (xmlIsID(cur->parent->doc, cur->parent, cur)) if (xmlIsID(cur->parent->doc, cur->parent, cur))
xmlRemoveID(cur->parent->doc, cur); xmlRemoveID(cur->parent->doc, cur);
} }
if (cur->name != NULL) xmlFree((char *) cur->name);
if (cur->children != NULL) xmlFreeNodeList(cur->children); if (cur->children != NULL) xmlFreeNodeList(cur->children);
DICT_FREE(cur->name)
xmlFree(cur); xmlFree(cur);
} }
@ -3187,13 +3192,9 @@ xmlGetLastChild(xmlNodePtr parent) {
void void
xmlFreeNodeList(xmlNodePtr cur) { xmlFreeNodeList(xmlNodePtr cur) {
xmlNodePtr next; xmlNodePtr next;
if (cur == NULL) { xmlDictPtr dict = NULL;
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext, if (cur == NULL) return;
"xmlFreeNodeList : node == NULL\n");
#endif
return;
}
if (cur->type == XML_NAMESPACE_DECL) { if (cur->type == XML_NAMESPACE_DECL) {
xmlFreeNsList((xmlNsPtr) cur); xmlFreeNsList((xmlNsPtr) cur);
return; return;
@ -3206,9 +3207,9 @@ xmlFreeNodeList(xmlNodePtr cur) {
xmlFreeDoc((xmlDocPtr) cur); xmlFreeDoc((xmlDocPtr) cur);
return; return;
} }
if (cur->doc != NULL) dict = cur->doc->dict;
while (cur != NULL) { while (cur != NULL) {
next = cur->next; next = cur->next;
/* unroll to speed up freeing the document */
if (cur->type != XML_DTD_NODE) { if (cur->type != XML_DTD_NODE) {
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
@ -3226,7 +3227,7 @@ xmlFreeNodeList(xmlNodePtr cur) {
(cur->type != XML_XINCLUDE_START) && (cur->type != XML_XINCLUDE_START) &&
(cur->type != XML_XINCLUDE_END) && (cur->type != XML_XINCLUDE_END) &&
(cur->type != XML_ENTITY_REF_NODE)) { (cur->type != XML_ENTITY_REF_NODE)) {
if (cur->content != NULL) xmlFree(cur->content); DICT_FREE(cur->content)
} }
if (((cur->type == XML_ELEMENT_NODE) || if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_XINCLUDE_START) || (cur->type == XML_XINCLUDE_START) ||
@ -3237,28 +3238,13 @@ xmlFreeNodeList(xmlNodePtr cur) {
/* /*
* When a node is a text node or a comment, it uses a global static * When a node is a text node or a comment, it uses a global static
* variable for the name of the node. * variable for the name of the node.
* * Otherwise the node name might come from the document's
* The xmlStrEqual comparisons need to be done when (happened with * dictionnary
* XML::libXML and XML::libXSLT) the library is included twice
* statically in the binary and a tree allocated by one occurrence
* of the lib gets freed by the other occurrence, in this case
* the string addresses compare are not sufficient.
*/ */
if ((cur->name != NULL) && if ((cur->name != NULL) &&
(cur->name != xmlStringText) && (cur->type != XML_TEXT_NODE) &&
(cur->name != xmlStringTextNoenc) && (cur->type != XML_COMMENT_NODE))
(cur->name != xmlStringComment)) { DICT_FREE(cur->name)
if (cur->type == XML_TEXT_NODE) {
if ((!xmlStrEqual(cur->name, xmlStringText)) &&
(!xmlStrEqual(cur->name, xmlStringTextNoenc)))
xmlFree((char *) cur->name);
} else if (cur->type == XML_COMMENT_NODE) {
if (!xmlStrEqual(cur->name, xmlStringComment))
xmlFree((char *) cur->name);
} else
xmlFree((char *) cur->name);
}
/* TODO : derecursivate this function */
xmlFree(cur); xmlFree(cur);
} }
cur = next; cur = next;
@ -3274,13 +3260,9 @@ xmlFreeNodeList(xmlNodePtr cur) {
*/ */
void void
xmlFreeNode(xmlNodePtr cur) { xmlFreeNode(xmlNodePtr cur) {
if (cur == NULL) { xmlDictPtr dict = NULL;
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext, if (cur == NULL) return;
"xmlFreeNode : node == NULL\n");
#endif
return;
}
/* use xmlFreeDtd for DTD nodes */ /* use xmlFreeDtd for DTD nodes */
if (cur->type == XML_DTD_NODE) { if (cur->type == XML_DTD_NODE) {
@ -3299,6 +3281,8 @@ xmlFreeNode(xmlNodePtr cur) {
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue)) if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue(cur); xmlDeregisterNodeDefaultValue(cur);
if (cur->doc != NULL) dict = cur->doc->dict;
if ((cur->children != NULL) && if ((cur->children != NULL) &&
(cur->type != XML_ENTITY_REF_NODE)) (cur->type != XML_ENTITY_REF_NODE))
xmlFreeNodeList(cur->children); xmlFreeNodeList(cur->children);
@ -3312,33 +3296,18 @@ xmlFreeNode(xmlNodePtr cur) {
(cur->type != XML_ENTITY_REF_NODE) && (cur->type != XML_ENTITY_REF_NODE) &&
(cur->type != XML_XINCLUDE_END) && (cur->type != XML_XINCLUDE_END) &&
(cur->type != XML_XINCLUDE_START)) { (cur->type != XML_XINCLUDE_START)) {
xmlFree(cur->content); DICT_FREE(cur->content)
} }
/* /*
* When a node is a text node or a comment, it uses a global static * When a node is a text node or a comment, it uses a global static
* variable for the name of the node. * variable for the name of the node.
* * Otherwise the node name might come from the document's dictionnary
* The xmlStrEqual comparisons need to be done when (happened with
* XML::libXML and XML::libXSLT) the library is included twice statically
* in the binary and a tree allocated by one occurence of the lib gets
* freed by the other occurrence, in this case the string addresses compare
* are not sufficient.
*/ */
if ((cur->name != NULL) && if ((cur->name != NULL) &&
(cur->name != xmlStringText) && (cur->type != XML_TEXT_NODE) &&
(cur->name != xmlStringTextNoenc) && (cur->type != XML_COMMENT_NODE))
(cur->name != xmlStringComment)) { DICT_FREE(cur->name)
if (cur->type == XML_TEXT_NODE) {
if ((!xmlStrEqual(cur->name, xmlStringText)) &&
(!xmlStrEqual(cur->name, xmlStringTextNoenc)))
xmlFree((char *) cur->name);
} else if (cur->type == XML_COMMENT_NODE) {
if (!xmlStrEqual(cur->name, xmlStringComment))
xmlFree((char *) cur->name);
} else
xmlFree((char *) cur->name);
}
if (((cur->type == XML_ELEMENT_NODE) || if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_XINCLUDE_START) || (cur->type == XML_XINCLUDE_START) ||

View File

@ -720,7 +720,7 @@ static void streamFile(char *filename) {
* Tree Test processing * * Tree Test processing *
* * * *
************************************************************************/ ************************************************************************/
static void parseAndPrintFile(char *filename) { static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
xmlDocPtr doc = NULL, tmp; xmlDocPtr doc = NULL, tmp;
if ((timing) && (!repeat)) if ((timing) && (!repeat))
@ -811,17 +811,26 @@ static void parseAndPrintFile(char *filename) {
FILE *f; FILE *f;
f = fopen(filename, "r"); f = fopen(filename, "r");
if (f != NULL) if (f != NULL) {
doc = xmlReadIO((xmlInputReadCallback) myRead, if (rectxt == NULL)
(xmlInputCloseCallback) myClose, f, doc = xmlReadIO((xmlInputReadCallback) myRead,
NULL, options); (xmlInputCloseCallback) myClose, f,
else NULL, options);
else
doc = xmlCtxtReadIO(rectxt,
(xmlInputReadCallback) myRead,
(xmlInputCloseCallback) myClose, f,
NULL, options);
} else
doc = NULL; doc = NULL;
} }
} else if (htmlout) { } else if (htmlout) {
xmlParserCtxtPtr ctxt; xmlParserCtxtPtr ctxt;
ctxt = xmlNewParserCtxt(); if (rectxt == NULL)
ctxt = xmlNewParserCtxt();
else
ctxt = rectxt;
if (ctxt == NULL) { if (ctxt == NULL) {
doc = NULL; doc = NULL;
} else { } else {
@ -832,7 +841,8 @@ static void parseAndPrintFile(char *filename) {
doc = xmlCtxtReadFile(ctxt, filename, NULL, options); doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
xmlFreeParserCtxt(ctxt); if (rectxt == NULL)
xmlFreeParserCtxt(ctxt);
} }
#ifdef HAVE_SYS_MMAN_H #ifdef HAVE_SYS_MMAN_H
} else if (memory) { } else if (memory) {
@ -847,13 +857,21 @@ static void parseAndPrintFile(char *filename) {
if (base == (void *) MAP_FAILED) if (base == (void *) MAP_FAILED)
return; return;
doc = xmlReadMemory((char *) base, info.st_size, NULL, options); if (rectxt == NULL)
doc = xmlReadMemory((char *) base, info.st_size, NULL, options);
else
doc = xmlCtxtReadMemory(rectxt,
(char *) base, info.st_size, NULL, options);
munmap((char *) base, info.st_size); munmap((char *) base, info.st_size);
#endif #endif
} else if (valid) { } else if (valid) {
xmlParserCtxtPtr ctxt; xmlParserCtxtPtr ctxt = NULL;
ctxt = xmlNewParserCtxt(); if (rectxt == NULL)
ctxt = xmlNewParserCtxt();
else
ctxt = rectxt;
if (ctxt == NULL) { if (ctxt == NULL) {
doc = NULL; doc = NULL;
} else { } else {
@ -861,10 +879,14 @@ static void parseAndPrintFile(char *filename) {
if (ctxt->valid == 0) if (ctxt->valid == 0)
progresult = 4; progresult = 4;
xmlFreeParserCtxt(ctxt); if (rectxt == NULL)
xmlFreeParserCtxt(ctxt);
} }
} else { } else {
doc = xmlReadFile(filename, NULL, options); if (rectxt != NULL)
doc = xmlCtxtReadFile(rectxt, filename, NULL, options);
else
doc = xmlReadFile(filename, NULL, options);
} }
} }
@ -1347,6 +1369,9 @@ main(int argc, char **argv) {
(!strcmp(argv[i], "--noent"))) { (!strcmp(argv[i], "--noent"))) {
noent++; noent++;
options |= XML_PARSE_NOENT; options |= XML_PARSE_NOENT;
} else if ((!strcmp(argv[i], "-nodict")) ||
(!strcmp(argv[i], "--nodict"))) {
options |= XML_PARSE_NODICT;
} else if ((!strcmp(argv[i], "-version")) || } else if ((!strcmp(argv[i], "-version")) ||
(!strcmp(argv[i], "--version"))) { (!strcmp(argv[i], "--version"))) {
showVersion(argv[0]); showVersion(argv[0]);
@ -1660,16 +1685,24 @@ main(int argc, char **argv) {
/* Remember file names. "-" means stdin. <sven@zen.org> */ /* Remember file names. "-" means stdin. <sven@zen.org> */
if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
if (repeat) { if (repeat) {
for (acount = 0;acount < repeat;acount++) xmlParserCtxtPtr ctxt = NULL;
for (acount = 0;acount < repeat;acount++) {
if (stream != 0) if (stream != 0)
streamFile(argv[i]); streamFile(argv[i]);
else else {
parseAndPrintFile(argv[i]); if (ctxt == NULL)
ctxt = xmlNewParserCtxt();
parseAndPrintFile(argv[i], ctxt);
}
}
if (ctxt != NULL)
xmlFreeParserCtxt(ctxt);
} else { } else {
if (stream != 0) if (stream != 0)
streamFile(argv[i]); streamFile(argv[i]);
else else
parseAndPrintFile(argv[i]); parseAndPrintFile(argv[i], NULL);
} }
files ++; files ++;
if ((timing) && (repeat)) { if ((timing) && (repeat)) {
@ -1678,7 +1711,7 @@ main(int argc, char **argv) {
} }
} }
if (generate) if (generate)
parseAndPrintFile(NULL); parseAndPrintFile(NULL, NULL);
if ((htmlout) && (!nowrap)) { if ((htmlout) && (!nowrap)) {
xmlGenericError(xmlGenericErrorContext, "</body></html>\n"); xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
} }

View File

@ -1246,7 +1246,7 @@ get_next_node:
(reader->node->prev->type != XML_DTD_NODE)) { (reader->node->prev->type != XML_DTD_NODE)) {
xmlNodePtr tmp = reader->node->prev; xmlNodePtr tmp = reader->node->prev;
xmlUnlinkNode(tmp); xmlUnlinkNode(tmp);
xmlTextReaderFreeNode(reader, tmp); xmlFreeNode(tmp);
} }
goto node_found; goto node_found;
@ -1279,7 +1279,7 @@ get_next_node:
*/ */
if (oldnode->type != XML_DTD_NODE) { if (oldnode->type != XML_DTD_NODE) {
xmlUnlinkNode(oldnode); xmlUnlinkNode(oldnode);
xmlTextReaderFreeNode(reader, oldnode); xmlFreeNode(oldnode);
} }
goto node_end; goto node_end;
@ -1677,16 +1677,17 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
} }
#endif #endif
if (reader->ctxt != NULL) { if (reader->ctxt != NULL) {
if (reader->ctxt->myDoc != NULL) {
xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
reader->ctxt->myDoc = NULL;
}
if ((reader->ctxt->vctxt.vstateTab != NULL) && if ((reader->ctxt->vctxt.vstateTab != NULL) &&
(reader->ctxt->vctxt.vstateMax > 0)){ (reader->ctxt->vctxt.vstateMax > 0)){
xmlFree(reader->ctxt->vctxt.vstateTab); xmlFree(reader->ctxt->vctxt.vstateTab);
reader->ctxt->vctxt.vstateTab = 0; reader->ctxt->vctxt.vstateTab = 0;
reader->ctxt->vctxt.vstateMax = 0; reader->ctxt->vctxt.vstateMax = 0;
} }
if (reader->ctxt->myDoc != NULL) {
xmlFreeDoc(reader->ctxt->myDoc);
reader->ctxt->myDoc = NULL;
}
reader->ctxt->dict = NULL;
if (reader->allocs & XML_TEXTREADER_CTXT) if (reader->allocs & XML_TEXTREADER_CTXT)
xmlFreeParserCtxt(reader->ctxt); xmlFreeParserCtxt(reader->ctxt);
} }