do string allocations in large pools, allowing to find if a string pertain

* dict.c include/libxml/dict.h: do string allocations in large
  pools, allowing to find if a string pertain to a dict quickly
* xmllint.c: fix --stream --repeat --timing
* Makefile.am: the testThreads run output should be seen.
Daniel
diff --git a/dict.c b/dict.c
index 380e908..20d1efb 100644
--- a/dict.c
+++ b/dict.c
@@ -40,11 +40,21 @@
 typedef xmlDictEntry *xmlDictEntryPtr;
 struct _xmlDictEntry {
     struct _xmlDictEntry *next;
-    xmlChar *name;
+    const xmlChar *name;
     int len;
     int valid;
 };
 
+typedef struct _xmlDictStrings xmlDictStrings;
+typedef xmlDictStrings *xmlDictStringsPtr;
+struct _xmlDictStrings {
+    xmlDictStringsPtr next;
+    xmlChar *free;
+    xmlChar *end;
+    int size;
+    int nbStrings;
+    xmlChar array[1];
+};
 /*
  * The entire dictionnary
  */
@@ -52,9 +62,59 @@
     struct _xmlDictEntry *dict;
     int size;
     int nbElems;
+    xmlDictStringsPtr strings;
 };
 
 /*
+ * xmlDictAddString:
+ * @dict: the dictionnary
+ * @name: the name of the userdata
+ * @len: the length of the name, if -1 it is recomputed
+ *
+ * Add the string to the array[s]
+ *
+ * Returns the pointer of the local string, or NULL in case of error.
+ */
+static const xmlChar *
+xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) {
+    xmlDictStringsPtr pool;
+    const xmlChar *ret;
+    int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */
+
+    pool = dict->strings;
+    while (pool != NULL) {
+	if (pool->end - pool->free > namelen)
+	    goto found_pool;
+	if (pool->size > size) size = pool->size;
+	pool = pool->next;
+    }
+    /*
+     * Not found, need to allocate
+     */
+    if (pool == NULL) {
+        if (size == 0) size = 1000;
+	else size *= 4; /* exponential growth */
+        if (size < 4 * namelen) 
+	    size = 4 * namelen; /* just in case ! */
+	pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size);
+	if (pool == NULL)
+	    return(NULL);
+	pool->size = size;
+	pool->nbStrings = 0;
+	pool->free = &pool->array[0];
+	pool->end = &pool->array[size];
+	pool->next = dict->strings;
+	dict->strings = pool;
+    }
+found_pool:
+    ret = pool->free;
+    memcpy(pool->free, name, namelen);
+    pool->free += namelen;
+    *(pool->free++) = 0;
+    return(ret);
+}
+
+/*
  * xmlDictComputeKey:
  * Calculate the hash key
  */
@@ -110,6 +170,7 @@
         dict->size = MIN_DICT_SIZE;
 	dict->nbElems = 0;
         dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
+	dict->strings = NULL;
         if (dict->dict) {
   	    memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
   	    return(dict);
@@ -226,6 +287,7 @@
     xmlDictEntryPtr iter;
     xmlDictEntryPtr next;
     int inside_dict = 0;
+    xmlDictStringsPtr pool, nextp;
 
     if (dict == NULL)
 	return;
@@ -237,8 +299,6 @@
 	    inside_dict = 1;
 	    while (iter) {
 		next = iter->next;
-		if (iter->name)
-		    xmlFree(iter->name);
 		if (!inside_dict)
 		    xmlFree(iter);
 		dict->nbElems--;
@@ -249,6 +309,12 @@
 	}
 	xmlFree(dict->dict);
     }
+    pool = dict->strings;
+    while (pool != NULL) {
+        nextp = pool->next;
+	xmlFree(pool);
+	pool = nextp;
+    }
     xmlFree(dict);
 }
 
@@ -294,6 +360,9 @@
 	    return(insert->name);
     }
 
+    ret = xmlDictAddString(dict, name, len);
+    if (ret == NULL)
+        return(NULL);
     if (insert == NULL) {
 	entry = &(dict->dict[key]);
     } else {
@@ -301,8 +370,7 @@
 	if (entry == NULL)
 	     return(NULL);
     }
-
-    ret = entry->name = xmlStrndup(name, len);
+    entry->name = ret;
     entry->len = len;
     entry->next = NULL;
     entry->valid = 1;
@@ -322,6 +390,30 @@
 }
 
 /**
+ * xmlDictOwns:
+ * @dict: the dictionnary
+ * @str: the string
+ *
+ * check if a string is owned by the disctionary
+ *
+ * Returns 1 if true, 0 if false and -1 in case of error
+ * -1 in case of error
+ */
+int
+xmlDictOwns(xmlDictPtr dict, const xmlChar *str) {
+    xmlDictStringsPtr pool;
+
+    if ((dict == NULL) || (str == NULL))
+	return(-1);
+    pool = dict->strings;
+    while (pool != NULL) {
+        if ((str >= pool->array) && (str <= pool->free))
+	    return(1);
+	pool = pool->next;
+    }
+    return(0);
+}
+/**
  * xmlDictSize:
  * @dict: the dictionnary
  *