|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
|
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 txXPathTreeWalker_h__ |
|
7 #define txXPathTreeWalker_h__ |
|
8 |
|
9 #include "txCore.h" |
|
10 #include "txXPathNode.h" |
|
11 #include "nsIContentInlines.h" |
|
12 #include "nsINodeInfo.h" |
|
13 #include "nsTArray.h" |
|
14 |
|
15 class nsIAtom; |
|
16 class nsIDOMDocument; |
|
17 |
|
18 class txUint32Array : public nsTArray<uint32_t> |
|
19 { |
|
20 public: |
|
21 bool AppendValue(uint32_t aValue) |
|
22 { |
|
23 return AppendElement(aValue) != nullptr; |
|
24 } |
|
25 bool RemoveValueAt(uint32_t aIndex) |
|
26 { |
|
27 if (aIndex < Length()) { |
|
28 RemoveElementAt(aIndex); |
|
29 } |
|
30 return true; |
|
31 } |
|
32 uint32_t ValueAt(uint32_t aIndex) const |
|
33 { |
|
34 return (aIndex < Length()) ? ElementAt(aIndex) : 0; |
|
35 } |
|
36 }; |
|
37 |
|
38 class txXPathTreeWalker |
|
39 { |
|
40 public: |
|
41 txXPathTreeWalker(const txXPathTreeWalker& aOther); |
|
42 explicit txXPathTreeWalker(const txXPathNode& aNode); |
|
43 |
|
44 bool getAttr(nsIAtom* aLocalName, int32_t aNSID, nsAString& aValue) const; |
|
45 int32_t getNamespaceID() const; |
|
46 uint16_t getNodeType() const; |
|
47 void appendNodeValue(nsAString& aResult) const; |
|
48 void getNodeName(nsAString& aName) const; |
|
49 |
|
50 void moveTo(const txXPathTreeWalker& aWalker); |
|
51 |
|
52 void moveToRoot(); |
|
53 bool moveToParent(); |
|
54 bool moveToElementById(const nsAString& aID); |
|
55 bool moveToFirstAttribute(); |
|
56 bool moveToNextAttribute(); |
|
57 bool moveToNamedAttribute(nsIAtom* aLocalName, int32_t aNSID); |
|
58 bool moveToFirstChild(); |
|
59 bool moveToLastChild(); |
|
60 bool moveToNextSibling(); |
|
61 bool moveToPreviousSibling(); |
|
62 |
|
63 bool isOnNode(const txXPathNode& aNode) const; |
|
64 |
|
65 const txXPathNode& getCurrentPosition() const; |
|
66 |
|
67 private: |
|
68 txXPathNode mPosition; |
|
69 |
|
70 bool moveToValidAttribute(uint32_t aStartIndex); |
|
71 bool moveToSibling(int32_t aDir); |
|
72 |
|
73 uint32_t mCurrentIndex; |
|
74 txUint32Array mDescendants; |
|
75 }; |
|
76 |
|
77 class txXPathNodeUtils |
|
78 { |
|
79 public: |
|
80 static bool getAttr(const txXPathNode& aNode, nsIAtom* aLocalName, |
|
81 int32_t aNSID, nsAString& aValue); |
|
82 static already_AddRefed<nsIAtom> getLocalName(const txXPathNode& aNode); |
|
83 static nsIAtom* getPrefix(const txXPathNode& aNode); |
|
84 static void getLocalName(const txXPathNode& aNode, nsAString& aLocalName); |
|
85 static void getNodeName(const txXPathNode& aNode, |
|
86 nsAString& aName); |
|
87 static int32_t getNamespaceID(const txXPathNode& aNode); |
|
88 static void getNamespaceURI(const txXPathNode& aNode, nsAString& aURI); |
|
89 static uint16_t getNodeType(const txXPathNode& aNode); |
|
90 static void appendNodeValue(const txXPathNode& aNode, nsAString& aResult); |
|
91 static bool isWhitespace(const txXPathNode& aNode); |
|
92 static txXPathNode* getOwnerDocument(const txXPathNode& aNode); |
|
93 static int32_t getUniqueIdentifier(const txXPathNode& aNode); |
|
94 static nsresult getXSLTId(const txXPathNode& aNode, |
|
95 const txXPathNode& aBase, nsAString& aResult); |
|
96 static void release(txXPathNode* aNode); |
|
97 static void getBaseURI(const txXPathNode& aNode, nsAString& aURI); |
|
98 static int comparePosition(const txXPathNode& aNode, |
|
99 const txXPathNode& aOtherNode); |
|
100 static bool localNameEquals(const txXPathNode& aNode, |
|
101 nsIAtom* aLocalName); |
|
102 static bool isRoot(const txXPathNode& aNode); |
|
103 static bool isElement(const txXPathNode& aNode); |
|
104 static bool isAttribute(const txXPathNode& aNode); |
|
105 static bool isProcessingInstruction(const txXPathNode& aNode); |
|
106 static bool isComment(const txXPathNode& aNode); |
|
107 static bool isText(const txXPathNode& aNode); |
|
108 static inline bool isHTMLElementInHTMLDocument(const txXPathNode& aNode) |
|
109 { |
|
110 if (!aNode.isContent()) { |
|
111 return false; |
|
112 } |
|
113 nsIContent* content = aNode.Content(); |
|
114 return content->IsHTML() && content->IsInHTMLDocument(); |
|
115 } |
|
116 }; |
|
117 |
|
118 class txXPathNativeNode |
|
119 { |
|
120 public: |
|
121 static txXPathNode* createXPathNode(nsIDOMNode* aNode, |
|
122 bool aKeepRootAlive = false); |
|
123 static txXPathNode* createXPathNode(nsIContent* aContent, |
|
124 bool aKeepRootAlive = false); |
|
125 static txXPathNode* createXPathNode(nsIDOMDocument* aDocument); |
|
126 static nsresult getNode(const txXPathNode& aNode, nsIDOMNode** aResult); |
|
127 static nsIContent* getContent(const txXPathNode& aNode); |
|
128 static nsIDocument* getDocument(const txXPathNode& aNode); |
|
129 static void addRef(const txXPathNode& aNode) |
|
130 { |
|
131 NS_ADDREF(aNode.mNode); |
|
132 } |
|
133 static void release(const txXPathNode& aNode) |
|
134 { |
|
135 nsINode *node = aNode.mNode; |
|
136 NS_RELEASE(node); |
|
137 } |
|
138 }; |
|
139 |
|
140 inline const txXPathNode& |
|
141 txXPathTreeWalker::getCurrentPosition() const |
|
142 { |
|
143 return mPosition; |
|
144 } |
|
145 |
|
146 inline bool |
|
147 txXPathTreeWalker::getAttr(nsIAtom* aLocalName, int32_t aNSID, |
|
148 nsAString& aValue) const |
|
149 { |
|
150 return txXPathNodeUtils::getAttr(mPosition, aLocalName, aNSID, aValue); |
|
151 } |
|
152 |
|
153 inline int32_t |
|
154 txXPathTreeWalker::getNamespaceID() const |
|
155 { |
|
156 return txXPathNodeUtils::getNamespaceID(mPosition); |
|
157 } |
|
158 |
|
159 inline void |
|
160 txXPathTreeWalker::appendNodeValue(nsAString& aResult) const |
|
161 { |
|
162 txXPathNodeUtils::appendNodeValue(mPosition, aResult); |
|
163 } |
|
164 |
|
165 inline void |
|
166 txXPathTreeWalker::getNodeName(nsAString& aName) const |
|
167 { |
|
168 txXPathNodeUtils::getNodeName(mPosition, aName); |
|
169 } |
|
170 |
|
171 inline void |
|
172 txXPathTreeWalker::moveTo(const txXPathTreeWalker& aWalker) |
|
173 { |
|
174 nsINode *root = nullptr; |
|
175 if (mPosition.mRefCountRoot) { |
|
176 root = mPosition.Root(); |
|
177 } |
|
178 mPosition.mIndex = aWalker.mPosition.mIndex; |
|
179 mPosition.mRefCountRoot = aWalker.mPosition.mRefCountRoot; |
|
180 mPosition.mNode = aWalker.mPosition.mNode; |
|
181 nsINode *newRoot = nullptr; |
|
182 if (mPosition.mRefCountRoot) { |
|
183 newRoot = mPosition.Root(); |
|
184 } |
|
185 if (root != newRoot) { |
|
186 NS_IF_ADDREF(newRoot); |
|
187 NS_IF_RELEASE(root); |
|
188 } |
|
189 |
|
190 mCurrentIndex = aWalker.mCurrentIndex; |
|
191 mDescendants.Clear(); |
|
192 } |
|
193 |
|
194 inline bool |
|
195 txXPathTreeWalker::isOnNode(const txXPathNode& aNode) const |
|
196 { |
|
197 return (mPosition == aNode); |
|
198 } |
|
199 |
|
200 /* static */ |
|
201 inline int32_t |
|
202 txXPathNodeUtils::getUniqueIdentifier(const txXPathNode& aNode) |
|
203 { |
|
204 NS_PRECONDITION(!aNode.isAttribute(), |
|
205 "Not implemented for attributes."); |
|
206 return NS_PTR_TO_INT32(aNode.mNode); |
|
207 } |
|
208 |
|
209 /* static */ |
|
210 inline void |
|
211 txXPathNodeUtils::release(txXPathNode* aNode) |
|
212 { |
|
213 NS_RELEASE(aNode->mNode); |
|
214 } |
|
215 |
|
216 /* static */ |
|
217 inline bool |
|
218 txXPathNodeUtils::localNameEquals(const txXPathNode& aNode, |
|
219 nsIAtom* aLocalName) |
|
220 { |
|
221 if (aNode.isContent() && |
|
222 aNode.Content()->IsElement()) { |
|
223 return aNode.Content()->NodeInfo()->Equals(aLocalName); |
|
224 } |
|
225 |
|
226 nsCOMPtr<nsIAtom> localName = txXPathNodeUtils::getLocalName(aNode); |
|
227 |
|
228 return localName == aLocalName; |
|
229 } |
|
230 |
|
231 /* static */ |
|
232 inline bool |
|
233 txXPathNodeUtils::isRoot(const txXPathNode& aNode) |
|
234 { |
|
235 return !aNode.isAttribute() && !aNode.mNode->GetParentNode(); |
|
236 } |
|
237 |
|
238 /* static */ |
|
239 inline bool |
|
240 txXPathNodeUtils::isElement(const txXPathNode& aNode) |
|
241 { |
|
242 return aNode.isContent() && |
|
243 aNode.Content()->IsElement(); |
|
244 } |
|
245 |
|
246 |
|
247 /* static */ |
|
248 inline bool |
|
249 txXPathNodeUtils::isAttribute(const txXPathNode& aNode) |
|
250 { |
|
251 return aNode.isAttribute(); |
|
252 } |
|
253 |
|
254 /* static */ |
|
255 inline bool |
|
256 txXPathNodeUtils::isProcessingInstruction(const txXPathNode& aNode) |
|
257 { |
|
258 return aNode.isContent() && |
|
259 aNode.Content()->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION); |
|
260 } |
|
261 |
|
262 /* static */ |
|
263 inline bool |
|
264 txXPathNodeUtils::isComment(const txXPathNode& aNode) |
|
265 { |
|
266 return aNode.isContent() && |
|
267 aNode.Content()->IsNodeOfType(nsINode::eCOMMENT); |
|
268 } |
|
269 |
|
270 /* static */ |
|
271 inline bool |
|
272 txXPathNodeUtils::isText(const txXPathNode& aNode) |
|
273 { |
|
274 return aNode.isContent() && |
|
275 aNode.Content()->IsNodeOfType(nsINode::eTEXT); |
|
276 } |
|
277 |
|
278 #endif /* txXPathTreeWalker_h__ */ |