1/*
2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include "RenderElement.h"
29
30namespace WebCore {
31
32class RenderText;
33
34template <typename T>
35class RenderIterator {
36public:
37 RenderIterator(const RenderElement* root);
38 RenderIterator(const RenderElement* root, T* current);
39
40 T& operator*();
41 T* operator->();
42
43 bool operator==(const RenderIterator& other) const;
44 bool operator!=(const RenderIterator& other) const;
45
46 RenderIterator& traverseNext();
47 RenderIterator& traverseNextSibling();
48 RenderIterator& traversePreviousSibling();
49 RenderIterator& traverseAncestor();
50
51private:
52 const RenderElement* m_root;
53 T* m_current;
54};
55
56template <typename T>
57class RenderConstIterator {
58public:
59 RenderConstIterator(const RenderElement* root);
60 RenderConstIterator(const RenderElement* root, const T* current);
61
62 const T& operator*() const;
63 const T* operator->() const;
64
65 bool operator==(const RenderConstIterator& other) const;
66 bool operator!=(const RenderConstIterator& other) const;
67
68 RenderConstIterator& traverseNext();
69 RenderConstIterator& traverseNextSibling();
70 RenderConstIterator& traversePreviousSibling();
71 RenderConstIterator& traverseAncestor();
72
73private:
74 const RenderElement* m_root;
75 const T* m_current;
76};
77
78// Similar to WTF::is<>() but without the static_assert() making sure the check is necessary.
79template <typename T, typename U>
80inline bool isRendererOfType(const U& renderer) { return TypeCastTraits<const T, const U>::isOfType(renderer); }
81
82// Traversal helpers
83
84namespace RenderObjectTraversal {
85
86template <typename U>
87inline RenderObject* firstChild(U& object)
88{
89 return object.firstChild();
90}
91
92inline RenderObject* firstChild(RenderObject& object)
93{
94 return object.firstChildSlow();
95}
96
97inline RenderObject* firstChild(RenderText&)
98{
99 return nullptr;
100}
101
102inline RenderObject* nextAncestorSibling(RenderObject& current, const RenderObject* stayWithin)
103{
104 for (auto* ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) {
105 if (ancestor == stayWithin)
106 return nullptr;
107 if (auto* sibling = ancestor->nextSibling())
108 return sibling;
109 }
110 return nullptr;
111}
112
113template <typename U>
114inline RenderObject* next(U& current, const RenderObject* stayWithin)
115{
116 if (auto* child = firstChild(current))
117 return child;
118
119 if (&current == stayWithin)
120 return nullptr;
121
122 if (auto* sibling = current.nextSibling())
123 return sibling;
124
125 return nextAncestorSibling(current, stayWithin);
126}
127
128inline RenderObject* nextSkippingChildren(RenderObject& current, const RenderObject* stayWithin)
129{
130 if (&current == stayWithin)
131 return nullptr;
132
133 if (auto* sibling = current.nextSibling())
134 return sibling;
135
136 return nextAncestorSibling(current, stayWithin);
137}
138
139}
140
141namespace RenderTraversal {
142
143template <typename T, typename U>
144inline T* firstChild(U& current)
145{
146 RenderObject* object = RenderObjectTraversal::firstChild(current);
147 while (object && !isRendererOfType<T>(*object))
148 object = object->nextSibling();
149 return static_cast<T*>(object);
150}
151
152template <typename T, typename U>
153inline T* lastChild(U& current)
154{
155 RenderObject* object = current.lastChild();
156 while (object && !isRendererOfType<T>(*object))
157 object = object->previousSibling();
158 return static_cast<T*>(object);
159}
160
161template <typename T, typename U>
162inline T* nextSibling(U& current)
163{
164 RenderObject* object = current.nextSibling();
165 while (object && !isRendererOfType<T>(*object))
166 object = object->nextSibling();
167 return static_cast<T*>(object);
168}
169
170template <typename T, typename U>
171inline T* previousSibling(U& current)
172{
173 RenderObject* object = current.previousSibling();
174 while (object && !isRendererOfType<T>(*object))
175 object = object->previousSibling();
176 return static_cast<T*>(object);
177}
178
179template <typename T>
180inline T* findAncestorOfType(const RenderObject& current)
181{
182 for (auto* ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) {
183 if (isRendererOfType<T>(*ancestor))
184 return static_cast<T*>(ancestor);
185 }
186 return nullptr;
187}
188
189template <typename T, typename U>
190inline T* firstWithin(U& current)
191{
192 auto* descendant = RenderObjectTraversal::firstChild(current);
193 while (descendant && !isRendererOfType<T>(*descendant))
194 descendant = RenderObjectTraversal::next(*descendant, &current);
195 return static_cast<T*>(descendant);
196}
197
198template <typename T, typename U>
199inline T* next(U& current, const RenderObject* stayWithin)
200{
201 auto* descendant = RenderObjectTraversal::next(current, stayWithin);
202 while (descendant && !isRendererOfType<T>(*descendant))
203 descendant = RenderObjectTraversal::next(*descendant, stayWithin);
204 return static_cast<T*>(descendant);
205}
206
207} // namespace WebCore::RenderTraversal
208
209// RenderIterator
210
211template <typename T>
212inline RenderIterator<T>::RenderIterator(const RenderElement* root)
213 : m_root(root)
214 , m_current(nullptr)
215{
216}
217
218template <typename T>
219inline RenderIterator<T>::RenderIterator(const RenderElement* root, T* current)
220 : m_root(root)
221 , m_current(current)
222{
223}
224
225template <typename T>
226inline RenderIterator<T>& RenderIterator<T>::traverseNextSibling()
227{
228 ASSERT(m_current);
229 m_current = RenderTraversal::nextSibling<T>(*m_current);
230 return *this;
231}
232
233template <typename T>
234inline RenderIterator<T>& RenderIterator<T>::traverseNext()
235{
236 ASSERT(m_current);
237 m_current = RenderTraversal::next<T>(*m_current, m_root);
238 return *this;
239}
240
241template <typename T>
242inline RenderIterator<T>& RenderIterator<T>::traversePreviousSibling()
243{
244 ASSERT(m_current);
245 m_current = RenderTraversal::previousSibling<T>(*m_current);
246 return *this;
247}
248
249template <typename T>
250inline RenderIterator<T>& RenderIterator<T>::traverseAncestor()
251{
252 ASSERT(m_current);
253 ASSERT(m_current != m_root);
254 m_current = RenderTraversal::findAncestorOfType<T>(*m_current);
255 return *this;
256}
257
258template <typename T>
259inline T& RenderIterator<T>::operator*()
260{
261 ASSERT(m_current);
262 return *m_current;
263}
264
265template <typename T>
266inline T* RenderIterator<T>::operator->()
267{
268 ASSERT(m_current);
269 return m_current;
270}
271
272template <typename T>
273inline bool RenderIterator<T>::operator==(const RenderIterator& other) const
274{
275 ASSERT(m_root == other.m_root);
276 return m_current == other.m_current;
277}
278
279template <typename T>
280inline bool RenderIterator<T>::operator!=(const RenderIterator& other) const
281{
282 return !(*this == other);
283}
284
285// RenderConstIterator
286
287template <typename T>
288inline RenderConstIterator<T>::RenderConstIterator(const RenderElement* root)
289 : m_root(root)
290 , m_current(nullptr)
291{
292}
293
294template <typename T>
295inline RenderConstIterator<T>::RenderConstIterator(const RenderElement* root, const T* current)
296 : m_root(root)
297 , m_current(current)
298{
299}
300
301template <typename T>
302inline RenderConstIterator<T>& RenderConstIterator<T>::traverseNextSibling()
303{
304 ASSERT(m_current);
305 m_current = RenderTraversal::nextSibling<T>(*m_current);
306 return *this;
307}
308
309template <typename T>
310inline RenderConstIterator<T>& RenderConstIterator<T>::traverseNext()
311{
312 ASSERT(m_current);
313 m_current = RenderTraversal::next<T>(*m_current, m_root);
314 return *this;
315}
316
317template <typename T>
318inline RenderConstIterator<T>& RenderConstIterator<T>::traversePreviousSibling()
319{
320 ASSERT(m_current);
321 m_current = RenderTraversal::previousSibling<T>(m_current);
322 return *this;
323}
324
325
326template <typename T>
327inline RenderConstIterator<T>& RenderConstIterator<T>::traverseAncestor()
328{
329 ASSERT(m_current);
330 ASSERT(m_current != m_root);
331 m_current = RenderTraversal::findAncestorOfType<const T>(*m_current);
332 return *this;
333}
334
335template <typename T>
336inline const T& RenderConstIterator<T>::operator*() const
337{
338 ASSERT(m_current);
339 return *m_current;
340}
341
342template <typename T>
343inline const T* RenderConstIterator<T>::operator->() const
344{
345 ASSERT(m_current);
346 return m_current;
347}
348
349template <typename T>
350inline bool RenderConstIterator<T>::operator==(const RenderConstIterator& other) const
351{
352 ASSERT(m_root == other.m_root);
353 return m_current == other.m_current;
354}
355
356template <typename T>
357inline bool RenderConstIterator<T>::operator!=(const RenderConstIterator& other) const
358{
359 return !(*this == other);
360}
361
362} // namespace WebCore
363
364#include "RenderAncestorIterator.h"
365#include "RenderChildIterator.h"
366