1 /*
2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #ifndef ContainerNodeAlgorithms_h
23 #define ContainerNodeAlgorithms_h
24
25 #include <wtf/Assertions.h>
26
27 namespace WebCore {
28
29 class Node;
30
31 namespace Private {
32
33 template<class GenericNode, class GenericNodeContainer>
34 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer* container);
35
36 };
37
38 // Helper functions for TreeShared-derived classes, which have a 'Node' style interface
39 // This applies to 'ContainerNode' and 'SVGElementInstance'
40 template<class GenericNode, class GenericNodeContainer>
removeAllChildrenInContainer(GenericNodeContainer * container)41 void removeAllChildrenInContainer(GenericNodeContainer* container)
42 {
43 // List of nodes to be deleted.
44 GenericNode* head = 0;
45 GenericNode* tail = 0;
46
47 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(head, tail, container);
48
49 GenericNode* n;
50 GenericNode* next;
51 while ((n = head) != 0) {
52 ASSERT(n->m_deletionHasBegun);
53
54 next = n->nextSibling();
55 n->setNextSibling(0);
56
57 head = next;
58 if (next == 0)
59 tail = 0;
60
61 if (n->hasChildNodes())
62 Private::addChildNodesToDeletionQueue<GenericNode, GenericNodeContainer>(head, tail, static_cast<GenericNodeContainer*>(n));
63
64 delete n;
65 }
66 }
67
68 template<class GenericNode, class GenericNodeContainer>
appendChildToContainer(GenericNode * child,GenericNodeContainer * container)69 void appendChildToContainer(GenericNode* child, GenericNodeContainer* container)
70 {
71 child->setParent(container);
72
73 GenericNode* lastChild = container->lastChild();
74 if (lastChild) {
75 child->setPreviousSibling(lastChild);
76 lastChild->setNextSibling(child);
77 } else
78 container->setFirstChild(child);
79
80 container->setLastChild(child);
81 }
82
83 // Helper methods for removeAllChildrenInContainer, hidden from WebCore namespace
84 namespace Private {
85
86 template<class GenericNode, bool dispatchRemovalNotification>
87 struct NodeRemovalDispatcher {
dispatchNodeRemovalDispatcher88 static void dispatch(GenericNode*)
89 {
90 // no-op, by default
91 }
92 };
93
94 template<class GenericNode>
95 struct NodeRemovalDispatcher<GenericNode, true> {
96 static void dispatch(GenericNode* node)
97 {
98 if (node->inDocument())
99 node->removedFromDocument();
100 }
101 };
102
103 template<class GenericNode>
104 struct ShouldDispatchRemovalNotification {
105 static const bool value = false;
106 };
107
108 template<>
109 struct ShouldDispatchRemovalNotification<Node> {
110 static const bool value = true;
111 };
112
113 template<class GenericNode, class GenericNodeContainer>
114 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer* container)
115 {
116 // We have to tell all children that their parent has died.
117 GenericNode* next = 0;
118 for (GenericNode* n = container->firstChild(); n != 0; n = next) {
119 ASSERT(!n->m_deletionHasBegun);
120
121 next = n->nextSibling();
122 n->setPreviousSibling(0);
123 n->setNextSibling(0);
124 n->setParent(0);
125
126 if (!n->refCount()) {
127 #ifndef NDEBUG
128 n->m_deletionHasBegun = true;
129 #endif
130 // Add the node to the list of nodes to be deleted.
131 // Reuse the nextSibling pointer for this purpose.
132 if (tail)
133 tail->setNextSibling(n);
134 else
135 head = n;
136
137 tail = n;
138 } else
139 NodeRemovalDispatcher<GenericNode, ShouldDispatchRemovalNotification<GenericNode>::value>::dispatch(n);
140 }
141
142 container->setFirstChild(0);
143 container->setLastChild(0);
144 }
145 };
146
147 } // namespace WebCore
148
149 #endif // ContainerNodeAlgorithms_h
150