2008-11-04 Anders Carlsson <andersca@apple.com>
[webkit/qt.git] / WebCore / dom / TreeWalker.cpp
blob7960fae6f5b67325f3f764ed0b2d88ec939aaf73
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.
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.
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.
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.
25 #include "config.h"
26 #include "TreeWalker.h"
28 #include <runtime/ExecState.h>
29 #include "ExceptionCode.h"
30 #include "ContainerNode.h"
31 #include "NodeFilter.h"
32 #include <wtf/PassRefPtr.h>
34 using namespace JSC;
36 namespace WebCore {
38 TreeWalker::TreeWalker(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
39 : Traversal(rootNode, whatToShow, filter, expandEntityReferences)
40 , m_current(root())
44 void TreeWalker::setCurrentNode(PassRefPtr<Node> node, ExceptionCode& ec)
46 if (!node) {
47 ec = NOT_SUPPORTED_ERR;
48 return;
50 m_current = node;
53 inline Node* TreeWalker::setCurrent(PassRefPtr<Node> node)
55 m_current = node;
56 return m_current.get();
59 Node* TreeWalker::parentNode(ExecState* exec)
61 RefPtr<Node> node = m_current;
62 while (node != root()) {
63 node = node->parentNode();
64 if (!node)
65 return 0;
66 short acceptNodeResult = acceptNode(exec, node.get());
67 if (exec && exec->hadException())
68 return 0;
69 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
70 return setCurrent(node.release());
72 return 0;
75 Node* TreeWalker::firstChild(ExecState* exec)
77 for (RefPtr<Node> node = m_current->firstChild(); node; ) {
78 short acceptNodeResult = acceptNode(exec, node.get());
79 if (exec && exec->hadException())
80 return 0;
81 switch (acceptNodeResult) {
82 case NodeFilter::FILTER_ACCEPT:
83 m_current = node.release();
84 return m_current.get();
85 case NodeFilter::FILTER_SKIP:
86 if (node->firstChild()) {
87 node = node->firstChild();
88 continue;
90 break;
91 case NodeFilter::FILTER_REJECT:
92 break;
94 do {
95 if (node->nextSibling()) {
96 node = node->nextSibling();
97 break;
99 Node* parent = node->parentNode();
100 if (!parent || parent == root() || parent == m_current)
101 return 0;
102 node = parent;
103 } while (node);
105 return 0;
108 Node* TreeWalker::lastChild(ExecState* exec)
110 for (RefPtr<Node> node = m_current->lastChild(); node; ) {
111 short acceptNodeResult = acceptNode(exec, node.get());
112 if (exec && exec->hadException())
113 return 0;
114 switch (acceptNodeResult) {
115 case NodeFilter::FILTER_ACCEPT:
116 m_current = node.release();
117 return m_current.get();
118 case NodeFilter::FILTER_SKIP:
119 if (node->lastChild()) {
120 node = node->lastChild();
121 continue;
123 break;
124 case NodeFilter::FILTER_REJECT:
125 break;
127 do {
128 if (node->previousSibling()) {
129 node = node->previousSibling();
130 break;
132 Node* parent = node->parentNode();
133 if (!parent || parent == root() || parent == m_current)
134 return 0;
135 node = parent;
136 } while (node);
138 return 0;
141 Node* TreeWalker::previousSibling(ExecState* exec)
143 RefPtr<Node> node = m_current;
144 if (node == root())
145 return 0;
146 while (1) {
147 for (RefPtr<Node> sibling = node->previousSibling(); sibling; ) {
148 short acceptNodeResult = acceptNode(exec, sibling.get());
149 if (exec && exec->hadException())
150 return 0;
151 switch (acceptNodeResult) {
152 case NodeFilter::FILTER_ACCEPT:
153 m_current = sibling.release();
154 return m_current.get();
155 case NodeFilter::FILTER_SKIP:
156 if (sibling->firstChild()) {
157 sibling = sibling->firstChild();
158 continue;
160 break;
161 case NodeFilter::FILTER_REJECT:
162 break;
164 sibling = sibling->previousSibling();
166 node = node->parentNode();
167 if (!node || node == root())
168 return 0;
169 short acceptNodeResult = acceptNode(exec, node.get());
170 if (exec && exec->hadException())
171 return 0;
172 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
173 return 0;
177 Node* TreeWalker::nextSibling(ExecState* exec)
179 RefPtr<Node> node = m_current;
180 if (node == root())
181 return 0;
182 while (1) {
183 for (RefPtr<Node> sibling = node->nextSibling(); sibling; ) {
184 short acceptNodeResult = acceptNode(exec, sibling.get());
185 if (exec && exec->hadException())
186 return 0;
187 switch (acceptNodeResult) {
188 case NodeFilter::FILTER_ACCEPT:
189 m_current = sibling.release();
190 return m_current.get();
191 case NodeFilter::FILTER_SKIP:
192 if (sibling->firstChild()) {
193 sibling = sibling->firstChild();
194 continue;
196 break;
197 case NodeFilter::FILTER_REJECT:
198 break;
200 sibling = sibling->nextSibling();
202 node = node->parentNode();
203 if (!node || node == root())
204 return 0;
205 short acceptNodeResult = acceptNode(exec, node.get());
206 if (exec && exec->hadException())
207 return 0;
208 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
209 return 0;
213 Node* TreeWalker::previousNode(ExecState* exec)
215 RefPtr<Node> node = m_current;
216 while (node != root()) {
217 while (Node* previousSibling = node->previousSibling()) {
218 node = previousSibling;
219 short acceptNodeResult = acceptNode(exec, node.get());
220 if (exec && exec->hadException())
221 return 0;
222 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
223 continue;
224 while (Node* lastChild = node->lastChild()) {
225 node = lastChild;
226 acceptNodeResult = acceptNode(exec, node.get());
227 if (exec && exec->hadException())
228 return 0;
229 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
230 continue;
232 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
233 m_current = node.release();
234 return m_current.get();
237 if (node == root())
238 return 0;
239 Node* parent = node->parentNode();
240 if (!parent)
241 return 0;
242 node = parent;
243 short acceptNodeResult = acceptNode(exec, node.get());
244 if (exec && exec->hadException())
245 return 0;
246 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
247 return setCurrent(node.release());
249 return 0;
252 Node* TreeWalker::nextNode(ExecState* exec)
254 RefPtr<Node> node = m_current;
255 Children:
256 while (Node* firstChild = node->firstChild()) {
257 node = firstChild;
258 short acceptNodeResult = acceptNode(exec, node.get());
259 if (exec && exec->hadException())
260 return 0;
261 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
262 return setCurrent(node.release());
263 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
264 break;
266 while (Node* nextSibling = node->traverseNextSibling(root())) {
267 node = nextSibling;
268 short acceptNodeResult = acceptNode(exec, node.get());
269 if (exec && exec->hadException())
270 return 0;
271 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
272 return setCurrent(node.release());
273 if (acceptNodeResult == NodeFilter::FILTER_SKIP)
274 goto Children;
276 return 0;
279 } // namespace WebCore