From 1fdfdb823980ffa01280c3961b780895e29cd139 Mon Sep 17 00:00:00 2001 From: Philippe Marguinaud Date: Mon, 8 Mar 2021 08:22:11 +0100 Subject: [PATCH] Add ends-with function --- doc/APIchunk2.html | 2 ++ doc/APIfiles.html | 1 + doc/APIfunctions.html | 1 + doc/APIsymbols.html | 1 + doc/devhelp/libxml2-xpathInternals.html | 9 ++++++ doc/devhelp/libxml2.devhelp | 1 + doc/html/libxml-xpathInternals.html | 5 ++-- doc/libxml2-api.xml | 8 +++++ doc/libxml2-refs.xml | 8 +++++ doc/symbols.xml | 1 + elfgcchack.h | 12 ++++++++ include/libxml/xpathInternals.h | 1 + libxml2.syms | 1 + os400/libxmlrpg/xpathInternals.rpgle | 5 ++++ result/XPath/expr/strings | 8 +++++ test/XPath/expr/strings | 2 ++ testapi.c | 40 +++++++++++++++++++++++++ win32/libxml2.def.src | 3 ++ xpath.c | 38 +++++++++++++++++++++++ xstc/xstc.py | 14 +++++++++ 20 files changed, 159 insertions(+), 2 deletions(-) diff --git a/doc/APIchunk2.html b/doc/APIchunk2.html index d5d363b1..94a32dba 100644 --- a/doc/APIchunk2.html +++ b/doc/APIchunk2.html @@ -267,6 +267,8 @@ A:link, A:visited, A:active { text-decoration: underline } xmlParseTextDecl
EncodingDecl?
xmlParseXMLDecl
End
_xmlDoc
+
ends
xmlXPathStartsWithFunction
+
ends-with
xmlXPathStartsWithFunction
_xmlDtd
_xmlNode
xmlTextReaderGetRemainder
diff --git a/doc/APIfiles.html b/doc/APIfiles.html index 35780565..2e6eeab9 100644 --- a/doc/APIfiles.html +++ b/doc/APIfiles.html @@ -3547,6 +3547,7 @@ A:link, A:visited, A:active { text-decoration: underline } xmlXPathStackIsExternal
xmlXPathStackIsNodeSet
xmlXPathStartsWithFunction
+xmlXPathEndsWithFunction
xmlXPathStringEvalNumber
xmlXPathStringFunction
xmlXPathStringLengthFunction
diff --git a/doc/APIfunctions.html b/doc/APIfunctions.html index 14995a23..690d3c7b 100644 --- a/doc/APIfunctions.html +++ b/doc/APIfunctions.html @@ -2331,6 +2331,7 @@ A:link, A:visited, A:active { text-decoration: underline } xmlXPathRoot
xmlXPathRoundFunction
xmlXPathStartsWithFunction
+xmlXPathEndsWithFunction
xmlXPathStringFunction
xmlXPathStringLengthFunction
xmlXPathSubValues
diff --git a/doc/APIsymbols.html b/doc/APIsymbols.html index 1af527ab..537fbc51 100644 --- a/doc/APIsymbols.html +++ b/doc/APIsymbols.html @@ -3541,6 +3541,7 @@ A:link, A:visited, A:active { text-decoration: underline } xmlXPathStackIsExternal
xmlXPathStackIsNodeSet
xmlXPathStartsWithFunction
+xmlXPathEndsWithFunction
xmlXPathStringEvalNumber
xmlXPathStringFunction
xmlXPathStringLengthFunction
diff --git a/doc/devhelp/libxml2-xpathInternals.html b/doc/devhelp/libxml2-xpathInternals.html index 45220b11..0c47dec0 100644 --- a/doc/devhelp/libxml2-xpathInternals.html +++ b/doc/devhelp/libxml2-xpathInternals.html @@ -104,6 +104,7 @@ void xmlXPathCeilingFunction (xmlXPathContainsFunction (xmlXPathParserContextPtr ctxt,
int nargs); void xmlXPathNodeSetSort (xmlNodeSetPtr set); void xmlXPathStartsWithFunction (xmlXPathParserContextPtr ctxt,
int nargs); +void xmlXPathEndsWithFunction (xmlXPathParserContextPtr ctxt,
int nargs); xmlNodeSetPtr xmlXPathNodeLeading (xmlNodeSetPtr nodes,
xmlNodePtr node); void xmlXPathSumFunction (xmlXPathParserContextPtr ctxt,
int nargs); int xmlXPathNotEqualValues (xmlXPathParserContextPtr ctxt); @@ -699,6 +700,14 @@ void xmlXPathDebugDumpObject (FILE * out

xmlXPathStartsWithFunction ()

void	xmlXPathStartsWithFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)

Implement the starts-with() XPath function boolean starts-with(string, string) The starts-with function returns true if the first argument string starts with the second argument string, and otherwise returns false.

+
ctxt:the XPath Parser context
nargs:the number of arguments
+
+

xmlXPathEndsWithFunction ()

void	xmlXPathEndsWithFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)
+

Implement the ends-with() XPath function boolean starts-with(string, string) The ends-with function returns true if the first argument string ends with the second argument string, and otherwise returns false.

+
ctxt:the XPath Parser context
nargs:the number of arguments
+
+

xmlXPathEndsWithFunction ()

void	xmlXPathEndsWithFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)
+

Implement the ends-with() XPath function boolean ends-with(string, string) The ends-with function returns true if the first argument string ends with the second argument string, and otherwise returns false.

ctxt:the XPath Parser context
nargs:the number of arguments

xmlXPathStringEvalNumber ()

double	xmlXPathStringEvalNumber	(const xmlChar * str)
diff --git a/doc/devhelp/libxml2.devhelp b/doc/devhelp/libxml2.devhelp index 51b6f262..15001cdb 100644 --- a/doc/devhelp/libxml2.devhelp +++ b/doc/devhelp/libxml2.devhelp @@ -3532,6 +3532,7 @@ + diff --git a/doc/html/libxml-xpathInternals.html b/doc/html/libxml-xpathInternals.html index 8b894af7..a4ac6aec 100644 --- a/doc/html/libxml-xpathInternals.html +++ b/doc/html/libxml-xpathInternals.html @@ -107,6 +107,7 @@ A:link, A:visited, A:active { text-decoration: underline }
void	xmlXPathRoot			(xmlXPathParserContextPtr ctxt)
void	xmlXPathRoundFunction		(xmlXPathParserContextPtr ctxt, 
int nargs)
void	xmlXPathStartsWithFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)
+
void	xmlXPathEndsWithFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)
double	xmlXPathStringEvalNumber	(const xmlChar * str)
void	xmlXPathStringFunction		(xmlXPathParserContextPtr ctxt, 
int nargs)
void	xmlXPathStringLengthFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)
@@ -349,8 +350,8 @@ A:link, A:visited, A:active { text-decoration: underline }

Initialize the context to the root of the document

ctxt:the XPath Parser context

Function: xmlXPathRoundFunction

void	xmlXPathRoundFunction		(xmlXPathParserContextPtr ctxt, 
int nargs)

Implement the round() XPath function number round(number) The round function returns the number that is closest to the argument and that is an integer. If there are two such numbers, then the one that is closest to positive infinity is returned.

-
ctxt:the XPath Parser context
nargs:the number of arguments

Function: xmlXPathStartsWithFunction

void	xmlXPathStartsWithFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)
-

Implement the starts-with() XPath function boolean starts-with(string, string) The starts-with function returns true if the first argument string starts with the second argument string, and otherwise returns false.

+
ctxt:the XPath Parser context
nargs:the number of arguments

Function: xmlXPathEndsWithFunction

void	xmlXPathEndsWithFunction	(xmlXPathParserContextPtr ctxt, 
int nargs)
+

Implement the ends-with() XPath function boolean ends-with(string, string) The ends-with function returns true if the first argument string ends with the second argument string, and otherwise returns false.

ctxt:the XPath Parser context
nargs:the number of arguments

Function: xmlXPathStringEvalNumber

double	xmlXPathStringEvalNumber	(const xmlChar * str)

[30a] Float ::= Number ('e' Digits?)? [30] Number ::= Digits ('.' Digits?)? | '.' Digits [31] Digits ::= [0-9]+ Compile a Number in the string In complement of the Number expression, this function also handles negative values : '-' Number.

str:A string to scan
Returns:the double value.

Function: xmlXPathStringFunction

void	xmlXPathStringFunction		(xmlXPathParserContextPtr ctxt, 
int nargs)
diff --git a/doc/libxml2-api.xml b/doc/libxml2-api.xml index f264a298..4829c87f 100644 --- a/doc/libxml2-api.xml +++ b/doc/libxml2-api.xml @@ -3707,6 +3707,7 @@ + @@ -18238,6 +18239,13 @@ Could we use @subtypes for this?'/> + + defined(LIBXML_XPATH_ENABLED) + Implement the ends-with() XPath function boolean ends-with(string, string) The ends-with function returns true if the first argument string ends with the second argument string, and otherwise returns false. + + + + defined(LIBXML_XPATH_ENABLED) [30a] Float ::= Number ('e' Digits?)? [30] Number ::= Digits ('.' Digits?)? | '.' Digits [31] Digits ::= [0-9]+ Compile a Number in the string In complement of the Number expression, this function also handles negative values : '-' Number. diff --git a/doc/libxml2-refs.xml b/doc/libxml2-refs.xml index ade2ab7c..72b0e075 100644 --- a/doc/libxml2-refs.xml +++ b/doc/libxml2-refs.xml @@ -3535,6 +3535,7 @@ + @@ -7176,6 +7177,7 @@ + @@ -10739,6 +10741,7 @@ + @@ -14389,6 +14392,7 @@ + @@ -22356,6 +22360,10 @@ + + + + diff --git a/doc/symbols.xml b/doc/symbols.xml index a52202a2..7e572ef3 100644 --- a/doc/symbols.xml +++ b/doc/symbols.xml @@ -328,6 +328,7 @@ xmlXPathRoot xmlXPathRoundFunction xmlXPathStartsWithFunction + xmlXPathEndsWithFunction xmlXPathStringEvalNumber xmlXPathStringFunction xmlXPathStringLengthFunction diff --git a/elfgcchack.h b/elfgcchack.h index af8ad114..1c33883f 100644 --- a/elfgcchack.h +++ b/elfgcchack.h @@ -17317,6 +17317,18 @@ extern __typeof (xmlXPathStartsWithFunction) xmlXPathStartsWithFunction__interna #endif #endif +#if defined(LIBXML_XPATH_ENABLED) +#ifdef bottom_xpath +#undef xmlXPathEndsWithFunction +extern __typeof (xmlXPathEndsWithFunction) xmlXPathEndsWithFunction __attribute((alias("xmlXPathEndsWithFunction__internal_alias"))); +#else +#ifndef xmlXPathEndsWithFunction +extern __typeof (xmlXPathEndsWithFunction) xmlXPathEndsWithFunction__internal_alias __attribute((visibility("hidden"))); +#define xmlXPathEndsWithFunction xmlXPathEndsWithFunction__internal_alias +#endif +#endif +#endif + #if defined(LIBXML_XPATH_ENABLED) #ifdef bottom_xpath #undef xmlXPathStringEvalNumber diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h index 76a6b481..d7cfb943 100644 --- a/include/libxml/xpathInternals.h +++ b/include/libxml/xpathInternals.h @@ -603,6 +603,7 @@ XMLPUBFUN void XMLCALL xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctx XMLPUBFUN void XMLCALL xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs); +XMLPUBFUN void XMLCALL xmlXPathEndsWithFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs); diff --git a/libxml2.syms b/libxml2.syms index 33bc112c..e195bfb8 100644 --- a/libxml2.syms +++ b/libxml2.syms @@ -372,6 +372,7 @@ LIBXML2_2.4.30 { xmlXPathRoot; xmlXPathRoundFunction; xmlXPathStartsWithFunction; + xmlXPathEndsWithFunction; xmlXPathStringEvalNumber; xmlXPathStringFunction; xmlXPathStringLengthFunction; diff --git a/os400/libxmlrpg/xpathInternals.rpgle b/os400/libxmlrpg/xpathInternals.rpgle index a6d12e15..e9455898 100644 --- a/os400/libxmlrpg/xpathInternals.rpgle +++ b/os400/libxmlrpg/xpathInternals.rpgle @@ -605,6 +605,11 @@ d ctxt value like(xmlXPathParserContextPtr) d nargs value like(xmlCint) + d xmlXPathEndsWithFunction... + d pr extproc('xmlXPathEndsWithFunction') + d ctxt value like(xmlXPathParserContextPtr) + d nargs value like(xmlCint) + d xmlXPathSubstringFunction... d pr extproc('xmlXPathSubstringFunction') d ctxt value like(xmlXPathParserContextPtr) diff --git a/result/XPath/expr/strings b/result/XPath/expr/strings index 4b0125cf..1cac6a57 100644 --- a/result/XPath/expr/strings +++ b/result/XPath/expr/strings @@ -51,6 +51,14 @@ Object is a Boolean : true Expression: starts-with("tititoto","to") Object is a Boolean : false +======================== +Expression: ends-with("tititoto","toto") +Object is a Boolean : true + +======================== +Expression: ends-with("tititoto","ti") +Object is a Boolean : false + ======================== Expression: contains("tititototata","titi") Object is a Boolean : true diff --git a/test/XPath/expr/strings b/test/XPath/expr/strings index c741ee25..308dfdab 100644 --- a/test/XPath/expr/strings +++ b/test/XPath/expr/strings @@ -11,6 +11,8 @@ concat("titi",'toto') concat("titi",'toto',"tata","last") starts-with("tititoto","titi") starts-with("tititoto","to") +ends-with("tititoto","toto") +ends-with("tititoto","ti") contains("tititototata","titi") contains("tititototata","toto") contains("tititototata","tata") diff --git a/testapi.c b/testapi.c index 8a4e23e3..be09cd3e 100644 --- a/testapi.c +++ b/testapi.c @@ -50709,6 +50709,45 @@ test_xmlXPathStartsWithFunction(void) { } +static int +test_xmlXPathEndsWithFunction(void) { + int test_ret = 0; + +#if defined(LIBXML_XPATH_ENABLED) + int mem_base; + xmlXPathParserContextPtr ctxt; /* the XPath Parser context */ + int n_ctxt; + int nargs; /* the number of arguments */ + int n_nargs; + + for (n_ctxt = 0;n_ctxt < gen_nb_xmlXPathParserContextPtr;n_ctxt++) { + for (n_nargs = 0;n_nargs < gen_nb_int;n_nargs++) { + mem_base = xmlMemBlocks(); + ctxt = gen_xmlXPathParserContextPtr(n_ctxt, 0); + nargs = gen_int(n_nargs, 1); + + xmlXPathEndsWithFunction(ctxt, nargs); + call_tests++; + des_xmlXPathParserContextPtr(n_ctxt, ctxt, 0); + des_int(n_nargs, nargs, 1); + xmlResetLastError(); + if (mem_base != xmlMemBlocks()) { + printf("Leak of %d blocks found in xmlXPathEndsWithFunction", + xmlMemBlocks() - mem_base); + test_ret++; + printf(" %d", n_ctxt); + printf(" %d", n_nargs); + printf("\n"); + } + } + } + function_tests++; +#endif + + return(test_ret); +} + + static int test_xmlXPathStringEvalNumber(void) { int test_ret = 0; @@ -51543,6 +51582,7 @@ test_xpathInternals(void) { test_ret += test_xmlXPathRoot(); test_ret += test_xmlXPathRoundFunction(); test_ret += test_xmlXPathStartsWithFunction(); + test_ret += test_xmlXPathEndsWithFunction(); test_ret += test_xmlXPathStringEvalNumber(); test_ret += test_xmlXPathStringFunction(); test_ret += test_xmlXPathStringLengthFunction(); diff --git a/win32/libxml2.def.src b/win32/libxml2.def.src index 1e771e85..2947025c 100644 --- a/win32/libxml2.def.src +++ b/win32/libxml2.def.src @@ -3067,6 +3067,9 @@ xmlXPathSetContextNode xmlXPathStartsWithFunction #endif #ifdef LIBXML_XPATH_ENABLED +xmlXPathEndsWithFunction +#endif +#ifdef LIBXML_XPATH_ENABLED xmlXPathStringEvalNumber #endif #ifdef LIBXML_XPATH_ENABLED diff --git a/xpath.c b/xpath.c index 6ee7e57e..2885e591 100644 --- a/xpath.c +++ b/xpath.c @@ -9065,6 +9065,42 @@ xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathReleaseObject(ctxt->context, needle); } +/** + * xmlXPathEndsWithFunction: + * @ctxt: the XPath Parser context + * @nargs: the number of arguments + * + * Implement the ends-with() XPath function + * boolean ends-with(string, string) + * The ends-with function returns true if the first argument string + * ends with the second argument string, and otherwise returns false. + */ +void +xmlXPathEndsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr hay, needle; + int n; + + CHECK_ARITY(2); + CAST_TO_STRING; + CHECK_TYPE(XPATH_STRING); + needle = valuePop(ctxt); + CAST_TO_STRING; + hay = valuePop(ctxt); + + if ((hay == NULL) || (hay->type != XPATH_STRING)) { + xmlXPathReleaseObject(ctxt->context, hay); + xmlXPathReleaseObject(ctxt->context, needle); + XP_ERROR(XPATH_INVALID_TYPE); + } + n = xmlStrlen(needle->stringval); + if (xmlStrncmp(hay->stringval, needle->stringval, n)) + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 0)); + else + valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt->context, 1)); + xmlXPathReleaseObject(ctxt->context, hay); + xmlXPathReleaseObject(ctxt->context, needle); +} + /** * xmlXPathSubstringFunction: * @ctxt: the XPath Parser context @@ -14716,6 +14752,8 @@ xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt) xmlXPathStringLengthFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with", xmlXPathStartsWithFunction); + xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ends-with", + xmlXPathEndsWithFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring", xmlXPathSubstringFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before", diff --git a/xstc/xstc.py b/xstc/xstc.py index 21c1f419..2f9eac46 100755 --- a/xstc/xstc.py +++ b/xstc/xstc.py @@ -47,6 +47,10 @@ opa.add_option("--tsw", "--test-starts-with", type="string", dest="testStartsWit default=None, help="Runs the specified test(s), starting with the given string") +opa.add_option("--tsw", "--test-ends-with", type="string", dest="testEndsWith", + default=None, + help="Runs the specified test(s), starting with the given string") + opa.add_option("--rieo", "--report-internal-errors-only", action="store_true", dest="reportInternalErrOnly", default=False, help="Display erroneous tests of type 'internal' only") @@ -67,6 +71,10 @@ opa.add_option("--csw", "--csw", type="string", dest="combineStartsWith", default=None, help="Combines to be run (all if omitted)") +opa.add_option("--csw", "--csw", type="string", dest="combineEndsWith", + default=None, + help="Combines to be run (all if omitted)") + opa.add_option("--rc", "--report-combines", action="store_true", dest="reportCombines", default=False, help="Display combine reports") @@ -647,9 +655,15 @@ class XSTCTestRunner: elif options.testStartsWith is not None: if not test.name.startswith(options.testStartsWith): continue + elif options.testEndsWith is not None: + if not test.name.startswith(options.testEndsWith): + continue elif options.combineStartsWith is not None: if not test.combineName.startswith(options.combineStartsWith): continue + elif options.combineEndsWith is not None: + if not test.combineName.startswith(options.combineEndsWith): + continue if options.maxTestCount != -1 and self.counters[self.CNT_RAN] >= options.maxTestCount: break -- GitLab