Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / dom / TreeWalker.cpp
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 "NodeTraversal.h"
31
32 #include <runtime/JSCJSValueInlines.h>
33
34 namespace WebCore {
35
36 TreeWalker::TreeWalker(Node& rootNode, unsigned long whatToShow, RefPtr<NodeFilter>&& filter)
37     : NodeIteratorBase(rootNode, whatToShow, WTFMove(filter))
38     , m_current(root())
39 {
40 }
41
42 void TreeWalker::setCurrentNode(Node* node, ExceptionCode& ec)
43 {
44     if (!node) {
45         ec = NOT_SUPPORTED_ERR;
46         return;
47     }
48     m_current = node;
49 }
50
51 inline Node* TreeWalker::setCurrent(PassRefPtr<Node> node)
52 {
53     m_current = node;
54     return m_current.get();
55 }
56
57 Node* TreeWalker::parentNode()
58 {
59     RefPtr<Node> node = m_current;
60     while (node != root()) {
61         node = node->parentNode();
62         if (!node)
63             return nullptr;
64         short acceptNodeResult = acceptNode(node.get());
65         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
66             return setCurrent(node.release());
67     }
68     return nullptr;
69 }
70
71 Node* TreeWalker::firstChild()
72 {
73     for (RefPtr<Node> node = m_current->firstChild(); node; ) {
74         short acceptNodeResult = acceptNode(node.get());
75         switch (acceptNodeResult) {
76             case NodeFilter::FILTER_ACCEPT:
77                 m_current = node.release();
78                 return m_current.get();
79             case NodeFilter::FILTER_SKIP:
80                 if (node->firstChild()) {
81                     node = node->firstChild();
82                     continue;
83                 }
84                 break;
85             case NodeFilter::FILTER_REJECT:
86                 break;
87         }
88         do {
89             if (node->nextSibling()) {
90                 node = node->nextSibling();
91                 break;
92             }
93             ContainerNode* parent = node->parentNode();
94             if (!parent || parent == root() || parent == m_current)
95                 return nullptr;
96             node = parent;
97         } while (node);
98     }
99     return nullptr;
100 }
101
102 Node* TreeWalker::lastChild()
103 {
104     for (RefPtr<Node> node = m_current->lastChild(); node; ) {
105         short acceptNodeResult = acceptNode(node.get());
106         switch (acceptNodeResult) {
107             case NodeFilter::FILTER_ACCEPT:
108                 m_current = node.release();
109                 return m_current.get();
110             case NodeFilter::FILTER_SKIP:
111                 if (node->lastChild()) {
112                     node = node->lastChild();
113                     continue;
114                 }
115                 break;
116             case NodeFilter::FILTER_REJECT:
117                 break;
118         }
119         do {
120             if (node->previousSibling()) {
121                 node = node->previousSibling();
122                 break;
123             }
124             ContainerNode* parent = node->parentNode();
125             if (!parent || parent == root() || parent == m_current)
126                 return nullptr;
127             node = parent;
128         } while (node);
129     }
130     return nullptr;
131 }
132
133 template<TreeWalker::SiblingTraversalType type> Node* TreeWalker::traverseSiblings()
134 {
135     RefPtr<Node> node = m_current;
136     if (node == root())
137         return nullptr;
138
139     auto isNext = type == SiblingTraversalType::Next;
140     while (true) {
141         for (RefPtr<Node> sibling = isNext ? node->nextSibling() : node->previousSibling(); sibling; ) {
142             short acceptNodeResult = acceptNode(sibling.get());
143             if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
144                 m_current = WTFMove(sibling);
145                 return m_current.get();
146             }
147             node = sibling;
148             sibling = isNext ? sibling->firstChild() : sibling->lastChild();
149             if (acceptNodeResult == NodeFilter::FILTER_REJECT || !sibling)
150                 sibling = isNext ? node->nextSibling() : node->previousSibling();
151         }
152         node = node->parentNode();
153         if (!node || node == root())
154             return nullptr;
155         short acceptNodeResult = acceptNode(node.get());
156         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
157             return nullptr;
158     }
159 }
160
161 Node* TreeWalker::previousSibling()
162 {
163     return traverseSiblings<SiblingTraversalType::Previous>();
164 }
165
166 Node* TreeWalker::nextSibling()
167 {
168     return traverseSiblings<SiblingTraversalType::Next>();
169 }
170
171 Node* TreeWalker::previousNode()
172 {
173     RefPtr<Node> node = m_current;
174     while (node != root()) {
175         while (Node* previousSibling = node->previousSibling()) {
176             node = previousSibling;
177             short acceptNodeResult = acceptNode(node.get());
178             if (acceptNodeResult == NodeFilter::FILTER_REJECT)
179                 continue;
180             while (Node* lastChild = node->lastChild()) {
181                 node = lastChild;
182                 acceptNodeResult = acceptNode(node.get());
183                 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
184                     break;
185             }
186             if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
187                 m_current = node.release();
188                 return m_current.get();
189             }
190         }
191         if (node == root())
192             return nullptr;
193         ContainerNode* parent = node->parentNode();
194         if (!parent)
195             return nullptr;
196         node = parent;
197         short acceptNodeResult = acceptNode(node.get());
198         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
199             return setCurrent(node.release());
200     }
201     return nullptr;
202 }
203
204 Node* TreeWalker::nextNode()
205 {
206     RefPtr<Node> node = m_current;
207 Children:
208     while (Node* firstChild = node->firstChild()) {
209         node = firstChild;
210         short acceptNodeResult = acceptNode(node.get());
211         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
212             return setCurrent(node.release());
213         if (acceptNodeResult == NodeFilter::FILTER_REJECT)
214             break;
215     }
216     while (Node* nextSibling = NodeTraversal::nextSkippingChildren(*node, root())) {
217         node = nextSibling;
218         short acceptNodeResult = acceptNode(node.get());
219         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
220             return setCurrent(node.release());
221         if (acceptNodeResult == NodeFilter::FILTER_SKIP)
222             goto Children;
223     }
224     return nullptr;
225 }
226
227 } // namespace WebCore