Drop NodeTraversal::nextSkippingChildren() overload taking a ContainerNode
[WebKit-https.git] / Source / WebCore / dom / ElementTraversal.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
6  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #ifndef ElementTraversal_h
26 #define ElementTraversal_h
27
28 #include "Element.h"
29 #include "NodeTraversal.h"
30
31 namespace WebCore {
32
33 template <typename ElementType>
34 class Traversal {
35 public:
36     // First or last ElementType child of the node.
37     static ElementType* firstChild(const Node*);
38     static ElementType* firstChild(const ContainerNode*);
39     static ElementType* lastChild(const Node*);
40     static ElementType* lastChild(const ContainerNode*);
41
42     // First or last ElementType descendant of the node. For Elements firstWithin is always the same as first child.
43     static ElementType* firstWithin(const Node*);
44     static ElementType* firstWithin(const ContainerNode*);
45     static ElementType* lastWithin(const Node*);
46     static ElementType* lastWithin(const ContainerNode*);
47
48     // Pre-order traversal skipping non-ElementType nodes.
49     static ElementType* next(const Node*);
50     static ElementType* next(const Node*, const Node* stayWithin);
51     static ElementType* next(const ContainerNode*);
52     static ElementType* next(const ContainerNode*, const Node* stayWithin);
53     static ElementType* previous(const Node*);
54     static ElementType* previous(const Node*, const Node* stayWithin);
55     static ElementType* previous(const ContainerNode*);
56     static ElementType* previous(const ContainerNode*, const Node* stayWithin);
57
58     // Next or previous ElementType sibling if there is one.
59     static ElementType* nextSibling(const Node*);
60     static ElementType* nextSibling(const ContainerNode*);
61     static ElementType* previousSibling(const Node*);
62     static ElementType* previousSibling(const ContainerNode*);
63
64     // Like next, but skips children.
65     static ElementType* nextSkippingChildren(const Node*);
66     static ElementType* nextSkippingChildren(const Node*, const Node* stayWithin);
67
68 private:
69     template <typename CurrentType> static ElementType* firstChildTemplate(CurrentType*);
70     template <typename CurrentType> static ElementType* lastChildTemplate(CurrentType*);
71     template <typename CurrentType> static ElementType* firstWithinTemplate(CurrentType*);
72     template <typename CurrentType> static ElementType* lastWithinTemplate(CurrentType*);
73     template <typename CurrentType> static ElementType* nextTemplate(CurrentType*);
74     template <typename CurrentType> static ElementType* nextTemplate(CurrentType*, const Node* stayWithin);
75     template <typename CurrentType> static ElementType* previousTemplate(CurrentType*);
76     template <typename CurrentType> static ElementType* previousTemplate(CurrentType*, const Node* stayWithin);
77     template <typename CurrentType> static ElementType* nextSiblingTemplate(CurrentType*);
78     template <typename CurrentType> static ElementType* previousSiblingTemplate(CurrentType*);
79 };
80
81 class ElementTraversal : public Traversal<Element> {
82 public:
83     // FIXME: These should go somewhere else.
84     // Pre-order traversal including the pseudo-elements.
85     static Element* previousIncludingPseudo(const Node*, const Node* = 0);
86     static Element* nextIncludingPseudo(const Node*, const Node* = 0);
87     static Element* nextIncludingPseudoSkippingChildren(const Node*, const Node* = 0);
88
89     // Utility function to traverse only the element and pseudo-element siblings of a node.
90     static Element* pseudoAwarePreviousSibling(const Node*);
91 };
92
93 // Specialized for pure Element to exploit the fact that Elements parent is always either another Element or the root.
94 template <>
95 template <typename CurrentType>
96 inline Element* Traversal<Element>::firstWithinTemplate(CurrentType* current)
97 {
98     return firstChildTemplate(current);
99 }
100
101 template <>
102 template <typename CurrentType>
103 inline Element* Traversal<Element>::lastWithinTemplate(CurrentType* current)
104 {
105     Node* node = NodeTraversal::last(current);
106     while (node && !node->isElementNode())
107         node = NodeTraversal::previous(node, current);
108     return toElement(node);
109 }
110
111 template <>
112 template <typename CurrentType>
113 inline Element* Traversal<Element>::nextTemplate(CurrentType* current)
114 {
115     Node* node = NodeTraversal::next(current);
116     while (node && !node->isElementNode())
117         node = NodeTraversal::nextSkippingChildren(node);
118     return toElement(node);
119 }
120
121 template <>
122 template <typename CurrentType>
123 inline Element* Traversal<Element>::nextTemplate(CurrentType* current, const Node* stayWithin)
124 {
125     Node* node = NodeTraversal::next(current, stayWithin);
126     while (node && !node->isElementNode())
127         node = NodeTraversal::nextSkippingChildren(node, stayWithin);
128     return toElement(node);
129 }
130
131 template <>
132 template <typename CurrentType>
133 inline Element* Traversal<Element>::previousTemplate(CurrentType* current)
134 {
135     Node* node = NodeTraversal::previous(current);
136     while (node && !node->isElementNode())
137         node = NodeTraversal::previous(node);
138     return toElement(node);
139 }
140
141 template <>
142 template <typename CurrentType>
143 inline Element* Traversal<Element>::previousTemplate(CurrentType* current, const Node* stayWithin)
144 {
145     Node* node = NodeTraversal::previous(current, stayWithin);
146     while (node && !node->isElementNode())
147         node = NodeTraversal::previous(node, stayWithin);
148     return toElement(node);
149 }
150
151 // Generic versions.
152 template <typename ElementType>
153 template <typename CurrentType>
154 inline ElementType* Traversal<ElementType>::firstChildTemplate(CurrentType* current)
155 {
156     Node* node = current->firstChild();
157     while (node && !isElementOfType<const ElementType>(*node))
158         node = node->nextSibling();
159     return static_cast<ElementType*>(node);
160 }
161
162 template <typename ElementType>
163 template <typename CurrentType>
164 inline ElementType* Traversal<ElementType>::lastChildTemplate(CurrentType* current)
165 {
166     Node* node = current->lastChild();
167     while (node && !isElementOfType<const ElementType>(*node))
168         node = node->previousSibling();
169     return static_cast<ElementType*>(node);
170 }
171
172 template <typename ElementType>
173 template <typename CurrentType>
174 inline ElementType* Traversal<ElementType>::firstWithinTemplate(CurrentType* current)
175 {
176     Element* element = Traversal<Element>::firstWithin(current);
177     while (element && !isElementOfType<const ElementType>(*element))
178         element = Traversal<Element>::next(element, current);
179     return static_cast<ElementType*>(element);
180 }
181
182 template <typename ElementType>
183 template <typename CurrentType>
184 inline ElementType* Traversal<ElementType>::lastWithinTemplate(CurrentType* current)
185 {
186     Element* element = Traversal<Element>::lastWithin(current);
187     while (element && !isElementOfType<const ElementType>(*element))
188         element = Traversal<Element>::previous(element, current);
189     return static_cast<ElementType*>(element);
190 }
191
192 template <typename ElementType>
193 template <typename CurrentType>
194 inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType* current)
195 {
196     Element* element = Traversal<Element>::next(current);
197     while (element && !isElementOfType<const ElementType>(*element))
198         element = Traversal<Element>::next(element);
199     return static_cast<ElementType*>(element);
200 }
201
202 template <typename ElementType>
203 template <typename CurrentType>
204 inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType* current, const Node* stayWithin)
205 {
206     Element* element = Traversal<Element>::next(current, stayWithin);
207     while (element && !isElementOfType<const ElementType>(*element))
208         element = Traversal<Element>::next(element, stayWithin);
209     return static_cast<ElementType*>(element);
210 }
211
212 template <typename ElementType>
213 template <typename CurrentType>
214 inline ElementType* Traversal<ElementType>::previousTemplate(CurrentType* current)
215 {
216     Element* element = Traversal<Element>::previous(current);
217     while (element && !isElementOfType<const ElementType>(*element))
218         element = Traversal<Element>::previous(element);
219     return static_cast<ElementType*>(element);
220 }
221
222 template <typename ElementType>
223 template <typename CurrentType>
224 inline ElementType* Traversal<ElementType>::previousTemplate(CurrentType* current, const Node* stayWithin)
225 {
226     Element* element = Traversal<Element>::previous(current, stayWithin);
227     while (element && !isElementOfType<const ElementType>(*element))
228         element = Traversal<Element>::previous(element, stayWithin);
229     return static_cast<ElementType*>(element);
230 }
231
232 template <typename ElementType>
233 template <typename CurrentType>
234 inline ElementType* Traversal<ElementType>::nextSiblingTemplate(CurrentType* current)
235 {
236     Node* node = current->nextSibling();
237     while (node && !isElementOfType<const ElementType>(*node))
238         node = node->nextSibling();
239     return static_cast<ElementType*>(node);
240 }
241
242 template <typename ElementType>
243 template <typename CurrentType>
244 inline ElementType* Traversal<ElementType>::previousSiblingTemplate(CurrentType* current)
245 {
246     Node* node = current->previousSibling();
247     while (node && !isElementOfType<const ElementType>(*node))
248         node = node->previousSibling();
249     return static_cast<ElementType*>(node);
250 }
251
252 template <typename ElementType>
253 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node* current)
254 {
255     Node* node = NodeTraversal::nextSkippingChildren(current);
256     while (node && !isElementOfType<const ElementType>(*node))
257         node = NodeTraversal::nextSkippingChildren(node);
258     return static_cast<ElementType*>(node);
259 }
260
261 template <typename ElementType>
262 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node* current, const Node* stayWithin)
263 {
264     Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
265     while (node && !isElementOfType<const ElementType>(*node))
266         node = NodeTraversal::nextSkippingChildren(node, stayWithin);
267     return static_cast<ElementType*>(node);
268 }
269
270 template <typename ElementType>
271 inline ElementType* Traversal<ElementType>::firstChild(const ContainerNode* current) { return firstChildTemplate(current); }
272 template <typename ElementType>
273 inline ElementType* Traversal<ElementType>::firstChild(const Node* current) { return firstChildTemplate(current); }
274 template <typename ElementType>
275
276 inline ElementType* Traversal<ElementType>::lastChild(const ContainerNode* current) { return lastChildTemplate(current); }
277 template <typename ElementType>
278 inline ElementType* Traversal<ElementType>::lastChild(const Node* current) { return lastChildTemplate(current); }
279
280 template <typename ElementType>
281 inline ElementType* Traversal<ElementType>::firstWithin(const ContainerNode* current) { return firstWithinTemplate(current); }
282 template <typename ElementType>
283 inline ElementType* Traversal<ElementType>::firstWithin(const Node* current) { return firstWithinTemplate(current); }
284 template <typename ElementType>
285
286 inline ElementType* Traversal<ElementType>::lastWithin(const ContainerNode* current) { return lastWithinTemplate(current); }
287 template <typename ElementType>
288 inline ElementType* Traversal<ElementType>::lastWithin(const Node* current) { return lastWithinTemplate(current); }
289
290 template <typename ElementType>
291 inline ElementType* Traversal<ElementType>::next(const ContainerNode* current) { return nextTemplate(current); }
292 template <typename ElementType>
293 inline ElementType* Traversal<ElementType>::next(const Node* current) { return nextTemplate(current); }
294 template <typename ElementType>
295 inline ElementType* Traversal<ElementType>::next(const ContainerNode* current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
296 template <typename ElementType>
297 inline ElementType* Traversal<ElementType>::next(const Node* current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
298
299 template <typename ElementType>
300 inline ElementType* Traversal<ElementType>::previous(const ContainerNode* current) { return previousTemplate(current); }
301 template <typename ElementType>
302 inline ElementType* Traversal<ElementType>::previous(const Node* current) { return previousTemplate(current); }
303 template <typename ElementType>
304 inline ElementType* Traversal<ElementType>::previous(const ContainerNode* current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
305 template <typename ElementType>
306 inline ElementType* Traversal<ElementType>::previous(const Node* current, const Node* stayWithin) { return previousTemplate(current, stayWithin); }
307
308 template <typename ElementType>
309 inline ElementType* Traversal<ElementType>::nextSibling(const ContainerNode* current) { return nextSiblingTemplate(current); }
310 template <typename ElementType>
311 inline ElementType* Traversal<ElementType>::nextSibling(const Node* current) { return nextSiblingTemplate(current); }
312
313 template <typename ElementType>
314 inline ElementType* Traversal<ElementType>::previousSibling(const ContainerNode* current) { return previousSiblingTemplate(current); }
315 template <typename ElementType>
316 inline ElementType* Traversal<ElementType>::previousSibling(const Node* current) { return previousSiblingTemplate(current); }
317
318 // FIXME: These should go somewhere else.
319 inline Element* ElementTraversal::previousIncludingPseudo(const Node* current, const Node* stayWithin)
320 {
321     Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
322     while (node && !node->isElementNode())
323         node = NodeTraversal::previousIncludingPseudo(node, stayWithin);
324     return toElement(node);
325 }
326
327 inline Element* ElementTraversal::nextIncludingPseudo(const Node* current, const Node* stayWithin)
328 {
329     Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
330     while (node && !node->isElementNode())
331         node = NodeTraversal::nextIncludingPseudo(node, stayWithin);
332     return toElement(node);
333 }
334
335 inline Element* ElementTraversal::nextIncludingPseudoSkippingChildren(const Node* current, const Node* stayWithin)
336 {
337     Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
338     while (node && !node->isElementNode())
339         node = NodeTraversal::nextIncludingPseudoSkippingChildren(node, stayWithin);
340     return toElement(node);
341 }
342
343 inline Element* ElementTraversal::pseudoAwarePreviousSibling(const Node* current)
344 {
345     Node* node = current->pseudoAwarePreviousSibling();
346     while (node && !node->isElementNode())
347         node = node->pseudoAwarePreviousSibling();
348     return toElement(node);
349 }
350
351 }
352
353 #endif