1/*
2 * Copyright (C) 2013-2015 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 "ElementIterator.h"
29
30namespace WebCore {
31
32template<typename ElementType> class DoubleTypedElementDescendantIterator;
33
34template <typename ElementType>
35class TypedElementDescendantIterator : public ElementIterator<ElementType> {
36public:
37 TypedElementDescendantIterator(const ContainerNode& root);
38 TypedElementDescendantIterator(const ContainerNode& root, ElementType* current);
39 TypedElementDescendantIterator& operator++();
40};
41
42template <typename ElementType>
43class TypedElementDescendantConstIterator : public ElementConstIterator<ElementType> {
44public:
45 TypedElementDescendantConstIterator(const ContainerNode& root);
46 TypedElementDescendantConstIterator(const ContainerNode& root, const ElementType* current);
47 TypedElementDescendantConstIterator& operator++();
48};
49
50template <typename ElementType>
51class TypedElementDescendantIteratorAdapter {
52public:
53 TypedElementDescendantIteratorAdapter(ContainerNode& root);
54 TypedElementDescendantIterator<ElementType> begin();
55 TypedElementDescendantIterator<ElementType> end();
56 TypedElementDescendantIterator<ElementType> beginAt(ElementType&);
57 TypedElementDescendantIterator<ElementType> from(Element&);
58
59 ElementType* first();
60 ElementType* last();
61
62private:
63 ContainerNode& m_root;
64};
65
66template <typename ElementType>
67class TypedElementDescendantConstIteratorAdapter {
68public:
69 TypedElementDescendantConstIteratorAdapter(const ContainerNode& root);
70 TypedElementDescendantConstIterator<ElementType> begin() const;
71 TypedElementDescendantConstIterator<ElementType> end() const;
72 TypedElementDescendantConstIterator<ElementType> beginAt(const ElementType&) const;
73 TypedElementDescendantConstIterator<ElementType> from(const Element&) const;
74
75 const ElementType* first() const;
76 const ElementType* last() const;
77
78private:
79 const ContainerNode& m_root;
80};
81
82template<typename ElementType> class DoubleTypedElementDescendantIteratorAdapter {
83public:
84 typedef TypedElementDescendantIteratorAdapter<ElementType> SingleAdapter;
85 typedef DoubleTypedElementDescendantIterator<ElementType> Iterator;
86
87 DoubleTypedElementDescendantIteratorAdapter(SingleAdapter&&, SingleAdapter&&);
88 Iterator begin();
89 Iterator end();
90
91private:
92 std::pair<SingleAdapter, SingleAdapter> m_pair;
93};
94
95template<typename ElementType> class DoubleTypedElementDescendantIterator {
96public:
97 typedef TypedElementDescendantIterator<ElementType> SingleIterator;
98 typedef std::pair<ElementType&, ElementType&> ReferenceProxy;
99
100 DoubleTypedElementDescendantIterator(SingleIterator&&, SingleIterator&&);
101 ReferenceProxy operator*() const;
102 bool operator==(const DoubleTypedElementDescendantIterator&) const;
103 bool operator!=(const DoubleTypedElementDescendantIterator&) const;
104 DoubleTypedElementDescendantIterator& operator++();
105
106private:
107 std::pair<SingleIterator, SingleIterator> m_pair;
108};
109
110template <typename ElementType> TypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode&);
111template <typename ElementType> TypedElementDescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode&);
112
113// This must only be used when both sets of descendants are known to be the same length.
114// If they are different lengths, this will stop when the shorter one reaches the end, but also an assertion will fail.
115template<typename ElementType> DoubleTypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& firstRoot, ContainerNode& secondRoot);
116
117// TypedElementDescendantIterator
118
119template <typename ElementType>
120inline TypedElementDescendantIterator<ElementType>::TypedElementDescendantIterator(const ContainerNode& root)
121 : ElementIterator<ElementType>(&root)
122{
123}
124
125template <typename ElementType>
126inline TypedElementDescendantIterator<ElementType>::TypedElementDescendantIterator(const ContainerNode& root, ElementType* current)
127 : ElementIterator<ElementType>(&root, current)
128{
129}
130
131template <typename ElementType>
132inline TypedElementDescendantIterator<ElementType>& TypedElementDescendantIterator<ElementType>::operator++()
133{
134 return static_cast<TypedElementDescendantIterator<ElementType>&>(ElementIterator<ElementType>::traverseNext());
135}
136
137// TypedElementDescendantConstIterator
138
139template <typename ElementType>
140inline TypedElementDescendantConstIterator<ElementType>::TypedElementDescendantConstIterator(const ContainerNode& root)
141 : ElementConstIterator<ElementType>(&root)
142
143{
144}
145
146template <typename ElementType>
147inline TypedElementDescendantConstIterator<ElementType>::TypedElementDescendantConstIterator(const ContainerNode& root, const ElementType* current)
148 : ElementConstIterator<ElementType>(&root, current)
149{
150}
151
152template <typename ElementType>
153inline TypedElementDescendantConstIterator<ElementType>& TypedElementDescendantConstIterator<ElementType>::operator++()
154{
155 return static_cast<TypedElementDescendantConstIterator<ElementType>&>(ElementConstIterator<ElementType>::traverseNext());
156}
157
158// TypedElementDescendantIteratorAdapter
159
160template <typename ElementType>
161inline TypedElementDescendantIteratorAdapter<ElementType>::TypedElementDescendantIteratorAdapter(ContainerNode& root)
162 : m_root(root)
163{
164}
165
166template <typename ElementType>
167inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::begin()
168{
169 return TypedElementDescendantIterator<ElementType>(m_root, Traversal<ElementType>::firstWithin(m_root));
170}
171
172template <typename ElementType>
173inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::end()
174{
175 return TypedElementDescendantIterator<ElementType>(m_root);
176}
177
178template <typename ElementType>
179inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::beginAt(ElementType& descendant)
180{
181 ASSERT(descendant.isDescendantOf(m_root));
182 return TypedElementDescendantIterator<ElementType>(m_root, &descendant);
183}
184
185template <typename ElementType>
186inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::from(Element& descendant)
187{
188 ASSERT(descendant.isDescendantOf(m_root));
189 if (is<ElementType>(descendant))
190 return TypedElementDescendantIterator<ElementType>(m_root, downcast<ElementType>(&descendant));
191 ElementType* next = Traversal<ElementType>::next(descendant, &m_root);
192 return TypedElementDescendantIterator<ElementType>(m_root, next);
193}
194
195template <typename ElementType>
196inline ElementType* TypedElementDescendantIteratorAdapter<ElementType>::first()
197{
198 return Traversal<ElementType>::firstWithin(m_root);
199}
200
201template <typename ElementType>
202inline ElementType* TypedElementDescendantIteratorAdapter<ElementType>::last()
203{
204 return Traversal<ElementType>::lastWithin(m_root);
205}
206
207// TypedElementDescendantConstIteratorAdapter
208
209template <typename ElementType>
210inline TypedElementDescendantConstIteratorAdapter<ElementType>::TypedElementDescendantConstIteratorAdapter(const ContainerNode& root)
211 : m_root(root)
212{
213}
214
215template <typename ElementType>
216inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::begin() const
217{
218 return TypedElementDescendantConstIterator<ElementType>(m_root, Traversal<ElementType>::firstWithin(m_root));
219}
220
221template <typename ElementType>
222inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::end() const
223{
224 return TypedElementDescendantConstIterator<ElementType>(m_root);
225}
226
227template <typename ElementType>
228inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::beginAt(const ElementType& descendant) const
229{
230 ASSERT(descendant.isDescendantOf(m_root));
231 return TypedElementDescendantConstIterator<ElementType>(m_root, &descendant);
232}
233
234template <typename ElementType>
235inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::from(const Element& descendant) const
236{
237 ASSERT(descendant.isDescendantOf(m_root));
238 if (is<ElementType>(descendant))
239 return TypedElementDescendantConstIterator<ElementType>(m_root, downcast<ElementType>(&descendant));
240 const ElementType* next = Traversal<ElementType>::next(descendant, &m_root);
241 return TypedElementDescendantConstIterator<ElementType>(m_root, next);
242}
243
244template <typename ElementType>
245inline const ElementType* TypedElementDescendantConstIteratorAdapter<ElementType>::first() const
246{
247 return Traversal<ElementType>::firstWithin(m_root);
248}
249
250template <typename ElementType>
251inline const ElementType* TypedElementDescendantConstIteratorAdapter<ElementType>::last() const
252{
253 return Traversal<ElementType>::lastWithin(m_root);
254}
255
256// DoubleTypedElementDescendantIteratorAdapter
257
258template<typename ElementType> inline DoubleTypedElementDescendantIteratorAdapter<ElementType>::DoubleTypedElementDescendantIteratorAdapter(SingleAdapter&& first, SingleAdapter&& second)
259 : m_pair(WTFMove(first), WTFMove(second))
260{
261}
262
263template<typename ElementType> inline auto DoubleTypedElementDescendantIteratorAdapter<ElementType>::begin() -> Iterator
264{
265 return Iterator(m_pair.first.begin(), m_pair.second.begin());
266}
267
268template<typename ElementType> inline auto DoubleTypedElementDescendantIteratorAdapter<ElementType>::end() -> Iterator
269{
270 return Iterator(m_pair.first.end(), m_pair.second.end());
271}
272
273// DoubleTypedElementDescendantIterator
274
275template<typename ElementType> inline DoubleTypedElementDescendantIterator<ElementType>::DoubleTypedElementDescendantIterator(SingleIterator&& first, SingleIterator&& second)
276 : m_pair(WTFMove(first), WTFMove(second))
277{
278}
279
280template<typename ElementType> inline auto DoubleTypedElementDescendantIterator<ElementType>::operator*() const -> ReferenceProxy
281{
282 return { *m_pair.first, *m_pair.second };
283}
284
285template<typename ElementType> inline bool DoubleTypedElementDescendantIterator<ElementType>::operator==(const DoubleTypedElementDescendantIterator& other) const
286{
287 ASSERT((m_pair.first == other.m_pair.first) == (m_pair.second == other.m_pair.second));
288 return m_pair.first == other.m_pair.first || m_pair.second == other.m_pair.second;
289}
290
291template<typename ElementType> inline bool DoubleTypedElementDescendantIterator<ElementType>::operator!=(const DoubleTypedElementDescendantIterator& other) const
292{
293 return !(*this == other);
294}
295
296template<typename ElementType> inline DoubleTypedElementDescendantIterator<ElementType>& DoubleTypedElementDescendantIterator<ElementType>::operator++()
297{
298 ++m_pair.first;
299 ++m_pair.second;
300 return *this;
301}
302
303// Standalone functions
304
305template <typename ElementType>
306inline TypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& root)
307{
308 return TypedElementDescendantIteratorAdapter<ElementType>(root);
309}
310
311template <typename ElementType>
312inline TypedElementDescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode& root)
313{
314 return TypedElementDescendantConstIteratorAdapter<ElementType>(root);
315}
316
317template<typename ElementType> inline DoubleTypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& firstRoot, ContainerNode& secondRoot)
318{
319 return { descendantsOfType<ElementType>(firstRoot), descendantsOfType<ElementType>(secondRoot) };
320}
321
322} // namespace WebCore
323