diff --git a/doc/APIchunk2.html b/doc/APIchunk2.html index d5d363b12b5c073096e4c1361d185ac97fe967d9..94a32dbaef8357d011c28c84f494c5d46be8b1f4 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 35780565720cb11e4d390c1a2baaf635a3112c34..2e6eeab94677bf30f1eb74a14c4a1055ab3acc6b 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 14995a23264023fec5b8fe141716ce38f9e79b55..690d3c7bfb6cadf5288203e89c22ad6499fb4f56 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 1af527abe11d034019888422355156050cc2cf83..537fbc51bd94bb6f3a8c31985cc6765ae00c3102 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 45220b1146943476bf99a127b458993a882b0a82..0c47dec0190616983a058d91d333fbd2ccdd9604 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 51b6f26272e9e3baf41c18ed034174be98b72549..15001cdb135f6d9271b57b69e38ee327d1e2aca9 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 8b894af7e7dfbca1946e7f034033b09db3c2deee..a4ac6aec45dfc7b4dc3abd4d20561cebe87b8811 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 f264a298619b3412944805ca4de7b8b473057443..4829c87f9b280c8b2cc821f052c0547d6e317a9b 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 ade2ab7c054a8191cf4255bed951e2cc8f0fe60b..72b0e075053962f05be79948515ddda60793047c 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 a52202a2ffcd4d6578330f4ffe5e33bf4b85ed16..7e572ef34bb2723d3209c2ae9c0fe588ac33d951 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 af8ad1148d25dd4bfe86e868d351fcada3d63333..1c33883fe3969de0c8cbca81850eeebf487723ff 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 76a6b481572d72a06c778ef949b0bf0df30382af..d7cfb9433258def8846699760a60c6572cdd88b9 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 33bc112c14f026b6a71c8dc36fd9199b55796245..e195bfb862252204a1dc7090e37abf5bc810b14c 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 a6d12e150d1102e266badb4410a027c61eb2ae4d..e9455898af84adb246eea2fb71fc495a3ea354f0 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 4b0125cf7bc4575669c0bc6cc71b7daa10e6eea6..1cac6a57e14c4193c5797bc226171b694a9f30b4 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 c741ee2519cc075a7dbddae3e0bc93d6463bf16c..308dfdabe2c8d4a9cc35bf1ccc4e2d3389282d84 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 8a4e23e332523bc5d35eedb78cc414877847f52f..be09cd3eaed143dc0fb1b1ba4f0e2b17df521918 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 1e771e850415d959a9d47e3396472f5e45ddd771..2947025cf99ba23bb6f7f2c061ed28c629167e5b 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 6ee7e57ef90895968c79dbeaf597b3170dc07a6d..2885e5918a87e6090bd8821848132130ac93c287 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 21c1f41914dce28e7343ca67a9912d52045cc312..2f9eac4670c3ca44a04dc83a39c3ca98cc3125c9 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