Index: third_party/libxml/dict.c |
diff --git a/third_party/libxml/dict.c b/third_party/libxml/dict.c |
index c071887f6f644286262c161b6776e875cb2d2a71..3eff2315e94112089cf487707a02f409740031fe 100644 |
--- a/third_party/libxml/dict.c |
+++ b/third_party/libxml/dict.c |
@@ -20,18 +20,48 @@ |
#include "libxml.h" |
#include <string.h> |
+#ifdef HAVE_STDINT_H |
+#include <stdint.h> |
+#else |
+#ifdef HAVE_INTTYPES_H |
+#include <inttypes.h> |
+#elif defined(WIN32) |
+typedef unsigned __int32 uint32_t; |
+#endif |
+#endif |
#include <libxml/tree.h> |
#include <libxml/dict.h> |
#include <libxml/xmlmemory.h> |
#include <libxml/xmlerror.h> |
#include <libxml/globals.h> |
-#define MAX_HASH_LEN 4 |
+/* #define DEBUG_GROW */ |
+/* #define DICT_DEBUG_PATTERNS */ |
+ |
+#define MAX_HASH_LEN 3 |
#define MIN_DICT_SIZE 128 |
#define MAX_DICT_HASH 8 * 2048 |
- |
-/* #define ALLOW_REMOVAL */ |
-/* #define DEBUG_GROW */ |
+#define WITH_BIG_KEY |
+ |
+#ifdef WITH_BIG_KEY |
+#define xmlDictComputeKey(dict, name, len) \ |
+ (((dict)->size == MIN_DICT_SIZE) ? \ |
+ xmlDictComputeFastKey(name, len) : \ |
+ xmlDictComputeBigKey(name, len)) |
+ |
+#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
+ (((prefix) == NULL) ? \ |
+ (xmlDictComputeKey(dict, name, len)) : \ |
+ (((dict)->size == MIN_DICT_SIZE) ? \ |
+ xmlDictComputeFastQKey(prefix, plen, name, len) : \ |
+ xmlDictComputeBigQKey(prefix, plen, name, len))) |
+ |
+#else /* !WITH_BIG_KEY */ |
+#define xmlDictComputeKey(dict, name, len) \ |
+ xmlDictComputeFastKey(name, len) |
+#define xmlDictComputeQKey(dict, prefix, plen, name, len) \ |
+ xmlDictComputeFastQKey(prefix, plen, name, len) |
+#endif /* WITH_BIG_KEY */ |
/* |
* An entry in the dictionnary |
@@ -43,6 +73,7 @@ struct _xmlDictEntry { |
const xmlChar *name; |
int len; |
int valid; |
+ unsigned long okey; |
}; |
typedef struct _xmlDictStrings xmlDictStrings; |
@@ -129,6 +160,9 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) { |
const xmlChar *ret; |
int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ |
+#ifdef DICT_DEBUG_PATTERNS |
+ fprintf(stderr, "-"); |
+#endif |
pool = dict->strings; |
while (pool != NULL) { |
if (pool->end - pool->free > namelen) |
@@ -153,12 +187,16 @@ xmlDictAddString(xmlDictPtr dict, const xmlChar *name, int namelen) { |
pool->end = &pool->array[size]; |
pool->next = dict->strings; |
dict->strings = pool; |
+#ifdef DICT_DEBUG_PATTERNS |
+ fprintf(stderr, "+"); |
+#endif |
} |
found_pool: |
ret = pool->free; |
memcpy(pool->free, name, namelen); |
pool->free += namelen; |
*(pool->free++) = 0; |
+ pool->nbStrings++; |
return(ret); |
} |
@@ -166,6 +204,7 @@ found_pool: |
* xmlDictAddQString: |
* @dict: the dictionnary |
* @prefix: the prefix of the userdata |
+ * @plen: the prefix length |
* @name: the name of the userdata |
* @len: the length of the name, if -1 it is recomputed |
* |
@@ -174,20 +213,21 @@ found_pool: |
* Returns the pointer of the local string, or NULL in case of error. |
*/ |
static const xmlChar * |
-xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, |
+xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, int plen, |
const xmlChar *name, int namelen) |
{ |
xmlDictStringsPtr pool; |
const xmlChar *ret; |
int size = 0; /* + sizeof(_xmlDictStrings) == 1024 */ |
- int plen; |
if (prefix == NULL) return(xmlDictAddString(dict, name, namelen)); |
- plen = xmlStrlen(prefix); |
+#ifdef DICT_DEBUG_PATTERNS |
+ fprintf(stderr, "="); |
+#endif |
pool = dict->strings; |
while (pool != NULL) { |
- if (pool->end - pool->free > namelen) |
+ if (pool->end - pool->free > namelen + plen + 1) |
goto found_pool; |
if (pool->size > size) size = pool->size; |
pool = pool->next; |
@@ -198,8 +238,8 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, |
if (pool == NULL) { |
if (size == 0) size = 1000; |
else size *= 4; /* exponential growth */ |
- if (size < 4 * namelen) |
- size = 4 * namelen; /* just in case ! */ |
+ if (size < 4 * (namelen + plen + 1)) |
+ size = 4 * (namelen + plen + 1); /* just in case ! */ |
pool = (xmlDictStringsPtr) xmlMalloc(sizeof(xmlDictStrings) + size); |
if (pool == NULL) |
return(NULL); |
@@ -209,27 +249,106 @@ xmlDictAddQString(xmlDictPtr dict, const xmlChar *prefix, |
pool->end = &pool->array[size]; |
pool->next = dict->strings; |
dict->strings = pool; |
+#ifdef DICT_DEBUG_PATTERNS |
+ fprintf(stderr, "+"); |
+#endif |
} |
found_pool: |
ret = pool->free; |
memcpy(pool->free, prefix, plen); |
pool->free += plen; |
*(pool->free++) = ':'; |
- namelen -= plen + 1; |
memcpy(pool->free, name, namelen); |
pool->free += namelen; |
*(pool->free++) = 0; |
+ pool->nbStrings++; |
return(ret); |
} |
+#ifdef WITH_BIG_KEY |
+/* |
+ * xmlDictComputeBigKey: |
+ * |
+ * Calculate a hash key using a good hash function that works well for |
+ * larger hash table sizes. |
+ * |
+ * Hash function by "One-at-a-Time Hash" see |
+ * http://burtleburtle.net/bob/hash/doobs.html |
+ */ |
+ |
+static uint32_t |
+xmlDictComputeBigKey(const xmlChar* data, int namelen) { |
+ uint32_t hash; |
+ int i; |
+ |
+ if (namelen <= 0 || data == NULL) return(0); |
+ |
+ hash = 0; |
+ |
+ for (i = 0;i < namelen; i++) { |
+ hash += data[i]; |
+ hash += (hash << 10); |
+ hash ^= (hash >> 6); |
+ } |
+ hash += (hash << 3); |
+ hash ^= (hash >> 11); |
+ hash += (hash << 15); |
+ |
+ return hash; |
+} |
+ |
+/* |
+ * xmlDictComputeBigQKey: |
+ * |
+ * Calculate a hash key for two strings using a good hash function |
+ * that works well for larger hash table sizes. |
+ * |
+ * Hash function by "One-at-a-Time Hash" see |
+ * http://burtleburtle.net/bob/hash/doobs.html |
+ * |
+ * Neither of the two strings must be NULL. |
+ */ |
+static unsigned long |
+xmlDictComputeBigQKey(const xmlChar *prefix, int plen, |
+ const xmlChar *name, int len) |
+{ |
+ uint32_t hash; |
+ int i; |
+ |
+ hash = 0; |
+ |
+ for (i = 0;i < plen; i++) { |
+ hash += prefix[i]; |
+ hash += (hash << 10); |
+ hash ^= (hash >> 6); |
+ } |
+ hash += ':'; |
+ hash += (hash << 10); |
+ hash ^= (hash >> 6); |
+ |
+ for (i = 0;i < len; i++) { |
+ hash += name[i]; |
+ hash += (hash << 10); |
+ hash ^= (hash >> 6); |
+ } |
+ hash += (hash << 3); |
+ hash ^= (hash >> 11); |
+ hash += (hash << 15); |
+ |
+ return hash; |
+} |
+#endif /* WITH_BIG_KEY */ |
+ |
/* |
- * xmlDictComputeKey: |
- * Calculate the hash key |
+ * xmlDictComputeFastKey: |
+ * |
+ * Calculate a hash key using a fast hash function that works well |
+ * for low hash table fill. |
*/ |
static unsigned long |
-xmlDictComputeKey(const xmlChar *name, int namelen) { |
+xmlDictComputeFastKey(const xmlChar *name, int namelen) { |
unsigned long value = 0L; |
- |
+ |
if (name == NULL) return(0); |
value = *name; |
value <<= 5; |
@@ -253,24 +372,24 @@ xmlDictComputeKey(const xmlChar *name, int namelen) { |
} |
/* |
- * xmlDictComputeQKey: |
- * Calculate the hash key |
+ * xmlDictComputeFastQKey: |
+ * |
+ * Calculate a hash key for two strings using a fast hash function |
+ * that works well for low hash table fill. |
+ * |
+ * Neither of the two strings must be NULL. |
*/ |
static unsigned long |
-xmlDictComputeQKey(const xmlChar *prefix, const xmlChar *name, int len) |
+xmlDictComputeFastQKey(const xmlChar *prefix, int plen, |
+ const xmlChar *name, int len) |
{ |
unsigned long value = 0L; |
- int plen; |
- |
- if (prefix == NULL) |
- return(xmlDictComputeKey(name, len)); |
- plen = xmlStrlen(prefix); |
if (plen == 0) |
value += 30 * (unsigned long) ':'; |
else |
value += 30 * (*prefix); |
- |
+ |
if (len > 10) { |
value += name[len - (plen + 1 + 1)]; |
len = 10; |
@@ -325,7 +444,11 @@ xmlDictCreate(void) { |
if (!xmlDictInitialized) |
if (!xmlInitializeDict()) |
return(NULL); |
- |
+ |
+#ifdef DICT_DEBUG_PATTERNS |
+ fprintf(stderr, "C"); |
+#endif |
+ |
dict = xmlMalloc(sizeof(xmlDict)); |
if (dict) { |
dict->ref_counter = 1; |
@@ -358,8 +481,11 @@ xmlDictCreate(void) { |
xmlDictPtr |
xmlDictCreateSub(xmlDictPtr sub) { |
xmlDictPtr dict = xmlDictCreate(); |
- |
+ |
if ((dict != NULL) && (sub != NULL)) { |
+#ifdef DICT_DEBUG_PATTERNS |
+ fprintf(stderr, "R"); |
+#endif |
dict->subdict = sub; |
xmlDictReference(dict->subdict); |
} |
@@ -398,14 +524,16 @@ xmlDictReference(xmlDictPtr dict) { |
*/ |
static int |
xmlDictGrow(xmlDictPtr dict, int size) { |
- unsigned long key; |
+ unsigned long key, okey; |
int oldsize, i; |
xmlDictEntryPtr iter, next; |
struct _xmlDictEntry *olddict; |
#ifdef DEBUG_GROW |
unsigned long nbElem = 0; |
#endif |
- |
+ int ret = 0; |
+ int keep_keys = 1; |
+ |
if (dict == NULL) |
return(-1); |
if (size < 8) |
@@ -413,11 +541,17 @@ xmlDictGrow(xmlDictPtr dict, int size) { |
if (size > 8 * 2048) |
return(-1); |
+#ifdef DICT_DEBUG_PATTERNS |
+ fprintf(stderr, "*"); |
+#endif |
+ |
oldsize = dict->size; |
olddict = dict->dict; |
if (olddict == NULL) |
return(-1); |
- |
+ if (oldsize == MIN_DICT_SIZE) |
+ keep_keys = 0; |
+ |
dict->dict = xmlMalloc(size * sizeof(xmlDictEntry)); |
if (dict->dict == NULL) { |
dict->dict = olddict; |
@@ -427,17 +561,44 @@ xmlDictGrow(xmlDictPtr dict, int size) { |
dict->size = size; |
/* If the two loops are merged, there would be situations where |
- a new entry needs to allocated and data copied into it from |
- the main dict. So instead, we run through the array twice, first |
- copying all the elements in the main array (where we can't get |
- conflicts) and then the rest, so we only free (and don't allocate) |
+ a new entry needs to allocated and data copied into it from |
+ the main dict. It is nicer to run through the array twice, first |
+ copying all the elements in the main array (less probability of |
+ allocate) and then the rest, so we only free in the second loop. |
*/ |
for (i = 0; i < oldsize; i++) { |
- if (olddict[i].valid == 0) |
+ if (olddict[i].valid == 0) |
continue; |
- key = xmlDictComputeKey(olddict[i].name, olddict[i].len) % dict->size; |
- memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry)); |
- dict->dict[key].next = NULL; |
+ |
+ if (keep_keys) |
+ okey = olddict[i].okey; |
+ else |
+ okey = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len); |
+ key = okey % dict->size; |
+ |
+ if (dict->dict[key].valid == 0) { |
+ memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry)); |
+ dict->dict[key].next = NULL; |
+ dict->dict[key].okey = okey; |
+ } else { |
+ xmlDictEntryPtr entry; |
+ |
+ entry = xmlMalloc(sizeof(xmlDictEntry)); |
+ if (entry != NULL) { |
+ entry->name = olddict[i].name; |
+ entry->len = olddict[i].len; |
+ entry->okey = okey; |
+ entry->next = dict->dict[key].next; |
+ entry->valid = 1; |
+ dict->dict[key].next = entry; |
+ } else { |
+ /* |
+ * we don't have much ways to alert from herei |
+ * result is loosing an entry and unicity garantee |
+ */ |
+ ret = -1; |
+ } |
+ } |
#ifdef DEBUG_GROW |
nbElem++; |
#endif |
@@ -452,15 +613,21 @@ xmlDictGrow(xmlDictPtr dict, int size) { |
* put back the entry in the new dict |
*/ |
- key = xmlDictComputeKey(iter->name, iter->len) % dict->size; |
+ if (keep_keys) |
+ okey = iter->okey; |
+ else |
+ okey = xmlDictComputeKey(dict, iter->name, iter->len); |
+ key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry)); |
dict->dict[key].next = NULL; |
dict->dict[key].valid = 1; |
+ dict->dict[key].okey = okey; |
xmlFree(iter); |
} else { |
- iter->next = dict->dict[key].next; |
- dict->dict[key].next = iter; |
+ iter->next = dict->dict[key].next; |
+ iter->okey = okey; |
+ dict->dict[key].next = iter; |
} |
#ifdef DEBUG_GROW |
@@ -478,7 +645,7 @@ xmlDictGrow(xmlDictPtr dict, int size) { |
"xmlDictGrow : from %d to %d, %d elems\n", oldsize, size, nbElem); |
#endif |
- return(0); |
+ return(ret); |
} |
/** |
@@ -531,7 +698,6 @@ xmlDictFree(xmlDictPtr dict) { |
inside_dict = 0; |
iter = next; |
} |
- inside_dict = 0; |
} |
xmlFree(dict->dict); |
} |
@@ -565,12 +731,12 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
return(NULL); |
if (len < 0) |
- len = xmlStrlen(name); |
+ len = strlen((const char *) name); |
/* |
* Check for duplicate and insertion location. |
*/ |
- okey = xmlDictComputeKey(name, len); |
+ okey = xmlDictComputeKey(dict, name, len); |
key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
insert = NULL; |
@@ -578,55 +744,66 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
for (insert = &(dict->dict[key]); insert->next != NULL; |
insert = insert->next) { |
#ifdef __GNUC__ |
- if (insert->len == len) { |
+ if ((insert->okey == okey) && (insert->len == len)) { |
if (!memcmp(insert->name, name, len)) |
return(insert->name); |
} |
#else |
- if ((insert->len == len) && |
+ if ((insert->okey == okey) && (insert->len == len) && |
(!xmlStrncmp(insert->name, name, len))) |
return(insert->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if (insert->len == len) { |
+ if ((insert->okey == okey) && (insert->len == len)) { |
if (!memcmp(insert->name, name, len)) |
return(insert->name); |
} |
#else |
- if ((insert->len == len) && |
+ if ((insert->okey == okey) && (insert->len == len) && |
(!xmlStrncmp(insert->name, name, len))) |
return(insert->name); |
#endif |
} |
if (dict->subdict) { |
- key = okey % dict->subdict->size; |
+ unsigned long skey; |
+ |
+ /* we cannot always reuse the same okey for the subdict */ |
+ if (((dict->size == MIN_DICT_SIZE) && |
+ (dict->subdict->size != MIN_DICT_SIZE)) || |
+ ((dict->size != MIN_DICT_SIZE) && |
+ (dict->subdict->size == MIN_DICT_SIZE))) |
+ skey = xmlDictComputeKey(dict->subdict, name, len); |
+ else |
+ skey = okey; |
+ |
+ key = skey % dict->subdict->size; |
if (dict->subdict->dict[key].valid != 0) { |
xmlDictEntryPtr tmp; |
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
tmp = tmp->next) { |
#ifdef __GNUC__ |
- if (tmp->len == len) { |
+ if ((tmp->okey == skey) && (tmp->len == len)) { |
if (!memcmp(tmp->name, name, len)) |
return(tmp->name); |
} |
#else |
- if ((tmp->len == len) && |
+ if ((tmp->okey == skey) && (tmp->len == len) && |
(!xmlStrncmp(tmp->name, name, len))) |
return(tmp->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if (tmp->len == len) { |
+ if ((tmp->okey == skey) && (tmp->len == len)) { |
if (!memcmp(tmp->name, name, len)) |
return(tmp->name); |
} |
#else |
- if ((tmp->len == len) && |
+ if ((tmp->okey == skey) && (tmp->len == len) && |
(!xmlStrncmp(tmp->name, name, len))) |
return(tmp->name); |
#endif |
@@ -648,6 +825,7 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
entry->len = len; |
entry->next = NULL; |
entry->valid = 1; |
+ entry->okey = okey; |
if (insert != NULL) |
@@ -656,8 +834,10 @@ xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) { |
dict->nbElems++; |
if ((nbi > MAX_HASH_LEN) && |
- (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) |
- xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size); |
+ (dict->size <= ((MAX_DICT_HASH / 2) / MAX_HASH_LEN))) { |
+ if (xmlDictGrow(dict, MAX_HASH_LEN * 2 * dict->size) != 0) |
+ return(NULL); |
+ } |
/* Note that entry may have been freed at this point by xmlDictGrow */ |
return(ret); |
@@ -682,12 +862,12 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
return(NULL); |
if (len < 0) |
- len = xmlStrlen(name); |
+ len = strlen((const char *) name); |
/* |
* Check for duplicate and insertion location. |
*/ |
- okey = xmlDictComputeKey(name, len); |
+ okey = xmlDictComputeKey(dict, name, len); |
key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
insert = NULL; |
@@ -695,60 +875,70 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
for (insert = &(dict->dict[key]); insert->next != NULL; |
insert = insert->next) { |
#ifdef __GNUC__ |
- if (insert->len == len) { |
+ if ((insert->okey == okey) && (insert->len == len)) { |
if (!memcmp(insert->name, name, len)) |
return(insert->name); |
} |
#else |
- if ((insert->len == len) && |
+ if ((insert->okey == okey) && (insert->len == len) && |
(!xmlStrncmp(insert->name, name, len))) |
return(insert->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if (insert->len == len) { |
+ if ((insert->okey == okey) && (insert->len == len)) { |
if (!memcmp(insert->name, name, len)) |
return(insert->name); |
} |
#else |
- if ((insert->len == len) && |
+ if ((insert->okey == okey) && (insert->len == len) && |
(!xmlStrncmp(insert->name, name, len))) |
return(insert->name); |
#endif |
} |
if (dict->subdict) { |
- key = okey % dict->subdict->size; |
+ unsigned long skey; |
+ |
+ /* we cannot always reuse the same okey for the subdict */ |
+ if (((dict->size == MIN_DICT_SIZE) && |
+ (dict->subdict->size != MIN_DICT_SIZE)) || |
+ ((dict->size != MIN_DICT_SIZE) && |
+ (dict->subdict->size == MIN_DICT_SIZE))) |
+ skey = xmlDictComputeKey(dict->subdict, name, len); |
+ else |
+ skey = okey; |
+ |
+ key = skey % dict->subdict->size; |
if (dict->subdict->dict[key].valid != 0) { |
xmlDictEntryPtr tmp; |
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
tmp = tmp->next) { |
#ifdef __GNUC__ |
- if (tmp->len == len) { |
+ if ((tmp->okey == skey) && (tmp->len == len)) { |
if (!memcmp(tmp->name, name, len)) |
return(tmp->name); |
} |
#else |
- if ((tmp->len == len) && |
+ if ((tmp->okey == skey) && (tmp->len == len) && |
(!xmlStrncmp(tmp->name, name, len))) |
return(tmp->name); |
#endif |
nbi++; |
} |
#ifdef __GNUC__ |
- if (tmp->len == len) { |
+ if ((tmp->okey == skey) && (tmp->len == len)) { |
if (!memcmp(tmp->name, name, len)) |
return(tmp->name); |
} |
#else |
- if ((tmp->len == len) && |
+ if ((tmp->okey == skey) && (tmp->len == len) && |
(!xmlStrncmp(tmp->name, name, len))) |
return(tmp->name); |
#endif |
} |
- key = okey % dict->size; |
} |
/* not found */ |
@@ -758,7 +948,7 @@ xmlDictExists(xmlDictPtr dict, const xmlChar *name, int len) { |
/** |
* xmlDictQLookup: |
* @dict: the dictionnary |
- * @prefix: the prefix |
+ * @prefix: the prefix |
* @name: the name |
* |
* Add the QName @prefix:@name to the hash @dict if not present. |
@@ -771,54 +961,67 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { |
xmlDictEntryPtr entry; |
xmlDictEntryPtr insert; |
const xmlChar *ret; |
- int len; |
+ int len, plen, l; |
if ((dict == NULL) || (name == NULL)) |
return(NULL); |
+ if (prefix == NULL) |
+ return(xmlDictLookup(dict, name, -1)); |
- len = xmlStrlen(name); |
- if (prefix != NULL) |
- len += 1 + xmlStrlen(prefix); |
+ l = len = strlen((const char *) name); |
+ plen = strlen((const char *) prefix); |
+ len += 1 + plen; |
/* |
* Check for duplicate and insertion location. |
*/ |
- okey = xmlDictComputeQKey(prefix, name, len); |
+ okey = xmlDictComputeQKey(dict, prefix, plen, name, l); |
key = okey % dict->size; |
if (dict->dict[key].valid == 0) { |
insert = NULL; |
} else { |
for (insert = &(dict->dict[key]); insert->next != NULL; |
insert = insert->next) { |
- if ((insert->len == len) && |
+ if ((insert->okey == okey) && (insert->len == len) && |
(xmlStrQEqual(prefix, name, insert->name))) |
return(insert->name); |
nbi++; |
} |
- if ((insert->len == len) && |
+ if ((insert->okey == okey) && (insert->len == len) && |
(xmlStrQEqual(prefix, name, insert->name))) |
return(insert->name); |
} |
if (dict->subdict) { |
- key = okey % dict->subdict->size; |
+ unsigned long skey; |
+ |
+ /* we cannot always reuse the same okey for the subdict */ |
+ if (((dict->size == MIN_DICT_SIZE) && |
+ (dict->subdict->size != MIN_DICT_SIZE)) || |
+ ((dict->size != MIN_DICT_SIZE) && |
+ (dict->subdict->size == MIN_DICT_SIZE))) |
+ skey = xmlDictComputeQKey(dict->subdict, prefix, plen, name, l); |
+ else |
+ skey = okey; |
+ |
+ key = skey % dict->subdict->size; |
if (dict->subdict->dict[key].valid != 0) { |
xmlDictEntryPtr tmp; |
for (tmp = &(dict->subdict->dict[key]); tmp->next != NULL; |
tmp = tmp->next) { |
- if ((tmp->len == len) && |
+ if ((tmp->okey == skey) && (tmp->len == len) && |
(xmlStrQEqual(prefix, name, tmp->name))) |
return(tmp->name); |
nbi++; |
} |
- if ((tmp->len == len) && |
+ if ((tmp->okey == skey) && (tmp->len == len) && |
(xmlStrQEqual(prefix, name, tmp->name))) |
return(tmp->name); |
} |
key = okey % dict->size; |
} |
- ret = xmlDictAddQString(dict, prefix, name, len); |
+ ret = xmlDictAddQString(dict, prefix, plen, name, l); |
if (ret == NULL) |
return(NULL); |
if (insert == NULL) { |
@@ -832,6 +1035,7 @@ xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) { |
entry->len = len; |
entry->next = NULL; |
entry->valid = 1; |
+ entry->okey = okey; |
if (insert != NULL) |
insert->next = entry; |