arabica/include/XPath/impl/xpath_function_holder.hpp

127 lines
6.3 KiB
C++
Raw Normal View History

2005-08-04 22:42:30 +02:00
#ifndef ARABICA_XPATH_FUNCTION_HOLDER_HPP
#define ARABICA_XPATH_FUNCTION_HOLDER_HPP
#include <boost/shared_ptr.hpp>
#include "xpath_value.hpp"
#include "xpath_function.hpp"
namespace Arabica
{
namespace XPath
{
namespace impl
{
2005-08-04 22:42:30 +02:00
2005-08-18 11:15:08 +02:00
template<class function_type, class string_type, class string_adaptor>
2007-10-25 22:42:00 +02:00
XPathFunction<string_type, string_adaptor>* CreateFn(const std::vector<XPathExpression<string_type, string_adaptor> >& argExprs) { return new function_type(argExprs); }
2005-08-04 22:42:30 +02:00
2005-08-18 11:15:08 +02:00
template<class string_type, class string_adaptor>
class FunctionHolder : public XPathExpression_impl<string_type, string_adaptor>
2005-08-04 22:42:30 +02:00
{
public:
FunctionHolder(XPathFunction<string_type, string_adaptor>* func,
const string_type& namespace_uri,
const string_type& name) :
func_(func),
namespace_uri_(namespace_uri),
name_(name)
2005-08-04 22:42:30 +02:00
{
} // FunctionHolder
virtual ~FunctionHolder()
{
delete func_;
} // ~FunctionHolder
const string_type& namespace_uri() const { return namespace_uri_; }
const string_type& name() const { return name_; }
virtual ValueType type() const { return func_->type(); }
virtual XPathValue<string_type, string_adaptor> evaluate(const DOM::Node<string_type, string_adaptor>& context,
2005-08-18 11:15:08 +02:00
const ExecutionContext<string_type, string_adaptor>& executionContext) const
2005-08-04 22:42:30 +02:00
{
return XPathValue<string_type, string_adaptor>(func_->evaluate(context, executionContext));
2005-08-04 22:42:30 +02:00
} // evaluate
2007-07-19 19:01:31 +02:00
static FunctionHolder* createFunction(const string_type& namespace_uri,
const string_type& name,
2007-10-25 22:42:00 +02:00
const std::vector<XPathExpression<string_type, string_adaptor> >& argExprs,
2005-08-18 11:15:08 +02:00
const CompilationContext<string_type, string_adaptor>& context)
2005-08-04 22:42:30 +02:00
{
2007-07-19 19:01:31 +02:00
if(string_adaptor::empty(namespace_uri))
for(const NamedFunction* fn = FunctionLookupTable; fn->name != 0; ++fn)
if(name == string_adaptor::construct_from_utf8(fn->name))
return new FunctionHolder(fn->creator(argExprs), namespace_uri, name);
2005-08-04 22:42:30 +02:00
2007-07-19 19:01:31 +02:00
XPathFunction<string_type, string_adaptor>* func =
context.functionResolver().resolveFunction(namespace_uri, name, argExprs);
2005-08-04 22:42:30 +02:00
if(func == 0)
2007-07-19 19:01:31 +02:00
{
string_type error;
if(!string_adaptor::empty(namespace_uri))
{
string_adaptor::append(error, string_adaptor::construct_from_utf8("{"));
string_adaptor::append(error, namespace_uri);
string_adaptor::append(error, string_adaptor::construct_from_utf8("}"));
} // if ...
string_adaptor::append(error, name);
throw UndefinedFunctionException(string_adaptor().asStdString(error));
} // if(func == 0)
return new FunctionHolder(func, namespace_uri, name);
2005-08-04 22:42:30 +02:00
} // createFunction
private:
2005-08-18 11:15:08 +02:00
XPathFunction<string_type, string_adaptor>* func_;
string_type namespace_uri_;
string_type name_;
2005-08-18 11:15:08 +02:00
2007-10-25 22:42:00 +02:00
typedef XPathFunction<string_type, string_adaptor>* (*CreateFnPtr)(const std::vector<XPathExpression<string_type, string_adaptor> >& argExprs);
2005-08-18 11:15:08 +02:00
struct NamedFunction { const char* name; CreateFnPtr creator; };
static const NamedFunction FunctionLookupTable[];
}; // class FunctionHolder
template<class string_type, class string_adaptor>
const typename FunctionHolder<string_type, string_adaptor>::NamedFunction
FunctionHolder<string_type, string_adaptor>::FunctionLookupTable[] =
{ // node-set functions
2005-08-18 11:33:19 +02:00
{ "position", CreateFn<PositionFn<string_type, string_adaptor>, string_type, string_adaptor> },
{ "last", CreateFn<LastFn<string_type, string_adaptor>, string_type, string_adaptor> },
{ "count", CreateFn<CountFn<string_type, string_adaptor>, string_type, string_adaptor> },
{ "local-name", CreateFn<LocalNameFn<string_type, string_adaptor>, string_type, string_adaptor> },
{ "namespace-uri", CreateFn<NamespaceURIFn<string_type, string_adaptor>, string_type, string_adaptor> },
{ "name", CreateFn<NameFn<string_type, string_adaptor>, string_type, string_adaptor> },
2005-08-18 11:15:08 +02:00
// string functions
2005-08-18 13:32:29 +02:00
{"string", CreateFn<StringFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"concat", CreateFn<ConcatFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"starts-with", CreateFn<StartsWithFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"contains", CreateFn<ContainsFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"substring-before", CreateFn<SubstringBeforeFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"substring-after", CreateFn<SubstringAfterFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"substring", CreateFn<SubstringFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"string-length", CreateFn<StringLengthFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"normalize-space", CreateFn<NormalizeSpaceFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"translate", CreateFn<TranslateFn<string_type, string_adaptor>, string_type, string_adaptor> },
2005-08-18 11:15:08 +02:00
// boolean functions
{"boolean", CreateFn<BooleanFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"not", CreateFn<NotFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"true", CreateFn<TrueFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"false", CreateFn<FalseFn<string_type, string_adaptor>, string_type, string_adaptor> },
2005-08-18 11:15:08 +02:00
// number functions
{"number", CreateFn<NumberFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"sum", CreateFn<SumFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"floor", CreateFn<FloorFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"ceiling", CreateFn<CeilingFn<string_type, string_adaptor>, string_type, string_adaptor> },
{"round", CreateFn<RoundFn<string_type, string_adaptor>, string_type, string_adaptor> },
2005-08-18 11:15:08 +02:00
{0, 0}
};
2005-08-04 22:42:30 +02:00
} // namespace impl
2005-08-04 22:42:30 +02:00
} // namespace XPath
} // namespace Arabica
#endif