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#ifndef RenderIterator_h
27#define RenderIterator_h
28
29#include "RenderElement.h"
30
31namespace WebCore {
32
33template <typename T>
34class RenderIterator {
35public:
36    RenderIterator(const RenderElement* root);
37    RenderIterator(const RenderElement* root, T* current);
38
39    T& operator*();
40    T* operator->();
41
42    bool operator==(const RenderIterator& other) const;
43    bool operator!=(const RenderIterator& other) const;
44
45    RenderIterator& traverseNextSibling();
46    RenderIterator& traversePreviousSibling();
47    RenderIterator& traverseAncestor();
48
49private:
50    const RenderElement* m_root;
51    T* m_current;
52};
53
54template <typename T>
55class RenderConstIterator {
56public:
57    RenderConstIterator(const RenderElement* root);
58    RenderConstIterator(const RenderElement* root, const T* current);
59
60    const T& operator*() const;
61    const T* operator->() const;
62
63    bool operator==(const RenderConstIterator& other) const;
64    bool operator!=(const RenderConstIterator& other) const;
65
66    RenderConstIterator& traverseNextSibling();
67    RenderConstIterator& traversePreviousSibling();
68    RenderConstIterator& traverseAncestor();
69
70private:
71    const RenderElement* m_root;
72    const T* m_current;
73};
74
75// Traversal helpers
76
77namespace RenderTraversal {
78
79template <typename T, typename U>
80inline T* firstChild(U& current)
81{
82    RenderObject* object = current.firstChild();
83    while (object && !isRendererOfType<const T>(*object))
84        object = object->nextSibling();
85    return static_cast<T*>(object);
86}
87
88template <typename T, typename U>
89inline T* lastChild(U& current)
90{
91    RenderObject* object = current.lastChild();
92    while (object && !isRendererOfType<const T>(*object))
93        object = object->previousSibling();
94    return static_cast<T*>(object);
95}
96
97template <typename T, typename U>
98inline T* nextSibling(U& current)
99{
100    RenderObject* object = current.nextSibling();
101    while (object && !isRendererOfType<const T>(*object))
102        object = object->nextSibling();
103    return static_cast<T*>(object);
104}
105
106template <typename T, typename U>
107inline T* previousSibling(U& current)
108{
109    RenderObject* object = current.previousSibling();
110    while (object && !isRendererOfType<const T>(*object))
111        object = object->previousSibling();
112    return static_cast<T*>(object);
113}
114
115template <typename T>
116inline T* findAncestorOfType(const RenderObject& current)
117{
118    for (auto ancestor = current.parent(); ancestor; ancestor = ancestor->parent()) {
119        if (isRendererOfType<const T>(*ancestor))
120            return static_cast<T*>(ancestor);
121    }
122    return nullptr;
123}
124
125} // namespace WebCore::RenderTraversal
126
127// RenderIterator
128
129template <typename T>
130inline RenderIterator<T>::RenderIterator(const RenderElement* root)
131    : m_root(root)
132    , m_current(nullptr)
133{
134}
135
136template <typename T>
137inline RenderIterator<T>::RenderIterator(const RenderElement* root, T* current)
138    : m_root(root)
139    , m_current(current)
140{
141}
142
143template <typename T>
144inline RenderIterator<T>& RenderIterator<T>::traverseNextSibling()
145{
146    ASSERT(m_current);
147    m_current = RenderTraversal::nextSibling<T>(*m_current);
148    return *this;
149}
150
151template <typename T>
152inline RenderIterator<T>& RenderIterator<T>::traversePreviousSibling()
153{
154    ASSERT(m_current);
155    m_current = RenderTraversal::previousSibling<T>(*m_current);
156    return *this;
157}
158
159template <typename T>
160inline RenderIterator<T>& RenderIterator<T>::traverseAncestor()
161{
162    ASSERT(m_current);
163    ASSERT(m_current != m_root);
164    m_current = RenderTraversal::findAncestorOfType<T>(*m_current);
165    return *this;
166}
167
168template <typename T>
169inline T& RenderIterator<T>::operator*()
170{
171    ASSERT(m_current);
172    return *m_current;
173}
174
175template <typename T>
176inline T* RenderIterator<T>::operator->()
177{
178    ASSERT(m_current);
179    return m_current;
180}
181
182template <typename T>
183inline bool RenderIterator<T>::operator==(const RenderIterator& other) const
184{
185    ASSERT(m_root == other.m_root);
186    return m_current == other.m_current;
187}
188
189template <typename T>
190inline bool RenderIterator<T>::operator!=(const RenderIterator& other) const
191{
192    return !(*this == other);
193}
194
195// RenderConstIterator
196
197template <typename T>
198inline RenderConstIterator<T>::RenderConstIterator(const RenderElement* root)
199    : m_root(root)
200    , m_current(nullptr)
201{
202}
203
204template <typename T>
205inline RenderConstIterator<T>::RenderConstIterator(const RenderElement* root, const T* current)
206    : m_root(root)
207    , m_current(current)
208{
209}
210
211template <typename T>
212inline RenderConstIterator<T>& RenderConstIterator<T>::traverseNextSibling()
213{
214    ASSERT(m_current);
215    m_current = RenderTraversal::nextSibling<T>(*m_current);
216    return *this;
217}
218
219template <typename T>
220inline RenderConstIterator<T>& RenderConstIterator<T>::traversePreviousSibling()
221{
222    ASSERT(m_current);
223    m_current = RenderTraversal::previousSibling<T>(m_current);
224    return *this;
225}
226
227
228template <typename T>
229inline RenderConstIterator<T>& RenderConstIterator<T>::traverseAncestor()
230{
231    ASSERT(m_current);
232    ASSERT(m_current != m_root);
233    m_current = RenderTraversal::findAncestorOfType<const T>(*m_current);
234    return *this;
235}
236
237template <typename T>
238inline const T& RenderConstIterator<T>::operator*() const
239{
240    ASSERT(m_current);
241    return *m_current;
242}
243
244template <typename T>
245inline const T* RenderConstIterator<T>::operator->() const
246{
247    ASSERT(m_current);
248    return m_current;
249}
250
251template <typename T>
252inline bool RenderConstIterator<T>::operator==(const RenderConstIterator& other) const
253{
254    ASSERT(m_root == other.m_root);
255    return m_current == other.m_current;
256}
257
258template <typename T>
259inline bool RenderConstIterator<T>::operator!=(const RenderConstIterator& other) const
260{
261    return !(*this == other);
262}
263
264}
265
266#include "RenderAncestorIterator.h"
267#include "RenderChildIterator.h"
268
269#endif
270