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