#ifndef ARABICA_XPATHIC_XPATH_EXPRESSION_H #define ARABICA_XPATHIC_XPATH_EXPRESSION_H #include #include #include "xpath_object.hpp" #include "xpath_execution_context.hpp" namespace Arabica { namespace XPath { template class XPathExpression_impl; namespace impl { template class Expression_scanner { protected: Expression_scanner() { } Expression_scanner(const Expression_scanner&) { } ~Expression_scanner() { } public: virtual void scan(const XPathExpression_impl* const expr) = 0; private: bool operator==(const Expression_scanner&) const; Expression_scanner& operator=(const Expression_scanner&); }; // class Expression_scanner } // namespace impl template class XPathExpression_impl { protected: XPathExpression_impl() { } public: virtual ~XPathExpression_impl() { } virtual ValueType type() const = 0; XPathValue evaluate(const DOM::Node& context) const { ExecutionContext executionContext; return evaluate(context, executionContext); } // evaluate virtual bool evaluateAsBool(const DOM::Node& context) const { return evaluate(context).asBool(); } virtual double evaluateAsNumber(const DOM::Node& context) const { return evaluate(context).asNumber(); } virtual string_type evaluateAsString(const DOM::Node& context) const { return evaluate(context).asString(); } virtual NodeSet evaluateAsNodeSet(const DOM::Node& context) const { return evaluate(context).asNodeSet(); } virtual XPathValue evaluate(const DOM::Node& context, const ExecutionContext& executionContext) const = 0; virtual bool evaluateAsBool(const DOM::Node& context, const ExecutionContext& executionContext) const { return evaluate(context, executionContext).asBool(); } virtual double evaluateAsNumber(const DOM::Node& context, const ExecutionContext& executionContext) const { return evaluate(context, executionContext).asNumber(); } virtual string_type evaluateAsString(const DOM::Node& context, const ExecutionContext& executionContext) const { return evaluate(context, executionContext).asString(); } virtual NodeSet evaluateAsNodeSet(const DOM::Node& context, const ExecutionContext& executionContext) const { return evaluate(context, executionContext).asNodeSet(); } virtual void scan(impl::Expression_scanner& scanner) const { scanner.scan(this); } private: XPathExpression_impl(const XPathExpression_impl&); bool operator==(const XPathExpression_impl&); XPathExpression_impl& operator=(const XPathExpression_impl&); }; // class XPathExpression_impl template class XPathExpressionPtr; template > class XPathExpression { public: XPathExpression() : ptr_() { } explicit XPathExpression(XPathExpression_impl* xp) : ptr_(xp) { } XPathExpression(const XPathExpression& rhs) : ptr_(rhs.ptr_) { } XPathExpression& operator=(const XPathExpression& rhs) { ptr_ = rhs.ptr_; return *this; } // operator= ValueType type() const { return ptr_->type(); } const XPathExpression_impl* get() const { return ptr_.get(); } operator bool() const { return ptr_.get(); } XPathValue evaluate(const DOM::Node& context) const { return ptr_->evaluate(context); } // evaluate bool evaluateAsBool(const DOM::Node& context) const { return ptr_->evaluateAsBool(context); } // evaluateAsBool double evaluateAsNumber(const DOM::Node& context) const { return ptr_->evaluateAsNumber(context); } // evaluateAsNumber string_type evaluateAsString(const DOM::Node& context) const { return ptr_->evaluateAsString(context); } // evaluateAsString NodeSet evaluateAsNodeSet(const DOM::Node& context) const { return ptr_->evaluate(context).asNodeSet(); } // evaluateAsNodeSet XPathValue evaluate(const DOM::Node& context, const ExecutionContext& executionContext) const { return ptr_->evaluate(context, executionContext); } // evaluate bool evaluateAsBool(const DOM::Node& context, const ExecutionContext& executionContext) const { return ptr_->evaluateAsBool(context, executionContext); } // evaluateAsBool double evaluateAsNumber(const DOM::Node& context, const ExecutionContext& executionContext) const { return ptr_->evaluateAsNumber(context, executionContext); } // evaluateAsNumber string_type evaluateAsString(const DOM::Node& context, const ExecutionContext& executionContext) const { return ptr_->evaluateAsString(context, executionContext); } // evaluateAsString NodeSet evaluateAsNodeSet(const DOM::Node& context, const ExecutionContext& executionContext) const { return ptr_->evaluate(context, executionContext).asNodeSet(); } // evaluateAsNodeSet private: typedef boost::shared_ptr > ExpressionPtr; ExpressionPtr ptr_; explicit XPathExpression(ExpressionPtr ptr) : ptr_(ptr) { } friend class XPathExpressionPtr; }; // class XPathExpression template > class XPathExpressionPtr { public: explicit XPathExpressionPtr() : ptr_() { } explicit XPathExpressionPtr(const XPathExpression_impl* v) : ptr_(v) { } XPathExpressionPtr(const XPathExpression& rhs) : ptr_(rhs.ptr_) { } XPathExpressionPtr(const XPathExpressionPtr& rhs) : ptr_(rhs.ptr_) { } XPathExpressionPtr& operator=(const XPathExpression& rhs) { ptr_ = rhs.ptr_; return *this; } // operator= XPathExpressionPtr& operator=(const XPathExpressionPtr& rhs) { ptr_ = rhs.ptr_; return *this; } // operator= const XPathExpression_impl* operator->() const { return ptr_.get(); } operator bool() const { return (ptr_.get() != 0); } operator XPathExpression() const { return XPathExpression(ptr_); } private: bool operator==(const XPathExpressionPtr&) const; typedef boost::shared_ptr > ExpressionPtr; ExpressionPtr ptr_; }; // class XPathExpressionPtr namespace impl { template class UnaryExpression : public XPathExpression_impl { public: UnaryExpression(XPathExpression_impl* expr) : expr_(expr) { } virtual void scan(impl::Expression_scanner& scanner) const { expr_->scan(scanner); scanner.scan(this); } // scan protected: ~UnaryExpression() { delete expr_; } // ~UnaryExpression XPathExpression_impl* expr() const { return expr_; } private: XPathExpression_impl* expr_; }; // class UnaryExpression template class BinaryExpression : public XPathExpression_impl { public: BinaryExpression(XPathExpression_impl* lhs, XPathExpression_impl* rhs) : lhs_(lhs), rhs_(rhs) { } // BinaryExpression virtual void scan(impl::Expression_scanner& scanner) const { lhs_->scan(scanner); rhs_->scan(scanner); scanner.scan(this); } // scan protected: ~BinaryExpression() { delete lhs_; delete rhs_; } // ~BinaryExpression XPathExpression_impl* lhs() const { return lhs_; } XPathExpression_impl* rhs() const { return rhs_; } private: XPathExpression_impl* lhs_; XPathExpression_impl* rhs_; }; // class BinaryExpression } // namespace impl } // namespace XPath } // namespace Arabica #endif