arabica/include/XPath/impl/xpath_function.hpp

675 lines
28 KiB
C++
Raw Normal View History

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>
2007-09-05 00:55:47 +02:00
#include <XML/XMLCharacterClasses.hpp>
#include <text/UnicodeCharacters.hpp>
#include <text/normalize_whitespace.hpp>
2005-08-04 22:42:30 +02:00
#include "xpath_value.hpp"
#include "xpath_execution_context.hpp"
namespace Arabica
{
namespace XPath
{
template<class string_type, class string_adaptor = Arabica::default_string_adaptor<string_type> >
2005-08-04 22:42:30 +02:00
class XPathFunction
{
protected:
2007-10-25 22:42:00 +02:00
XPathFunction(int minArgs, int maxArgs, const std::vector<XPathExpression<string_type, string_adaptor> >& 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() { }
virtual ValueType type() const = 0;
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:00:35 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
2005-08-04 22:42:30 +02:00
protected:
size_t argCount() const { return args_.size(); }
XPathValue<string_type, string_adaptor> arg(size_t index,
const DOM::Node<string_type, string_adaptor>& context,
2007-07-19 19:01:31 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
{
2007-10-25 22:42:00 +02:00
return args_[index].evaluate(context, executionContext);
} // arg
2007-07-19 19:01:31 +02:00
2005-08-04 22:42:30 +02:00
bool argAsBool(size_t index,
const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:00:35 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return args_[index].evaluateAsBool(context, executionContext);
2005-08-04 22:42:30 +02:00
} // argAsBool
double argAsNumber(size_t index,
const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:00:35 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return args_[index].evaluateAsNumber(context, executionContext);
2005-08-04 22:42:30 +02:00
} // argAsNumber
2005-08-18 11:00:35 +02:00
string_type argAsString(size_t index,
const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:00:35 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return args_[index].evaluateAsString(context, executionContext);
2005-08-04 22:42:30 +02:00
} // argAsString
NodeSet<string_type, string_adaptor> argAsNodeSet(size_t index,
const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:00:35 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return args_[index].evaluateAsNodeSet(context, executionContext);
2005-08-04 22:42:30 +02:00
} // argAsNodeSet
private:
2007-10-25 22:42:00 +02:00
const std::vector<XPathExpression<string_type, string_adaptor> > args_;
2005-08-04 22:42:30 +02:00
}; // class XPathFunction
namespace impl
{
2005-08-18 11:33:19 +02:00
template<class string_type, class string_adaptor>
class BooleanFunction : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
BooleanFunction(int minArgs, int maxArgs, const std::vector<XPathExpression<string_type, string_adaptor> >& args) :
XPathFunction(minArgs, maxArgs, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return BOOL; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:33:19 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return new BoolValue<string_type, string_adaptor>(doEvaluate(context, executionContext));
2005-08-04 22:42:30 +02:00
} // evaluate
protected:
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
}; // class BooleanFunction
2005-08-18 11:33:19 +02:00
template<class string_type, class string_adaptor>
class NumericFunction : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
NumericFunction(int minArgs, int maxArgs, const std::vector<XPathExpression<string_type, string_adaptor> >& args) :
XPathFunction(minArgs, maxArgs, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return NUMBER; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:33:19 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return new NumericValue<string_type, string_adaptor>(doEvaluate(context, executionContext));
} // evaluate
protected:
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const = 0;
}; // class NumericFunction
////////////////////////////////
// node-set functions
// number last()
template<class string_type, class string_adaptor>
class LastFn : public NumericFunction<string_type, string_adaptor>
{
public:
LastFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 0, args) { }
protected:
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
{
return executionContext.last();
} // evaluate
}; // class LastFn
// number position()
template<class string_type, class string_adaptor>
class PositionFn : public NumericFunction<string_type, string_adaptor>
{
public:
PositionFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 0, args) { }
protected:
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
{
return executionContext.position();
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class PositionFn
// number count(node-set)
2005-08-18 11:33:19 +02:00
template<class string_type, class string_adaptor>
class CountFn : public NumericFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef NumericFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
CountFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return baseT::argAsNodeSet(0, context, executionContext).size();
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class CountFn
// node-set id(object)
// string local-name(node-set?)
2005-08-18 11:33:19 +02:00
template<class string_type, class string_adaptor>
class LocalNameFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 11:33:19 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
LocalNameFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:33:19 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
DOM::Node<string_type, string_adaptor> node;
2005-08-18 11:33:19 +02:00
if(baseT::argCount() == 0)
2005-08-04 22:42:30 +02:00
node = context;
else
{
NodeSet<string_type, string_adaptor> ns = baseT::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:
2007-11-10 23:23:36 +01:00
case NAMESPACE_NODE_TYPE:
2005-08-18 11:33:19 +02:00
return new StringValue<string_type, string_adaptor>(node.hasNamespaceURI() ? node.getLocalName() : node.getNodeName());
default: // put this in to keep gcc quiet
;
2005-08-04 22:42:30 +02:00
} // switch ...
2005-08-18 11:33:19 +02:00
return new StringValue<string_type, string_adaptor>("");
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class LocalNameFn
// string namespace-uri(node-set?)
2005-08-18 11:33:19 +02:00
template<class string_type, class string_adaptor>
class NamespaceURIFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 11:33:19 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
NamespaceURIFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:33:19 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
DOM::Node<string_type, string_adaptor> node;
2005-08-18 11:33:19 +02:00
if(baseT::argCount() == 0)
2005-08-04 22:42:30 +02:00
node = context;
else
{
NodeSet<string_type, string_adaptor> ns = baseT::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:
2005-08-18 11:33:19 +02:00
return new StringValue<string_type, string_adaptor>(node.getNamespaceURI());
default: // put this in to keep gcc quiet
;
2005-08-04 22:42:30 +02:00
} // switch ...
2005-08-18 11:33:19 +02:00
return new StringValue<string_type, string_adaptor>("");
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class NamespaceURIFn
// string name(node-set?)
2005-08-18 11:33:19 +02:00
template<class string_type, class string_adaptor>
class NameFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 11:33:19 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
NameFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:33:19 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
DOM::Node<string_type, string_adaptor> node;
2005-08-18 11:33:19 +02:00
if(baseT::argCount() == 0)
2005-08-04 22:42:30 +02:00
node = context;
else
{
NodeSet<string_type, string_adaptor> ns = baseT::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:
2007-07-19 19:01:31 +02:00
case NAMESPACE_NODE_TYPE:
2005-08-18 11:33:19 +02:00
return new StringValue<string_type, string_adaptor>(node.getNodeName());
default: // stop gcc generating a warning about unhandled enum values
;
2005-08-04 22:42:30 +02:00
} // switch ...
2005-08-18 11:33:19 +02:00
return new StringValue<string_type, string_adaptor>("");
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class NameFn
///////////////////////////////////////////////
// string functions
// string string(object?)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class StringFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
StringFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-23 21:19:17 +02:00
return new StringValue<string_type, string_adaptor>((baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue<string_type, string_adaptor>(context));
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class StringFn
// string concat(string, string, string*)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class ConcatFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
ConcatFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, -1, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
string_type s;
for(size_t a = 0, ae = baseT::argCount(); a < ae; ++a)
2005-09-30 23:36:11 +02:00
string_adaptor::append(s, baseT::argAsString(a, context, executionContext));
2005-08-18 13:32:29 +02:00
return new StringValue<string_type, string_adaptor>(s);
2005-08-04 22:42:30 +02:00
} // evaluate
}; // ConcatFn
// boolean starts-with(string, string)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class StartsWithFn : public BooleanFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef BooleanFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
StartsWithFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(2, 2, args) { }
protected:
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
string_type value = baseT::argAsString(0, context, executionContext);
string_type start = baseT::argAsString(1, context, executionContext);
2005-08-04 22:42:30 +02:00
2005-09-30 23:36:11 +02:00
if(string_adaptor::length(value) < string_adaptor::length(start))
return false;
2005-08-04 22:42:30 +02:00
typename string_adaptor::const_iterator i = string_adaptor::begin(value);
typename string_adaptor::const_iterator s = string_adaptor::begin(start);
typename string_adaptor::const_iterator e = string_adaptor::end(start);
2005-09-30 23:36:11 +02:00
for(; s != e; ++s, ++i)
if(*i != *s)
return false;
2005-08-04 22:42:30 +02:00
return true;
2005-08-04 22:42:30 +02:00
} // evaluate
}; // StartsWithFn
// boolean contains(string, string)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class ContainsFn : public BooleanFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef BooleanFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
ContainsFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(2, 2, args) { }
protected:
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return string_adaptor::find(baseT::argAsString(0, context, executionContext),
baseT::argAsString(1, context, executionContext)) != string_adaptor::npos();
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class ContainsFn
// string substring-before(string, string)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class SubstringBeforeFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
SubstringBeforeFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
string_type value = baseT::argAsString(0, context, executionContext);
2005-09-30 23:36:11 +02:00
size_t splitAt = string_adaptor::find(value, baseT::argAsString(1, context, executionContext));
2005-08-04 22:42:30 +02:00
2006-06-08 11:51:18 +02:00
if(splitAt == string_adaptor::npos())
2005-08-18 13:32:29 +02:00
return new StringValue<string_type, string_adaptor>("");
2005-08-04 22:42:30 +02:00
2005-09-30 23:36:11 +02:00
return new StringValue<string_type, string_adaptor>(string_adaptor::substr(value, 0, splitAt));
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class SubstringBeforeFn
// string substring-after(string, string)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class SubstringAfterFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
SubstringAfterFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 2, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
string_type value = baseT::argAsString(0, context, executionContext);
string_type split = baseT::argAsString(1, context, executionContext);
2005-09-30 23:36:11 +02:00
size_t splitAt = string_adaptor::find(value, split);
2005-08-04 22:42:30 +02:00
2006-06-08 11:51:18 +02:00
if((splitAt == string_adaptor::npos()) || ((splitAt + string_adaptor::length(split)) >= string_adaptor::length(value)))
2005-08-18 13:32:29 +02:00
return new StringValue<string_type, string_adaptor>("");
2005-08-04 22:42:30 +02:00
2005-09-30 23:36:11 +02:00
return new StringValue<string_type, string_adaptor>(string_adaptor::substr(value, splitAt + string_adaptor::length(split)));
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class SubstringAfterFn
// string substring(string, number, number?)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class SubstringFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
SubstringFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(2, 3, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
string_type value = baseT::argAsString(0, context, executionContext);
2007-07-19 19:01:31 +02:00
if(string_adaptor::empty(value))
return new StringValue<string_type, string_adaptor>(value);
2005-08-18 13:32:29 +02:00
double startAt = roundNumber(baseT::argAsNumber(1, context, executionContext)) - 1;
double endAt = roundNumber((baseT::argCount() == 3 ? baseT::argAsNumber(2, context, executionContext) : Infinity)) + startAt;
2005-08-04 22:42:30 +02:00
2005-08-07 22:11:43 +02:00
if((endAt < 0) || (endAt < startAt) || (isNaN(endAt)))
2005-08-18 13:32:29 +02:00
return new StringValue<string_type, string_adaptor>("");
2005-08-04 22:42:30 +02:00
if(startAt < 0)
startAt = 0;
2005-09-30 23:36:11 +02:00
if((isInfinite(endAt)) || (endAt > string_adaptor::length(value)))
endAt = string_adaptor::length(value);
2005-08-04 22:42:30 +02:00
2005-09-30 23:36:11 +02:00
return new StringValue<string_type, string_adaptor>(string_adaptor::substr(value, static_cast<int>(startAt), static_cast<int>(endAt - startAt)));
2005-08-04 22:42:30 +02:00
} // evaluate
}; // SubstringFn
// number string-length(string?)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class StringLengthFn : public NumericFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef NumericFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
StringLengthFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 1, args) { }
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-09-30 23:36:11 +02:00
string_type v = (baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue<string_type, string_adaptor>(context);
return string_adaptor::length(v);
2005-08-04 22:42:30 +02:00
} // evaluate
}; // StringLengthFn
// string normalize-space(string?)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class NormalizeSpaceFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
NormalizeSpaceFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(0, 1, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
string_type initial = ((baseT::argCount() > 0) ? baseT::argAsString(0, context, executionContext) : nodeStringValue<string_type, string_adaptor>(context));
string_type value = Arabica::text::normalize_whitespace<string_type, string_adaptor>(initial);
2007-07-19 19:01:31 +02:00
return new StringValue<string_type, string_adaptor>(value);
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class NormalizeSpaceFn
// string translate(string, string, string)
2005-08-18 13:32:29 +02:00
template<class string_type, class string_adaptor>
class TranslateFn : public XPathFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
typedef XPathFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
2007-10-25 22:42:00 +02:00
TranslateFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : XPathFunction<string_type, string_adaptor>(3, 3, args) { }
2005-08-04 22:42:30 +02:00
virtual ValueType type() const { return STRING; }
virtual XPathValue_impl<string_type, string_adaptor>* evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 13:32:29 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
2005-08-18 13:32:29 +02:00
string_type str = baseT::argAsString(0, context, executionContext);
string_type from = baseT::argAsString(1, context, executionContext);
string_type to = baseT::argAsString(2, context, executionContext);
2005-08-04 22:42:30 +02:00
typename string_adaptor::mutable_iterator p = string_adaptor::begin(str);
for(typename string_adaptor::mutable_iterator i = string_adaptor::begin(str), ie = string_adaptor::end(str); i != ie; ++i)
2005-08-04 22:42:30 +02:00
{
2005-09-30 23:36:11 +02:00
size_t r = string_adaptor::find(from, *i);
2006-06-08 11:51:18 +02:00
if(r == string_adaptor::npos())
2005-08-04 22:42:30 +02:00
++p;
2005-09-30 23:36:11 +02:00
else if(r < string_adaptor::length(to))
*p++ = *(string_adaptor::begin(to) + r);
2005-08-04 22:42:30 +02:00
} // for ...
2005-09-30 23:36:11 +02:00
if(p != string_adaptor::end(str))
*p = 0;
2005-08-04 22:42:30 +02:00
return new StringValue<string_type, string_adaptor>(string_adaptor::construct(string_adaptor::begin(str), p));
2005-08-04 22:42:30 +02:00
} // evaluate
}; // class TranslateFn
///////////////////////////////////////////////////////
// boolean functions
// boolean boolean(object)
template<class string_type, class string_adaptor>
class BooleanFn : public BooleanFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef BooleanFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
BooleanFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(1, 1, args) { }
protected:
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return baseT::argAsBool(0, context, executionContext);
} // doEvaluate
2005-08-04 22:42:30 +02:00
}; // class BooleanFn
// boolean not(boolean)
template<class string_type, class string_adaptor>
class NotFn : public BooleanFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef BooleanFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
NotFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(1, 1, args) { }
protected:
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return !baseT::argAsBool(0, context, executionContext);
} // doEvaluate
2005-08-04 22:42:30 +02:00
}; // class NotFn
// boolean true()
template<class string_type, class string_adaptor>
class TrueFn : public BooleanFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
TrueFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(0, 0, args) { }
2005-08-04 22:42:30 +02:00
protected:
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return true;
} // doEvaluate
2005-08-04 22:42:30 +02:00
}; // TrueFn
// boolean false()
template<class string_type, class string_adaptor>
class FalseFn : public BooleanFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
FalseFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : BooleanFunction<string_type, string_adaptor>(0, 0, args) { }
protected:
virtual bool doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return false;
2005-08-04 22:42:30 +02:00
} // evaluate
}; // FalseFn
// boolean lang(string)
/////////////////////////////////////////////////
// number functions
// number number(object?)
template<class string_type, class string_adaptor>
class NumberFn : public NumericFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef NumericFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
NumberFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(0, 1, args) { }
2005-08-04 22:42:30 +02:00
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
double result = (baseT::argCount() > 0) ? baseT::argAsNumber(0, context, executionContext) :
2005-08-23 21:19:17 +02:00
StringValue<string_type, string_adaptor>(nodeStringValue<string_type, string_adaptor>(context)).asNumber();
return result;
2005-08-04 22:42:30 +02:00
} // evaluate
}; // NumberFn
// number sum(node-set)
template<class string_type, class string_adaptor>
class SumFn : public NumericFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef NumericFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
SumFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
protected:
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
double sum = 0;
NodeSet<string_type, string_adaptor> ns = baseT::argAsNodeSet(0, context, executionContext);
for(typename NodeSet<string_type, string_adaptor>::const_iterator n = ns.begin(), end = ns.end(); n != end; ++n)
2005-08-23 21:19:17 +02:00
sum += nodeNumberValue<string_type, string_adaptor>(*n);
return sum;
} // doEvaluate
2005-08-04 22:42:30 +02:00
}; // class SumFn
// number floor(number)
template<class string_type, class string_adaptor>
class FloorFn : public NumericFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef NumericFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
FloorFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
protected:
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return std::floor(baseT::argAsNumber(0, context, executionContext));
} // doEvaluate
2005-08-04 22:42:30 +02:00
}; // class FloorFn
// number ceiling(number)
template<class string_type, class string_adaptor>
class CeilingFn : public NumericFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef NumericFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
CeilingFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
protected:
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return std::ceil(baseT::argAsNumber(0, context, executionContext));
} // doEvaluate
2005-08-04 22:42:30 +02:00
}; // class CeilingFn
// number round(number)
template<class string_type, class string_adaptor>
class RoundFn : public NumericFunction<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
typedef NumericFunction<string_type, string_adaptor> baseT;
2005-08-04 22:42:30 +02:00
public:
RoundFn(const std::vector<XPathExpression<string_type, string_adaptor> >& args) : NumericFunction<string_type, string_adaptor>(1, 1, args) { }
protected:
virtual double doEvaluate(const DOM::Node<string_type, string_adaptor>& context,
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return roundNumber(baseT::argAsNumber(0, context, executionContext));
} // doEvaluate
2005-08-04 22:42:30 +02:00
}; // class RoundFn
} // namespace impl
2005-08-04 22:42:30 +02:00
} // namespace XPath
} // namespace Arabica
#endif