#ifndef ARABICA_XPATHIC_XPATH_OBJECT_H #define ARABICA_XPATHIC_XPATH_OBJECT_H #include #include #include #include #include #include namespace Arabica { namespace XPath { enum ValueType { ANY , BOOL, NUMBER, STRING, NODE_SET }; // ValueType int compareNodes(const DOM::Node& n1, const DOM::Node& n2); bool nodes_less_than(const DOM::Node& n1, const DOM::Node& n2); template class NodeSet : public std::vector > { private: typedef std::vector > baseT; public: NodeSet() : std::vector >(), forward_(true), sorted_(false) { } // NodeSet NodeSet(bool forward) : std::vector >(), forward_(forward), sorted_(true) { } // NodeSet NodeSet(const NodeSet& rhs) : std::vector >(rhs), forward_(rhs.forward_), sorted_(rhs.sorted_) { } // NodeSet NodeSet& operator=(const NodeSet& rhs) { forward_ = rhs.forward_; sorted_ = rhs.sorted_; std::vector >::operator=(rhs); return *this; } // operator= void swap(NodeSet& rhs) { std::vector >::swap(rhs); std::swap(forward_, rhs.forward_); std::swap(sorted_, rhs.sorted_); } // swap bool forward() const { return sorted_ && forward_; } bool reverse() const { return sorted_ && !forward_; } void forward(bool forward) { forward_ = forward; sorted_ = true; } void to_document_order() { if(!sorted_) { std::sort(baseT::begin(), baseT::end(), nodes_less_than); sorted_ = true; forward_ = true; } // if(!sorted) if(!forward_) { std::reverse(baseT::begin(), baseT::end()); forward_ = true; } // if(!forward_) } // to_document_order DOM::Node top() const { if(forward_) return (*this)[0]; return (*this)[baseT::size()-1]; } // top() private: bool forward_; bool sorted_; }; // NodeSet template class XPathValue { protected: XPathValue() { } public: virtual ~XPathValue() { } virtual bool asBool() const = 0; virtual double asNumber() const = 0; virtual string_type asString() const = 0; virtual const NodeSet& asNodeSet() const = 0; virtual ValueType type() const = 0; private: XPathValue(const XPathValue&); bool operator==(const XPathValue&); XPathValue& operator=(const XPathValue&); }; // class XPathValue template class XPathValuePtr : public boost::shared_ptr > { public: explicit XPathValuePtr(const XPathValue* v) : boost::shared_ptr >(v) { } }; const double NaN = std::sqrt(-2.0); const double Zero = 0.0; const double Negative_Zero = -Zero; const double Infinity = HUGE_VAL; const double Negative_Infinity = -Infinity; inline bool isNaN(double value) { return (value != value); } inline bool isInfinity(double value) { return (value == Infinity); } inline bool isNegativeInfinity(double value) { return (value == Negative_Infinity); } inline bool isInfinite(double value) { return isInfinity(value) || isNegativeInfinity(value); } inline double roundNumber(double value) { if(!(isNaN(value) || isInfinite(value) || (std::fabs(value) == 0))) if((value < 0.0) && (value > -0.5)) value = -0.0; else value = std::floor(value + 0.5); return value; } // roundNumber template double stringAsNumber(const string_type& str) { try { return boost::lexical_cast(str); } // try catch(const boost::bad_lexical_cast&) { return NaN; } // catch } // stringAsNumber template double nodeNumberValue(const DOM::Node& node) { return stringAsNumber(nodeStringValue(node)); } // nodeNumberValue template string_type nodeStringValue(const DOM::Node& node) { switch(node.getNodeType()) { case DOM::Node_base::DOCUMENT_NODE: case DOM::Node_base::DOCUMENT_FRAGMENT_NODE: case DOM::Node_base::ELEMENT_NODE: { std::ostringstream os; AxisEnumerator ae(node, DESCENDANT); while(*ae != 0) { if((ae->getNodeType() == DOM::Node_base::TEXT_NODE) || (ae->getNodeType() == DOM::Node_base::CDATA_SECTION_NODE)) os << ae->getNodeValue(); ++ae; } // while return os.str(); } // case case DOM::Node_base::ATTRIBUTE_NODE: case DOM::Node_base::PROCESSING_INSTRUCTION_NODE: case DOM::Node_base::COMMENT_NODE: case DOM::Node_base::TEXT_NODE: case DOM::Node_base::CDATA_SECTION_NODE: return node.getNodeValue(); default: throw std::runtime_error("Don't know how to calculate string-value of " + node.getNodeName()); } // switch } // nodeStringValue template bool areEqual(const XPathValuePtr& lhs, const XPathValuePtr& rhs); template bool isLessThan(const XPathValuePtr& lhs, const XPathValuePtr& rhs); template bool isLessThanEquals(const XPathValuePtr& lhs, const XPathValuePtr& rhs); template bool isGreaterThan(const XPathValuePtr& lhs, const XPathValuePtr& rhs); template bool isGreaterThanEquals(const XPathValuePtr& lhs, const XPathValuePtr& rhs); } // namespace XPath } // namespace Arabica #endif