added io1.c an example ox xmlIO usage and io1.res test result, fixed a
* doc/examples/*: added io1.c an example ox xmlIO usage and io1.res
test result, fixed a awful lot of memory leaks showing up in
testWriter.c, changed the examples and the Makefiles to test
memory leaks.
* xmlwriter.c: fixed a memory leak
* Makefile.am: run the doc/examples regression tests as part of
make tests
* xpath.c include/libxml/xpath.h: added xmlXPathCtxtCompile() to
compile an XPath expression within a context, currently the goal
is to be able to reuse the XSLT stylesheet dictionnary, but this
opens the door to others possible optimizations.
* dict.c include/libxml/dict.h: added xmlDictCreateSub() which allows
to build a new dictionnary based on another read-only dictionnary.
This is needed for XSLT to keep the stylesheet dictionnary read-only
while being able to reuse the strings for the transformation
dictionnary.
* xinclude.c: fixed a dictionnar reference counting problem occuring
when document parsing failed.
* testSAX.c: adding option --repeat for timing 100times the parsing
* doc/* : rebuilt all the docs
Daniel
diff --git a/dict.c b/dict.c
index 0a9aebe..2ffd6a5 100644
--- a/dict.c
+++ b/dict.c
@@ -65,6 +65,8 @@
int size;
int nbElems;
xmlDictStringsPtr strings;
+
+ struct _xmlDict *subdict;
};
/*
@@ -181,11 +183,12 @@
* Calculate the hash key
*/
static unsigned long
-xmlDictComputeKey(xmlDictPtr dict, const xmlChar *name, int namelen) {
+xmlDictComputeKey(const xmlChar *name, int namelen) {
unsigned long value = 0L;
if (name == NULL) return(0);
- value += 30 * (*name);
+ value = *name;
+ value <<= 5;
if (namelen > 10) {
value += name[namelen - 1];
namelen = 10;
@@ -200,10 +203,9 @@
case 4: value += name[3];
case 3: value += name[2];
case 2: value += name[1];
- case 1: value += name[0];
default: break;
}
- return (value % dict->size);
+ return(value);
}
/*
@@ -211,14 +213,13 @@
* Calculate the hash key
*/
static unsigned long
-xmlDictComputeQKey(xmlDictPtr dict, const xmlChar *prefix,
- const xmlChar *name, int len)
+xmlDictComputeQKey(const xmlChar *prefix, const xmlChar *name, int len)
{
unsigned long value = 0L;
int plen;
if (prefix == NULL)
- return(xmlDictComputeKey(dict, name, len));
+ return(xmlDictComputeKey(name, len));
plen = xmlStrlen(prefix);
if (plen == 0)
@@ -263,7 +264,7 @@
case 1: value += name[0];
default: break;
}
- return (value % dict->size);
+ return(value);
}
/**
@@ -271,7 +272,7 @@
*
* Create a new dictionary
*
- * Returns the newly created object, or NULL if an error occured.
+ * Returns the newly created dictionnary, or NULL if an error occured.
*/
xmlDictPtr
xmlDictCreate(void) {
@@ -285,6 +286,7 @@
dict->nbElems = 0;
dict->dict = xmlMalloc(MIN_DICT_SIZE * sizeof(xmlDictEntry));
dict->strings = NULL;
+ dict->subdict = NULL;
if (dict->dict) {
memset(dict->dict, 0, MIN_DICT_SIZE * sizeof(xmlDictEntry));
return(dict);
@@ -295,6 +297,28 @@
}
/**
+ * xmlDictCreateSub:
+ * @sub: an existing dictionnary
+ *
+ * Create a new dictionary, inheriting strings from the read-only
+ * dictionnary @sub. On lookup, strings are first searched in the
+ * new dictionnary, then in @sub, and if not found are created in the
+ * new dictionnary.
+ *
+ * Returns the newly created dictionnary, or NULL if an error occured.
+ */
+xmlDictPtr
+xmlDictCreateSub(xmlDictPtr sub) {
+ xmlDictPtr dict = xmlDictCreate();
+
+ if ((dict != NULL) && (sub != NULL)) {
+ dict->subdict = sub;
+ xmlDictReference(dict->subdict);
+ }
+ return(dict);
+}
+
+/**
* xmlDictReference:
* @dict: the dictionnary
*
@@ -357,7 +381,7 @@
for (i = 0; i < oldsize; i++) {
if (olddict[i].valid == 0)
continue;
- key = xmlDictComputeKey(dict, olddict[i].name, olddict[i].len);
+ key = xmlDictComputeKey(olddict[i].name, olddict[i].len) % dict->size;
memcpy(&(dict->dict[key]), &(olddict[i]), sizeof(xmlDictEntry));
dict->dict[key].next = NULL;
#ifdef DEBUG_GROW
@@ -374,7 +398,7 @@
* put back the entry in the new dict
*/
- key = xmlDictComputeKey(dict, iter->name, iter->len);
+ key = xmlDictComputeKey(iter->name, iter->len) % dict->size;
if (dict->dict[key].valid == 0) {
memcpy(&(dict->dict[key]), iter, sizeof(xmlDictEntry));
dict->dict[key].next = NULL;
@@ -425,6 +449,10 @@
dict->ref_counter--;
if (dict->ref_counter > 0) return;
+ if (dict->subdict != NULL) {
+ xmlDictFree(dict->subdict);
+ }
+
if (dict->dict) {
for(i = 0; ((i < dict->size) && (dict->nbElems > 0)); i++) {
iter = &(dict->dict[i]);
@@ -464,7 +492,7 @@
*/
const xmlChar *
xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len) {
- unsigned long key, nbi = 0;
+ unsigned long key, okey, nbi = 0;
xmlDictEntryPtr entry;
xmlDictEntryPtr insert;
const xmlChar *ret;
@@ -478,7 +506,8 @@
/*
* Check for duplicate and insertion location.
*/
- key = xmlDictComputeKey(dict, name, len);
+ okey = xmlDictComputeKey(name, len);
+ key = okey % dict->size;
if (dict->dict[key].valid == 0) {
insert = NULL;
} else {
@@ -486,8 +515,7 @@
insert = insert->next) {
#ifdef __GNUC__
if (insert->len == len) {
- register int tmp = memcmp(insert->name, name, len);
- if (!tmp)
+ if (!memcmp(insert->name, name, len))
return(insert->name);
}
#else
@@ -499,8 +527,7 @@
}
#ifdef __GNUC__
if (insert->len == len) {
- register int tmp = memcmp(insert->name, name, len);
- if (!tmp)
+ if (!memcmp(insert->name, name, len))
return(insert->name);
}
#else
@@ -510,6 +537,39 @@
#endif
}
+ if (dict->subdict) {
+ key = okey % 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 (!memcmp(tmp->name, name, len))
+ return(tmp->name);
+ }
+#else
+ if ((tmp->len == len) &&
+ (!xmlStrncmp(tmp->name, name, len)))
+ return(tmp->name);
+#endif
+ nbi++;
+ }
+#ifdef __GNUC__
+ if (tmp->len == len) {
+ if (!memcmp(tmp->name, name, len))
+ return(tmp->name);
+ }
+#else
+ if ((tmp->len == len) &&
+ (!xmlStrncmp(tmp->name, name, len)))
+ return(tmp->name);
+#endif
+ }
+ key = okey % dict->size;
+ }
+
ret = xmlDictAddString(dict, name, len);
if (ret == NULL)
return(NULL);
@@ -551,7 +611,7 @@
*/
const xmlChar *
xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name) {
- unsigned long key, nbi = 0;
+ unsigned long okey, key, nbi = 0;
xmlDictEntryPtr entry;
xmlDictEntryPtr insert;
const xmlChar *ret;
@@ -567,7 +627,8 @@
/*
* Check for duplicate and insertion location.
*/
- key = xmlDictComputeQKey(dict, prefix, name, len);
+ okey = xmlDictComputeQKey(prefix, name, len);
+ key = okey % dict->size;
if (dict->dict[key].valid == 0) {
insert = NULL;
} else {
@@ -583,6 +644,24 @@
return(insert->name);
}
+ if (dict->subdict) {
+ key = okey % 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) &&
+ (xmlStrQEqual(prefix, name, tmp->name)))
+ return(tmp->name);
+ nbi++;
+ }
+ if ((tmp->len == len) &&
+ (xmlStrQEqual(prefix, name, tmp->name)))
+ return(tmp->name);
+ }
+ key = okey % dict->size;
+ }
+
ret = xmlDictAddQString(dict, prefix, name, len);
if (ret == NULL)
return(NULL);
@@ -633,6 +712,8 @@
return(1);
pool = pool->next;
}
+ if (dict->subdict)
+ return(xmlDictOwns(dict->subdict, str));
return(0);
}
@@ -649,6 +730,8 @@
xmlDictSize(xmlDictPtr dict) {
if (dict == NULL)
return(-1);
+ if (dict->subdict)
+ return(dict->nbElems + dict->subdict->nbElems);
return(dict->nbElems);
}