optimization when freeing hash tables. some tuning of buffer allocations

* dict.c hash.c: optimization when freeing hash tables.
* parser.c xmlIO.c include/libxml/tree.h: some tuning of buffer
  allocations
* parser.c parserInternals.c include/libxml/parser.h: keep a
  single allocated block for all the attributes callbacks,
  avoid useless malloc()/free()
* tree.c: do not realloc() when growing a buffer if the buffer
  ain't full, malloc/memcpy/free avoid copying memory.
Daniel
diff --git a/tree.c b/tree.c
index 4dd1027..135c92b 100644
--- a/tree.c
+++ b/tree.c
@@ -6413,9 +6413,21 @@
 
     if (buf->content == NULL)
 	rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar));
-    else
+    else if (buf->size - buf->use < 100) {
 	rebuf = (xmlChar *) xmlRealloc(buf->content, 
 				       newSize * sizeof(xmlChar));
+   } else {
+        /*
+	 * if we are reallocating a buffer far from being full, it's
+	 * better to make a new allocation and copy only the used range
+	 * and free the old one.
+	 */
+	rebuf = (xmlChar *) xmlMallocAtomic(newSize * sizeof(xmlChar));
+	if (rebuf != NULL) {
+	    memcpy(rebuf, buf->content, buf->use);
+	    xmlFree(buf->content);
+	}
+    }
     if (rebuf == NULL) {
         xmlGenericError(xmlGenericErrorContext,
 		"xmlBufferResize : out of memory!\n");