txXPathNode.h (4904B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef txXPathNode_h__ 7 #define txXPathNode_h__ 8 9 #include "mozilla/dom/Document.h" 10 #include "nsIContent.h" 11 #include "nsINode.h" 12 #include "nsNameSpaceManager.h" 13 14 using txXPathNodeType = nsINode; 15 16 /** 17 * txXPathNode represents a node in XPath's data model (which is a bit different 18 * from the DOM's). While XPath 1.0 has 7 node types, we essentially deal with 3 19 * kinds: a document node, any other node type that is backed by an 20 * implementation of nsIContent in Gecko, and attribute nodes. Because we try to 21 * avoid creating actual node objects for attribute nodes in Gecko's DOM, we 22 * store attribute nodes as a pointer to their owner element and an index into 23 * that element's attribute node list. So to represent the 3 kinds of node we 24 * need to store: 25 * 26 * - a pointer to a document (a nsIDocument as a nsINode pointer) 27 * - a pointer to a nsIContent object (as a nsINode pointer) 28 * - a pointer to a nsIContent object (a nsIContent as a nsINode pointer) and 29 * an index 30 * 31 * So we make txXPathNode store a |nsCOMPtr<nsINode>| and a uint32_t for the 32 * index. To be able to distinguish between the attribute nodes and other nodes 33 * we store a flag value for the other nodes in the index. To be able to quickly 34 * cast from the nsINode pointer to a nsIDocument or nsIContent pointer we 35 * actually use 2 different flag values (see txXPathNode::PositionType). 36 * 37 * We provide 2 fast constructors for txXPathNode, one that takes a nsIContent 38 * and one that takes a nsIDocument, since for those kinds of nodes we can 39 * simply store the pointer and the relevant flag value. For attribute nodes, or 40 * if you have just a nsINode pointer, then there is a helper function 41 * (txXPathNativeNode::createXPathNode) that either picks the right flag value 42 * or the correct index (for attribute nodes) when creating the txXPathNode. 43 */ 44 class txXPathNode { 45 public: 46 explicit txXPathNode(const txXPathNode& aNode) 47 : mNode(aNode.mNode), mIndex(aNode.mIndex) { 48 MOZ_COUNT_CTOR(txXPathNode); 49 } 50 txXPathNode(txXPathNode&& aNode) 51 : mNode(std::move(aNode.mNode)), mIndex(aNode.mIndex) { 52 MOZ_COUNT_CTOR(txXPathNode); 53 } 54 55 explicit txXPathNode(mozilla::dom::Document* aDocument) 56 : mNode(aDocument), mIndex(eDocument) { 57 MOZ_COUNT_CTOR(txXPathNode); 58 } 59 explicit txXPathNode(nsIContent* aContent) 60 : mNode(aContent), mIndex(eContent) { 61 MOZ_COUNT_CTOR(txXPathNode); 62 } 63 64 txXPathNode& operator=(txXPathNode&& aOther) = default; 65 bool operator==(const txXPathNode& aNode) const; 66 bool operator!=(const txXPathNode& aNode) const { return !(*this == aNode); } 67 ~txXPathNode() { MOZ_COUNT_DTOR(txXPathNode); } 68 69 mozilla::dom::Document* OwnerDoc() const { return mNode->OwnerDoc(); } 70 71 private: 72 friend class txXPathNativeNode; 73 friend class txXPathNodeUtils; 74 friend class txXPathTreeWalker; 75 76 txXPathNode(nsINode* aNode, uint32_t aIndex) : mNode(aNode), mIndex(aIndex) { 77 MOZ_COUNT_CTOR(txXPathNode); 78 } 79 80 static nsINode* RootOf(nsINode* aNode) { return aNode->SubtreeRoot(); } 81 nsINode* Root() const { return RootOf(mNode); } 82 83 bool isDocument() const { return mIndex == eDocument; } 84 bool isContent() const { return mIndex == eContent; } 85 bool isAttribute() const { return mIndex != eDocument && mIndex != eContent; } 86 87 nsIContent* Content() const { 88 NS_ASSERTION(isContent() || isAttribute(), "wrong type"); 89 return static_cast<nsIContent*>(mNode.get()); 90 } 91 mozilla::dom::Document* Document() const { 92 NS_ASSERTION(isDocument(), "wrong type"); 93 return static_cast<mozilla::dom::Document*>(mNode.get()); 94 } 95 96 enum PositionType : uint32_t { 97 eDocument = UINT32_MAX, 98 eContent = eDocument - 1 99 }; 100 101 nsCOMPtr<nsINode> mNode; 102 uint32_t mIndex; 103 }; 104 105 class txNamespaceManager { 106 public: 107 static int32_t getNamespaceID(const nsAString& aNamespaceURI); 108 static nsresult getNamespaceURI(const int32_t aID, nsAString& aResult); 109 }; 110 111 /* static */ 112 inline int32_t txNamespaceManager::getNamespaceID( 113 const nsAString& aNamespaceURI) { 114 int32_t namespaceID = kNameSpaceID_Unknown; 115 nsNameSpaceManager::GetInstance()->RegisterNameSpace(aNamespaceURI, 116 namespaceID); 117 return namespaceID; 118 } 119 120 /* static */ 121 inline nsresult txNamespaceManager::getNamespaceURI(const int32_t aID, 122 nsAString& aResult) { 123 return nsNameSpaceManager::GetInstance()->GetNameSpaceURI(aID, aResult); 124 } 125 126 inline bool txXPathNode::operator==(const txXPathNode& aNode) const { 127 return mIndex == aNode.mIndex && mNode == aNode.mNode; 128 } 129 130 #endif /* txXPathNode_h__ */