mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-08 11:02:18 +03:00
* libexslt/math.c libxslt/numbers.c: use xmlXPathIsNaN() and xmlXPathIsInf() * libxslt/pattern.c: tag a potential threading problem. Daniel
294 lines
6.4 KiB
C
294 lines
6.4 KiB
C
#include <libxml/tree.h>
|
|
#include <libxml/xpath.h>
|
|
#include <libxml/xpathInternals.h>
|
|
|
|
#include <libxslt/xsltconfig.h>
|
|
#include <libxslt/xsltutils.h>
|
|
#include <libxslt/xsltInternals.h>
|
|
#include <libxslt/extensions.h>
|
|
|
|
#include "exslt.h"
|
|
|
|
/**
|
|
* exsltMathMin:
|
|
* @ns: a node-set
|
|
*
|
|
* Implements the EXSLT - Math min() function:
|
|
* number math:min (node-set)
|
|
*
|
|
* Returns the minimum value of the nodes passed as the argument, or
|
|
* xmlXPathNAN if @ns is NULL or empty or if one of the nodes
|
|
* turns into NaN.
|
|
*/
|
|
static double
|
|
exsltMathMin (xmlNodeSetPtr ns) {
|
|
double ret, cur;
|
|
int i;
|
|
|
|
if ((ns == NULL) || (ns->nodeNr == 0))
|
|
return(xmlXPathNAN);
|
|
ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
|
|
if (xmlXPathIsNaN(ret))
|
|
return(xmlXPathNAN);
|
|
for (i = 1; i < ns->nodeNr; i++) {
|
|
cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
|
|
if (xmlXPathIsNaN(cur))
|
|
return(xmlXPathNAN);
|
|
if (cur < ret)
|
|
ret = cur;
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
/**
|
|
* exsltMathMinFunction:
|
|
* @ctxt: an XPath parser context
|
|
* @nargs: the number of arguments
|
|
*
|
|
* Wraps #exsltMathMin for use by the XPath processor.
|
|
*/
|
|
static void
|
|
exsltMathMinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|
xmlNodeSetPtr ns;
|
|
double ret;
|
|
|
|
if (nargs != 1) {
|
|
xsltGenericError(xsltGenericErrorContext,
|
|
"math:min: invalid number of arguments\n");
|
|
ctxt->error = XPATH_INVALID_ARITY;
|
|
return;
|
|
}
|
|
ns = xmlXPathPopNodeSet(ctxt);
|
|
if (xmlXPathCheckError(ctxt))
|
|
return;
|
|
|
|
ret = exsltMathMin(ns);
|
|
|
|
xmlXPathFreeNodeSet(ns);
|
|
|
|
xmlXPathReturnNumber(ctxt, ret);
|
|
}
|
|
|
|
|
|
/**
|
|
* exsltMathMax:
|
|
* @ns: a node-set
|
|
*
|
|
* Implements the EXSLT - Math max() function:
|
|
* number math:max (node-set)
|
|
*
|
|
* Returns the maximum value of the nodes passed as arguments, or
|
|
* xmlXPathNAN if @ns is NULL or empty or if one of the nodes
|
|
* turns into NaN.
|
|
*/
|
|
static double
|
|
exsltMathMax (xmlNodeSetPtr ns) {
|
|
double ret, cur;
|
|
int i;
|
|
|
|
if ((ns == NULL) || (ns->nodeNr == 0))
|
|
return(xmlXPathNAN);
|
|
ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
|
|
if (xmlXPathIsNaN(ret))
|
|
return(xmlXPathNAN);
|
|
for (i = 1; i < ns->nodeNr; i++) {
|
|
cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
|
|
if (xmlXPathIsNaN(cur))
|
|
return(xmlXPathNAN);
|
|
if (cur > ret)
|
|
ret = cur;
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
/**
|
|
* exsltMathMaxFunction:
|
|
* @ctxt: an XPath parser context
|
|
* @nargs: the number of arguments
|
|
*
|
|
* Wraps #exsltMathMax for use by the XPath processor.
|
|
*/
|
|
static void
|
|
exsltMathMaxFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|
xmlNodeSetPtr ns;
|
|
double ret;
|
|
|
|
if (nargs != 1) {
|
|
xmlXPathSetArityError(ctxt);
|
|
return;
|
|
}
|
|
ns = xmlXPathPopNodeSet(ctxt);
|
|
if (xmlXPathCheckError(ctxt))
|
|
return;
|
|
|
|
ret = exsltMathMax(ns);
|
|
|
|
xmlXPathFreeNodeSet(ns);
|
|
|
|
xmlXPathReturnNumber(ctxt, ret);
|
|
}
|
|
|
|
/**
|
|
* exsltMathHighest:
|
|
* @ns: a node-set
|
|
*
|
|
* Implements the EXSLT - Math highest() function:
|
|
* node-set math:highest (node-set)
|
|
*
|
|
* Returns the nodes in the node-set whose value is the maximum value
|
|
* for the node-set.
|
|
*/
|
|
static xmlNodeSetPtr
|
|
exsltMathHighest (xmlNodeSetPtr ns) {
|
|
xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
|
|
double max, cur;
|
|
int i;
|
|
|
|
if ((ns == NULL) || (ns->nodeNr == 0))
|
|
return(ret);
|
|
|
|
max = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
|
|
if (xmlXPathIsNaN(max))
|
|
return(ret);
|
|
else
|
|
xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);
|
|
|
|
for (i = 1; i < ns->nodeNr; i++) {
|
|
cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
|
|
if (xmlXPathIsNaN(cur)) {
|
|
xmlXPathEmptyNodeSet(ret);
|
|
return(ret);
|
|
}
|
|
if (cur < max)
|
|
continue;
|
|
if (cur > max) {
|
|
max = cur;
|
|
xmlXPathEmptyNodeSet(ret);
|
|
xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
|
|
continue;
|
|
}
|
|
xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
/**
|
|
* exsltMathHighestFunction:
|
|
* @ctxt: an XPath parser context
|
|
* @nargs: the number of arguments
|
|
*
|
|
* Wraps #exsltMathHighest for use by the XPath processor
|
|
*/
|
|
static void
|
|
exsltMathHighestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|
xmlNodeSetPtr ns, ret;
|
|
|
|
if (nargs != 1) {
|
|
xmlXPathSetArityError(ctxt);
|
|
return;
|
|
}
|
|
|
|
ns = xmlXPathPopNodeSet(ctxt);
|
|
if (xmlXPathCheckError(ctxt))
|
|
return;
|
|
|
|
ret = exsltMathHighest(ns);
|
|
|
|
xmlXPathFreeNodeSet(ns);
|
|
|
|
xmlXPathReturnNodeSet(ctxt, ret);
|
|
}
|
|
|
|
/**
|
|
* exsltMathLowest:
|
|
* @ns: a node-set
|
|
*
|
|
* Implements the EXSLT - Math lowest() function
|
|
* node-set math:lowest (node-set)
|
|
*
|
|
* Returns the nodes in the node-set whose value is the minimum value
|
|
* for the node-set.
|
|
*/
|
|
static xmlNodeSetPtr
|
|
exsltMathLowest (xmlNodeSetPtr ns) {
|
|
xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
|
|
double min, cur;
|
|
int i;
|
|
|
|
if ((ns == NULL) || (ns->nodeNr == 0))
|
|
return(ret);
|
|
|
|
min = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
|
|
if (xmlXPathIsNaN(min))
|
|
return(ret);
|
|
else
|
|
xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);
|
|
|
|
for (i = 1; i < ns->nodeNr; i++) {
|
|
cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
|
|
if (xmlXPathIsNaN(cur)) {
|
|
xmlXPathEmptyNodeSet(ret);
|
|
return(ret);
|
|
}
|
|
if (cur > min)
|
|
continue;
|
|
if (cur < min) {
|
|
min = cur;
|
|
xmlXPathEmptyNodeSet(ret);
|
|
xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
|
|
continue;
|
|
}
|
|
xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
/**
|
|
* exsltMathLowestFunction:
|
|
* @ctxt: an XPath parser context
|
|
* @nargs: the number of arguments
|
|
*
|
|
* Wraps #exsltMathLowest for use by the XPath processor
|
|
*/
|
|
static void
|
|
exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
|
|
xmlNodeSetPtr ns, ret;
|
|
|
|
if (nargs != 1) {
|
|
xmlXPathSetArityError(ctxt);
|
|
return;
|
|
}
|
|
|
|
ns = xmlXPathPopNodeSet(ctxt);
|
|
if (xmlXPathCheckError(ctxt))
|
|
return;
|
|
|
|
ret = exsltMathLowest(ns);
|
|
|
|
xmlXPathFreeNodeSet(ns);
|
|
|
|
xmlXPathReturnNodeSet(ctxt, ret);
|
|
}
|
|
|
|
/**
|
|
* exsltMathRegister:
|
|
*
|
|
* Registers the EXSLT - Math module
|
|
*/
|
|
|
|
void
|
|
exsltMathRegister (void) {
|
|
xsltRegisterExtModuleFunction ((const xmlChar *) "min",
|
|
EXSLT_MATH_NAMESPACE,
|
|
exsltMathMinFunction);
|
|
xsltRegisterExtModuleFunction ((const xmlChar *) "max",
|
|
EXSLT_MATH_NAMESPACE,
|
|
exsltMathMaxFunction);
|
|
xsltRegisterExtModuleFunction ((const xmlChar *) "highest",
|
|
EXSLT_MATH_NAMESPACE,
|
|
exsltMathHighestFunction);
|
|
xsltRegisterExtModuleFunction ((const xmlChar *) "lowest",
|
|
EXSLT_MATH_NAMESPACE,
|
|
exsltMathLowestFunction);
|
|
}
|