• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             ContainerNode* 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             ContainerNode* 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->lastChild()) {
155                         sibling = sibling->lastChild();
156                         node = sibling;
157                         continue;
158                     }
159                     break;
160                 case NodeFilter::FILTER_REJECT:
161                     break;
162             }
163             sibling = sibling->previousSibling();
164         }
165         node = node->parentNode();
166         if (!node || node == root())
167             return 0;
168         short acceptNodeResult = acceptNode(state, node.get());
169         if (state && state->hadException())
170             return 0;
171         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
172             return 0;
173     }
174 }
175 
nextSibling(ScriptState * state)176 Node* TreeWalker::nextSibling(ScriptState* state)
177 {
178     RefPtr<Node> node = m_current;
179     if (node == root())
180         return 0;
181     while (1) {
182         for (RefPtr<Node> sibling = node->nextSibling(); sibling; ) {
183             short acceptNodeResult = acceptNode(state, sibling.get());
184             if (state && state->hadException())
185                 return 0;
186             switch (acceptNodeResult) {
187                 case NodeFilter::FILTER_ACCEPT:
188                     m_current = sibling.release();
189                     return m_current.get();
190                 case NodeFilter::FILTER_SKIP:
191                     if (sibling->firstChild()) {
192                         sibling = sibling->firstChild();
193                         node = sibling;
194                         continue;
195                     }
196                     break;
197                 case NodeFilter::FILTER_REJECT:
198                     break;
199             }
200             sibling = sibling->nextSibling();
201         }
202         node = node->parentNode();
203         if (!node || node == root())
204             return 0;
205         short acceptNodeResult = acceptNode(state, node.get());
206         if (state && state->hadException())
207             return 0;
208         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
209             return 0;
210     }
211 }
212 
previousNode(ScriptState * state)213 Node* TreeWalker::previousNode(ScriptState* state)
214 {
215     RefPtr<Node> node = m_current;
216     while (node != root()) {
217         while (Node* previousSibling = node->previousSibling()) {
218             node = previousSibling;
219             short acceptNodeResult = acceptNode(state, node.get());
220             if (state && state->hadException())
221                 return 0;
222             if (acceptNodeResult == NodeFilter::FILTER_REJECT)
223                 continue;
224             while (Node* lastChild = node->lastChild()) {
225                 node = lastChild;
226                 acceptNodeResult = acceptNode(state, node.get());
227                 if (state && state->hadException())
228                     return 0;
229                 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
230                     break;
231             }
232             if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
233                 m_current = node.release();
234                 return m_current.get();
235             }
236         }
237         if (node == root())
238             return 0;
239         ContainerNode* parent = node->parentNode();
240         if (!parent)
241             return 0;
242         node = parent;
243         short acceptNodeResult = acceptNode(state, node.get());
244         if (state && state->hadException())
245             return 0;
246         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
247             return setCurrent(node.release());
248     }
249     return 0;
250 }
251 
nextNode(ScriptState * state)252 Node* TreeWalker::nextNode(ScriptState* state)
253 {
254     RefPtr<Node> node = m_current;
255 Children:
256     while (Node* firstChild = node->firstChild()) {
257         node = firstChild;
258         short acceptNodeResult = acceptNode(state, node.get());
259         if (state && state->hadException())
260             return 0;
261         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
262             return setCurrent(node.release());
263         if (acceptNodeResult == NodeFilter::FILTER_REJECT)
264             break;
265     }
266     while (Node* nextSibling = node->traverseNextSibling(root())) {
267         node = nextSibling;
268         short acceptNodeResult = acceptNode(state, node.get());
269         if (state && state->hadException())
270             return 0;
271         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
272             return setCurrent(node.release());
273         if (acceptNodeResult == NodeFilter::FILTER_SKIP)
274             goto Children;
275     }
276     return 0;
277 }
278 
279 } // namespace WebCore
280