summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2000-10-22 16:56:02 +0000
committerDaniel Veillard <veillard@src.gnome.org>2000-10-22 16:56:02 +0000
commit52afe800ace426d98ef98f742cabbbf08c7d83e3 (patch)
tree8124d4cf20521252920384e4af5e9923d2d54dff
parent683cb026362f6f41000bda3a541b19c17e81ae48 (diff)
downloadlibxml2-52afe800ace426d98ef98f742cabbbf08c7d83e3.tar.gz
Started working on the hash table module integration, fixed a bug:
- entities.[ch] xpath.[ch] hash.[ch] debugXML.c tree.h: added/hacked hash tables from Bjorn Reese <breese@mail1.stofanet.dk>. Switched XPath functions and XML entities table to them. More to come... - xmlIO.c: fixed libxml closing FILEs it didn't open. Daniel
-rw-r--r--ChangeLog7
-rw-r--r--Makefile.am1
-rw-r--r--configure.in1
-rw-r--r--debugXML.c19
-rw-r--r--entities.c468
-rw-r--r--entities.h28
-rw-r--r--include/Makefile.am1
-rw-r--r--include/libxml/entities.h28
-rw-r--r--include/libxml/tree.h1
-rw-r--r--include/libxml/xpath.h7
-rw-r--r--tree.h1
-rw-r--r--xmlIO.c15
-rw-r--r--xpath.c208
-rw-r--r--xpath.h7
14 files changed, 180 insertions, 612 deletions
diff --git a/ChangeLog b/ChangeLog
index 59735384..004eacbc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sun Oct 22 18:39:19 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+ * entities.[ch] xpath.[ch] hash.[ch] debugXML.c tree.h: added/hacked
+ hash tables from Bjorn Reese <breese@mail1.stofanet.dk>. Switched
+ XPath functions and XML entities table to them. More to come...
+ * xmlIO.c: fixed libxml closing FILEs it didn't open.
+
Sun Oct 22 13:59:50 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* tree.c: coalesce adjacent text nodes
diff --git a/Makefile.am b/Makefile.am
index e837a143..713ecd27 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,6 +23,7 @@ libxml_la_SOURCES = \
parserInternals.c \
parser.c \
tree.c \
+ hash.c \
xmlIO.c \
xmlmemory.c \
uri.c \
diff --git a/configure.in b/configure.in
index 032d8f24..1fd2ea3b 100644
--- a/configure.in
+++ b/configure.in
@@ -264,6 +264,7 @@ AC_SUBST(HTML_OBJ)
AC_ARG_WITH(xpath, [ --with-xpath Add the XPATH support (on)])
if test "$with_xpath" = "no" ; then
echo Disabling XPATH support
+ with_xptr="no"
WITH_XPATH=0
XPATH_OBJ=
else
diff --git a/debugXML.c b/debugXML.c
index 1f172683..2ebb57e2 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -773,6 +773,7 @@ void xmlDebugDumpDTD(FILE *output, xmlDtdPtr dtd) {
void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
int i;
+ xmlHashEntryPtr ent;
xmlEntityPtr cur;
if (output == NULL) output = stdout;
@@ -828,9 +829,10 @@ void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
doc->intSubset->entities;
fprintf(output, "Entities in internal subset\n");
- for (i = 0;i < table->max_entities;i++) {
- cur = table->table[i];
- while (cur != NULL) {
+ for (i = 0;i < table->size;i++) {
+ ent = table->table[i];
+ while (ent != NULL) {
+ cur = (xmlEntityPtr) ent->payload;
fprintf(output, "%d : %s : ", i, cur->name);
switch (cur->etype) {
case XML_INTERNAL_GENERAL_ENTITY:
@@ -861,7 +863,7 @@ void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
if (cur->content != NULL)
fprintf(output, "\n content \"%s\"", cur->content);
fprintf(output, "\n");
- cur = cur->nexte;
+ ent = ent->next;
}
}
} else
@@ -870,9 +872,10 @@ void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
xmlEntitiesTablePtr table = (xmlEntitiesTablePtr)
doc->extSubset->entities;
fprintf(output, "Entities in external subset\n");
- for (i = 0;i < table->max_entities;i++) {
- cur = table->table[i];
- while (cur != NULL) {
+ for (i = 0;i < table->size;i++) {
+ ent = table->table[i];
+ while (ent != NULL) {
+ cur = (xmlEntityPtr) ent->payload;
fprintf(output, "%d : %s : ", i, cur->name);
switch (cur->etype) {
case XML_INTERNAL_GENERAL_ENTITY:
@@ -903,7 +906,7 @@ void xmlDebugDumpEntities(FILE *output, xmlDocPtr doc) {
if (cur->content != NULL)
fprintf(output, "\n content \"%s\"", cur->content);
fprintf(output, "\n");
- cur = cur->nexte;
+ ent = ent->next;
}
}
} else
diff --git a/entities.c b/entities.c
index 7c314928..d609fd34 100644
--- a/entities.c
+++ b/entities.c
@@ -18,6 +18,7 @@
#include <stdlib.h>
#endif
#include <libxml/xmlmemory.h>
+#include <libxml/hash.h>
#include <libxml/entities.h>
#include <libxml/parser.h>
@@ -60,7 +61,7 @@ struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
* TODO: !!!!!!! This is GROSS, allocation of a 256 entry hash for
* a fixed number of 4 elements !
*/
-xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
+xmlHashTablePtr xmlPredefinedEntities = NULL;
/*
* xmlFreeEntity : clean-up an entity record.
@@ -82,15 +83,6 @@ void xmlFreeEntity(xmlEntityPtr entity) {
xmlFree((char *) entity->content);
if (entity->orig != NULL)
xmlFree((char *) entity->orig);
-#ifdef WITH_EXTRA_ENT_DETECT
- if (entity->entTab != NULL) {
- int i;
-
- for (i = 0; i < entity->entNr; i++)
- xmlFree(entity->entTab[i]);
- xmlFree(entity->entTab);
- }
-#endif
memset(entity, -1, sizeof(xmlEntity));
xmlFree(entity);
}
@@ -99,77 +91,35 @@ void xmlFreeEntity(xmlEntityPtr entity) {
* xmlAddEntity : register a new entity for an entities table.
*/
static xmlEntityPtr
-xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
+xmlAddEntity(xmlDtdPtr dtd, const xmlChar *name, int type,
const xmlChar *ExternalID, const xmlChar *SystemID,
const xmlChar *content) {
-#ifndef ENTITY_HASH_SIZE
- int i;
-#endif
- int hash;
+ xmlEntitiesTablePtr table = NULL;
xmlEntityPtr ret;
if (name == NULL)
return(NULL);
-#ifdef ENTITY_HASH_SIZE
- hash = xmlEntityComputeHash(name);
- ret = table->table[hash];
- while (ret != NULL) {
- if (xmlStrEqual(ret->name, name)) {
- /*
- * The entity is already defined in this Dtd, the spec says to NOT
- * override it ... Is it worth a Warning ??? !!!
- * Not having a cprinting context this seems hard ...
- */
- if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
- (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
- ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
- (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
- return(NULL);
- else
- if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
- (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
- ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
- (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
- return(NULL);
- }
- ret = ret->nexte;
- }
-#else
- for (i = 0;i < table->nb_entities;i++) {
- ret = table->table[i];
- if (xmlStrEqual(ret->name, name)) {
- /*
- * The entity is already defined in this Dtd, the spec says to NOT
- * override it ... Is it worth a Warning ??? !!!
- * Not having a cprinting context this seems hard ...
- */
- if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
- (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
- ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
- (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
- return(NULL);
- else
- if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
- (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
- ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
- (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
- return(NULL);
- }
- }
- if (table->nb_entities >= table->max_entities) {
- /*
- * need more elements.
- */
- table->max_entities *= 2;
- table->table = (xmlEntityPtr *)
- xmlRealloc(table->table,
- table->max_entities * sizeof(xmlEntityPtr));
- if (table->table == NULL) {
- perror("realloc failed");
- return(NULL);
- }
+ switch (type) {
+ case XML_INTERNAL_GENERAL_ENTITY:
+ case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
+ case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
+ if (dtd->entities == NULL)
+ dtd->entities = xmlHashCreate(0);
+ table = dtd->entities;
+ break;
+ case XML_INTERNAL_PARAMETER_ENTITY:
+ case XML_EXTERNAL_PARAMETER_ENTITY:
+ if (dtd->pentities == NULL)
+ dtd->pentities = xmlHashCreate(0);
+ table = dtd->pentities;
+ break;
+ case XML_INTERNAL_PREDEFINED_ENTITY:
+ if (xmlPredefinedEntities == NULL)
+ xmlPredefinedEntities = xmlHashCreate(8);
+ table = xmlPredefinedEntities;
}
-#endif
+ if (table == NULL)
+ return(NULL);
ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
if (ret == NULL) {
fprintf(stderr, "xmlAddEntity: out of memory\n");
@@ -177,12 +127,6 @@ xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
}
memset(ret, 0, sizeof(xmlEntity));
ret->type = XML_ENTITY_DECL;
-#ifdef ENTITY_HASH_SIZE
- ret->nexte = table->table[hash];
- table->table[hash] = ret;
-#else
- table->table[table->nb_entities] = ret;
-#endif
/*
* fill the structure.
@@ -203,8 +147,13 @@ xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
ret->URI = NULL; /* to be computed by the layer knowing
the defining entity */
ret->orig = NULL;
- table->nb_entities++;
+ if (xmlHashAddEntry(table, name, ret)) {
+ /*
+ * entity was already defined at another level.
+ */
+ xmlFreeEntity(ret);
+ }
return(ret);
}
@@ -231,7 +180,8 @@ void xmlInitializePredefinedEntities(void) {
in = xmlPredefinedEntityValues[i].value;
out = &value[0];
for (;(*out++ = (xmlChar) *in);)in++;
- xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0],
+
+ xmlAddEntity(NULL, (const xmlChar *) &name[0],
XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
&value[0]);
}
@@ -259,26 +209,9 @@ void xmlCleanupPredefinedEntities(void) {
*/
xmlEntityPtr
xmlGetPredefinedEntity(const xmlChar *name) {
- int i;
- xmlEntityPtr cur;
-
if (xmlPredefinedEntities == NULL)
xmlInitializePredefinedEntities();
-#ifdef ENTITY_HASH_SIZE
- i = xmlEntityComputeHash(name);
- cur = xmlPredefinedEntities->table[i];
- while (cur != NULL) {
- if (xmlStrEqual(cur->name, name))
- return(cur);
- cur = cur->nexte;
- }
-#else
- for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
- cur = xmlPredefinedEntities->table[i];
- if (xmlStrEqual(cur->name, name)) return(cur);
- }
-#endif
- return(NULL);
+ return((xmlEntityPtr) xmlHashLookup(xmlPredefinedEntities, name));
}
/**
@@ -298,7 +231,6 @@ xmlEntityPtr
xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
const xmlChar *ExternalID, const xmlChar *SystemID,
const xmlChar *content) {
- xmlEntitiesTablePtr table;
xmlEntityPtr ret;
xmlDtdPtr dtd;
@@ -313,12 +245,7 @@ xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
return(NULL);
}
dtd = doc->extSubset;
- table = (xmlEntitiesTablePtr) dtd->entities;
- if (table == NULL) {
- table = xmlCreateEntitiesTable();
- dtd->entities = table;
- }
- ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
+ ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
if (ret == NULL) return(NULL);
/*
@@ -353,7 +280,6 @@ xmlEntityPtr
xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
const xmlChar *ExternalID, const xmlChar *SystemID,
const xmlChar *content) {
- xmlEntitiesTablePtr table;
xmlEntityPtr ret;
xmlDtdPtr dtd;
@@ -368,12 +294,7 @@ xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
return(NULL);
}
dtd = doc->intSubset;
- table = (xmlEntitiesTablePtr) doc->intSubset->entities;
- if (table == NULL) {
- table = xmlCreateEntitiesTable();
- doc->intSubset->entities = table;
- }
- ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
+ ret = xmlAddEntity(dtd, name, type, ExternalID, SystemID, content);
if (ret == NULL) return(NULL);
/*
@@ -391,143 +312,6 @@ xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
return(ret);
}
-#ifdef WITH_EXTRA_ENT_DETECT
-/**
- * xmlEntityCheckReference:
- * @ent: an existing entity
- * @to: the entity name it's referencing
- *
- * Function to keep track of references and detect cycles (well formedness
- * errors !).
- *
- * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
- * detection.
- */
-int
-xmlEntityCheckReference(xmlEntityPtr ent, const xmlChar *to) {
- int i;
- xmlDocPtr doc;
-
- if (ent == NULL) return(-1);
- if (to == NULL) return(-1);
-
- doc = ent->doc;
- if (doc == NULL) return(-1);
-
-#ifdef DEBUG_ENT_REF
- printf("xmlEntityCheckReference(%s to %s)\n", ent->name, to);
-#endif
-
-
- /*
- * Do a recursive checking
- */
- for (i = 0;i < ent->entNr;i++) {
- xmlEntityPtr indir = NULL;
-
- if (xmlStrEqual(to, ent->entTab[i]))
- return(1);
-
- switch (ent->etype) {
- case XML_INTERNAL_GENERAL_ENTITY:
- case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
- indir = xmlGetDocEntity(doc, ent->entTab[i]);
- break;
- case XML_INTERNAL_PARAMETER_ENTITY:
- case XML_EXTERNAL_PARAMETER_ENTITY:
- indir = xmlGetDtdEntity(doc, ent->entTab[i]);
- break;
- case XML_INTERNAL_PREDEFINED_ENTITY:
- case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
- break;
- }
- if (xmlEntityCheckReference(indir, to) == 1)
- return(1);
- }
- return(0);
-}
-
-/**
- * xmlEntityAddReference:
- * @ent: an existing entity
- * @to: the entity name it's referencing
- *
- * Function to register reuse of an existing entity from a (new) one
- * Used to keep track of references and detect cycles (well formedness
- * errors !).
- *
- * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
- * detection.
- */
-int
-xmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) {
- int i;
- xmlDocPtr doc;
- xmlEntityPtr indir = NULL;
-
- if (ent == NULL) return(-1);
- if (to == NULL) return(-1);
-
- doc = ent->doc;
- if (doc == NULL) return(-1);
-
-#ifdef DEBUG_ENT_REF
- printf("xmlEntityAddReference(%s to %s)\n", ent->name, to);
-#endif
- if (ent->entTab == NULL) {
- ent->entNr = 0;
- ent->entMax = 5;
- ent->entTab = (xmlChar **) xmlMalloc(ent->entMax * sizeof(xmlChar *));
- if (ent->entTab == NULL) {
- fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
- return(-1);
- }
- }
-
- for (i = 0;i < ent->entNr;i++) {
- if (xmlStrEqual(to, ent->entTab[i]))
- return(0);
- }
-
- /*
- * Do a recursive checking
- */
-
- switch (ent->etype) {
- case XML_INTERNAL_GENERAL_ENTITY:
- case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
- indir = xmlGetDocEntity(doc, to);
- break;
- case XML_INTERNAL_PARAMETER_ENTITY:
- case XML_EXTERNAL_PARAMETER_ENTITY:
- indir = xmlGetDtdEntity(doc, to);
- break;
- case XML_INTERNAL_PREDEFINED_ENTITY:
- case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
- break;
- }
- if ((indir != NULL) &&
- (xmlEntityCheckReference(indir, ent->name) == 1))
- return(1);
-
- /*
- * Add this to the list
- */
- if (ent->entMax <= ent->entNr) {
- ent->entMax *= 2;
- ent->entTab = (xmlChar **) xmlRealloc(ent->entTab,
- ent->entMax * sizeof(xmlChar *));
- if (ent->entTab == NULL) {
- fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
- return(-1);
- }
- }
- ent->entTab[ent->entNr++] = xmlStrdup(to);
- return(0);
-}
-#endif
-
-
/**
* xmlGetEntityFromTable:
* @table: an entity table
@@ -540,43 +324,8 @@ xmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) {
* Returns A pointer to the entity structure or NULL if not found.
*/
xmlEntityPtr
-xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name,
- int parameter) {
- xmlEntityPtr cur;
-#ifdef ENTITY_HASH_SIZE
- int hash;
-
- hash = xmlEntityComputeHash(name);
- cur = table->table[hash];
- while (cur != NULL) {
- switch (cur->etype) {
- case XML_INTERNAL_PARAMETER_ENTITY:
- case XML_EXTERNAL_PARAMETER_ENTITY:
- if ((parameter) && (xmlStrEqual(cur->name, name)))
- return(cur);
- default:
- if ((!parameter) && (xmlStrEqual(cur->name, name)))
- return(cur);
- }
- cur = cur->nexte;
- }
-#else
- int i;
-
- for (i = 0;i < table->nb_entities;i++) {
- cur = table->table[i];
- switch (cur->etype) {
- case XML_INTERNAL_PARAMETER_ENTITY:
- case XML_EXTERNAL_PARAMETER_ENTITY:
- if ((parameter) && (xmlStrEqual(cur->name, name)))
- return(cur);
- default:
- if ((!parameter) && (xmlStrEqual(cur->name, name)))
- return(cur);
- }
- }
-#endif
- return(NULL);
+xmlGetEntityFromTable(xmlEntitiesTablePtr table, const xmlChar *name) {
+ return((xmlEntityPtr) xmlHashLookup(table, name));
}
/**
@@ -594,15 +343,15 @@ xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
xmlEntitiesTablePtr table;
xmlEntityPtr ret;
- if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
- table = (xmlEntitiesTablePtr) doc->intSubset->entities;
- ret = xmlGetEntityFromTable(table, name, 1);
+ if ((doc->intSubset != NULL) && (doc->intSubset->pentities != NULL)) {
+ table = (xmlEntitiesTablePtr) doc->intSubset->pentities;
+ ret = xmlGetEntityFromTable(table, name);
if (ret != NULL)
return(ret);
}
- if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
- table = (xmlEntitiesTablePtr) doc->extSubset->entities;
- return(xmlGetEntityFromTable(table, name, 1));
+ if ((doc->extSubset != NULL) && (doc->extSubset->pentities != NULL)) {
+ table = (xmlEntitiesTablePtr) doc->extSubset->pentities;
+ return(xmlGetEntityFromTable(table, name));
}
return(NULL);
}
@@ -623,7 +372,7 @@ xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
table = (xmlEntitiesTablePtr) doc->extSubset->entities;
- return(xmlGetEntityFromTable(table, name, 0));
+ return(xmlGetEntityFromTable(table, name));
}
return(NULL);
}
@@ -647,13 +396,13 @@ xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
if (doc != NULL) {
if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
table = (xmlEntitiesTablePtr) doc->intSubset->entities;
- cur = xmlGetEntityFromTable(table, name, 0);
+ cur = xmlGetEntityFromTable(table, name);
if (cur != NULL)
return(cur);
}
if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
table = (xmlEntitiesTablePtr) doc->extSubset->entities;
- cur = xmlGetEntityFromTable(table, name, 0);
+ cur = xmlGetEntityFromTable(table, name);
if (cur != NULL)
return(cur);
}
@@ -661,7 +410,7 @@ xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
if (xmlPredefinedEntities == NULL)
xmlInitializePredefinedEntities();
table = xmlPredefinedEntities;
- return(xmlGetEntityFromTable(table, name, 0));
+ return(xmlGetEntityFromTable(table, name));
}
/*
@@ -1117,39 +866,7 @@ xmlEncodeSpecialChars(xmlDocPtr doc, const xmlChar *input) {
*/
xmlEntitiesTablePtr
xmlCreateEntitiesTable(void) {
- xmlEntitiesTablePtr ret;
-
- ret = (xmlEntitiesTablePtr)
- xmlMalloc(sizeof(xmlEntitiesTable));
- if (ret == NULL) {
- fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
- (long)sizeof(xmlEntitiesTable));
- return(NULL);
- }
- ret->nb_entities = 0;
-#ifdef ENTITY_HASH_SIZE
- ret->max_entities = ENTITY_HASH_SIZE;
- ret->table = (xmlEntityPtr *)
- xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
- if (ret == NULL) {
- fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
- ret->max_entities * (long)sizeof(xmlEntityPtr));
- xmlFree(ret);
- return(NULL);
- }
- memset(ret->table, 0, ret->max_entities * sizeof(xmlEntityPtr));
-#else
- ret->max_entities = XML_MIN_ENTITIES_TABLE;
- ret->table = (xmlEntityPtr *)
- xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
- if (ret == NULL) {
- fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
- ret->max_entities * (long)sizeof(xmlEntityPtr));
- xmlFree(ret);
- return(NULL);
- }
-#endif
- return(ret);
+ return((xmlEntitiesTablePtr) xmlHashCreate(0));
}
/**
@@ -1160,29 +877,7 @@ xmlCreateEntitiesTable(void) {
*/
void
xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
- int i;
-#ifdef ENTITY_HASH_SIZE
- xmlEntityPtr cur, next;
-#endif
-
- if (table == NULL) return;
-
-#ifdef ENTITY_HASH_SIZE
- for (i = 0;i < ENTITY_HASH_SIZE;i++) {
- cur = table->table[i];
- while (cur != NULL) {
- next = cur->nexte;
- xmlFreeEntity(cur);
- cur = next;
- }
- }
-#else
- for (i = 0;i < table->nb_entities;i++) {
- xmlFreeEntity(table->table[i]);
- }
-#endif
- xmlFree(table->table);
- xmlFree(table);
+ xmlHashFree(table, (xmlHashDeallocator) xmlFreeEntity);
}
/**
@@ -1229,50 +924,7 @@ xmlCopyEntity(xmlEntityPtr ent) {
*/
xmlEntitiesTablePtr
xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
- xmlEntitiesTablePtr ret;
- xmlEntityPtr cur, ent;
- int i;
-
- ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
- if (ret == NULL) {
- fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
- return(NULL);
- }
-#ifdef ENTITY_HASH_SIZE
- ret->table = (xmlEntityPtr *) xmlMalloc(ENTITY_HASH_SIZE *
- sizeof(xmlEntityPtr));
- if (ret->table == NULL) {
- fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
- xmlFree(ret);
- return(NULL);
- }
-#else
- ret->table = (xmlEntityPtr *) xmlMalloc(table->max_entities *
- sizeof(xmlEntityPtr));
- if (ret->table == NULL) {
- fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
- xmlFree(ret);
- return(NULL);
- }
-#endif
- ret->max_entities = table->max_entities;
- ret->nb_entities = table->nb_entities;
- for (i = 0;i < ret->nb_entities;i++) {
- ent = table->table[i];
- if (ent == NULL)
- cur = NULL;
- else
- cur = xmlCopyEntity(ent);
- ret->table[i] = cur;
-#ifdef ENTITY_HASH_SIZE
- ent = ent->nexte;
- while ((ent != NULL) && (cur != NULL)) {
- cur->nexte = xmlCopyEntity(ent);
- cur = cur->nexte;
- }
-#endif
- }
- return(ret);
+ return(xmlHashCopy(table, (xmlHashCopier) xmlCopyEntity));
}
/**
@@ -1370,23 +1022,5 @@ xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
*/
void
xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
- int i;
- xmlEntityPtr cur;
-
- if (table == NULL) return;
-
-#ifdef ENTITY_HASH_SIZE
- for (i = 0;i < ENTITY_HASH_SIZE;i++) {
- cur = table->table[i];
- while (cur != NULL) {
- xmlDumpEntityDecl(buf, cur);
- cur = cur->nexte;
- }
- }
-#else
- for (i = 0;i < table->nb_entities;i++) {
- cur = table->table[i];
- xmlDumpEntityDecl(buf, cur);
- }
-#endif
+ xmlHashScan(table, (xmlHashScanner)xmlDumpEntityDecl, buf);
}
diff --git a/entities.h b/entities.h
index 2fad326b..305d043c 100644
--- a/entities.h
+++ b/entities.h
@@ -54,33 +54,17 @@ struct _xmlEntity {
const xmlChar *ExternalID; /* External identifier for PUBLIC */
const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */
- struct _xmlEntity *nexte; /* next entity in the hash table */
+ struct _xmlEntity *nexte; /* unused */
const xmlChar *URI; /* the full URI as computed */
-
-#ifdef WITH_EXTRA_ENT_DETECT
- /* Referenced entities name stack */
- xmlChar *ent; /* Current parsed Node */
- int entNr; /* Depth of the parsing stack */
- int entMax; /* Max depth of the parsing stack */
- xmlChar * *entTab; /* array of nodes */
-#endif
};
/*
- * ALl entities are stored in a table there is one table per DTD
- * and one extra per document.
+ * ALl entities are stored in an hash table
+ * there is 2 separate hash tables for global and parmeter entities
*/
-#define XML_MIN_ENTITIES_TABLE 32
-
-typedef struct _xmlEntitiesTable xmlEntitiesTable;
+typedef struct _xmlHashTable xmlEntitiesTable;
typedef xmlEntitiesTable *xmlEntitiesTablePtr;
-struct _xmlEntitiesTable {
- int nb_entities; /* number of elements stored */
- int max_entities; /* maximum number of elements */
- xmlEntityPtr *table; /* the table of entities */
-};
-
/*
* External functions :
@@ -122,10 +106,6 @@ void xmlDumpEntityDecl (xmlBufferPtr buf,
xmlEntitiesTablePtr xmlCopyEntitiesTable (xmlEntitiesTablePtr table);
void xmlCleanupPredefinedEntities(void);
-#ifdef WITH_EXTRA_ENT_DETECT
-int xmlEntityAddReference (xmlEntityPtr ent,
- const xmlChar *to);
-#endif
#ifdef __cplusplus
}
diff --git a/include/Makefile.am b/include/Makefile.am
index aa845776..18d7cfaa 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -14,6 +14,7 @@ xmlinc_HEADERS = \
libxml/HTMLtree.h \
libxml/debugXML.h \
libxml/tree.h \
+ libxml/hash.h \
libxml/xpath.h \
libxml/xpointer.h \
libxml/xmlIO.h \
diff --git a/include/libxml/entities.h b/include/libxml/entities.h
index 2fad326b..305d043c 100644
--- a/include/libxml/entities.h
+++ b/include/libxml/entities.h
@@ -54,33 +54,17 @@ struct _xmlEntity {
const xmlChar *ExternalID; /* External identifier for PUBLIC */
const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */
- struct _xmlEntity *nexte; /* next entity in the hash table */
+ struct _xmlEntity *nexte; /* unused */
const xmlChar *URI; /* the full URI as computed */
-
-#ifdef WITH_EXTRA_ENT_DETECT
- /* Referenced entities name stack */
- xmlChar *ent; /* Current parsed Node */
- int entNr; /* Depth of the parsing stack */
- int entMax; /* Max depth of the parsing stack */
- xmlChar * *entTab; /* array of nodes */
-#endif
};
/*
- * ALl entities are stored in a table there is one table per DTD
- * and one extra per document.
+ * ALl entities are stored in an hash table
+ * there is 2 separate hash tables for global and parmeter entities
*/
-#define XML_MIN_ENTITIES_TABLE 32
-
-typedef struct _xmlEntitiesTable xmlEntitiesTable;
+typedef struct _xmlHashTable xmlEntitiesTable;
typedef xmlEntitiesTable *xmlEntitiesTablePtr;
-struct _xmlEntitiesTable {
- int nb_entities; /* number of elements stored */
- int max_entities; /* maximum number of elements */
- xmlEntityPtr *table; /* the table of entities */
-};
-
/*
* External functions :
@@ -122,10 +106,6 @@ void xmlDumpEntityDecl (xmlBufferPtr buf,
xmlEntitiesTablePtr xmlCopyEntitiesTable (xmlEntitiesTablePtr table);
void xmlCleanupPredefinedEntities(void);
-#ifdef WITH_EXTRA_ENT_DETECT
-int xmlEntityAddReference (xmlEntityPtr ent,
- const xmlChar *to);
-#endif
#ifdef __cplusplus
}
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 2a14d1d2..062f551b 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -233,6 +233,7 @@ struct _xmlDtd {
void *entities; /* Hash table for entities if any */
const xmlChar *ExternalID; /* External identifier for PUBLIC DTD */
const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC DTD */
+ void *pentities; /* Hash table for param entities if any */
};
/*
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index a0a55785..add4edda 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -13,6 +13,7 @@
#define __XML_XPATH_H__
#include <libxml/tree.h>
+#include <libxml/hash.h>
#ifdef __cplusplus
extern "C" {
@@ -184,9 +185,9 @@ struct _xmlXPathContext {
int max_types; /* max number of types */
xmlXPathTypePtr types; /* Array of defined types */
- int nb_funcs; /* number of defined funcs */
- int max_funcs; /* max number of funcs */
- xmlXPathFuncPtr funcs; /* Array of defined funcs */
+ int nb_funcs_unused; /* unused (hash table) */
+ int max_funcs_unused; /* unused (hash table) */
+ xmlHashTablePtr funcHash; /* Hash table of defined funcs */
int nb_axis; /* number of defined axis */
int max_axis; /* max number of axis */
diff --git a/tree.h b/tree.h
index 2a14d1d2..062f551b 100644
--- a/tree.h
+++ b/tree.h
@@ -233,6 +233,7 @@ struct _xmlDtd {
void *entities; /* Hash table for entities if any */
const xmlChar *ExternalID; /* External identifier for PUBLIC DTD */
const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC DTD */
+ void *pentities; /* Hash table for param entities if any */
};
/*
diff --git a/xmlIO.c b/xmlIO.c
index 0631dd23..667b3dd1 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -340,6 +340,17 @@ xmlFileClose (void * context) {
fclose((FILE *) context);
}
+/**
+ * xmlFileFlush:
+ * @context: the I/O context
+ *
+ * Flush an I/O channel
+ */
+void
+xmlFileFlush (void * context) {
+ fflush((FILE *) context);
+}
+
#ifdef HAVE_ZLIB_H
/************************************************************************
* *
@@ -990,7 +1001,7 @@ xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
if (ret != NULL) {
ret->context = file;
ret->readcallback = xmlFileRead;
- ret->closecallback = xmlFileClose;
+ ret->closecallback = xmlFileFlush;
}
return(ret);
@@ -1019,7 +1030,7 @@ xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
if (ret != NULL) {
ret->context = file;
ret->writecallback = xmlFileWrite;
- ret->closecallback = xmlFileClose;
+ ret->closecallback = xmlFileFlush;
}
return(ret);
diff --git a/xpath.c b/xpath.c
index 78152993..cd2533bb 100644
--- a/xpath.c
+++ b/xpath.c
@@ -49,6 +49,7 @@
#include <libxml/valid.h>
#include <libxml/xpath.h>
#include <libxml/parserInternals.h>
+#include <libxml/hash.h>
#ifdef LIBXML_XPTR_ENABLED
#include <libxml/xpointer.h>
#endif
@@ -184,6 +185,7 @@ FILE *xmlXPathDebug = NULL;
#ifdef LIBXML_DEBUG_ENABLED
double xmlXPathStringEvalNumber(const xmlChar *str);
void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs);
+void xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt);
void xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
int i;
@@ -832,40 +834,16 @@ xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
int
xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
xmlXPathFunction f) {
- int i;
-
if (ctxt == NULL)
return(-1);
if (name == NULL)
return(-1);
- for (i = 0;i < ctxt->nb_funcs;i++) {
- if (xmlStrEqual(ctxt->funcs[i].name, name)) {
- /*
- * It's just an update or a removal
- */
- ctxt->funcs[i].func = f;
- return(0);
- }
- }
- if (ctxt->max_funcs <= 0) {
- ctxt->max_funcs = 10;
- ctxt->nb_funcs = 0;
- ctxt->funcs = (xmlXPathFuncPtr) xmlMalloc(ctxt->max_funcs *
- sizeof(xmlXPathFunct));
- } else if (ctxt->max_funcs <= ctxt->nb_funcs) {
- ctxt->max_funcs *= 2;
- ctxt->funcs = (xmlXPathFuncPtr) xmlRealloc(ctxt->funcs,
- ctxt->max_funcs * sizeof(xmlXPathFunct));
- }
- if (ctxt->funcs == NULL) {
- fprintf(xmlXPathDebug, "xmlXPathRegisterFunc: out of memory\n");
+ if (ctxt->funcHash == NULL)
+ ctxt->funcHash = xmlHashCreate(0);
+ if (ctxt->funcHash == NULL)
return(-1);
- }
- ctxt->funcs[ctxt->nb_funcs].name = xmlStrdup(name);
- ctxt->funcs[ctxt->nb_funcs].func = f;
- ctxt->nb_funcs++;
- return(0);
+ return(xmlHashAddEntry(ctxt->funcHash, name, (void *) f));
}
/**
@@ -880,19 +858,14 @@ xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
*/
xmlXPathFunction
xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
- int i;
-
if (ctxt == NULL)
return(NULL);
+ if (ctxt->funcHash == NULL)
+ return(NULL);
if (name == NULL)
return(NULL);
- for (i = 0;i < ctxt->nb_funcs;i++) {
- if (xmlStrEqual(ctxt->funcs[i].name, name)) {
- return(ctxt->funcs[i].func);
- }
- }
- return(NULL);
+ return((xmlXPathFunction) xmlHashLookup(ctxt->funcHash, name));
}
/**
@@ -903,19 +876,11 @@ xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
*/
void
xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
- int i;
-
if (ctxt == NULL)
return;
- for (i = 0;i < ctxt->nb_funcs;i++) {
- xmlFree((xmlChar *) ctxt->funcs[i].name);
- }
- ctxt->nb_funcs = -1;
- ctxt->max_funcs = -1;
- if (ctxt->funcs != NULL)
- xmlFree(ctxt->funcs);
- ctxt->funcs = NULL;
+ xmlHashFree(ctxt->funcHash, NULL);
+ ctxt->funcHash = NULL;
}
/************************************************************************
@@ -1239,9 +1204,7 @@ xmlXPathNewContext(xmlDocPtr doc) {
ret->max_types = 0;
ret->types = NULL;
- ret->nb_funcs = 0;
- ret->max_funcs = 0;
- ret->funcs = NULL;
+ ret->funcHash = xmlHashCreate(0);
ret->nb_axis = 0;
ret->max_axis = 0;
@@ -1253,6 +1216,9 @@ xmlXPathNewContext(xmlDocPtr doc) {
ret->contextSize = -1;
ret->proximityPosition = -1;
+
+ xmlXPathRegisterAllFunctions(ret);
+
return(ret);
}
@@ -4012,88 +3978,7 @@ xmlXPathIsNodeType(const xmlChar *name) {
*/
xmlXPathFunction
xmlXPathIsFunction(xmlXPathParserContextPtr ctxt, const xmlChar *name) {
- if (name == NULL)
- return(NULL);
-
- switch (name[0]) {
- case 'b':
- if (xmlStrEqual(name, BAD_CAST "boolean"))
- return(xmlXPathBooleanFunction);
- break;
- case 'c':
- if (xmlStrEqual(name, BAD_CAST "ceiling"))
- return(xmlXPathCeilingFunction);
- if (xmlStrEqual(name, BAD_CAST "count"))
- return(xmlXPathCountFunction);
- if (xmlStrEqual(name, BAD_CAST "concat"))
- return(xmlXPathConcatFunction);
- if (xmlStrEqual(name, BAD_CAST "contains"))
- return(xmlXPathContainsFunction);
- break;
- case 'i':
- if (xmlStrEqual(name, BAD_CAST "id"))
- return(xmlXPathIdFunction);
- break;
- case 'f':
- if (xmlStrEqual(name, BAD_CAST "false"))
- return(xmlXPathFalseFunction);
- if (xmlStrEqual(name, BAD_CAST "floor"))
- return(xmlXPathFloorFunction);
- break;
- case 'l':
- if (xmlStrEqual(name, BAD_CAST "last"))
- return(xmlXPathLastFunction);
- if (xmlStrEqual(name, BAD_CAST "lang"))
- return(xmlXPathLangFunction);
- if (xmlStrEqual(name, BAD_CAST "local-part"))
- return(xmlXPathLocalPartFunction);
- break;
- case 'n':
- if (xmlStrEqual(name, BAD_CAST "not"))
- return(xmlXPathNotFunction);
- if (xmlStrEqual(name, BAD_CAST "name"))
- return(xmlXPathNameFunction);
- if (xmlStrEqual(name, BAD_CAST "namespace"))
- return(xmlXPathNamespaceFunction);
- if (xmlStrEqual(name, BAD_CAST "normalize-space"))
- return(xmlXPathNormalizeFunction);
- if (xmlStrEqual(name, BAD_CAST "normalize"))
- return(xmlXPathNormalizeFunction);
- if (xmlStrEqual(name, BAD_CAST "number"))
- return(xmlXPathNumberFunction);
- break;
- case 'p':
- if (xmlStrEqual(name, BAD_CAST "position"))
- return(xmlXPathPositionFunction);
- break;
- case 'r':
- if (xmlStrEqual(name, BAD_CAST "round"))
- return(xmlXPathRoundFunction);
- break;
- case 's':
- if (xmlStrEqual(name, BAD_CAST "string"))
- return(xmlXPathStringFunction);
- if (xmlStrEqual(name, BAD_CAST "string-length"))
- return(xmlXPathStringLengthFunction);
- if (xmlStrEqual(name, BAD_CAST "starts-with"))
- return(xmlXPathStartsWithFunction);
- if (xmlStrEqual(name, BAD_CAST "substring"))
- return(xmlXPathSubstringFunction);
- if (xmlStrEqual(name, BAD_CAST "substring-before"))
- return(xmlXPathSubstringBeforeFunction);
- if (xmlStrEqual(name, BAD_CAST "substring-after"))
- return(xmlXPathSubstringAfterFunction);
- if (xmlStrEqual(name, BAD_CAST "sum"))
- return(xmlXPathSumFunction);
- break;
- case 't':
- if (xmlStrEqual(name, BAD_CAST "true"))
- return(xmlXPathTrueFunction);
- if (xmlStrEqual(name, BAD_CAST "translate"))
- return(xmlXPathTranslateFunction);
- break;
- }
- return(xmlXPathFunctionLookup(ctxt->context, name));
+ return((xmlXPathFunction) xmlHashLookup(ctxt->context->funcHash, name));
}
/**
@@ -5383,4 +5268,65 @@ xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
return(res);
}
+void
+xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
+{
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
+ xmlXPathBooleanFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
+ xmlXPathCeilingFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
+ xmlXPathCountFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
+ xmlXPathConcatFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
+ xmlXPathContainsFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
+ xmlXPathIdFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
+ xmlXPathFalseFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
+ xmlXPathFloorFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
+ xmlXPathLastFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
+ xmlXPathLangFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-part",
+ xmlXPathLocalPartFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
+ xmlXPathNotFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
+ xmlXPathNameFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace",
+ xmlXPathNamespaceFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
+ xmlXPathNormalizeFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize",
+ xmlXPathNormalizeFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
+ xmlXPathNumberFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
+ xmlXPathPositionFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
+ xmlXPathRoundFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
+ xmlXPathStringFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
+ xmlXPathStringLengthFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
+ xmlXPathStartsWithFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
+ xmlXPathSubstringFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
+ xmlXPathSubstringBeforeFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
+ xmlXPathSubstringAfterFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
+ xmlXPathSumFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
+ xmlXPathTrueFunction);
+ xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
+ xmlXPathTranslateFunction);
+}
+
#endif /* LIBXML_XPATH_ENABLED */
diff --git a/xpath.h b/xpath.h
index a0a55785..add4edda 100644
--- a/xpath.h
+++ b/xpath.h
@@ -13,6 +13,7 @@
#define __XML_XPATH_H__
#include <libxml/tree.h>
+#include <libxml/hash.h>
#ifdef __cplusplus
extern "C" {
@@ -184,9 +185,9 @@ struct _xmlXPathContext {
int max_types; /* max number of types */
xmlXPathTypePtr types; /* Array of defined types */
- int nb_funcs; /* number of defined funcs */
- int max_funcs; /* max number of funcs */
- xmlXPathFuncPtr funcs; /* Array of defined funcs */
+ int nb_funcs_unused; /* unused (hash table) */
+ int max_funcs_unused; /* unused (hash table) */
+ xmlHashTablePtr funcHash; /* Hash table of defined funcs */
int nb_axis; /* number of defined axis */
int max_axis; /* max number of axis */