#ifndef ARABICA_XPATH_FUNCTION_HOLDER_HPP #define ARABICA_XPATH_FUNCTION_HOLDER_HPP #include #include "xpath_value.hpp" #include "xpath_function.hpp" namespace Arabica { namespace XPath { namespace impl { template XPathFunction* CreateFn(const std::vector >& argExprs) { return new function_type(argExprs); } template class FunctionHolder : public XPathExpression_impl { public: FunctionHolder(XPathFunction* func) : func_(func) { } // FunctionHolder virtual ~FunctionHolder() { delete func_; } // ~FunctionHolder virtual XPathValue evaluate(const DOM::Node& context, const ExecutionContext& executionContext) const { return XPathValue(func_->evaluate(context, executionContext)); } // evaluate static FunctionHolder* createFunction(const string_type& namespace_uri, const string_type& name, const std::vector >& argExprs, const CompilationContext& context) { 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)); XPathFunction* func = context.functionResolver().resolveFunction(namespace_uri, name, argExprs); if(func == 0) { 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); } // createFunction private: XPathFunction* func_; typedef XPathFunction* (*CreateFnPtr)(const std::vector >& argExprs); struct NamedFunction { const char* name; CreateFnPtr creator; }; static const NamedFunction FunctionLookupTable[]; }; // class FunctionHolder template const typename FunctionHolder::NamedFunction FunctionHolder::FunctionLookupTable[] = { // node-set functions { "position", CreateFn, string_type, string_adaptor> }, { "last", CreateFn, string_type, string_adaptor> }, { "count", CreateFn, string_type, string_adaptor> }, { "local-name", CreateFn, string_type, string_adaptor> }, { "namespace-uri", CreateFn, string_type, string_adaptor> }, { "name", CreateFn, string_type, string_adaptor> }, // string functions {"string", CreateFn, string_type, string_adaptor> }, {"concat", CreateFn, string_type, string_adaptor> }, {"starts-with", CreateFn, string_type, string_adaptor> }, {"contains", CreateFn, string_type, string_adaptor> }, {"substring-before", CreateFn, string_type, string_adaptor> }, {"substring-after", CreateFn, string_type, string_adaptor> }, {"substring", CreateFn, string_type, string_adaptor> }, {"string-length", CreateFn, string_type, string_adaptor> }, {"normalize-space", CreateFn, string_type, string_adaptor> }, {"translate", CreateFn, string_type, string_adaptor> }, // boolean functions {"boolean", CreateFn, string_type, string_adaptor> }, {"not", CreateFn, string_type, string_adaptor> }, {"true", CreateFn, string_type, string_adaptor> }, {"false", CreateFn, string_type, string_adaptor> }, // number functions {"number", CreateFn, string_type, string_adaptor> }, {"sum", CreateFn, string_type, string_adaptor> }, {"floor", CreateFn, string_type, string_adaptor> }, {"ceiling", CreateFn, string_type, string_adaptor> }, {"round", CreateFn, string_type, string_adaptor> }, {0, 0} }; } // namespace impl } // namespace XPath } // namespace Arabica #endif