[webcore/dom] Remove extra header includes from cpp files.
[WebKit-https.git] / Source / WebCore / dom / NodeIterator.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 "NodeIterator.h"
27
28 #include "Document.h"
29 #include "ExceptionCode.h"
30 #include "NodeTraversal.h"
31
32 namespace WebCore {
33
34 NodeIterator::NodePointer::NodePointer()
35 {
36 }
37
38 NodeIterator::NodePointer::NodePointer(PassRefPtr<Node> n, bool b)
39     : node(n)
40     , isPointerBeforeNode(b)
41 {
42 }
43
44 void NodeIterator::NodePointer::clear()
45 {
46     node.clear();
47 }
48
49 bool NodeIterator::NodePointer::moveToNext(Node* root)
50 {
51     if (!node)
52         return false;
53     if (isPointerBeforeNode) {
54         isPointerBeforeNode = false;
55         return true;
56     }
57     node = NodeTraversal::next(node.get(), root);
58     return node;
59 }
60
61 bool NodeIterator::NodePointer::moveToPrevious(Node* root)
62 {
63     if (!node)
64         return false;
65     if (!isPointerBeforeNode) {
66         isPointerBeforeNode = true;
67         return true;
68     }
69     node = NodeTraversal::previous(node.get(), root);
70     return node;
71 }
72
73 NodeIterator::NodeIterator(PassRefPtr<Node> rootNode, unsigned whatToShow, PassRefPtr<NodeFilter> filter, bool expandEntityReferences)
74     : NodeIteratorBase(rootNode, whatToShow, filter, expandEntityReferences)
75     , m_referenceNode(root(), true)
76     , m_detached(false)
77 {
78     root()->document().attachNodeIterator(this);
79 }
80
81 NodeIterator::~NodeIterator()
82 {
83     root()->document().detachNodeIterator(this);
84 }
85
86 PassRefPtr<Node> NodeIterator::nextNode(JSC::ExecState* state, ExceptionCode& ec)
87 {
88     if (m_detached) {
89         ec = INVALID_STATE_ERR;
90         return 0;
91     }
92
93     RefPtr<Node> result;
94
95     m_candidateNode = m_referenceNode;
96     while (m_candidateNode.moveToNext(root())) {
97         // NodeIterators treat the DOM tree as a flat list of nodes.
98         // In other words, FILTER_REJECT does not pass over descendants
99         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
100         RefPtr<Node> provisionalResult = m_candidateNode.node;
101         bool nodeWasAccepted = acceptNode(state, provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
102         if (state && state->hadException())
103             break;
104         if (nodeWasAccepted) {
105             m_referenceNode = m_candidateNode;
106             result = provisionalResult.release();
107             break;
108         }
109     }
110
111     m_candidateNode.clear();
112     return result.release();
113 }
114
115 PassRefPtr<Node> NodeIterator::previousNode(JSC::ExecState* state, ExceptionCode& ec)
116 {
117     if (m_detached) {
118         ec = INVALID_STATE_ERR;
119         return 0;
120     }
121
122     RefPtr<Node> result;
123
124     m_candidateNode = m_referenceNode;
125     while (m_candidateNode.moveToPrevious(root())) {
126         // NodeIterators treat the DOM tree as a flat list of nodes.
127         // In other words, FILTER_REJECT does not pass over descendants
128         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
129         RefPtr<Node> provisionalResult = m_candidateNode.node;
130         bool nodeWasAccepted = acceptNode(state, provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
131         if (state && state->hadException())
132             break;
133         if (nodeWasAccepted) {
134             m_referenceNode = m_candidateNode;
135             result = provisionalResult.release();
136             break;
137         }
138     }
139
140     m_candidateNode.clear();
141     return result.release();
142 }
143
144 void NodeIterator::detach()
145 {
146     root()->document().detachNodeIterator(this);
147     m_detached = true;
148     m_referenceNode.node.clear();
149 }
150
151 void NodeIterator::nodeWillBeRemoved(Node* removedNode)
152 {
153     updateForNodeRemoval(removedNode, m_candidateNode);
154     updateForNodeRemoval(removedNode, m_referenceNode);
155 }
156
157 void NodeIterator::updateForNodeRemoval(Node* removedNode, NodePointer& referenceNode) const
158 {
159     ASSERT(!m_detached);
160     ASSERT(removedNode);
161     ASSERT(&root()->document() == &removedNode->document());
162
163     // Iterator is not affected if the removed node is the reference node and is the root.
164     // or if removed node is not the reference node, or the ancestor of the reference node.
165     if (!removedNode->isDescendantOf(root()))
166         return;
167     bool willRemoveReferenceNode = removedNode == referenceNode.node;
168     bool willRemoveReferenceNodeAncestor = referenceNode.node && referenceNode.node->isDescendantOf(removedNode);
169     if (!willRemoveReferenceNode && !willRemoveReferenceNodeAncestor)
170         return;
171
172     if (referenceNode.isPointerBeforeNode) {
173         Node* node = NodeTraversal::next(removedNode, root());
174         if (node) {
175             // Move out from under the node being removed if the new reference
176             // node is a descendant of the node being removed.
177             while (node && node->isDescendantOf(removedNode))
178                 node = NodeTraversal::next(node, root());
179             if (node)
180                 referenceNode.node = node;
181         } else {
182             node = NodeTraversal::previous(removedNode, root());
183             if (node) {
184                 // Move out from under the node being removed if the reference node is
185                 // a descendant of the node being removed.
186                 if (willRemoveReferenceNodeAncestor) {
187                     while (node && node->isDescendantOf(removedNode))
188                         node = NodeTraversal::previous(node, root());
189                 }
190                 if (node) {
191                     // Removing last node.
192                     // Need to move the pointer after the node preceding the 
193                     // new reference node.
194                     referenceNode.node = node;
195                     referenceNode.isPointerBeforeNode = false;
196                 }
197             }
198         }
199     } else {
200         Node* node = NodeTraversal::previous(removedNode, root());
201         if (node) {
202             // Move out from under the node being removed if the reference node is
203             // a descendant of the node being removed.
204             if (willRemoveReferenceNodeAncestor) {
205                 while (node && node->isDescendantOf(removedNode))
206                     node = NodeTraversal::previous(node, root());
207             }
208             if (node)
209                 referenceNode.node = node;
210         } else {
211             // FIXME: This branch doesn't appear to have any LayoutTests.
212             node = NodeTraversal::next(removedNode, root());
213             // Move out from under the node being removed if the reference node is
214             // a descendant of the node being removed.
215             if (willRemoveReferenceNodeAncestor) {
216                 while (node && node->isDescendantOf(removedNode))
217                     node = NodeTraversal::previous(node, root());
218             }
219             if (node)
220                 referenceNode.node = node;
221         }
222     }
223 }
224
225
226 } // namespace WebCore