2005-08-04 22:42:30 +02:00
|
|
|
#ifndef ARABICA_XPATH_FUNCTION_HPP
|
|
|
|
#define ARABICA_XPATH_FUNCTION_HPP
|
|
|
|
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
#include <cmath>
|
|
|
|
#include <XML/XMLCharacterClasses.h>
|
|
|
|
#include <XML/UnicodeCharacters.h>
|
|
|
|
#include "xpath_value.hpp"
|
|
|
|
#include "xpath_execution_context.hpp"
|
|
|
|
|
|
|
|
namespace Arabica
|
|
|
|
{
|
|
|
|
namespace XPath
|
|
|
|
{
|
|
|
|
|
|
|
|
class XPathFunction
|
|
|
|
{
|
|
|
|
protected:
|
2005-08-16 18:04:24 +02:00
|
|
|
XPathFunction(int minArgs, int maxArgs, const std::vector<XPathExpressionPtr<std::string> >& args) :
|
2005-08-04 22:42:30 +02:00
|
|
|
args_(args)
|
|
|
|
{
|
|
|
|
if(((minArgs != -1) && (static_cast<int>(args.size()) < minArgs)) ||
|
|
|
|
((maxArgs != -1) && (static_cast<int>(args.size()) > maxArgs)))
|
|
|
|
throw SyntaxException("wrong number of arguments to function");
|
|
|
|
} // XPathFunction
|
|
|
|
|
|
|
|
public:
|
|
|
|
virtual ~XPathFunction() { }
|
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const = 0;
|
2005-08-04 22:42:30 +02:00
|
|
|
|
|
|
|
protected:
|
|
|
|
size_t argCount() const { return args_.size(); }
|
|
|
|
|
|
|
|
bool argAsBool(size_t index,
|
|
|
|
const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asBool();
|
|
|
|
} // argAsBool
|
|
|
|
|
|
|
|
double argAsNumber(size_t index,
|
|
|
|
const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asNumber();
|
|
|
|
} // argAsNumber
|
|
|
|
|
|
|
|
std::string argAsString(size_t index,
|
|
|
|
const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asString();
|
|
|
|
} // argAsString
|
|
|
|
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> argAsNodeSet(size_t index,
|
|
|
|
const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return args_[index]->evaluate(context, executionContext)->asNodeSet();
|
|
|
|
} // argAsNodeSet
|
|
|
|
|
|
|
|
private:
|
2005-08-16 18:04:24 +02:00
|
|
|
const std::vector<XPathExpressionPtr<std::string> > args_;
|
2005-08-04 22:42:30 +02:00
|
|
|
}; // class XPathFunction
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
// node-set functions
|
|
|
|
// number last()
|
|
|
|
class LastFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
LastFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new NumericValue(executionContext.last());
|
|
|
|
} // evaluate
|
|
|
|
}; // class LastFn
|
|
|
|
|
|
|
|
// number position()
|
|
|
|
class PositionFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
PositionFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new NumericValue(executionContext.position());
|
|
|
|
} // evaluate
|
|
|
|
}; // class PositionFn
|
|
|
|
|
|
|
|
// number count(node-set)
|
|
|
|
class CountFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
CountFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new NumericValue(argAsNodeSet(0, context, executionContext).size());
|
|
|
|
} // evaluate
|
|
|
|
}; // class CountFn
|
|
|
|
|
|
|
|
// node-set id(object)
|
|
|
|
// string local-name(node-set?)
|
|
|
|
class LocalNameFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
LocalNameFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
DOM::Node<std::string> node;
|
|
|
|
if(argCount() == 0)
|
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> ns = argAsNodeSet(0, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
if(ns.size() != 0)
|
|
|
|
node = ns.top();
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
if(node != 0)
|
|
|
|
switch(node.getNodeType())
|
|
|
|
{
|
|
|
|
case DOM::Node_base::ATTRIBUTE_NODE:
|
|
|
|
case DOM::Node_base::ELEMENT_NODE:
|
|
|
|
case DOM::Node_base::PROCESSING_INSTRUCTION_NODE:
|
|
|
|
return new StringValue(node.hasNamespaceURI() ? node.getLocalName() : node.getNodeName());
|
2005-08-05 22:56:15 +02:00
|
|
|
default: // put this in to keep gcc quiet
|
|
|
|
;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // switch ...
|
|
|
|
return new StringValue("");
|
|
|
|
} // evaluate
|
|
|
|
}; // class LocalNameFn
|
|
|
|
|
|
|
|
// string namespace-uri(node-set?)
|
|
|
|
class NamespaceURIFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
NamespaceURIFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
DOM::Node<std::string> node;
|
|
|
|
if(argCount() == 0)
|
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> ns = argAsNodeSet(0, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
if(ns.size() != 0)
|
|
|
|
node = ns.top();
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
if(node != 0)
|
|
|
|
switch(node.getNodeType())
|
|
|
|
{
|
|
|
|
case DOM::Node_base::ATTRIBUTE_NODE:
|
|
|
|
case DOM::Node_base::ELEMENT_NODE:
|
|
|
|
return new StringValue(node.getNamespaceURI());
|
2005-08-05 22:56:15 +02:00
|
|
|
default: // put this in to keep gcc quiet
|
|
|
|
;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // switch ...
|
|
|
|
return new StringValue("");
|
|
|
|
} // evaluate
|
|
|
|
}; // class NamespaceURIFn
|
|
|
|
|
|
|
|
// string name(node-set?)
|
|
|
|
class NameFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
NameFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
DOM::Node<std::string> node;
|
|
|
|
if(argCount() == 0)
|
|
|
|
node = context;
|
|
|
|
else
|
|
|
|
{
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> ns = argAsNodeSet(0, context, executionContext);
|
2005-08-04 22:42:30 +02:00
|
|
|
if(ns.size() != 0)
|
|
|
|
node = ns.top();
|
|
|
|
} // if ...
|
|
|
|
|
|
|
|
if(node != 0)
|
|
|
|
switch(node.getNodeType())
|
|
|
|
{
|
|
|
|
case DOM::Node_base::ATTRIBUTE_NODE:
|
|
|
|
case DOM::Node_base::ELEMENT_NODE:
|
|
|
|
case DOM::Node_base::PROCESSING_INSTRUCTION_NODE:
|
|
|
|
return new StringValue(node.getNodeName());
|
2005-08-05 22:56:15 +02:00
|
|
|
default: // stop gcc generating a warning about unhandled enum values
|
|
|
|
;
|
2005-08-04 22:42:30 +02:00
|
|
|
} // switch ...
|
|
|
|
return new StringValue("");
|
|
|
|
} // evaluate
|
|
|
|
}; // class NameFn
|
|
|
|
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
// string functions
|
|
|
|
|
|
|
|
// string string(object?)
|
|
|
|
class StringFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
StringFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new StringValue((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context));
|
|
|
|
} // evaluate
|
|
|
|
}; // class StringFn
|
|
|
|
|
|
|
|
// string concat(string, string, string*)
|
|
|
|
class ConcatFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
ConcatFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(2, -1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
for(size_t a = 0, ae = argCount(); a < ae; ++a)
|
|
|
|
s.append(argAsString(a, context, executionContext));
|
|
|
|
return new StringValue(s);
|
|
|
|
} // evaluate
|
|
|
|
}; // ConcatFn
|
|
|
|
|
|
|
|
// boolean starts-with(string, string)
|
|
|
|
class StartsWithFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
StartsWithFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
std::string start = argAsString(1, context, executionContext);
|
|
|
|
|
|
|
|
if(value.length() < start.length())
|
|
|
|
return new BoolValue(false);
|
|
|
|
|
|
|
|
for(size_t i = 0, ie = start.length(); i < ie; ++i)
|
|
|
|
if(value[i] != start[i])
|
|
|
|
return new BoolValue(false);
|
|
|
|
|
|
|
|
return new BoolValue(true);
|
|
|
|
} // evaluate
|
|
|
|
}; // StartsWithFn
|
|
|
|
|
|
|
|
// boolean contains(string, string)
|
|
|
|
class ContainsFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
ContainsFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new BoolValue(argAsString(0, context, executionContext).find(argAsString(1, context, executionContext)) != std::string::npos);
|
|
|
|
} // evaluate
|
|
|
|
}; // class ContainsFn
|
|
|
|
|
|
|
|
// string substring-before(string, string)
|
|
|
|
class SubstringBeforeFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
SubstringBeforeFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
size_t splitAt = value.find(argAsString(1, context, executionContext));
|
|
|
|
|
|
|
|
if(splitAt == std::string::npos)
|
|
|
|
return new StringValue("");
|
|
|
|
|
|
|
|
return new StringValue(value.substr(0, splitAt));
|
|
|
|
} // evaluate
|
|
|
|
}; // class SubstringBeforeFn
|
|
|
|
|
|
|
|
// string substring-after(string, string)
|
|
|
|
class SubstringAfterFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
SubstringAfterFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(2, 2, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
std::string split = argAsString(1, context, executionContext);
|
|
|
|
size_t splitAt = value.find(split);
|
|
|
|
|
|
|
|
if((splitAt == std::string::npos) || ((splitAt + split.length()) >= value.length()))
|
|
|
|
return new StringValue("");
|
|
|
|
|
|
|
|
return new StringValue(value.substr(splitAt + split.length()));
|
|
|
|
} // evaluate
|
|
|
|
}; // class SubstringAfterFn
|
|
|
|
|
|
|
|
// string substring(string, number, number?)
|
|
|
|
class SubstringFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
SubstringFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(2, 3, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = argAsString(0, context, executionContext);
|
|
|
|
double startAt = roundNumber(argAsNumber(1, context, executionContext)) - 1;
|
|
|
|
double endAt = roundNumber((argCount() == 3 ? argAsNumber(2, context, executionContext) : Infinity)) + startAt;
|
|
|
|
|
2005-08-07 22:11:43 +02:00
|
|
|
if((endAt < 0) || (endAt < startAt) || (isNaN(endAt)))
|
2005-08-04 22:42:30 +02:00
|
|
|
return new StringValue("");
|
|
|
|
|
|
|
|
if(startAt < 0)
|
|
|
|
startAt = 0;
|
|
|
|
if((isInfinite(endAt)) || (endAt > value.length()))
|
|
|
|
endAt = value.length();
|
|
|
|
|
|
|
|
return new StringValue(value.substr(static_cast<int>(startAt), static_cast<int>(endAt - startAt)));
|
|
|
|
} // evaluate
|
|
|
|
}; // SubstringFn
|
|
|
|
|
|
|
|
// number string-length(string?)
|
|
|
|
class StringLengthFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
StringLengthFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new NumericValue(((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context)).length());
|
|
|
|
} // evaluate
|
|
|
|
}; // StringLengthFn
|
|
|
|
|
|
|
|
// string normalize-space(string?)
|
|
|
|
class NormalizeSpaceFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
NormalizeSpaceFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string value = ((argCount() > 0) ? argAsString(0, context, executionContext) : nodeStringValue(context));
|
|
|
|
size_t i = 0, ie = value.length();
|
|
|
|
|
|
|
|
// string leading space
|
|
|
|
while((i != ie) && (XML::is_space(static_cast<wchar_t>(value[i]))))
|
|
|
|
++i;
|
|
|
|
|
|
|
|
size_t p = 0;
|
|
|
|
while(i != ie)
|
|
|
|
{
|
|
|
|
while((i != ie) && (!XML::is_space(static_cast<wchar_t>(value[i]))))
|
|
|
|
value[p++] = value[i++];
|
|
|
|
while((i != ie) && (XML::is_space(static_cast<wchar_t>(value[i]))))
|
|
|
|
++i;
|
|
|
|
if(i != ie)
|
|
|
|
value[p++] = Unicode<char>::SPACE;
|
|
|
|
} // while ...
|
|
|
|
if(p != ie)
|
|
|
|
value.resize(p);
|
|
|
|
|
|
|
|
return new StringValue(value);
|
|
|
|
} // evaluate
|
|
|
|
}; // class NormalizeSpaceFn
|
|
|
|
|
|
|
|
// string translate(string, string, string)
|
|
|
|
class TranslateFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
TranslateFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(3, 3, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
std::string str = argAsString(0, context, executionContext);
|
|
|
|
std::string from = argAsString(1, context, executionContext);
|
|
|
|
std::string to = argAsString(2, context, executionContext);
|
|
|
|
|
|
|
|
size_t p = 0;
|
|
|
|
for(size_t i = 0, ie = str.length(); i != ie; ++i)
|
|
|
|
{
|
|
|
|
size_t r = from.find(str[i]);
|
|
|
|
if(r == std::string::npos)
|
|
|
|
++p;
|
|
|
|
else if(r < to.length())
|
|
|
|
str[p++] = to[r];
|
|
|
|
} // for ...
|
|
|
|
if(p != str.length())
|
|
|
|
str.resize(p);
|
|
|
|
|
|
|
|
return new StringValue(str);
|
|
|
|
} // evaluate
|
|
|
|
}; // class TranslateFn
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// boolean functions
|
|
|
|
|
|
|
|
// boolean boolean(object)
|
|
|
|
class BooleanFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
BooleanFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new BoolValue(argAsBool(0, context, executionContext));
|
|
|
|
} // evaluate
|
|
|
|
}; // class BooleanFn
|
|
|
|
|
|
|
|
// boolean not(boolean)
|
|
|
|
class NotFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
NotFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new BoolValue(!argAsBool(0, context, executionContext));
|
|
|
|
}
|
|
|
|
}; // class NotFn
|
|
|
|
|
|
|
|
// boolean true()
|
|
|
|
class TrueFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
TrueFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new BoolValue(true);
|
|
|
|
} // evaluate
|
|
|
|
}; // TrueFn
|
|
|
|
|
|
|
|
// boolean false()
|
|
|
|
class FalseFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
FalseFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 0, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new BoolValue(false);
|
|
|
|
} // evaluate
|
|
|
|
}; // FalseFn
|
|
|
|
|
|
|
|
// boolean lang(string)
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
// number functions
|
|
|
|
|
|
|
|
// number number(object?)
|
|
|
|
class NumberFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
NumberFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(0, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
double result = (argCount() > 0) ? argAsNumber(0, context, executionContext) :
|
|
|
|
StringValue(nodeStringValue(context)).asNumber();
|
|
|
|
return new NumericValue(result);
|
|
|
|
} // evaluate
|
|
|
|
}; // NumberFn
|
|
|
|
|
|
|
|
// number sum(node-set)
|
|
|
|
class SumFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
SumFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
double sum = 0;
|
2005-08-16 16:17:22 +02:00
|
|
|
NodeSet<std::string> ns = argAsNodeSet(0, context, executionContext);
|
|
|
|
for(NodeSet<std::string>::const_iterator n = ns.begin(), end = ns.end(); n != end; ++n)
|
2005-08-04 22:42:30 +02:00
|
|
|
sum += nodeNumberValue(*n);
|
|
|
|
return new NumericValue(sum);
|
|
|
|
} // evaluate
|
|
|
|
}; // class SumFn
|
|
|
|
|
|
|
|
// number floor(number)
|
|
|
|
class FloorFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
FloorFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new NumericValue(std::floor(argAsNumber(0, context, executionContext)));
|
|
|
|
} // evaluate
|
|
|
|
}; // class FloorFn
|
|
|
|
|
|
|
|
// number ceiling(number)
|
|
|
|
class CeilingFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
CeilingFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new NumericValue(std::ceil(argAsNumber(0, context, executionContext)));
|
|
|
|
} // evaluate
|
|
|
|
}; // class CeilingFn
|
|
|
|
|
|
|
|
// number round(number)
|
|
|
|
class RoundFn : public XPathFunction
|
|
|
|
{
|
|
|
|
public:
|
2005-08-16 18:04:24 +02:00
|
|
|
RoundFn(const std::vector<XPathExpressionPtr<std::string> >& args) : XPathFunction(1, 1, args) { }
|
2005-08-04 22:42:30 +02:00
|
|
|
|
2005-08-16 17:29:02 +02:00
|
|
|
virtual XPathValue<std::string>* evaluate(const DOM::Node<std::string>& context,
|
|
|
|
const ExecutionContext& executionContext) const
|
2005-08-04 22:42:30 +02:00
|
|
|
{
|
|
|
|
return new NumericValue(roundNumber(argAsNumber(0, context, executionContext)));
|
|
|
|
} // evaluate
|
|
|
|
}; // class RoundFn
|
|
|
|
|
|
|
|
} // namespace XPath
|
|
|
|
} // namespace Arabica
|
|
|
|
|
|
|
|
#endif
|