1 /* 2 * Copyright (C) 2007 Apple Inc. All rights reserved. 3 * (C) 2008 Nikolas Zimmermann <zimmermann (at) 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> 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> 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 { 88 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