• 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             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