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