Home | History | Annotate | Download | only in dom
      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