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
diff --git a/ChangeLog b/ChangeLog
index 173a0c5..178fe83 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* parser.c include/libxml/parser.h: adding a new set of
diff --git a/Makefile.am b/Makefile.am
index 84f5fe9..fd6fdf3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -724,8 +724,10 @@
@echo "##"
@echo "## Timing tests to try to detect performance"
@echo "## as well a memory usage breakage when streaming"
- @echo "## first when using the file interface"
- @echo "## then when using the memory interface"
+ @echo "## 1/ using the file interface"
+ @echo "## 2/ using the memory interface"
+ @echo "## 3/ repeated DOM parsing"
+ @echo "## 4/ repeated DOM validation"
@echo "##"
-@(xmllint --stream --timing $(srcdir)/dba100000.xml; \
MEM=`cat .memdump | grep "MEMORY ALLOCATED" | awk '{ print $$7}'`;\
@@ -737,6 +739,16 @@
if [ "$$MEM" != "" ] ; then echo Using $$MEM bytes ; fi ; \
grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 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)
@echo "##"
diff --git a/SAX2.c b/SAX2.c
index d0c1854..f305158 100644
--- a/SAX2.c
+++ b/SAX2.c
@@ -802,6 +802,8 @@
ctxt->disableSAX = 1;
return;
}
+ if ((ctxt->dictNames) && (doc != NULL))
+ doc->dict = ctxt->dict;
}
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
@@ -1564,6 +1566,7 @@
nodePop(ctxt);
}
+int nb_interned = 0;
/*
* xmlSAX2TextNode:
* @ctxt: the parser context
@@ -1577,21 +1580,17 @@
static xmlNodePtr
xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
xmlNodePtr ret;
+ const xmlChar *intern = NULL;
+ /*
+ * Allocate
+ */
if (ctxt->freeElems != NULL) {
ret = ctxt->freeElems;
ctxt->freeElems = ret->next;
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 {
- ret = xmlNewTextLen(str, len);
+ ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
}
if (ret == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
@@ -1602,6 +1601,36 @@
ctxt->disableSAX = 1;
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);
}
diff --git a/dict.c b/dict.c
index 93c8b8e..b56cef2 100644
--- a/dict.c
+++ b/dict.c
@@ -59,6 +59,8 @@
* The entire dictionnary
*/
struct _xmlDict {
+ int ref_counter;
+
struct _xmlDictEntry *dict;
int size;
int nbElems;
@@ -277,6 +279,8 @@
dict = xmlMalloc(sizeof(xmlDict));
if (dict) {
+ dict->ref_counter = 1;
+
dict->size = MIN_DICT_SIZE;
dict->nbElems = 0;
dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
@@ -291,6 +295,21 @@
}
/**
+ * 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:
* @dict: the dictionnary
* @size: the new size of the dictionnary
@@ -401,6 +420,11 @@
if (dict == NULL)
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) {
for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
iter = &(dict->dict[i]);
@@ -595,6 +619,7 @@
}
return(0);
}
+
/**
* xmlDictSize:
* @dict: the dictionnary
diff --git a/include/libxml/dict.h b/include/libxml/dict.h
index 56e8565..d04a973 100644
--- a/include/libxml/dict.h
+++ b/include/libxml/dict.h
@@ -37,6 +37,8 @@
*/
XMLPUBFUN xmlDictPtr XMLCALL
xmlDictCreate (void);
+XMLPUBFUN int XMLCALL
+ xmlDictReference(xmlDictPtr dict);
XMLPUBFUN void XMLCALL
xmlDictFree (xmlDictPtr dict);
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index 4ddaa69..965fbc4 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -1044,7 +1044,8 @@
XML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */
XML_PARSE_SAX1 = 1<<9, /* use the SAX1 interface internally */
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;
XMLPUBFUN void XMLCALL
diff --git a/parser.c b/parser.c
index deace02..eb3a8a0 100644
--- a/parser.c
+++ b/parser.c
@@ -11926,6 +11926,18 @@
************************************************************************/
/**
+ * 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:
* @ctxt: an XML parser context
*
@@ -11935,6 +11947,7 @@
xmlCtxtReset(xmlParserCtxtPtr ctxt)
{
xmlParserInputPtr input;
+ xmlDictPtr dict = ctxt->dict;
while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
xmlFreeInputStream(input);
@@ -11953,8 +11966,20 @@
ctxt->nameNr = 0;
ctxt->name = NULL;
+ DICT_FREE(ctxt->version);
ctxt->version = NULL;
+ DICT_FREE(ctxt->encoding);
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->hasExternalSubset = 0;
ctxt->hasPErefs = 0;
@@ -11962,9 +11987,7 @@
ctxt->external = 0;
ctxt->instate = XML_PARSER_START;
ctxt->token = 0;
- ctxt->directory = NULL;
- ctxt->myDoc = NULL;
ctxt->wellFormed = 1;
ctxt->nsWellFormed = 1;
ctxt->valid = 1;
@@ -12064,6 +12087,12 @@
ctxt->sax->initialized = 1;
options -= XML_PARSE_SAX1;
}
+ if (options & XML_PARSE_NODICT) {
+ ctxt->dictNames = 0;
+ options -= XML_PARSE_NODICT;
+ } else {
+ ctxt->dictNames = 1;
+ }
return (options);
}
@@ -12096,11 +12125,25 @@
ret = ctxt->myDoc;
else {
ret = NULL;
- xmlFreeDoc(ctxt->myDoc);
- ctxt->myDoc = NULL;
+ if (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);
+ } else {
+ /* Must duplicate the reference to the dictionary */
+ if ((ctxt->dictNames) &&
+ (ret != NULL) &&
+ (ret->dict == ctxt->dict))
+ xmlDictReference(ctxt->dict);
+ }
return (ret);
}
diff --git a/python/libxml.c b/python/libxml.c
index f323d81..cd71ff1 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -2288,7 +2288,9 @@
return (NULL);
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);
return (Py_None);
}
diff --git a/tree.c b/tree.c
index 0fcfedf..4eed575 100644
--- a/tree.c
+++ b/tree.c
@@ -914,6 +914,18 @@
}
/**
+ * 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:
* @cur: the DTD structure to free up
*
@@ -921,13 +933,12 @@
*/
void
xmlFreeDtd(xmlDtdPtr cur) {
+ xmlDictPtr dict = NULL;
+
if (cur == NULL) {
-#ifdef DEBUG_TREE
- xmlGenericError(xmlGenericErrorContext,
- "xmlFreeDtd : DTD == NULL\n");
-#endif
return;
}
+ if (cur->doc != NULL) dict = cur->doc->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
@@ -948,9 +959,9 @@
c = next;
}
}
- if (cur->name != NULL) xmlFree((char *) cur->name);
- if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID);
- if (cur->ExternalID != NULL) xmlFree((char *) cur->ExternalID);
+ DICT_FREE(cur->name)
+ DICT_FREE(cur->SystemID)
+ DICT_FREE(cur->ExternalID)
/* TODO !!! */
if (cur->notations != NULL)
xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
@@ -1019,6 +1030,7 @@
void
xmlFreeDoc(xmlDocPtr cur) {
xmlDtdPtr extSubset, intSubset;
+ xmlDictPtr dict = NULL;
if (cur == NULL) {
#ifdef DEBUG_TREE
@@ -1027,6 +1039,7 @@
#endif
return;
}
+ if (cur != NULL) dict = cur->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
@@ -1054,13 +1067,14 @@
}
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->URL != NULL) xmlFree((char *) cur->URL);
+
+ DICT_FREE(cur->version)
+ DICT_FREE(cur->name)
+ DICT_FREE(cur->encoding)
+ DICT_FREE(cur->URL)
xmlFree(cur);
+ if (dict) xmlDictFree(dict);
}
/**
@@ -1915,13 +1929,7 @@
void
xmlFreePropList(xmlAttrPtr cur) {
xmlAttrPtr next;
- if (cur == NULL) {
-#ifdef DEBUG_TREE
- xmlGenericError(xmlGenericErrorContext,
- "xmlFreePropList : property == NULL\n");
-#endif
- return;
- }
+ if (cur == NULL) return;
while (cur != NULL) {
next = cur->next;
xmlFreeProp(cur);
@@ -1937,13 +1945,10 @@
*/
void
xmlFreeProp(xmlAttrPtr cur) {
- if (cur == NULL) {
-#ifdef DEBUG_TREE
- xmlGenericError(xmlGenericErrorContext,
- "xmlFreeProp : property == NULL\n");
-#endif
- return;
- }
+ xmlDictPtr dict = NULL;
+ if (cur == NULL) return;
+
+ if (cur->doc != NULL) dict = cur->doc->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
@@ -1955,8 +1960,8 @@
if (xmlIsID(cur->parent->doc, cur->parent, cur))
xmlRemoveID(cur->parent->doc, cur);
}
- if (cur->name != NULL) xmlFree((char *) cur->name);
if (cur->children != NULL) xmlFreeNodeList(cur->children);
+ DICT_FREE(cur->name)
xmlFree(cur);
}
@@ -3187,13 +3192,9 @@
void
xmlFreeNodeList(xmlNodePtr cur) {
xmlNodePtr next;
- if (cur == NULL) {
-#ifdef DEBUG_TREE
- xmlGenericError(xmlGenericErrorContext,
- "xmlFreeNodeList : node == NULL\n");
-#endif
- return;
- }
+ xmlDictPtr dict = NULL;
+
+ if (cur == NULL) return;
if (cur->type == XML_NAMESPACE_DECL) {
xmlFreeNsList((xmlNsPtr) cur);
return;
@@ -3206,9 +3207,9 @@
xmlFreeDoc((xmlDocPtr) cur);
return;
}
+ if (cur->doc != NULL) dict = cur->doc->dict;
while (cur != NULL) {
next = cur->next;
- /* unroll to speed up freeing the document */
if (cur->type != XML_DTD_NODE) {
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
@@ -3226,7 +3227,7 @@
(cur->type != XML_XINCLUDE_START) &&
(cur->type != XML_XINCLUDE_END) &&
(cur->type != XML_ENTITY_REF_NODE)) {
- if (cur->content != NULL) xmlFree(cur->content);
+ DICT_FREE(cur->content)
}
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_XINCLUDE_START) ||
@@ -3237,28 +3238,13 @@
/*
* When a node is a text node or a comment, it uses a global static
* variable for the name of the node.
- *
- * 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 occurrence
- * of the lib gets freed by the other occurrence, in this case
- * the string addresses compare are not sufficient.
+ * Otherwise the node name might come from the document's
+ * dictionnary
*/
if ((cur->name != NULL) &&
- (cur->name != xmlStringText) &&
- (cur->name != xmlStringTextNoenc) &&
- (cur->name != xmlStringComment)) {
- 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 */
+ (cur->type != XML_TEXT_NODE) &&
+ (cur->type != XML_COMMENT_NODE))
+ DICT_FREE(cur->name)
xmlFree(cur);
}
cur = next;
@@ -3274,13 +3260,9 @@
*/
void
xmlFreeNode(xmlNodePtr cur) {
- if (cur == NULL) {
-#ifdef DEBUG_TREE
- xmlGenericError(xmlGenericErrorContext,
- "xmlFreeNode : node == NULL\n");
-#endif
- return;
- }
+ xmlDictPtr dict = NULL;
+
+ if (cur == NULL) return;
/* use xmlFreeDtd for DTD nodes */
if (cur->type == XML_DTD_NODE) {
@@ -3299,6 +3281,8 @@
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue(cur);
+ if (cur->doc != NULL) dict = cur->doc->dict;
+
if ((cur->children != NULL) &&
(cur->type != XML_ENTITY_REF_NODE))
xmlFreeNodeList(cur->children);
@@ -3312,33 +3296,18 @@
(cur->type != XML_ENTITY_REF_NODE) &&
(cur->type != XML_XINCLUDE_END) &&
(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
* variable for the name of the node.
- *
- * 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.
+ * Otherwise the node name might come from the document's dictionnary
*/
if ((cur->name != NULL) &&
- (cur->name != xmlStringText) &&
- (cur->name != xmlStringTextNoenc) &&
- (cur->name != xmlStringComment)) {
- 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);
- }
+ (cur->type != XML_TEXT_NODE) &&
+ (cur->type != XML_COMMENT_NODE))
+ DICT_FREE(cur->name)
if (((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_XINCLUDE_START) ||
diff --git a/xmllint.c b/xmllint.c
index 5f6893b..bdc198c 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -720,7 +720,7 @@
* Tree Test processing *
* *
************************************************************************/
-static void parseAndPrintFile(char *filename) {
+static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
xmlDocPtr doc = NULL, tmp;
if ((timing) && (!repeat))
@@ -811,17 +811,26 @@
FILE *f;
f = fopen(filename, "r");
- if (f != NULL)
- doc = xmlReadIO((xmlInputReadCallback) myRead,
- (xmlInputCloseCallback) myClose, f,
- NULL, options);
- else
+ if (f != NULL) {
+ if (rectxt == NULL)
+ doc = xmlReadIO((xmlInputReadCallback) myRead,
+ (xmlInputCloseCallback) myClose, f,
+ NULL, options);
+ else
+ doc = xmlCtxtReadIO(rectxt,
+ (xmlInputReadCallback) myRead,
+ (xmlInputCloseCallback) myClose, f,
+ NULL, options);
+ } else
doc = NULL;
}
} else if (htmlout) {
xmlParserCtxtPtr ctxt;
- ctxt = xmlNewParserCtxt();
+ if (rectxt == NULL)
+ ctxt = xmlNewParserCtxt();
+ else
+ ctxt = rectxt;
if (ctxt == NULL) {
doc = NULL;
} else {
@@ -832,7 +841,8 @@
doc = xmlCtxtReadFile(ctxt, filename, NULL, options);
- xmlFreeParserCtxt(ctxt);
+ if (rectxt == NULL)
+ xmlFreeParserCtxt(ctxt);
}
#ifdef HAVE_SYS_MMAN_H
} else if (memory) {
@@ -847,13 +857,21 @@
if (base == (void *) MAP_FAILED)
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);
#endif
} else if (valid) {
- xmlParserCtxtPtr ctxt;
+ xmlParserCtxtPtr ctxt = NULL;
- ctxt = xmlNewParserCtxt();
+ if (rectxt == NULL)
+ ctxt = xmlNewParserCtxt();
+ else
+ ctxt = rectxt;
if (ctxt == NULL) {
doc = NULL;
} else {
@@ -861,10 +879,14 @@
if (ctxt->valid == 0)
progresult = 4;
- xmlFreeParserCtxt(ctxt);
+ if (rectxt == NULL)
+ xmlFreeParserCtxt(ctxt);
}
} 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 @@
(!strcmp(argv[i], "--noent"))) {
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")) ||
(!strcmp(argv[i], "--version"))) {
showVersion(argv[0]);
@@ -1660,16 +1685,24 @@
/* Remember file names. "-" means stdin. <sven@zen.org> */
if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
if (repeat) {
- for (acount = 0;acount < repeat;acount++)
+ xmlParserCtxtPtr ctxt = NULL;
+
+ for (acount = 0;acount < repeat;acount++) {
if (stream != 0)
streamFile(argv[i]);
- else
- parseAndPrintFile(argv[i]);
+ else {
+ if (ctxt == NULL)
+ ctxt = xmlNewParserCtxt();
+ parseAndPrintFile(argv[i], ctxt);
+ }
+ }
+ if (ctxt != NULL)
+ xmlFreeParserCtxt(ctxt);
} else {
if (stream != 0)
streamFile(argv[i]);
else
- parseAndPrintFile(argv[i]);
+ parseAndPrintFile(argv[i], NULL);
}
files ++;
if ((timing) && (repeat)) {
@@ -1678,7 +1711,7 @@
}
}
if (generate)
- parseAndPrintFile(NULL);
+ parseAndPrintFile(NULL, NULL);
if ((htmlout) && (!nowrap)) {
xmlGenericError(xmlGenericErrorContext, "</body></html>\n");
}
diff --git a/xmlreader.c b/xmlreader.c
index 8109cf8..4c02a03 100644
--- a/xmlreader.c
+++ b/xmlreader.c
@@ -1246,7 +1246,7 @@
(reader->node->prev->type != XML_DTD_NODE)) {
xmlNodePtr tmp = reader->node->prev;
xmlUnlinkNode(tmp);
- xmlTextReaderFreeNode(reader, tmp);
+ xmlFreeNode(tmp);
}
goto node_found;
@@ -1279,7 +1279,7 @@
*/
if (oldnode->type != XML_DTD_NODE) {
xmlUnlinkNode(oldnode);
- xmlTextReaderFreeNode(reader, oldnode);
+ xmlFreeNode(oldnode);
}
goto node_end;
@@ -1677,16 +1677,17 @@
}
#endif
if (reader->ctxt != NULL) {
- if (reader->ctxt->myDoc != NULL) {
- xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc);
- reader->ctxt->myDoc = NULL;
- }
if ((reader->ctxt->vctxt.vstateTab != NULL) &&
(reader->ctxt->vctxt.vstateMax > 0)){
xmlFree(reader->ctxt->vctxt.vstateTab);
reader->ctxt->vctxt.vstateTab = 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)
xmlFreeParserCtxt(reader->ctxt);
}