#ifndef ARABICA_XPATHIC_XPATH_ARITHMETIC_HPP #define ARABICA_XPATHIC_XPATH_ARITHMETIC_HPP #include #include "xpath_value.hpp" #include "xpath_expression_impl.hpp" namespace Arabica { namespace XPath { namespace impl { template class ArithmeticOperator : public BinaryExpression, public NumericExpression { typedef BinaryExpression baseT; public: ArithmeticOperator(XPathExpression_impl* lhs, XPathExpression_impl* rhs) : BinaryExpression(lhs, rhs) { } virtual double doEvaluateAsNumber(const DOM::Node& context, const ExecutionContext& executionContext) const { return Op()(baseT::lhs()->evaluateAsNumber(context, executionContext), baseT::rhs()->evaluateAsNumber(context, executionContext)); } // evaluateAsNumber }; // class ArithmeticOperator template class PlusOperator : public ArithmeticOperator > { public: PlusOperator(XPathExpression_impl* lhs, XPathExpression_impl* rhs) : ArithmeticOperator >(lhs, rhs) { } }; // class PlusOperator template class MinusOperator : public ArithmeticOperator > { public: MinusOperator(XPathExpression_impl* lhs, XPathExpression_impl* rhs) : ArithmeticOperator >(lhs, rhs) { } }; // class MinusOperator template class MultiplyOperator : public ArithmeticOperator > { public: MultiplyOperator(XPathExpression_impl* lhs, XPathExpression_impl* rhs) : ArithmeticOperator >(lhs, rhs) { } }; // class MultiplyOperator template class DivideOperator : public ArithmeticOperator > { public: DivideOperator(XPathExpression_impl* lhs, XPathExpression_impl* rhs) : ArithmeticOperator >(lhs, rhs) { } }; // class DivideOperator struct NaN_aware_modulus { double operator()(const double& lhs, const double& rhs) const { // apply operator% to operands if(isNaN(lhs) || isNaN(rhs)) return NaN; return (static_cast(lhs) % static_cast(rhs)); } }; // NaN_aware_modulus template class ModOperator : public ArithmeticOperator { typedef BinaryExpression baseT; public: ModOperator(XPathExpression_impl* lhs, XPathExpression_impl* rhs) : ArithmeticOperator(lhs, rhs) { } }; // class ModOperator template class UnaryNegative : public UnaryExpression { typedef UnaryExpression baseT; public: UnaryNegative(XPathExpression_impl* expr) : UnaryExpression(expr) { } virtual ValueType type() const { return NUMBER; } virtual XPathValue evaluate(const DOM::Node& context, const ExecutionContext& executionContext) const { return NumericValue::createValue(evaluateAsNumber(context, executionContext)); } // evaluate virtual double evaluateAsNumber(const DOM::Node& context, const ExecutionContext& executionContext) const { return -baseT::expr()->evaluateAsNumber(context, executionContext); } // evaluateAsNumber }; // class UnaryNegative } // namespace impl } // namespace XPath } // namespace Arabica #endif