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 TypedElementDescendantIterator_h
27#define TypedElementDescendantIterator_h
28
29#include "ElementIterator.h"
30
31namespace WebCore {
32
33template <typename ElementType>
34class TypedElementDescendantIterator : public ElementIterator<ElementType> {
35public:
36    TypedElementDescendantIterator(const ContainerNode& root);
37    TypedElementDescendantIterator(const ContainerNode& root, ElementType* current);
38    TypedElementDescendantIterator& operator++();
39};
40
41template <typename ElementType>
42class TypedElementDescendantConstIterator : public ElementConstIterator<ElementType>  {
43public:
44    TypedElementDescendantConstIterator(const ContainerNode& root);
45    TypedElementDescendantConstIterator(const ContainerNode& root, const ElementType* current);
46    TypedElementDescendantConstIterator& operator++();
47};
48
49template <typename ElementType>
50class TypedElementDescendantIteratorAdapter {
51public:
52    TypedElementDescendantIteratorAdapter(ContainerNode& root);
53    TypedElementDescendantIterator<ElementType> begin();
54    TypedElementDescendantIterator<ElementType> end();
55    TypedElementDescendantIterator<ElementType> beginAt(ElementType&);
56    TypedElementDescendantIterator<ElementType> from(Element&);
57
58    ElementType* first();
59    ElementType* last();
60
61private:
62    ContainerNode& m_root;
63};
64
65template <typename ElementType>
66class TypedElementDescendantConstIteratorAdapter {
67public:
68    TypedElementDescendantConstIteratorAdapter(const ContainerNode& root);
69    TypedElementDescendantConstIterator<ElementType> begin() const;
70    TypedElementDescendantConstIterator<ElementType> end() const;
71    TypedElementDescendantConstIterator<ElementType> beginAt(const ElementType&) const;
72    TypedElementDescendantConstIterator<ElementType> from(const Element&) const;
73
74    const ElementType* first() const;
75    const ElementType* last() const;
76
77private:
78    const ContainerNode& m_root;
79};
80
81template <typename ElementType> TypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode&);
82template <typename ElementType> TypedElementDescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode&);
83
84// TypedElementDescendantIterator
85
86template <typename ElementType>
87inline TypedElementDescendantIterator<ElementType>::TypedElementDescendantIterator(const ContainerNode& root)
88    : ElementIterator<ElementType>(&root)
89{
90}
91
92template <typename ElementType>
93inline TypedElementDescendantIterator<ElementType>::TypedElementDescendantIterator(const ContainerNode& root, ElementType* current)
94    : ElementIterator<ElementType>(&root, current)
95{
96}
97
98template <typename ElementType>
99inline TypedElementDescendantIterator<ElementType>& TypedElementDescendantIterator<ElementType>::operator++()
100{
101    return static_cast<TypedElementDescendantIterator<ElementType>&>(ElementIterator<ElementType>::traverseNext());
102}
103
104// TypedElementDescendantConstIterator
105
106template <typename ElementType>
107inline TypedElementDescendantConstIterator<ElementType>::TypedElementDescendantConstIterator(const ContainerNode& root)
108    : ElementConstIterator<ElementType>(&root)
109
110{
111}
112
113template <typename ElementType>
114inline TypedElementDescendantConstIterator<ElementType>::TypedElementDescendantConstIterator(const ContainerNode& root, const ElementType* current)
115    : ElementConstIterator<ElementType>(&root, current)
116{
117}
118
119template <typename ElementType>
120inline TypedElementDescendantConstIterator<ElementType>& TypedElementDescendantConstIterator<ElementType>::operator++()
121{
122    return static_cast<TypedElementDescendantConstIterator<ElementType>&>(ElementConstIterator<ElementType>::traverseNext());
123}
124
125// TypedElementDescendantIteratorAdapter
126
127template <typename ElementType>
128inline TypedElementDescendantIteratorAdapter<ElementType>::TypedElementDescendantIteratorAdapter(ContainerNode& root)
129    : m_root(root)
130{
131}
132
133template <typename ElementType>
134inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::begin()
135{
136    return TypedElementDescendantIterator<ElementType>(m_root, Traversal<ElementType>::firstWithin(&m_root));
137}
138
139template <typename ElementType>
140inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::end()
141{
142    return TypedElementDescendantIterator<ElementType>(m_root);
143}
144
145template <typename ElementType>
146inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::beginAt(ElementType& descendant)
147{
148    ASSERT(descendant.isDescendantOf(&m_root));
149    return TypedElementDescendantIterator<ElementType>(m_root, &descendant);
150}
151
152template <typename ElementType>
153inline TypedElementDescendantIterator<ElementType> TypedElementDescendantIteratorAdapter<ElementType>::from(Element& descendant)
154{
155    ASSERT(descendant.isDescendantOf(&m_root));
156    if (isElementOfType<const ElementType>(descendant))
157        return TypedElementDescendantIterator<ElementType>(m_root, static_cast<ElementType*>(&descendant));
158    ElementType* next = Traversal<ElementType>::next(&m_root, &descendant);
159    return TypedElementDescendantIterator<ElementType>(m_root, next);
160}
161
162template <typename ElementType>
163inline ElementType* TypedElementDescendantIteratorAdapter<ElementType>::first()
164{
165    return Traversal<ElementType>::firstWithin(&m_root);
166}
167
168template <typename ElementType>
169inline ElementType* TypedElementDescendantIteratorAdapter<ElementType>::last()
170{
171    return Traversal<ElementType>::lastWithin(&m_root);
172}
173
174// TypedElementDescendantConstIteratorAdapter
175
176template <typename ElementType>
177inline TypedElementDescendantConstIteratorAdapter<ElementType>::TypedElementDescendantConstIteratorAdapter(const ContainerNode& root)
178    : m_root(root)
179{
180}
181
182template <typename ElementType>
183inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::begin() const
184{
185    return TypedElementDescendantConstIterator<ElementType>(m_root, Traversal<ElementType>::firstWithin(&m_root));
186}
187
188template <typename ElementType>
189inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::end() const
190{
191    return TypedElementDescendantConstIterator<ElementType>(m_root);
192}
193
194template <typename ElementType>
195inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::beginAt(const ElementType& descendant) const
196{
197    ASSERT(descendant.isDescendantOf(&m_root));
198    return TypedElementDescendantConstIterator<ElementType>(m_root, &descendant);
199}
200
201template <typename ElementType>
202inline TypedElementDescendantConstIterator<ElementType> TypedElementDescendantConstIteratorAdapter<ElementType>::from(const Element& descendant) const
203{
204    ASSERT(descendant.isDescendantOf(&m_root));
205    if (isElementOfType<const ElementType>(descendant))
206        return TypedElementDescendantConstIterator<ElementType>(m_root, static_cast<const ElementType*>(&descendant));
207    const ElementType* next = Traversal<ElementType>::next(&m_root, &descendant);
208    return TypedElementDescendantConstIterator<ElementType>(m_root, next);
209}
210
211template <typename ElementType>
212inline const ElementType* TypedElementDescendantConstIteratorAdapter<ElementType>::first() const
213{
214    return Traversal<ElementType>::firstWithin(&m_root);
215}
216
217template <typename ElementType>
218inline const ElementType* TypedElementDescendantConstIteratorAdapter<ElementType>::last() const
219{
220    return Traversal<ElementType>::lastWithin(&m_root);
221}
222
223// Standalone functions
224
225template <typename ElementType>
226inline TypedElementDescendantIteratorAdapter<ElementType> descendantsOfType(ContainerNode& root)
227{
228    return TypedElementDescendantIteratorAdapter<ElementType>(root);
229}
230
231template <typename ElementType>
232inline TypedElementDescendantConstIteratorAdapter<ElementType> descendantsOfType(const ContainerNode& root)
233{
234    return TypedElementDescendantConstIteratorAdapter<ElementType>(root);
235}
236
237}
238
239#endif
240