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.
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>
38 TreeWalker::TreeWalker(PassRefPtr
<Node
> rootNode
, unsigned whatToShow
, PassRefPtr
<NodeFilter
> filter
, bool expandEntityReferences
)
39 : Traversal(rootNode
, whatToShow
, filter
, expandEntityReferences
)
44 void TreeWalker::setCurrentNode(PassRefPtr
<Node
> node
, ExceptionCode
& ec
)
47 ec
= NOT_SUPPORTED_ERR
;
53 inline Node
* TreeWalker::setCurrent(PassRefPtr
<Node
> 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();
66 short acceptNodeResult
= acceptNode(exec
, node
.get());
67 if (exec
&& exec
->hadException())
69 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
70 return setCurrent(node
.release());
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())
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();
91 case NodeFilter::FILTER_REJECT
:
95 if (node
->nextSibling()) {
96 node
= node
->nextSibling();
99 Node
* parent
= node
->parentNode();
100 if (!parent
|| parent
== root() || parent
== m_current
)
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())
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();
124 case NodeFilter::FILTER_REJECT
:
128 if (node
->previousSibling()) {
129 node
= node
->previousSibling();
132 Node
* parent
= node
->parentNode();
133 if (!parent
|| parent
== root() || parent
== m_current
)
141 Node
* TreeWalker::previousSibling(ExecState
* exec
)
143 RefPtr
<Node
> node
= m_current
;
147 for (RefPtr
<Node
> sibling
= node
->previousSibling(); sibling
; ) {
148 short acceptNodeResult
= acceptNode(exec
, sibling
.get());
149 if (exec
&& exec
->hadException())
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();
161 case NodeFilter::FILTER_REJECT
:
164 sibling
= sibling
->previousSibling();
166 node
= node
->parentNode();
167 if (!node
|| node
== root())
169 short acceptNodeResult
= acceptNode(exec
, node
.get());
170 if (exec
&& exec
->hadException())
172 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
177 Node
* TreeWalker::nextSibling(ExecState
* exec
)
179 RefPtr
<Node
> node
= m_current
;
183 for (RefPtr
<Node
> sibling
= node
->nextSibling(); sibling
; ) {
184 short acceptNodeResult
= acceptNode(exec
, sibling
.get());
185 if (exec
&& exec
->hadException())
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();
197 case NodeFilter::FILTER_REJECT
:
200 sibling
= sibling
->nextSibling();
202 node
= node
->parentNode();
203 if (!node
|| node
== root())
205 short acceptNodeResult
= acceptNode(exec
, node
.get());
206 if (exec
&& exec
->hadException())
208 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
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())
222 if (acceptNodeResult
== NodeFilter::FILTER_REJECT
)
224 while (Node
* lastChild
= node
->lastChild()) {
226 acceptNodeResult
= acceptNode(exec
, node
.get());
227 if (exec
&& exec
->hadException())
229 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
232 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
) {
233 m_current
= node
.release();
234 return m_current
.get();
239 Node
* parent
= node
->parentNode();
243 short acceptNodeResult
= acceptNode(exec
, node
.get());
244 if (exec
&& exec
->hadException())
246 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
247 return setCurrent(node
.release());
252 Node
* TreeWalker::nextNode(ExecState
* exec
)
254 RefPtr
<Node
> node
= m_current
;
256 while (Node
* firstChild
= node
->firstChild()) {
258 short acceptNodeResult
= acceptNode(exec
, node
.get());
259 if (exec
&& exec
->hadException())
261 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
262 return setCurrent(node
.release());
263 if (acceptNodeResult
== NodeFilter::FILTER_REJECT
)
266 while (Node
* nextSibling
= node
->traverseNextSibling(root())) {
268 short acceptNodeResult
= acceptNode(exec
, node
.get());
269 if (exec
&& exec
->hadException())
271 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
272 return setCurrent(node
.release());
273 if (acceptNodeResult
== NodeFilter::FILTER_SKIP
)
279 } // namespace WebCore