[WebIDL] Remove the need for the generator to know about native type mapping
[WebKit.git] / Source / WebCore / dom / TreeWalker.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
4  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6  * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  *
23  */
24
25 #include "config.h"
26 #include "TreeWalker.h"
27
28 #include "ContainerNode.h"
29 #include "NodeTraversal.h"
30 #include <runtime/JSCJSValueInlines.h>
31
32 namespace WebCore {
33
34 TreeWalker::TreeWalker(Node& rootNode, unsigned long whatToShow, RefPtr<NodeFilter>&& filter)
35     : NodeIteratorBase(rootNode, whatToShow, WTFMove(filter))
36     , m_current(root())
37 {
38 }
39
40 void TreeWalker::setCurrentNode(Node& node)
41 {
42     m_current = node;
43 }
44
45 inline Node* TreeWalker::setCurrent(Ref<Node>&& node)
46 {
47     m_current = WTFMove(node);
48     return m_current.ptr();
49 }
50
51 Node* TreeWalker::parentNode()
52 {
53     RefPtr<Node> node = m_current.ptr();
54     while (node != &root()) {
55         node = node->parentNode();
56         if (!node)
57             return nullptr;
58         short acceptNodeResult = acceptNode(*node);
59         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
60             return setCurrent(node.releaseNonNull());
61     }
62     return nullptr;
63 }
64
65 Node* TreeWalker::firstChild()
66 {
67     for (RefPtr<Node> node = m_current->firstChild(); node; ) {
68         short acceptNodeResult = acceptNode(*node);
69         switch (acceptNodeResult) {
70             case NodeFilter::FILTER_ACCEPT:
71                 m_current = node.releaseNonNull();
72                 return m_current.ptr();
73             case NodeFilter::FILTER_SKIP:
74                 if (node->firstChild()) {
75                     node = node->firstChild();
76                     continue;
77                 }
78                 break;
79             case NodeFilter::FILTER_REJECT:
80                 break;
81         }
82         do {
83             if (node->nextSibling()) {
84                 node = node->nextSibling();
85                 break;
86             }
87             ContainerNode* parent = node->parentNode();
88             if (!parent || parent == &root() || parent == m_current.ptr())
89                 return nullptr;
90             node = parent;
91         } while (node);
92     }
93     return nullptr;
94 }
95
96 Node* TreeWalker::lastChild()
97 {
98     for (RefPtr<Node> node = m_current->lastChild(); node; ) {
99         short acceptNodeResult = acceptNode(*node);
100         switch (acceptNodeResult) {
101             case NodeFilter::FILTER_ACCEPT:
102                 m_current = node.releaseNonNull();
103                 return m_current.ptr();
104             case NodeFilter::FILTER_SKIP:
105                 if (node->lastChild()) {
106                     node = node->lastChild();
107                     continue;
108                 }
109                 break;
110             case NodeFilter::FILTER_REJECT:
111                 break;
112         }
113         do {
114             if (node->previousSibling()) {
115                 node = node->previousSibling();
116                 break;
117             }
118             ContainerNode* parent = node->parentNode();
119             if (!parent || parent == &root() || parent == m_current.ptr())
120                 return nullptr;
121             node = parent;
122         } while (node);
123     }
124     return nullptr;
125 }
126
127 template<TreeWalker::SiblingTraversalType type> Node* TreeWalker::traverseSiblings()
128 {
129     RefPtr<Node> node = m_current.ptr();
130     if (node == &root())
131         return nullptr;
132
133     auto isNext = type == SiblingTraversalType::Next;
134     while (true) {
135         for (RefPtr<Node> sibling = isNext ? node->nextSibling() : node->previousSibling(); sibling; ) {
136             short acceptNodeResult = acceptNode(*sibling);
137             if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
138                 m_current = sibling.releaseNonNull();
139                 return m_current.ptr();
140             }
141             node = sibling;
142             sibling = isNext ? sibling->firstChild() : sibling->lastChild();
143             if (acceptNodeResult == NodeFilter::FILTER_REJECT || !sibling)
144                 sibling = isNext ? node->nextSibling() : node->previousSibling();
145         }
146         node = node->parentNode();
147         if (!node || node == &root())
148             return nullptr;
149         short acceptNodeResult = acceptNode(*node);
150         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
151             return nullptr;
152     }
153 }
154
155 Node* TreeWalker::previousSibling()
156 {
157     return traverseSiblings<SiblingTraversalType::Previous>();
158 }
159
160 Node* TreeWalker::nextSibling()
161 {
162     return traverseSiblings<SiblingTraversalType::Next>();
163 }
164
165 Node* TreeWalker::previousNode()
166 {
167     RefPtr<Node> node = m_current.ptr();
168     while (node != &root()) {
169         while (Node* previousSibling = node->previousSibling()) {
170             node = previousSibling;
171             short acceptNodeResult = acceptNode(*node);
172             if (acceptNodeResult == NodeFilter::FILTER_REJECT)
173                 continue;
174             while (Node* lastChild = node->lastChild()) {
175                 node = lastChild;
176                 acceptNodeResult = acceptNode(*node);
177                 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
178                     break;
179             }
180             if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
181                 m_current = node.releaseNonNull();
182                 return m_current.ptr();
183             }
184         }
185         if (node == &root())
186             return nullptr;
187         ContainerNode* parent = node->parentNode();
188         if (!parent)
189             return nullptr;
190         node = parent;
191         short acceptNodeResult = acceptNode(*node);
192         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
193             return setCurrent(node.releaseNonNull());
194     }
195     return nullptr;
196 }
197
198 Node* TreeWalker::nextNode()
199 {
200     RefPtr<Node> node = m_current.ptr();
201 Children:
202     while (Node* firstChild = node->firstChild()) {
203         node = firstChild;
204         short acceptNodeResult = acceptNode(*node);
205         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
206             return setCurrent(node.releaseNonNull());
207         if (acceptNodeResult == NodeFilter::FILTER_REJECT)
208             break;
209     }
210     while (Node* nextSibling = NodeTraversal::nextSkippingChildren(*node, &root())) {
211         node = nextSibling;
212         short acceptNodeResult = acceptNode(*node);
213         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
214             return setCurrent(node.releaseNonNull());
215         if (acceptNodeResult == NodeFilter::FILTER_SKIP)
216             goto Children;
217     }
218     return nullptr;
219 }
220
221 } // namespace WebCore