From d3e3526111097560cf7c002613e2cb1d469b59e0 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer <wellnhofer@aevum.de> Date: Sat, 21 Dec 2024 16:03:46 +0100 Subject: [PATCH] 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.
(cherry picked from commit bf5fcf6e646bb51a0f6a3655a1d64bea97274867)
xpath.c | 170 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 98 insertions(+), 72 deletions(-)
diff –git a/xpath.c b/xpath.c index 485d7747..21711653 100644 — a/xpath.c +++ b/xpath.c @@ -136,11 +136,48 @@
#if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
-/************************************************************************
-
*
-
-
Floating point stuff *
-
-
*
-
-
************************************************************************/
+static void +xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs); + +static const struct { + const char *name; + xmlXPathFunction func; +} xmlXPathStandardFunctions[] = { + { “boolean”, xmlXPathBooleanFunction }, + { “ceiling”, xmlXPathCeilingFunction }, + { “count”, xmlXPathCountFunction }, + { “concat”, xmlXPathConcatFunction }, + { “contains”, xmlXPathContainsFunction }, + { “id”, xmlXPathIdFunction }, + { “false”, xmlXPathFalseFunction }, + { “floor”, xmlXPathFloorFunction }, + { “last”, xmlXPathLastFunction }, + { “lang”, xmlXPathLangFunction }, + { “local-name”, xmlXPathLocalNameFunction }, + { “not”, xmlXPathNotFunction }, + { “name”, xmlXPathNameFunction }, + { “namespace-uri”, xmlXPathNamespaceURIFunction }, + { “normalize-space”, xmlXPathNormalizeFunction }, + { “number”, xmlXPathNumberFunction }, + { “position”, xmlXPathPositionFunction }, + { “round”, xmlXPathRoundFunction }, + { “string”, xmlXPathStringFunction }, + { “string-length”, xmlXPathStringLengthFunction }, + { “starts-with”, xmlXPathStartsWithFunction }, + { “substring”, xmlXPathSubstringFunction }, + { “substring-before”, xmlXPathSubstringBeforeFunction }, + { “substring-after”, xmlXPathSubstringAfterFunction }, + { “sum”, xmlXPathSumFunction }, + { “true”, xmlXPathTrueFunction }, + { “translate”, xmlXPathTranslateFunction } +}; + +#define NUM_STANDARD_FUNCTIONS \ + (sizeof(xmlXPathStandardFunctions) / sizeof(xmlXPathStandardFunctions)) + +#define SF_HASH_SIZE 64 + +static unsigned char xmlXPathSFHash;
double xmlXPathNAN = 0.0; double xmlXPathPINF = 0.0;
@@ -156,6 +193,18 @@ xmlXPathInit(void) {
xmlInitParser(); }
+ATTRIBUTE_NO_SANITIZE_INTEGER +static unsigned +xmlXPathSFComputeHash(const xmlChar *name) { + unsigned hashValue = 5381; + const xmlChar *ptr; + + for (ptr = name; *ptr; ptr++) + hashValue = hashValue * 33 + *ptr; + + return(hashValue); +} +
/** * xmlInitXPathInternal: *
@@ -164,6 +213,8 @@ xmlXPathInit(void) {
ATTRIBUTE_NO_SANITIZE("float-divide-by-zero") void xmlInitXPathInternal(void) {
+ size_t i; +
#if defined(NAN) && defined(INFINITY) xmlXPathNAN = NAN; xmlXPathPINF = INFINITY;
@@ -175,8 +226,34 @@ xmlInitXPathInternal(void) {
xmlXPathPINF = 1.0 / zero; xmlXPathNINF = -xmlXPathPINF; #endif
+ + /* + * Initialize hash table for standard functions + */ + + for (i = 0; i < SF_HASH_SIZE; i++) + xmlXPathSFHash = UCHAR_MAX; + + for (i = 0; i < NUM_STANDARD_FUNCTIONS; i++) { + const char *name = xmlXPathStandardFunctions.name; + int bucketIndex = xmlXPathSFComputeHash(BAD_CAST name) % SF_HASH_SIZE; + + while (xmlXPathSFHash != UCHAR_MAX) { + bucketIndex += 1; + if (bucketIndex >= SF_HASH_SIZE) + bucketIndex = 0; + } + + xmlXPathSFHash = i; + }
}
+/************************************************************************ + * * + * Floating point stuff * + * * + ************************************************************************/ +
/** * xmlXPathIsNaN: * @val: a double value
@@ -3979,18 +4056,6 @@ xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
*/ xmlXPathFunction xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
-
if (ctxt == NULL)
-
return (NULL);
-
-
if (ctxt->funcLookupFunc != NULL) {
-
xmlXPathFunction ret;
-
xmlXPathFuncLookupFunc f;
-
-
f = ctxt->funcLookupFunc;
-
ret = f(ctxt->funcLookupData, name, NULL);
-
if (ret != NULL)
-
return(ret);
-
} return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
}
@@ -4015,6 +4080,22 @@ xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
if (name == NULL) return(NULL);
+ if (ns_uri == NULL) { + int bucketIndex = xmlXPathSFComputeHash(name) % SF_HASH_SIZE; + + while (xmlXPathSFHash != UCHAR_MAX) { + int funcIndex = xmlXPathSFHash; + + if (strcmp(xmlXPathStandardFunctions.name, + (char *) name) == 0) + return(xmlXPathStandardFunctions.func); + + bucketIndex += 1; + if (bucketIndex >= SF_HASH_SIZE) + bucketIndex = 0; + } + } +
if (ctxt->funcLookupFunc != NULL) { xmlXPathFuncLookupFunc f;
@@ -13494,61 +13575,6 @@ xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
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-name”,
-
xmlXPathLocalNameFunction);
-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)“not”,
-
xmlXPathNotFunction);
-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)“name”,
-
xmlXPathNameFunction);
-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)“namespace-uri”,
-
xmlXPathNamespaceURIFunction);
-
xmlXPathRegisterFunc(ctxt, (const xmlChar *)“normalize-space”,
-
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);
-
xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri", (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions", xmlXPathEscapeUriFunction);
– 2.47.1