added xmlHashCreateDict where the hash reuses the dictionnary for internal
* hash.c include/libxml/hash.h: added xmlHashCreateDict where
the hash reuses the dictionnary for internal strings
* entities.c valid.c parser.c: reuse that new API, leads to a decent
speedup when parsing for example DocBook documents.
Daniel
diff --git a/ChangeLog b/ChangeLog
index eaebf87..52b5845 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sun Jan 23 23:54:39 CET 2005 Daniel Veillard <daniel@veillard.com>
+
+ * hash.c include/libxml/hash.h: added xmlHashCreateDict where
+ the hash reuses the dictionnary for internal strings
+ * entities.c valid.c parser.c: reuse that new API, leads to a decent
+ speedup when parsing for example DocBook documents.
+
Sun Jan 23 21:14:20 CET 2005 Daniel Veillard <daniel@veillard.com>
* parser.c: small speedup in skipping blanks characters
diff --git a/entities.c b/entities.c
index 87a18d3..619a4d6 100644
--- a/entities.c
+++ b/entities.c
@@ -161,13 +161,13 @@
case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
if (dtd->entities == NULL)
- dtd->entities = xmlHashCreate(0);
+ dtd->entities = xmlHashCreateDict(0, dict);
table = dtd->entities;
break;
case XML_INTERNAL_PARAMETER_ENTITY:
case XML_EXTERNAL_PARAMETER_ENTITY:
if (dtd->pentities == NULL)
- dtd->pentities = xmlHashCreate(0);
+ dtd->pentities = xmlHashCreateDict(0, dict);
table = dtd->pentities;
break;
case XML_INTERNAL_PREDEFINED_ENTITY:
@@ -726,6 +726,7 @@
* xmlCreateEntitiesTable:
*
* create and initialize an empty entities hash table.
+ * This really doesn't make sense and should be deprecated
*
* Returns the xmlEntitiesTablePtr just created or NULL in case of error.
*/
diff --git a/hash.c b/hash.c
index ff06b01..cc38f1e 100644
--- a/hash.c
+++ b/hash.c
@@ -52,6 +52,7 @@
struct _xmlHashEntry *table;
int size;
int nbElems;
+ xmlDictPtr dict;
};
/*
@@ -149,6 +150,7 @@
table = xmlMalloc(sizeof(xmlHashTable));
if (table) {
+ table->dict = NULL;
table->size = size;
table->nbElems = 0;
table->table = xmlMalloc(size * sizeof(xmlHashEntry));
@@ -162,6 +164,27 @@
}
/**
+ * xmlHashCreateDict:
+ * @size: the size of the hash table
+ * @dict: a dictionary to use for the hash
+ *
+ * Create a new xmlHashTablePtr which will use @dict as the internal dictionary
+ *
+ * Returns the newly created object, or NULL if an error occured.
+ */
+xmlHashTablePtr
+xmlHashCreateDict(int size, xmlDictPtr dict) {
+ xmlHashTablePtr table;
+
+ table = xmlHashCreate(size);
+ if (table != NULL) {
+ table->dict = dict;
+ xmlDictReference(dict);
+ }
+ return(table);
+}
+
+/**
* xmlHashGrow:
* @table: the hash table
* @size: the new size of the hash table
@@ -282,12 +305,14 @@
next = iter->next;
if ((f != NULL) && (iter->payload != NULL))
f(iter->payload, iter->name);
- if (iter->name)
- xmlFree(iter->name);
- if (iter->name2)
- xmlFree(iter->name2);
- if (iter->name3)
- xmlFree(iter->name3);
+ if (table->dict == NULL) {
+ if (iter->name)
+ xmlFree(iter->name);
+ if (iter->name2)
+ xmlFree(iter->name2);
+ if (iter->name3)
+ xmlFree(iter->name3);
+ }
iter->payload = NULL;
if (!inside_table)
xmlFree(iter);
@@ -299,6 +324,8 @@
}
xmlFree(table->table);
}
+ if (table->dict)
+ xmlDictFree(table->dict);
xmlFree(table);
}
@@ -463,28 +490,64 @@
xmlHashEntryPtr entry;
xmlHashEntryPtr insert;
- if ((table == NULL) || name == NULL)
+ if ((table == NULL) || (name == NULL))
return(-1);
/*
+ * If using a dict internalize if needed
+ */
+ if (table->dict) {
+ if (!xmlDictOwns(table->dict, name)) {
+ name = xmlDictLookup(table->dict, name, -1);
+ if (name == NULL)
+ return(-1);
+ }
+ if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
+ name2 = xmlDictLookup(table->dict, name2, -1);
+ if (name2 == NULL)
+ return(-1);
+ }
+ if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
+ name3 = xmlDictLookup(table->dict, name3, -1);
+ if (name3 == NULL)
+ return(-1);
+ }
+ }
+
+ /*
* Check for duplicate and insertion location.
*/
key = xmlHashComputeKey(table, name, name2, name3);
if (table->table[key].valid == 0) {
insert = NULL;
} else {
- for (insert = &(table->table[key]); insert->next != NULL;
- insert = insert->next) {
+ if (table->dict) {
+ for (insert = &(table->table[key]); insert->next != NULL;
+ insert = insert->next) {
+ if ((insert->name == name) &&
+ (insert->name2 == name2) &&
+ (insert->name3 == name3))
+ return(-1);
+ len++;
+ }
+ if ((insert->name == name) &&
+ (insert->name2 == name2) &&
+ (insert->name3 == name3))
+ return(-1);
+ } else {
+ for (insert = &(table->table[key]); insert->next != NULL;
+ insert = insert->next) {
+ if ((xmlStrEqual(insert->name, name)) &&
+ (xmlStrEqual(insert->name2, name2)) &&
+ (xmlStrEqual(insert->name3, name3)))
+ return(-1);
+ len++;
+ }
if ((xmlStrEqual(insert->name, name)) &&
(xmlStrEqual(insert->name2, name2)) &&
(xmlStrEqual(insert->name3, name3)))
return(-1);
- len++;
}
- if ((xmlStrEqual(insert->name, name)) &&
- (xmlStrEqual(insert->name2, name2)) &&
- (xmlStrEqual(insert->name3, name3)))
- return(-1);
}
if (insert == NULL) {
@@ -495,9 +558,15 @@
return(-1);
}
- entry->name = xmlStrdup(name);
- entry->name2 = xmlStrdup(name2);
- entry->name3 = xmlStrdup(name3);
+ if (table->dict != NULL) {
+ entry->name = (xmlChar *) name;
+ entry->name2 = (xmlChar *) name2;
+ entry->name3 = (xmlChar *) name3;
+ } else {
+ entry->name = xmlStrdup(name);
+ entry->name2 = xmlStrdup(name2);
+ entry->name3 = xmlStrdup(name3);
+ }
entry->payload = userdata;
entry->next = NULL;
entry->valid = 1;
@@ -541,14 +610,65 @@
return(-1);
/*
+ * If using a dict internalize if needed
+ */
+ if (table->dict) {
+ if (!xmlDictOwns(table->dict, name)) {
+ name = xmlDictLookup(table->dict, name, -1);
+ if (name == NULL)
+ return(-1);
+ }
+ if ((name2 != NULL) && (!xmlDictOwns(table->dict, name2))) {
+ name2 = xmlDictLookup(table->dict, name2, -1);
+ if (name2 == NULL)
+ return(-1);
+ }
+ if ((name3 != NULL) && (!xmlDictOwns(table->dict, name3))) {
+ name3 = xmlDictLookup(table->dict, name3, -1);
+ if (name3 == NULL)
+ return(-1);
+ }
+ }
+
+ /*
* Check for duplicate and insertion location.
*/
key = xmlHashComputeKey(table, name, name2, name3);
if (table->table[key].valid == 0) {
insert = NULL;
} else {
- for (insert = &(table->table[key]); insert->next != NULL;
- insert = insert->next) {
+ if (table ->dict) {
+ for (insert = &(table->table[key]); insert->next != NULL;
+ insert = insert->next) {
+ if ((insert->name == name) &&
+ (insert->name2 == name2) &&
+ (insert->name3 == name3)) {
+ if (f)
+ f(insert->payload, insert->name);
+ insert->payload = userdata;
+ return(0);
+ }
+ }
+ if ((insert->name == name) &&
+ (insert->name2 == name2) &&
+ (insert->name3 == name3)) {
+ if (f)
+ f(insert->payload, insert->name);
+ insert->payload = userdata;
+ return(0);
+ }
+ } else {
+ for (insert = &(table->table[key]); insert->next != NULL;
+ insert = insert->next) {
+ if ((xmlStrEqual(insert->name, name)) &&
+ (xmlStrEqual(insert->name2, name2)) &&
+ (xmlStrEqual(insert->name3, name3))) {
+ if (f)
+ f(insert->payload, insert->name);
+ insert->payload = userdata;
+ return(0);
+ }
+ }
if ((xmlStrEqual(insert->name, name)) &&
(xmlStrEqual(insert->name2, name2)) &&
(xmlStrEqual(insert->name3, name3))) {
@@ -558,14 +678,6 @@
return(0);
}
}
- if ((xmlStrEqual(insert->name, name)) &&
- (xmlStrEqual(insert->name2, name2)) &&
- (xmlStrEqual(insert->name3, name3))) {
- if (f)
- f(insert->payload, insert->name);
- insert->payload = userdata;
- return(0);
- }
}
if (insert == NULL) {
@@ -576,9 +688,15 @@
return(-1);
}
- entry->name = xmlStrdup(name);
- entry->name2 = xmlStrdup(name2);
- entry->name3 = xmlStrdup(name3);
+ if (table->dict != NULL) {
+ entry->name = (xmlChar *) name;
+ entry->name2 = (xmlChar *) name2;
+ entry->name3 = (xmlChar *) name3;
+ } else {
+ entry->name = xmlStrdup(name);
+ entry->name2 = xmlStrdup(name2);
+ entry->name3 = xmlStrdup(name3);
+ }
entry->payload = userdata;
entry->next = NULL;
entry->valid = 1;
@@ -615,6 +733,14 @@
key = xmlHashComputeKey(table, name, name2, name3);
if (table->table[key].valid == 0)
return(NULL);
+ if (table->dict) {
+ for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
+ if ((entry->name == name) &&
+ (entry->name2 == name2) &&
+ (entry->name3 == name3))
+ return(entry->payload);
+ }
+ }
for (entry = &(table->table[key]); entry != NULL; entry = entry->next) {
if ((xmlStrEqual(entry->name, name)) &&
(xmlStrEqual(entry->name2, name2)) &&
@@ -920,12 +1046,14 @@
if ((f != NULL) && (entry->payload != NULL))
f(entry->payload, entry->name);
entry->payload = NULL;
- if(entry->name)
- xmlFree(entry->name);
- if(entry->name2)
- xmlFree(entry->name2);
- if(entry->name3)
- xmlFree(entry->name3);
+ if (table->dict == NULL) {
+ if(entry->name)
+ xmlFree(entry->name);
+ if(entry->name2)
+ xmlFree(entry->name2);
+ if(entry->name3)
+ xmlFree(entry->name3);
+ }
if(prev) {
prev->next = entry->next;
xmlFree(entry);
diff --git a/include/libxml/hash.h b/include/libxml/hash.h
index b2f7b41..efc29a7 100644
--- a/include/libxml/hash.h
+++ b/include/libxml/hash.h
@@ -27,6 +27,7 @@
#include <libxml/xmlversion.h>
#include <libxml/parser.h>
+#include <libxml/dict.h>
#ifdef __cplusplus
extern "C" {
@@ -99,6 +100,9 @@
*/
XMLPUBFUN xmlHashTablePtr XMLCALL
xmlHashCreate (int size);
+XMLPUBFUN xmlHashTablePtr XMLCALL
+ xmlHashCreateDict(int size,
+ xmlDictPtr dict);
XMLPUBFUN void XMLCALL
xmlHashFree (xmlHashTablePtr table,
xmlHashDeallocator f);
diff --git a/parser.c b/parser.c
index 39ebf55..4ecff39 100644
--- a/parser.c
+++ b/parser.c
@@ -642,7 +642,7 @@
const xmlChar *prefix;
if (ctxt->attsDefault == NULL) {
- ctxt->attsDefault = xmlHashCreate(10);
+ ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
if (ctxt->attsDefault == NULL)
goto mem_error;
}
@@ -729,7 +729,7 @@
int type)
{
if (ctxt->attsSpecial == NULL) {
- ctxt->attsSpecial = xmlHashCreate(10);
+ ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
if (ctxt->attsSpecial == NULL)
goto mem_error;
}
@@ -3588,7 +3588,7 @@
xmlParseComment(xmlParserCtxtPtr ctxt) {
xmlChar *buf = NULL;
int size = XML_PARSER_BUFFER_SIZE;
- int len;
+ int len = 0;
xmlParserInputState state;
const xmlChar *in;
int nbchar = 0, ccol;
diff --git a/valid.c b/valid.c
index 60ac127..8a29831 100644
--- a/valid.c
+++ b/valid.c
@@ -1207,18 +1207,6 @@
****************************************************************/
/**
- * xmlCreateElementTable:
- *
- * create and initialize an empty element hash table.
- *
- * Returns the xmlElementTablePtr just created or NULL in case of error.
- */
-static xmlElementTablePtr
-xmlCreateElementTable(void) {
- return(xmlHashCreate(0));
-}
-
-/**
* xmlFreeElement:
* @elem: An element
*
@@ -1269,6 +1257,7 @@
if (name == NULL) {
return(NULL);
}
+
switch (type) {
case XML_ELEMENT_TYPE_EMPTY:
if (content != NULL) {
@@ -1321,7 +1310,11 @@
*/
table = (xmlElementTablePtr) dtd->elements;
if (table == NULL) {
- table = xmlCreateElementTable();
+ xmlDictPtr dict = NULL;
+
+ if (dtd->doc != NULL)
+ dict = dtd->doc->dict;
+ table = xmlHashCreateDict(0, dict);
dtd->elements = (void *) table;
}
if (table == NULL) {
@@ -1683,19 +1676,6 @@
}
#endif /* LIBXML_OUTPUT_ENABLED */
-/**
- * xmlCreateAttributeTable:
- *
- * create and initialize an empty attribute hash table.
- *
- * Returns the xmlAttributeTablePtr just created or NULL in case
- * of error.
- */
-static xmlAttributeTablePtr
-xmlCreateAttributeTable(void) {
- return(xmlHashCreate(0));
-}
-
#ifdef LIBXML_VALID_ENABLED
/**
* xmlScanAttributeDeclCallback:
@@ -1899,7 +1879,10 @@
*/
table = (xmlAttributeTablePtr) dtd->attributes;
if (table == NULL) {
- table = xmlCreateAttributeTable();
+ xmlDictPtr dict = NULL;
+ if (dtd->doc != NULL)
+ dict = dtd->doc->dict;
+ table = xmlHashCreateDict(0, dict);
dtd->attributes = (void *) table;
}
if (table == NULL) {
@@ -2185,19 +2168,6 @@
* *
************************************************************************/
/**
- * xmlCreateNotationTable:
- *
- * create and initialize an empty notation hash table.
- *
- * Returns the xmlNotationTablePtr just created or NULL in case
- * of error.
- */
-static xmlNotationTablePtr
-xmlCreateNotationTable(void) {
- return(xmlHashCreate(0));
-}
-
-/**
* xmlFreeNotation:
* @not: A notation
*
@@ -2249,8 +2219,13 @@
* Create the Notation table if needed.
*/
table = (xmlNotationTablePtr) dtd->notations;
- if (table == NULL)
- dtd->notations = table = xmlCreateNotationTable();
+ if (table == NULL) {
+ xmlDictPtr dict = NULL;
+ if (dtd->doc != NULL)
+ dict = dtd->doc->dict;
+
+ dtd->notations = table = xmlHashCreateDict(0, dict);
+ }
if (table == NULL) {
xmlVErrMemory(ctxt,
"xmlAddNotationDecl: Table creation failed!\n");
@@ -2421,19 +2396,6 @@
xmlFree((char *)(str));
/**
- * xmlCreateIDTable:
- *
- * create and initialize an empty id hash table.
- *
- * Returns the xmlIDTablePtr just created or NULL in case
- * of error.
- */
-static xmlIDTablePtr
-xmlCreateIDTable(void) {
- return(xmlHashCreate(0));
-}
-
-/**
* xmlFreeID:
* @not: A id
*
@@ -2487,8 +2449,9 @@
* Create the ID table if needed.
*/
table = (xmlIDTablePtr) doc->ids;
- if (table == NULL)
- doc->ids = table = xmlCreateIDTable();
+ if (table == NULL) {
+ doc->ids = table = xmlHashCreateDict(0, doc->dict);
+ }
if (table == NULL) {
xmlVErrMemory(ctxt,
"xmlAddID: Table creation failed!\n");
@@ -2705,19 +2668,6 @@
typedef xmlValidateMemo *xmlValidateMemoPtr;
/**
- * xmlCreateRefTable:
- *
- * create and initialize an empty ref hash table.
- *
- * Returns the xmlRefTablePtr just created or NULL in case
- * of error.
- */
-static xmlRefTablePtr
-xmlCreateRefTable(void) {
- return(xmlHashCreate(0));
-}
-
-/**
* xmlFreeRef:
* @lk: A list link
*
@@ -2813,8 +2763,9 @@
* Create the Ref table if needed.
*/
table = (xmlRefTablePtr) doc->refs;
- if (table == NULL)
- doc->refs = table = xmlCreateRefTable();
+ if (table == NULL) {
+ doc->refs = table = xmlHashCreateDict(0, doc->dict);
+ }
if (table == NULL) {
xmlVErrMemory(ctxt,
"xmlAddRef: Table creation failed!\n");
@@ -3063,6 +3014,11 @@
if (dtd == NULL) return(NULL);
if (dtd->elements == NULL) {
+ xmlDictPtr dict = NULL;
+
+ if (dtd->doc != NULL)
+ dict = dtd->doc->dict;
+
if (!create)
return(NULL);
/*
@@ -3070,7 +3026,7 @@
*/
table = (xmlElementTablePtr) dtd->elements;
if (table == NULL) {
- table = xmlCreateElementTable();
+ table = xmlHashCreateDict(0, dict);
dtd->elements = (void *) table;
}
if (table == NULL) {