michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef txXPathTreeWalker_h__ michael@0: #define txXPathTreeWalker_h__ michael@0: michael@0: #include "txCore.h" michael@0: #include "txXPathNode.h" michael@0: #include "nsIContentInlines.h" michael@0: #include "nsINodeInfo.h" michael@0: #include "nsTArray.h" michael@0: michael@0: class nsIAtom; michael@0: class nsIDOMDocument; michael@0: michael@0: class txUint32Array : public nsTArray michael@0: { michael@0: public: michael@0: bool AppendValue(uint32_t aValue) michael@0: { michael@0: return AppendElement(aValue) != nullptr; michael@0: } michael@0: bool RemoveValueAt(uint32_t aIndex) michael@0: { michael@0: if (aIndex < Length()) { michael@0: RemoveElementAt(aIndex); michael@0: } michael@0: return true; michael@0: } michael@0: uint32_t ValueAt(uint32_t aIndex) const michael@0: { michael@0: return (aIndex < Length()) ? ElementAt(aIndex) : 0; michael@0: } michael@0: }; michael@0: michael@0: class txXPathTreeWalker michael@0: { michael@0: public: michael@0: txXPathTreeWalker(const txXPathTreeWalker& aOther); michael@0: explicit txXPathTreeWalker(const txXPathNode& aNode); michael@0: michael@0: bool getAttr(nsIAtom* aLocalName, int32_t aNSID, nsAString& aValue) const; michael@0: int32_t getNamespaceID() const; michael@0: uint16_t getNodeType() const; michael@0: void appendNodeValue(nsAString& aResult) const; michael@0: void getNodeName(nsAString& aName) const; michael@0: michael@0: void moveTo(const txXPathTreeWalker& aWalker); michael@0: michael@0: void moveToRoot(); michael@0: bool moveToParent(); michael@0: bool moveToElementById(const nsAString& aID); michael@0: bool moveToFirstAttribute(); michael@0: bool moveToNextAttribute(); michael@0: bool moveToNamedAttribute(nsIAtom* aLocalName, int32_t aNSID); michael@0: bool moveToFirstChild(); michael@0: bool moveToLastChild(); michael@0: bool moveToNextSibling(); michael@0: bool moveToPreviousSibling(); michael@0: michael@0: bool isOnNode(const txXPathNode& aNode) const; michael@0: michael@0: const txXPathNode& getCurrentPosition() const; michael@0: michael@0: private: michael@0: txXPathNode mPosition; michael@0: michael@0: bool moveToValidAttribute(uint32_t aStartIndex); michael@0: bool moveToSibling(int32_t aDir); michael@0: michael@0: uint32_t mCurrentIndex; michael@0: txUint32Array mDescendants; michael@0: }; michael@0: michael@0: class txXPathNodeUtils michael@0: { michael@0: public: michael@0: static bool getAttr(const txXPathNode& aNode, nsIAtom* aLocalName, michael@0: int32_t aNSID, nsAString& aValue); michael@0: static already_AddRefed getLocalName(const txXPathNode& aNode); michael@0: static nsIAtom* getPrefix(const txXPathNode& aNode); michael@0: static void getLocalName(const txXPathNode& aNode, nsAString& aLocalName); michael@0: static void getNodeName(const txXPathNode& aNode, michael@0: nsAString& aName); michael@0: static int32_t getNamespaceID(const txXPathNode& aNode); michael@0: static void getNamespaceURI(const txXPathNode& aNode, nsAString& aURI); michael@0: static uint16_t getNodeType(const txXPathNode& aNode); michael@0: static void appendNodeValue(const txXPathNode& aNode, nsAString& aResult); michael@0: static bool isWhitespace(const txXPathNode& aNode); michael@0: static txXPathNode* getOwnerDocument(const txXPathNode& aNode); michael@0: static int32_t getUniqueIdentifier(const txXPathNode& aNode); michael@0: static nsresult getXSLTId(const txXPathNode& aNode, michael@0: const txXPathNode& aBase, nsAString& aResult); michael@0: static void release(txXPathNode* aNode); michael@0: static void getBaseURI(const txXPathNode& aNode, nsAString& aURI); michael@0: static int comparePosition(const txXPathNode& aNode, michael@0: const txXPathNode& aOtherNode); michael@0: static bool localNameEquals(const txXPathNode& aNode, michael@0: nsIAtom* aLocalName); michael@0: static bool isRoot(const txXPathNode& aNode); michael@0: static bool isElement(const txXPathNode& aNode); michael@0: static bool isAttribute(const txXPathNode& aNode); michael@0: static bool isProcessingInstruction(const txXPathNode& aNode); michael@0: static bool isComment(const txXPathNode& aNode); michael@0: static bool isText(const txXPathNode& aNode); michael@0: static inline bool isHTMLElementInHTMLDocument(const txXPathNode& aNode) michael@0: { michael@0: if (!aNode.isContent()) { michael@0: return false; michael@0: } michael@0: nsIContent* content = aNode.Content(); michael@0: return content->IsHTML() && content->IsInHTMLDocument(); michael@0: } michael@0: }; michael@0: michael@0: class txXPathNativeNode michael@0: { michael@0: public: michael@0: static txXPathNode* createXPathNode(nsIDOMNode* aNode, michael@0: bool aKeepRootAlive = false); michael@0: static txXPathNode* createXPathNode(nsIContent* aContent, michael@0: bool aKeepRootAlive = false); michael@0: static txXPathNode* createXPathNode(nsIDOMDocument* aDocument); michael@0: static nsresult getNode(const txXPathNode& aNode, nsIDOMNode** aResult); michael@0: static nsIContent* getContent(const txXPathNode& aNode); michael@0: static nsIDocument* getDocument(const txXPathNode& aNode); michael@0: static void addRef(const txXPathNode& aNode) michael@0: { michael@0: NS_ADDREF(aNode.mNode); michael@0: } michael@0: static void release(const txXPathNode& aNode) michael@0: { michael@0: nsINode *node = aNode.mNode; michael@0: NS_RELEASE(node); michael@0: } michael@0: }; michael@0: michael@0: inline const txXPathNode& michael@0: txXPathTreeWalker::getCurrentPosition() const michael@0: { michael@0: return mPosition; michael@0: } michael@0: michael@0: inline bool michael@0: txXPathTreeWalker::getAttr(nsIAtom* aLocalName, int32_t aNSID, michael@0: nsAString& aValue) const michael@0: { michael@0: return txXPathNodeUtils::getAttr(mPosition, aLocalName, aNSID, aValue); michael@0: } michael@0: michael@0: inline int32_t michael@0: txXPathTreeWalker::getNamespaceID() const michael@0: { michael@0: return txXPathNodeUtils::getNamespaceID(mPosition); michael@0: } michael@0: michael@0: inline void michael@0: txXPathTreeWalker::appendNodeValue(nsAString& aResult) const michael@0: { michael@0: txXPathNodeUtils::appendNodeValue(mPosition, aResult); michael@0: } michael@0: michael@0: inline void michael@0: txXPathTreeWalker::getNodeName(nsAString& aName) const michael@0: { michael@0: txXPathNodeUtils::getNodeName(mPosition, aName); michael@0: } michael@0: michael@0: inline void michael@0: txXPathTreeWalker::moveTo(const txXPathTreeWalker& aWalker) michael@0: { michael@0: nsINode *root = nullptr; michael@0: if (mPosition.mRefCountRoot) { michael@0: root = mPosition.Root(); michael@0: } michael@0: mPosition.mIndex = aWalker.mPosition.mIndex; michael@0: mPosition.mRefCountRoot = aWalker.mPosition.mRefCountRoot; michael@0: mPosition.mNode = aWalker.mPosition.mNode; michael@0: nsINode *newRoot = nullptr; michael@0: if (mPosition.mRefCountRoot) { michael@0: newRoot = mPosition.Root(); michael@0: } michael@0: if (root != newRoot) { michael@0: NS_IF_ADDREF(newRoot); michael@0: NS_IF_RELEASE(root); michael@0: } michael@0: michael@0: mCurrentIndex = aWalker.mCurrentIndex; michael@0: mDescendants.Clear(); michael@0: } michael@0: michael@0: inline bool michael@0: txXPathTreeWalker::isOnNode(const txXPathNode& aNode) const michael@0: { michael@0: return (mPosition == aNode); michael@0: } michael@0: michael@0: /* static */ michael@0: inline int32_t michael@0: txXPathNodeUtils::getUniqueIdentifier(const txXPathNode& aNode) michael@0: { michael@0: NS_PRECONDITION(!aNode.isAttribute(), michael@0: "Not implemented for attributes."); michael@0: return NS_PTR_TO_INT32(aNode.mNode); michael@0: } michael@0: michael@0: /* static */ michael@0: inline void michael@0: txXPathNodeUtils::release(txXPathNode* aNode) michael@0: { michael@0: NS_RELEASE(aNode->mNode); michael@0: } michael@0: michael@0: /* static */ michael@0: inline bool michael@0: txXPathNodeUtils::localNameEquals(const txXPathNode& aNode, michael@0: nsIAtom* aLocalName) michael@0: { michael@0: if (aNode.isContent() && michael@0: aNode.Content()->IsElement()) { michael@0: return aNode.Content()->NodeInfo()->Equals(aLocalName); michael@0: } michael@0: michael@0: nsCOMPtr localName = txXPathNodeUtils::getLocalName(aNode); michael@0: michael@0: return localName == aLocalName; michael@0: } michael@0: michael@0: /* static */ michael@0: inline bool michael@0: txXPathNodeUtils::isRoot(const txXPathNode& aNode) michael@0: { michael@0: return !aNode.isAttribute() && !aNode.mNode->GetParentNode(); michael@0: } michael@0: michael@0: /* static */ michael@0: inline bool michael@0: txXPathNodeUtils::isElement(const txXPathNode& aNode) michael@0: { michael@0: return aNode.isContent() && michael@0: aNode.Content()->IsElement(); michael@0: } michael@0: michael@0: michael@0: /* static */ michael@0: inline bool michael@0: txXPathNodeUtils::isAttribute(const txXPathNode& aNode) michael@0: { michael@0: return aNode.isAttribute(); michael@0: } michael@0: michael@0: /* static */ michael@0: inline bool michael@0: txXPathNodeUtils::isProcessingInstruction(const txXPathNode& aNode) michael@0: { michael@0: return aNode.isContent() && michael@0: aNode.Content()->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION); michael@0: } michael@0: michael@0: /* static */ michael@0: inline bool michael@0: txXPathNodeUtils::isComment(const txXPathNode& aNode) michael@0: { michael@0: return aNode.isContent() && michael@0: aNode.Content()->IsNodeOfType(nsINode::eCOMMENT); michael@0: } michael@0: michael@0: /* static */ michael@0: inline bool michael@0: txXPathNodeUtils::isText(const txXPathNode& aNode) michael@0: { michael@0: return aNode.isContent() && michael@0: aNode.Content()->IsNodeOfType(nsINode::eTEXT); michael@0: } michael@0: michael@0: #endif /* txXPathTreeWalker_h__ */