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 | |
30 | namespace WebCore { |
31 | |
32 | template<typename ElementType> class DoubleTypedElementDescendantIterator; |
33 | |
34 | template <typename ElementType> |
35 | class TypedElementDescendantIterator : public ElementIterator<ElementType> { |
36 | public: |
37 | TypedElementDescendantIterator(const ContainerNode& root); |
38 | TypedElementDescendantIterator(const ContainerNode& root, ElementType* current); |
39 | TypedElementDescendantIterator& operator++(); |
40 | }; |
41 | |
42 | template <typename ElementType> |
43 | class TypedElementDescendantConstIterator : public ElementConstIterator<ElementType> { |
44 | public: |
45 | TypedElementDescendantConstIterator(const ContainerNode& root); |
46 | TypedElementDescendantConstIterator(const ContainerNode& root, const ElementType* current); |
47 | TypedElementDescendantConstIterator& operator++(); |
48 | }; |
49 | |
50 | template <typename ElementType> |
51 | class TypedElementDescendantIteratorAdapter { |
52 | public: |
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 | |
62 | private: |
63 | ContainerNode& m_root; |
64 | }; |
65 | |
66 | template <typename ElementType> |
67 | class TypedElementDescendantConstIteratorAdapter { |
68 | public: |
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 | |
78 | private: |
79 | const ContainerNode& m_root; |
80 | }; |
81 | |
82 | template<typename ElementType> class DoubleTypedElementDescendantIteratorAdapter { |
83 | public: |
84 | typedef TypedElementDescendantIteratorAdapter<ElementType> SingleAdapter; |
85 | typedef DoubleTypedElementDescendantIterator<ElementType> Iterator; |
86 | |
87 | DoubleTypedElementDescendantIteratorAdapter(SingleAdapter&&, SingleAdapter&&); |
88 | Iterator begin(); |
89 | Iterator end(); |
90 | |
91 | private: |
92 | std::pair<SingleAdapter, SingleAdapter> m_pair; |
93 | }; |
94 | |
95 | template<typename ElementType> class DoubleTypedElementDescendantIterator { |
96 | public: |
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 | |
106 | private: |
107 | std::pair<SingleIterator, SingleIterator> m_pair; |
108 | }; |
109 | |
110 | template <typename ElementType> TypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode&); |
111 | template <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. |
115 | template<typename ElementType> DoubleTypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& firstRoot, ContainerNode& secondRoot); |
116 | |
117 | // TypedElementDescendantIterator |
118 | |
119 | template <typename ElementType> |
120 | inline TypedElementDescendantIterator<ElementType>::TypedElementDescendantIterator(const ContainerNode& root) |
121 | : ElementIterator<ElementType>(&root) |
122 | { |
123 | } |
124 | |
125 | template <typename ElementType> |
126 | inline TypedElementDescendantIterator<ElementType>::TypedElementDescendantIterator(const ContainerNode& root, ElementType* current) |
127 | : ElementIterator<ElementType>(&root, current) |
128 | { |
129 | } |
130 | |
131 | template <typename ElementType> |
132 | inline TypedElementDescendantIterator<ElementType>& TypedElementDescendantIterator<ElementType>::operator++() |
133 | { |
134 | return static_cast<TypedElementDescendantIterator<ElementType>&>(ElementIterator<ElementType>::traverseNext()); |
135 | } |
136 | |
137 | // TypedElementDescendantConstIterator |
138 | |
139 | template <typename ElementType> |
140 | inline TypedElementDescendantConstIterator<ElementType>::TypedElementDescendantConstIterator(const ContainerNode& root) |
141 | : ElementConstIterator<ElementType>(&root) |
142 | |
143 | { |
144 | } |
145 | |
146 | template <typename ElementType> |
147 | inline TypedElementDescendantConstIterator<ElementType>::TypedElementDescendantConstIterator(const ContainerNode& root, const ElementType* current) |
148 | : ElementConstIterator<ElementType>(&root, current) |
149 | { |
150 | } |
151 | |
152 | template <typename ElementType> |
153 | inline TypedElementDescendantConstIterator<ElementType>& TypedElementDescendantConstIterator<ElementType>::operator++() |
154 | { |
155 | return static_cast<TypedElementDescendantConstIterator<ElementType>&>(ElementConstIterator<ElementType>::traverseNext()); |
156 | } |
157 | |
158 | // TypedElementDescendantIteratorAdapter |
159 | |
160 | template <typename ElementType> |
161 | inline TypedElementDescendantIteratorAdapter<ElementType>::TypedElementDescendantIteratorAdapter(ContainerNode& root) |
162 | : m_root(root) |
163 | { |
164 | } |
165 | |
166 | template <typename ElementType> |
167 | inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::begin() |
168 | { |
169 | return TypedElementDescendantIterator<ElementType>(m_root, Traversal<ElementType>::firstWithin(m_root)); |
170 | } |
171 | |
172 | template <typename ElementType> |
173 | inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::end() |
174 | { |
175 | return TypedElementDescendantIterator<ElementType>(m_root); |
176 | } |
177 | |
178 | template <typename ElementType> |
179 | inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::beginAt(ElementType& descendant) |
180 | { |
181 | ASSERT(descendant.isDescendantOf(m_root)); |
182 | return TypedElementDescendantIterator<ElementType>(m_root, &descendant); |
183 | } |
184 | |
185 | template <typename ElementType> |
186 | inline 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 | |
195 | template <typename ElementType> |
196 | inline ElementType* TypedElementDescendantIteratorAdapter<ElementType>::first() |
197 | { |
198 | return Traversal<ElementType>::firstWithin(m_root); |
199 | } |
200 | |
201 | template <typename ElementType> |
202 | inline ElementType* TypedElementDescendantIteratorAdapter<ElementType>::last() |
203 | { |
204 | return Traversal<ElementType>::lastWithin(m_root); |
205 | } |
206 | |
207 | // TypedElementDescendantConstIteratorAdapter |
208 | |
209 | template <typename ElementType> |
210 | inline TypedElementDescendantConstIteratorAdapter<ElementType>::TypedElementDescendantConstIteratorAdapter(const ContainerNode& root) |
211 | : m_root(root) |
212 | { |
213 | } |
214 | |
215 | template <typename ElementType> |
216 | inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::begin() const |
217 | { |
218 | return TypedElementDescendantConstIterator<ElementType>(m_root, Traversal<ElementType>::firstWithin(m_root)); |
219 | } |
220 | |
221 | template <typename ElementType> |
222 | inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::end() const |
223 | { |
224 | return TypedElementDescendantConstIterator<ElementType>(m_root); |
225 | } |
226 | |
227 | template <typename ElementType> |
228 | inline 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 | |
234 | template <typename ElementType> |
235 | inline 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 | |
244 | template <typename ElementType> |
245 | inline const ElementType* TypedElementDescendantConstIteratorAdapter<ElementType>::first() const |
246 | { |
247 | return Traversal<ElementType>::firstWithin(m_root); |
248 | } |
249 | |
250 | template <typename ElementType> |
251 | inline const ElementType* TypedElementDescendantConstIteratorAdapter<ElementType>::last() const |
252 | { |
253 | return Traversal<ElementType>::lastWithin(m_root); |
254 | } |
255 | |
256 | // DoubleTypedElementDescendantIteratorAdapter |
257 | |
258 | template<typename ElementType> inline DoubleTypedElementDescendantIteratorAdapter<ElementType>::DoubleTypedElementDescendantIteratorAdapter(SingleAdapter&& first, SingleAdapter&& second) |
259 | : m_pair(WTFMove(first), WTFMove(second)) |
260 | { |
261 | } |
262 | |
263 | template<typename ElementType> inline auto DoubleTypedElementDescendantIteratorAdapter<ElementType>::begin() -> Iterator |
264 | { |
265 | return Iterator(m_pair.first.begin(), m_pair.second.begin()); |
266 | } |
267 | |
268 | template<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 | |
275 | template<typename ElementType> inline DoubleTypedElementDescendantIterator<ElementType>::DoubleTypedElementDescendantIterator(SingleIterator&& first, SingleIterator&& second) |
276 | : m_pair(WTFMove(first), WTFMove(second)) |
277 | { |
278 | } |
279 | |
280 | template<typename ElementType> inline auto DoubleTypedElementDescendantIterator<ElementType>::operator*() const -> ReferenceProxy |
281 | { |
282 | return { *m_pair.first, *m_pair.second }; |
283 | } |
284 | |
285 | template<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 | |
291 | template<typename ElementType> inline bool DoubleTypedElementDescendantIterator<ElementType>::operator!=(const DoubleTypedElementDescendantIterator& other) const |
292 | { |
293 | return !(*this == other); |
294 | } |
295 | |
296 | template<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 | |
305 | template <typename ElementType> |
306 | inline TypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& root) |
307 | { |
308 | return TypedElementDescendantIteratorAdapter<ElementType>(root); |
309 | } |
310 | |
311 | template <typename ElementType> |
312 | inline TypedElementDescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode& root) |
313 | { |
314 | return TypedElementDescendantConstIteratorAdapter<ElementType>(root); |
315 | } |
316 | |
317 | template<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 | |