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
*