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 "ElementTraversal.h"
29
30#if !ASSERT_DISABLED
31#include "ElementIteratorAssertions.h"
32#endif
33
34namespace WebCore {
35
36template <typename ElementType>
37class ElementIterator {
38public:
39 ElementIterator(const ContainerNode* root);
40 ElementIterator(const ContainerNode* root, ElementType* current);
41
42 ElementType& operator*() const;
43 ElementType* operator->() const;
44
45 bool operator==(const ElementIterator& other) const;
46 bool operator!=(const ElementIterator& other) const;
47
48 ElementIterator& traverseNext();
49 ElementIterator& traversePrevious();
50 ElementIterator& traverseNextSibling();
51 ElementIterator& traversePreviousSibling();
52 ElementIterator& traverseNextSkippingChildren();
53 ElementIterator& traverseAncestor();
54
55 void dropAssertions();
56
57private:
58 const ContainerNode* m_root;
59 ElementType* m_current;
60
61#if !ASSERT_DISABLED
62 ElementIteratorAssertions m_assertions;
63#endif
64};
65
66template <typename ElementType>
67class ElementConstIterator {
68public:
69 ElementConstIterator(const ContainerNode* root);
70 ElementConstIterator(const ContainerNode* root, const ElementType* current);
71
72 const ElementType& operator*() const;
73 const ElementType* operator->() const;
74
75 bool operator==(const ElementConstIterator& other) const;
76 bool operator!=(const ElementConstIterator& other) const;
77
78 ElementConstIterator& traverseNext();
79 ElementConstIterator& traversePrevious();
80 ElementConstIterator& traverseNextSibling();
81 ElementConstIterator& traversePreviousSibling();
82 ElementConstIterator& traverseNextSkippingChildren();
83 ElementConstIterator& traverseAncestor();
84
85 void dropAssertions();
86
87private:
88 const ContainerNode* m_root;
89 const ElementType* m_current;
90
91#if !ASSERT_DISABLED
92 ElementIteratorAssertions m_assertions;
93#endif
94};
95
96// ElementIterator
97
98template <typename ElementType>
99inline ElementIterator<ElementType>::ElementIterator(const ContainerNode* root)
100 : m_root(root)
101 , m_current(nullptr)
102{
103}
104
105template <typename ElementType>
106inline ElementIterator<ElementType>::ElementIterator(const ContainerNode* root, ElementType* current)
107 : m_root(root)
108 , m_current(current)
109#if !ASSERT_DISABLED
110 , m_assertions(current)
111#endif
112{
113}
114
115template <typename ElementType>
116inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseNext()
117{
118 ASSERT(m_current);
119 ASSERT(!m_assertions.domTreeHasMutated());
120 m_current = Traversal<ElementType>::next(*m_current, m_root);
121#if !ASSERT_DISABLED
122 // Drop the assertion when the iterator reaches the end.
123 if (!m_current)
124 m_assertions.dropEventDispatchAssertion();
125#endif
126 return *this;
127}
128
129template <typename ElementType>
130inline ElementIterator<ElementType>& ElementIterator<ElementType>::traversePrevious()
131{
132 ASSERT(m_current);
133 ASSERT(!m_assertions.domTreeHasMutated());
134 m_current = Traversal<ElementType>::previous(*m_current, m_root);
135#if !ASSERT_DISABLED
136 // Drop the assertion when the iterator reaches the end.
137 if (!m_current)
138 m_assertions.dropEventDispatchAssertion();
139#endif
140 return *this;
141}
142
143template <typename ElementType>
144inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseNextSibling()
145{
146 ASSERT(m_current);
147 ASSERT(!m_assertions.domTreeHasMutated());
148 m_current = Traversal<ElementType>::nextSibling(*m_current);
149#if !ASSERT_DISABLED
150 // Drop the assertion when the iterator reaches the end.
151 if (!m_current)
152 m_assertions.dropEventDispatchAssertion();
153#endif
154 return *this;
155}
156
157template <typename ElementType>
158inline ElementIterator<ElementType>& ElementIterator<ElementType>::traversePreviousSibling()
159{
160 ASSERT(m_current);
161 ASSERT(!m_assertions.domTreeHasMutated());
162 m_current = Traversal<ElementType>::previousSibling(*m_current);
163#if !ASSERT_DISABLED
164 // Drop the assertion when the iterator reaches the end.
165 if (!m_current)
166 m_assertions.dropEventDispatchAssertion();
167#endif
168 return *this;
169}
170
171template <typename ElementType>
172inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseNextSkippingChildren()
173{
174 ASSERT(m_current);
175 ASSERT(!m_assertions.domTreeHasMutated());
176 m_current = Traversal<ElementType>::nextSkippingChildren(*m_current, m_root);
177#if !ASSERT_DISABLED
178 // Drop the assertion when the iterator reaches the end.
179 if (!m_current)
180 m_assertions.dropEventDispatchAssertion();
181#endif
182 return *this;
183}
184
185template <typename ElementType>
186inline void ElementIterator<ElementType>::dropAssertions()
187{
188#if !ASSERT_DISABLED
189 m_assertions.clear();
190#endif
191}
192
193template <typename ElementType>
194inline ElementType* findElementAncestorOfType(const Node& current)
195{
196 for (Element* ancestor = current.parentElement(); ancestor; ancestor = ancestor->parentElement()) {
197 if (is<ElementType>(*ancestor))
198 return downcast<ElementType>(ancestor);
199 }
200 return nullptr;
201}
202
203template <>
204inline Element* findElementAncestorOfType<Element>(const Node& current)
205{
206 return current.parentElement();
207}
208
209template <typename ElementType>
210inline ElementIterator<ElementType>& ElementIterator<ElementType>::traverseAncestor()
211{
212 ASSERT(m_current);
213 ASSERT(m_current != m_root);
214 ASSERT(!m_assertions.domTreeHasMutated());
215 m_current = findElementAncestorOfType<ElementType>(*m_current);
216#if !ASSERT_DISABLED
217 // Drop the assertion when the iterator reaches the end.
218 if (!m_current)
219 m_assertions.dropEventDispatchAssertion();
220#endif
221 return *this;
222}
223
224template <typename ElementType>
225inline ElementType& ElementIterator<ElementType>::operator*() const
226{
227 ASSERT(m_current);
228 ASSERT(!m_assertions.domTreeHasMutated());
229 return *m_current;
230}
231
232template <typename ElementType>
233inline ElementType* ElementIterator<ElementType>::operator->() const
234{
235 ASSERT(m_current);
236 ASSERT(!m_assertions.domTreeHasMutated());
237 return m_current;
238}
239
240template <typename ElementType>
241inline bool ElementIterator<ElementType>::operator==(const ElementIterator& other) const
242{
243 ASSERT(m_root == other.m_root);
244 ASSERT(!m_assertions.domTreeHasMutated());
245 return m_current == other.m_current;
246}
247
248template <typename ElementType>
249inline bool ElementIterator<ElementType>::operator!=(const ElementIterator& other) const
250{
251 return !(*this == other);
252}
253
254// ElementConstIterator
255
256template <typename ElementType>
257inline ElementConstIterator<ElementType>::ElementConstIterator(const ContainerNode* root)
258 : m_root(root)
259 , m_current(nullptr)
260{
261}
262
263template <typename ElementType>
264inline ElementConstIterator<ElementType>::ElementConstIterator(const ContainerNode* root, const ElementType* current)
265 : m_root(root)
266 , m_current(current)
267#if !ASSERT_DISABLED
268 , m_assertions(current)
269#endif
270{
271}
272
273template <typename ElementType>
274inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseNext()
275{
276 ASSERT(m_current);
277 ASSERT(!m_assertions.domTreeHasMutated());
278 m_current = Traversal<ElementType>::next(*m_current, m_root);
279#if !ASSERT_DISABLED
280 // Drop the assertion when the iterator reaches the end.
281 if (!m_current)
282 m_assertions.dropEventDispatchAssertion();
283#endif
284 return *this;
285}
286
287template <typename ElementType>
288inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traversePrevious()
289{
290 ASSERT(m_current);
291 ASSERT(!m_assertions.domTreeHasMutated());
292 m_current = Traversal<ElementType>::previous(*m_current, m_root);
293#if !ASSERT_DISABLED
294 // Drop the assertion when the iterator reaches the end.
295 if (!m_current)
296 m_assertions.dropEventDispatchAssertion();
297#endif
298 return *this;
299}
300
301template <typename ElementType>
302inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseNextSibling()
303{
304 ASSERT(m_current);
305 ASSERT(!m_assertions.domTreeHasMutated());
306 m_current = Traversal<ElementType>::nextSibling(*m_current);
307#if !ASSERT_DISABLED
308 // Drop the assertion when the iterator reaches the end.
309 if (!m_current)
310 m_assertions.dropEventDispatchAssertion();
311#endif
312 return *this;
313}
314
315template <typename ElementType>
316inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traversePreviousSibling()
317{
318 ASSERT(m_current);
319 ASSERT(!m_assertions.domTreeHasMutated());
320 m_current = Traversal<ElementType>::previousSibling(*m_current);
321#if !ASSERT_DISABLED
322 // Drop the assertion when the iterator reaches the end.
323 if (!m_current)
324 m_assertions.dropEventDispatchAssertion();
325#endif
326 return *this;
327}
328
329template <typename ElementType>
330inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseNextSkippingChildren()
331{
332 ASSERT(m_current);
333 ASSERT(!m_assertions.domTreeHasMutated());
334 m_current = Traversal<ElementType>::nextSkippingChildren(*m_current, m_root);
335#if !ASSERT_DISABLED
336 // Drop the assertion when the iterator reaches the end.
337 if (!m_current)
338 m_assertions.dropEventDispatchAssertion();
339#endif
340 return *this;
341}
342
343template <typename ElementType>
344inline ElementConstIterator<ElementType>& ElementConstIterator<ElementType>::traverseAncestor()
345{
346 ASSERT(m_current);
347 ASSERT(m_current != m_root);
348 ASSERT(!m_assertions.domTreeHasMutated());
349 m_current = findElementAncestorOfType<const ElementType>(*m_current);
350#if !ASSERT_DISABLED
351 // Drop the assertion when the iterator reaches the end.
352 if (!m_current)
353 m_assertions.dropEventDispatchAssertion();
354#endif
355 return *this;
356}
357
358template <typename ElementType>
359inline void ElementConstIterator<ElementType>::dropAssertions()
360{
361#if !ASSERT_DISABLED
362 m_assertions.clear();
363#endif
364}
365
366template <typename ElementType>
367inline const ElementType& ElementConstIterator<ElementType>::operator*() const
368{
369 ASSERT(m_current);
370 ASSERT(!m_assertions.domTreeHasMutated());
371 return *m_current;
372}
373
374template <typename ElementType>
375inline const ElementType* ElementConstIterator<ElementType>::operator->() const
376{
377 ASSERT(m_current);
378 ASSERT(!m_assertions.domTreeHasMutated());
379 return m_current;
380}
381
382template <typename ElementType>
383inline bool ElementConstIterator<ElementType>::operator==(const ElementConstIterator& other) const
384{
385 ASSERT(m_root == other.m_root);
386 ASSERT(!m_assertions.domTreeHasMutated());
387 return m_current == other.m_current;
388}
389
390template <typename ElementType>
391inline bool ElementConstIterator<ElementType>::operator!=(const ElementConstIterator& other) const
392{
393 return !(*this == other);
394}
395
396} // namespace WebCore
397
398#include "ElementAncestorIterator.h"
399#include "ElementChildIterator.h"
400#include "TypedElementDescendantIterator.h"
401