Skip to content

Commit bf5fcf6

Browse files
committed
xpath: Use separate static hash table for standard functions
This avoids registering standard functions when creating an XPath context. Lookup of extension functions is a bit slower now, but ultimately, all function lookups should be moved to the compilation phase.
1 parent 0dd910e commit bf5fcf6

File tree

1 file changed

+98
-72
lines changed

1 file changed

+98
-72
lines changed

xpath.c

Lines changed: 98 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,48 @@
133133

134134
#if defined(LIBXML_XPATH_ENABLED)
135135

136-
/************************************************************************
137-
* *
138-
* Floating point stuff *
139-
* *
140-
************************************************************************/
136+
static void
137+
xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs);
138+
139+
static const struct {
140+
const char *name;
141+
xmlXPathFunction func;
142+
} xmlXPathStandardFunctions[] = {
143+
{ "boolean", xmlXPathBooleanFunction },
144+
{ "ceiling", xmlXPathCeilingFunction },
145+
{ "count", xmlXPathCountFunction },
146+
{ "concat", xmlXPathConcatFunction },
147+
{ "contains", xmlXPathContainsFunction },
148+
{ "id", xmlXPathIdFunction },
149+
{ "false", xmlXPathFalseFunction },
150+
{ "floor", xmlXPathFloorFunction },
151+
{ "last", xmlXPathLastFunction },
152+
{ "lang", xmlXPathLangFunction },
153+
{ "local-name", xmlXPathLocalNameFunction },
154+
{ "not", xmlXPathNotFunction },
155+
{ "name", xmlXPathNameFunction },
156+
{ "namespace-uri", xmlXPathNamespaceURIFunction },
157+
{ "normalize-space", xmlXPathNormalizeFunction },
158+
{ "number", xmlXPathNumberFunction },
159+
{ "position", xmlXPathPositionFunction },
160+
{ "round", xmlXPathRoundFunction },
161+
{ "string", xmlXPathStringFunction },
162+
{ "string-length", xmlXPathStringLengthFunction },
163+
{ "starts-with", xmlXPathStartsWithFunction },
164+
{ "substring", xmlXPathSubstringFunction },
165+
{ "substring-before", xmlXPathSubstringBeforeFunction },
166+
{ "substring-after", xmlXPathSubstringAfterFunction },
167+
{ "sum", xmlXPathSumFunction },
168+
{ "true", xmlXPathTrueFunction },
169+
{ "translate", xmlXPathTranslateFunction }
170+
};
171+
172+
#define NUM_STANDARD_FUNCTIONS \
173+
(sizeof(xmlXPathStandardFunctions) / sizeof(xmlXPathStandardFunctions[0]))
174+
175+
#define SF_HASH_SIZE 64
176+
177+
static unsigned char xmlXPathSFHash[SF_HASH_SIZE];
141178

142179
double xmlXPathNAN = 0.0;
143180
double xmlXPathPINF = 0.0;
@@ -153,6 +190,18 @@ xmlXPathInit(void) {
153190
xmlInitParser();
154191
}
155192

193+
ATTRIBUTE_NO_SANITIZE_INTEGER
194+
static unsigned
195+
xmlXPathSFComputeHash(const xmlChar *name) {
196+
unsigned hashValue = 5381;
197+
const xmlChar *ptr;
198+
199+
for (ptr = name; *ptr; ptr++)
200+
hashValue = hashValue * 33 + *ptr;
201+
202+
return(hashValue);
203+
}
204+
156205
/**
157206
* xmlInitXPathInternal:
158207
*
@@ -161,6 +210,8 @@ xmlXPathInit(void) {
161210
ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
162211
void
163212
xmlInitXPathInternal(void) {
213+
size_t i;
214+
164215
#if defined(NAN) && defined(INFINITY)
165216
xmlXPathNAN = NAN;
166217
xmlXPathPINF = INFINITY;
@@ -172,8 +223,34 @@ xmlInitXPathInternal(void) {
172223
xmlXPathPINF = 1.0 / zero;
173224
xmlXPathNINF = -xmlXPathPINF;
174225
#endif
226+
227+
/*
228+
* Initialize hash table for standard functions
229+
*/
230+
231+
for (i = 0; i < SF_HASH_SIZE; i++)
232+
xmlXPathSFHash[i] = UCHAR_MAX;
233+
234+
for (i = 0; i < NUM_STANDARD_FUNCTIONS; i++) {
235+
const char *name = xmlXPathStandardFunctions[i].name;
236+
int bucketIndex = xmlXPathSFComputeHash(BAD_CAST name) % SF_HASH_SIZE;
237+
238+
while (xmlXPathSFHash[bucketIndex] != UCHAR_MAX) {
239+
bucketIndex += 1;
240+
if (bucketIndex >= SF_HASH_SIZE)
241+
bucketIndex = 0;
242+
}
243+
244+
xmlXPathSFHash[bucketIndex] = i;
245+
}
175246
}
176247

248+
/************************************************************************
249+
* *
250+
* Floating point stuff *
251+
* *
252+
************************************************************************/
253+
177254
/**
178255
* xmlXPathIsNaN:
179256
* @val: a double value
@@ -3858,18 +3935,6 @@ xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
38583935
*/
38593936
xmlXPathFunction
38603937
xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
3861-
if (ctxt == NULL)
3862-
return (NULL);
3863-
3864-
if (ctxt->funcLookupFunc != NULL) {
3865-
xmlXPathFunction ret;
3866-
xmlXPathFuncLookupFunc f;
3867-
3868-
f = ctxt->funcLookupFunc;
3869-
ret = f(ctxt->funcLookupData, name, NULL);
3870-
if (ret != NULL)
3871-
return(ret);
3872-
}
38733938
return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
38743939
}
38753940

@@ -3894,6 +3959,22 @@ xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
38943959
if (name == NULL)
38953960
return(NULL);
38963961

3962+
if (ns_uri == NULL) {
3963+
int bucketIndex = xmlXPathSFComputeHash(name) % SF_HASH_SIZE;
3964+
3965+
while (xmlXPathSFHash[bucketIndex] != UCHAR_MAX) {
3966+
int funcIndex = xmlXPathSFHash[bucketIndex];
3967+
3968+
if (strcmp(xmlXPathStandardFunctions[funcIndex].name,
3969+
(char *) name) == 0)
3970+
return(xmlXPathStandardFunctions[funcIndex].func);
3971+
3972+
bucketIndex += 1;
3973+
if (bucketIndex >= SF_HASH_SIZE)
3974+
bucketIndex = 0;
3975+
}
3976+
}
3977+
38973978
if (ctxt->funcLookupFunc != NULL) {
38983979
xmlXPathFuncLookupFunc f;
38993980

@@ -12807,61 +12888,6 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
1280712888
void
1280812889
xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
1280912890
{
12810-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
12811-
xmlXPathBooleanFunction);
12812-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
12813-
xmlXPathCeilingFunction);
12814-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
12815-
xmlXPathCountFunction);
12816-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
12817-
xmlXPathConcatFunction);
12818-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
12819-
xmlXPathContainsFunction);
12820-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
12821-
xmlXPathIdFunction);
12822-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
12823-
xmlXPathFalseFunction);
12824-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
12825-
xmlXPathFloorFunction);
12826-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
12827-
xmlXPathLastFunction);
12828-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
12829-
xmlXPathLangFunction);
12830-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
12831-
xmlXPathLocalNameFunction);
12832-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
12833-
xmlXPathNotFunction);
12834-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
12835-
xmlXPathNameFunction);
12836-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
12837-
xmlXPathNamespaceURIFunction);
12838-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
12839-
xmlXPathNormalizeFunction);
12840-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
12841-
xmlXPathNumberFunction);
12842-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
12843-
xmlXPathPositionFunction);
12844-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
12845-
xmlXPathRoundFunction);
12846-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
12847-
xmlXPathStringFunction);
12848-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
12849-
xmlXPathStringLengthFunction);
12850-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
12851-
xmlXPathStartsWithFunction);
12852-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
12853-
xmlXPathSubstringFunction);
12854-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
12855-
xmlXPathSubstringBeforeFunction);
12856-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
12857-
xmlXPathSubstringAfterFunction);
12858-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
12859-
xmlXPathSumFunction);
12860-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
12861-
xmlXPathTrueFunction);
12862-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
12863-
xmlXPathTranslateFunction);
12864-
1286512891
xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
1286612892
(const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
1286712893
xmlXPathEscapeUriFunction);

0 commit comments

Comments
 (0)