Avoid redundant isElementNode() checks in Traversal<HTML*Element> / Traversal<SVG...
[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
56     // Next or previous ElementType sibling if there is one.
57     static ElementType* nextSibling(const Node*);
58     static ElementType* previousSibling(const Node*);
59
60     // Like next, but skips children.
61     static ElementType* nextSkippingChildren(const Node*);
62     static ElementType* nextSkippingChildren(const Node*, const Node* stayWithin);
63
64 private:
65     template <typename CurrentType> static ElementType* firstChildTemplate(CurrentType*);
66     template <typename CurrentType> static ElementType* lastChildTemplate(CurrentType*);
67     template <typename CurrentType> static ElementType* firstWithinTemplate(CurrentType*);
68     template <typename CurrentType> static ElementType* lastWithinTemplate(CurrentType*);
69     template <typename CurrentType> static ElementType* nextTemplate(CurrentType*);
70     template <typename CurrentType> static ElementType* nextTemplate(CurrentType*, const Node* stayWithin);
71 };
72
73 class ElementTraversal : public Traversal<Element> {
74 public:
75     // FIXME: These should go somewhere else.
76     // Pre-order traversal including the pseudo-elements.
77     static Element* previousIncludingPseudo(const Node*, const Node* = 0);
78     static Element* nextIncludingPseudo(const Node*, const Node* = 0);
79     static Element* nextIncludingPseudoSkippingChildren(const Node*, const Node* = 0);
80
81     // Utility function to traverse only the element and pseudo-element siblings of a node.
82     static Element* pseudoAwarePreviousSibling(const Node*);
83 };
84
85 // Specialized for pure Element to exploit the fact that Elements parent is always either another Element or the root.
86 template <>
87 template <typename CurrentType>
88 inline Element* Traversal<Element>::firstWithinTemplate(CurrentType* current)
89 {
90     return firstChildTemplate(current);
91 }
92
93 template <>
94 template <typename CurrentType>
95 inline Element* Traversal<Element>::nextTemplate(CurrentType* current)
96 {
97     Node* node = NodeTraversal::next(current);
98     while (node && !node->isElementNode())
99         node = NodeTraversal::nextSkippingChildren(node);
100     return toElement(node);
101 }
102
103 template <>
104 template <typename CurrentType>
105 inline Element* Traversal<Element>::nextTemplate(CurrentType* current, const Node* stayWithin)
106 {
107     Node* node = NodeTraversal::next(current, stayWithin);
108     while (node && !node->isElementNode())
109         node = NodeTraversal::nextSkippingChildren(node, stayWithin);
110     return toElement(node);
111 }
112
113 // Generic versions.
114 template <typename ElementType>
115 template <typename CurrentType>
116 inline ElementType* Traversal<ElementType>::firstChildTemplate(CurrentType* current)
117 {
118     Node* node = current->firstChild();
119     while (node && !isElementOfType<const ElementType>(*node))
120         node = node->nextSibling();
121     return static_cast<ElementType*>(node);
122 }
123
124 template <typename ElementType>
125 template <typename CurrentType>
126 inline ElementType* Traversal<ElementType>::lastChildTemplate(CurrentType* current)
127 {
128     Node* node = current->lastChild();
129     while (node && !isElementOfType<const ElementType>(*node))
130         node = node->previousSibling();
131     return static_cast<ElementType*>(node);
132 }
133
134 template <typename ElementType>
135 template <typename CurrentType>
136 inline ElementType* Traversal<ElementType>::firstWithinTemplate(CurrentType* current)
137 {
138     Node* node = current->firstChild();
139     while (node && !isElementOfType<const ElementType>(*node))
140         node = NodeTraversal::next(node, current);
141     return static_cast<ElementType*>(node);
142 }
143
144 template <typename ElementType>
145 template <typename CurrentType>
146 inline ElementType* Traversal<ElementType>::lastWithinTemplate(CurrentType* current)
147 {
148     Node* node = NodeTraversal::last(current);
149     while (node && !isElementOfType<const ElementType>(*node))
150         node = NodeTraversal::previous(node, current);
151     return static_cast<ElementType*>(node);
152 }
153
154 template <typename ElementType>
155 template <typename CurrentType>
156 inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType* current)
157 {
158     Node* node = NodeTraversal::next(current);
159     while (node && !isElementOfType<const ElementType>(*node))
160         node = NodeTraversal::next(node);
161     return static_cast<ElementType*>(node);
162 }
163
164 template <typename ElementType>
165 template <typename CurrentType>
166 inline ElementType* Traversal<ElementType>::nextTemplate(CurrentType* current, const Node* stayWithin)
167 {
168     Node* node = NodeTraversal::next(current, stayWithin);
169     while (node && !isElementOfType<const ElementType>(*node))
170         node = NodeTraversal::next(node, stayWithin);
171     return static_cast<ElementType*>(node);
172 }
173
174 template <typename ElementType>
175 inline ElementType* Traversal<ElementType>::previous(const Node* current)
176 {
177     Node* node = NodeTraversal::previous(current);
178     while (node && !isElementOfType<const ElementType>(*node))
179         node = NodeTraversal::previous(node);
180     return static_cast<ElementType*>(node);
181 }
182
183 template <typename ElementType>
184 inline ElementType* Traversal<ElementType>::previous(const Node* current, const Node* stayWithin)
185 {
186     Node* node = NodeTraversal::previous(current, stayWithin);
187     while (node && !isElementOfType<const ElementType>(*node))
188         node = NodeTraversal::previous(node, stayWithin);
189     return static_cast<ElementType*>(node);
190 }
191
192 template <typename ElementType>
193 inline ElementType* Traversal<ElementType>::nextSibling(const Node* current)
194 {
195     Node* node = current->nextSibling();
196     while (node && !isElementOfType<const ElementType>(*node))
197         node = node->nextSibling();
198     return static_cast<ElementType*>(node);
199 }
200
201 template <typename ElementType>
202 inline ElementType* Traversal<ElementType>::previousSibling(const Node* current)
203 {
204     Node* node = current->previousSibling();
205     while (node && !isElementOfType<const ElementType>(*node))
206         node = node->previousSibling();
207     return static_cast<ElementType*>(node);
208 }
209
210 template <typename ElementType>
211 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node* current)
212 {
213     Node* node = NodeTraversal::nextSkippingChildren(current);
214     while (node && !isElementOfType<const ElementType>(*node))
215         node = NodeTraversal::nextSkippingChildren(node);
216     return static_cast<ElementType*>(node);
217 }
218
219 template <typename ElementType>
220 inline ElementType* Traversal<ElementType>::nextSkippingChildren(const Node* current, const Node* stayWithin)
221 {
222     Node* node = NodeTraversal::nextSkippingChildren(current, stayWithin);
223     while (node && !isElementOfType<const ElementType>(*node))
224         node = NodeTraversal::nextSkippingChildren(node, stayWithin);
225     return static_cast<ElementType*>(node);
226 }
227
228 template <typename ElementType>
229 inline ElementType* Traversal<ElementType>::firstChild(const ContainerNode* current) { return firstChildTemplate(current); }
230 template <typename ElementType>
231 inline ElementType* Traversal<ElementType>::firstChild(const Node* current) { return firstChildTemplate(current); }
232 template <typename ElementType>
233
234 inline ElementType* Traversal<ElementType>::lastChild(const ContainerNode* current) { return lastChildTemplate(current); }
235 template <typename ElementType>
236 inline ElementType* Traversal<ElementType>::lastChild(const Node* current) { return lastChildTemplate(current); }
237
238 template <typename ElementType>
239 inline ElementType* Traversal<ElementType>::firstWithin(const ContainerNode* current) { return firstWithinTemplate(current); }
240 template <typename ElementType>
241 inline ElementType* Traversal<ElementType>::firstWithin(const Node* current) { return firstWithinTemplate(current); }
242 template <typename ElementType>
243
244 inline ElementType* Traversal<ElementType>::lastWithin(const ContainerNode* current) { return lastWithinTemplate(current); }
245 template <typename ElementType>
246 inline ElementType* Traversal<ElementType>::lastWithin(const Node* current) { return lastWithinTemplate(current); }
247
248 template <typename ElementType>
249 inline ElementType* Traversal<ElementType>::next(const ContainerNode* current) { return nextTemplate(current); }
250 template <typename ElementType>
251 inline ElementType* Traversal<ElementType>::next(const Node* current) { return nextTemplate(current); }
252 template <typename ElementType>
253 inline ElementType* Traversal<ElementType>::next(const ContainerNode* current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
254 template <typename ElementType>
255 inline ElementType* Traversal<ElementType>::next(const Node* current, const Node* stayWithin) { return nextTemplate(current, stayWithin); }
256
257 // FIXME: These should go somewhere else.
258 inline Element* ElementTraversal::previousIncludingPseudo(const Node* current, const Node* stayWithin)
259 {
260     Node* node = NodeTraversal::previousIncludingPseudo(current, stayWithin);
261     while (node && !node->isElementNode())
262         node = NodeTraversal::previousIncludingPseudo(node, stayWithin);
263     return toElement(node);
264 }
265
266 inline Element* ElementTraversal::nextIncludingPseudo(const Node* current, const Node* stayWithin)
267 {
268     Node* node = NodeTraversal::nextIncludingPseudo(current, stayWithin);
269     while (node && !node->isElementNode())
270         node = NodeTraversal::nextIncludingPseudo(node, stayWithin);
271     return toElement(node);
272 }
273
274 inline Element* ElementTraversal::nextIncludingPseudoSkippingChildren(const Node* current, const Node* stayWithin)
275 {
276     Node* node = NodeTraversal::nextIncludingPseudoSkippingChildren(current, stayWithin);
277     while (node && !node->isElementNode())
278         node = NodeTraversal::nextIncludingPseudoSkippingChildren(node, stayWithin);
279     return toElement(node);
280 }
281
282 inline Element* ElementTraversal::pseudoAwarePreviousSibling(const Node* current)
283 {
284     Node* node = current->pseudoAwarePreviousSibling();
285     while (node && !node->isElementNode())
286         node = node->pseudoAwarePreviousSibling();
287     return toElement(node);
288 }
289
290 }
291
292 #endif