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 "ExceptionCode.h"
29 #include "ContainerNode.h"
30 #include "NodeFilter.h"
31 #include "ScriptState.h"
32 #include <wtf/PassRefPtr.h>
33
34 namespace WebCore {
35
TreeWalker(PassRefPtr<Node> rootNode,unsigned whatToShow,PassRefPtr<NodeFilter> filter,bool expandEntityReferences)36 TreeWalker::TreeWalker(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
37 : Traversal(rootNode, whatToShow, filter, expandEntityReferences)
38 , m_current(root())
39 {
40 }
41
setCurrentNode(PassRefPtr<Node> node,ExceptionCode & ec)42 void TreeWalker::setCurrentNode(PassRefPtr<Node> node, ExceptionCode& ec)
43 {
44 if (!node) {
45 ec = NOT_SUPPORTED_ERR;
46 return;
47 }
48 m_current = node;
49 }
50
setCurrent(PassRefPtr<Node> node)51 inline Node* TreeWalker::setCurrent(PassRefPtr<Node> node)
52 {
53 m_current = node;
54 return m_current.get();
55 }
56
parentNode(ScriptState * state)57 Node* TreeWalker::parentNode(ScriptState* state)
58 {
59 RefPtr<Node> node = m_current;
60 while (node != root()) {
61 node = node->parentNode();
62 if (!node)
63 return 0;
64 short acceptNodeResult = acceptNode(state, node.get());
65 if (state && state->hadException())
66 return 0;
67 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
68 return setCurrent(node.release());
69 }
70 return 0;
71 }
72
firstChild(ScriptState * state)73 Node* TreeWalker::firstChild(ScriptState* state)
74 {
75 for (RefPtr<Node> node = m_current->firstChild(); node; ) {
76 short acceptNodeResult = acceptNode(state, node.get());
77 if (state && state->hadException())
78 return 0;
79 switch (acceptNodeResult) {
80 case NodeFilter::FILTER_ACCEPT:
81 m_current = node.release();
82 return m_current.get();
83 case NodeFilter::FILTER_SKIP:
84 if (node->firstChild()) {
85 node = node->firstChild();
86 continue;
87 }
88 break;
89 case NodeFilter::FILTER_REJECT:
90 break;
91 }
92 do {
93 if (node->nextSibling()) {
94 node = node->nextSibling();
95 break;
96 }
97 Node* parent = node->parentNode();
98 if (!parent || parent == root() || parent == m_current)
99 return 0;
100 node = parent;
101 } while (node);
102 }
103 return 0;
104 }
105
lastChild(ScriptState * state)106 Node* TreeWalker::lastChild(ScriptState* state)
107 {
108 for (RefPtr<Node> node = m_current->lastChild(); node; ) {
109 short acceptNodeResult = acceptNode(state, node.get());
110 if (state && state->hadException())
111 return 0;
112 switch (acceptNodeResult) {
113 case NodeFilter::FILTER_ACCEPT:
114 m_current = node.release();
115 return m_current.get();
116 case NodeFilter::FILTER_SKIP:
117 if (node->lastChild()) {
118 node = node->lastChild();
119 continue;
120 }
121 break;
122 case NodeFilter::FILTER_REJECT:
123 break;
124 }
125 do {
126 if (node->previousSibling()) {
127 node = node->previousSibling();
128 break;
129 }
130 Node* parent = node->parentNode();
131 if (!parent || parent == root() || parent == m_current)
132 return 0;
133 node = parent;
134 } while (node);
135 }
136 return 0;
137 }
138
previousSibling(ScriptState * state)139 Node* TreeWalker::previousSibling(ScriptState* state)
140 {
141 RefPtr<Node> node = m_current;
142 if (node == root())
143 return 0;
144 while (1) {
145 for (RefPtr<Node> sibling = node->previousSibling(); sibling; ) {
146 short acceptNodeResult = acceptNode(state, sibling.get());
147 if (state && state->hadException())
148 return 0;
149 switch (acceptNodeResult) {
150 case NodeFilter::FILTER_ACCEPT:
151 m_current = sibling.release();
152 return m_current.get();
153 case NodeFilter::FILTER_SKIP:
154 if (sibling->firstChild()) {
155 sibling = sibling->firstChild();
156 continue;
157 }
158 break;
159 case NodeFilter::FILTER_REJECT:
160 break;
161 }
162 sibling = sibling->previousSibling();
163 }
164 node = node->parentNode();
165 if (!node || node == root())
166 return 0;
167 short acceptNodeResult = acceptNode(state, node.get());
168 if (state && state->hadException())
169 return 0;
170 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
171 return 0;
172 }
173 }
174
nextSibling(ScriptState * state)175 Node* TreeWalker::nextSibling(ScriptState* state)
176 {
177 RefPtr<Node> node = m_current;
178 if (node == root())
179 return 0;
180 while (1) {
181 for (RefPtr<Node> sibling = node->nextSibling(); sibling; ) {
182 short acceptNodeResult = acceptNode(state, sibling.get());
183 if (state && state->hadException())
184 return 0;
185 switch (acceptNodeResult) {
186 case NodeFilter::FILTER_ACCEPT:
187 m_current = sibling.release();
188 return m_current.get();
189 case NodeFilter::FILTER_SKIP:
190 if (sibling->firstChild()) {
191 sibling = sibling->firstChild();
192 continue;
193 }
194 break;
195 case NodeFilter::FILTER_REJECT:
196 break;
197 }
198 sibling = sibling->nextSibling();
199 }
200 node = node->parentNode();
201 if (!node || node == root())
202 return 0;
203 short acceptNodeResult = acceptNode(state, node.get());
204 if (state && state->hadException())
205 return 0;
206 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
207 return 0;
208 }
209 }
210
previousNode(ScriptState * state)211 Node* TreeWalker::previousNode(ScriptState* state)
212 {
213 RefPtr<Node> node = m_current;
214 while (node != root()) {
215 while (Node* previousSibling = node->previousSibling()) {
216 node = previousSibling;
217 short acceptNodeResult = acceptNode(state, node.get());
218 if (state && state->hadException())
219 return 0;
220 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
221 continue;
222 while (Node* lastChild = node->lastChild()) {
223 node = lastChild;
224 acceptNodeResult = acceptNode(state, node.get());
225 if (state && state->hadException())
226 return 0;
227 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
228 continue;
229 }
230 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
231 m_current = node.release();
232 return m_current.get();
233 }
234 }
235 if (node == root())
236 return 0;
237 Node* parent = node->parentNode();
238 if (!parent)
239 return 0;
240 node = parent;
241 short acceptNodeResult = acceptNode(state, node.get());
242 if (state && state->hadException())
243 return 0;
244 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
245 return setCurrent(node.release());
246 }
247 return 0;
248 }
249
nextNode(ScriptState * state)250 Node* TreeWalker::nextNode(ScriptState* state)
251 {
252 RefPtr<Node> node = m_current;
253 Children:
254 while (Node* firstChild = node->firstChild()) {
255 node = firstChild;
256 short acceptNodeResult = acceptNode(state, node.get());
257 if (state && state->hadException())
258 return 0;
259 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
260 return setCurrent(node.release());
261 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
262 break;
263 }
264 while (Node* nextSibling = node->traverseNextSibling(root())) {
265 node = nextSibling;
266 short acceptNodeResult = acceptNode(state, node.get());
267 if (state && state->hadException())
268 return 0;
269 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
270 return setCurrent(node.release());
271 if (acceptNodeResult == NodeFilter::FILTER_SKIP)
272 goto Children;
273 }
274 return 0;
275 }
276
277 } // namespace WebCore
278