Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2000 Frederik Holljen (frederik.holljen (at) hig.no)
      4  * Copyright (C) 2001 Peter Kelly (pmk (at) post.com)
      5  * Copyright (C) 2006 Samuel Weinig (sam.weinig (at) 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 "core/dom/TreeWalker.h"
     27 
     28 #include "bindings/core/v8/ExceptionMessages.h"
     29 #include "bindings/core/v8/ExceptionState.h"
     30 #include "core/dom/ContainerNode.h"
     31 #include "core/dom/ExceptionCode.h"
     32 #include "core/dom/NodeTraversal.h"
     33 
     34 namespace blink {
     35 
     36 TreeWalker::TreeWalker(PassRefPtrWillBeRawPtr<Node> rootNode, unsigned whatToShow, PassRefPtrWillBeRawPtr<NodeFilter> filter)
     37     : NodeIteratorBase(rootNode, whatToShow, filter)
     38     , m_current(root())
     39 {
     40 }
     41 
     42 void TreeWalker::setCurrentNode(PassRefPtrWillBeRawPtr<Node> node, ExceptionState& exceptionState)
     43 {
     44     if (!node) {
     45         exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
     46         return;
     47     }
     48     m_current = node;
     49 }
     50 
     51 inline Node* TreeWalker::setCurrent(PassRefPtrWillBeRawPtr<Node> node)
     52 {
     53     m_current = node;
     54     return m_current.get();
     55 }
     56 
     57 Node* TreeWalker::parentNode(ExceptionState& exceptionState)
     58 {
     59     RefPtrWillBeRawPtr<Node> node = m_current;
     60     while (node != root()) {
     61         node = node->parentNode();
     62         if (!node)
     63             return 0;
     64         short acceptNodeResult = acceptNode(node.get(), exceptionState);
     65         if (exceptionState.hadException())
     66             return 0;
     67         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
     68             return setCurrent(node.release());
     69     }
     70     return 0;
     71 }
     72 
     73 Node* TreeWalker::firstChild(ExceptionState& exceptionState)
     74 {
     75     for (RefPtrWillBeRawPtr<Node> node = m_current->firstChild(); node; ) {
     76         short acceptNodeResult = acceptNode(node.get(), exceptionState);
     77         if (exceptionState.hadException())
     78             return 0;
     79         switch (acceptNodeResult) {
     80             case NodeFilter::FILTER_ACCEPT:
     81                 m_current = node.release();
     82                 return m_current.get();
     83             case NodeFilter::FILTER_SKIP:
     84                 if (node->hasChildren()) {
     85                     node = node->firstChild();
     86                     continue;
     87                 }
     88                 break;
     89             case NodeFilter::FILTER_REJECT:
     90                 break;
     91         }
     92         do {
     93             if (node->nextSibling()) {
     94                 node = node->nextSibling();
     95                 break;
     96             }
     97             ContainerNode* parent = node->parentNode();
     98             if (!parent || parent == root() || parent == m_current)
     99                 return 0;
    100             node = parent;
    101         } while (node);
    102     }
    103     return 0;
    104 }
    105 
    106 Node* TreeWalker::lastChild(ExceptionState& exceptionState)
    107 {
    108     for (RefPtrWillBeRawPtr<Node> node = m_current->lastChild(); node; ) {
    109         short acceptNodeResult = acceptNode(node.get(), exceptionState);
    110         if (exceptionState.hadException())
    111             return 0;
    112         switch (acceptNodeResult) {
    113             case NodeFilter::FILTER_ACCEPT:
    114                 m_current = node.release();
    115                 return m_current.get();
    116             case NodeFilter::FILTER_SKIP:
    117                 if (node->lastChild()) {
    118                     node = node->lastChild();
    119                     continue;
    120                 }
    121                 break;
    122             case NodeFilter::FILTER_REJECT:
    123                 break;
    124         }
    125         do {
    126             if (node->previousSibling()) {
    127                 node = node->previousSibling();
    128                 break;
    129             }
    130             ContainerNode* parent = node->parentNode();
    131             if (!parent || parent == root() || parent == m_current)
    132                 return 0;
    133             node = parent;
    134         } while (node);
    135     }
    136     return 0;
    137 }
    138 
    139 Node* TreeWalker::previousSibling(ExceptionState& exceptionState)
    140 {
    141     RefPtrWillBeRawPtr<Node> node = m_current;
    142     if (node == root())
    143         return 0;
    144     while (1) {
    145         for (RefPtrWillBeRawPtr<Node> sibling = node->previousSibling(); sibling; ) {
    146             short acceptNodeResult = acceptNode(sibling.get(), exceptionState);
    147             if (exceptionState.hadException())
    148                 return 0;
    149             switch (acceptNodeResult) {
    150                 case NodeFilter::FILTER_ACCEPT:
    151                     m_current = sibling.release();
    152                     return m_current.get();
    153                 case NodeFilter::FILTER_SKIP:
    154                     if (sibling->lastChild()) {
    155                         sibling = sibling->lastChild();
    156                         node = sibling;
    157                         continue;
    158                     }
    159                     break;
    160                 case NodeFilter::FILTER_REJECT:
    161                     break;
    162             }
    163             sibling = sibling->previousSibling();
    164         }
    165         node = node->parentNode();
    166         if (!node || node == root())
    167             return 0;
    168         short acceptNodeResult = acceptNode(node.get(), exceptionState);
    169         if (exceptionState.hadException())
    170             return 0;
    171         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
    172             return 0;
    173     }
    174 }
    175 
    176 Node* TreeWalker::nextSibling(ExceptionState& exceptionState)
    177 {
    178     RefPtrWillBeRawPtr<Node> node = m_current;
    179     if (node == root())
    180         return 0;
    181     while (1) {
    182         for (RefPtrWillBeRawPtr<Node> sibling = node->nextSibling(); sibling; ) {
    183             short acceptNodeResult = acceptNode(sibling.get(), exceptionState);
    184             if (exceptionState.hadException())
    185                 return 0;
    186             switch (acceptNodeResult) {
    187                 case NodeFilter::FILTER_ACCEPT:
    188                     m_current = sibling.release();
    189                     return m_current.get();
    190                 case NodeFilter::FILTER_SKIP:
    191                     if (sibling->hasChildren()) {
    192                         sibling = sibling->firstChild();
    193                         node = sibling;
    194                         continue;
    195                     }
    196                     break;
    197                 case NodeFilter::FILTER_REJECT:
    198                     break;
    199             }
    200             sibling = sibling->nextSibling();
    201         }
    202         node = node->parentNode();
    203         if (!node || node == root())
    204             return 0;
    205         short acceptNodeResult = acceptNode(node.get(), exceptionState);
    206         if (exceptionState.hadException())
    207             return 0;
    208         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
    209             return 0;
    210     }
    211 }
    212 
    213 Node* TreeWalker::previousNode(ExceptionState& exceptionState)
    214 {
    215     RefPtrWillBeRawPtr<Node> node = m_current;
    216     while (node != root()) {
    217         while (Node* previousSibling = node->previousSibling()) {
    218             node = previousSibling;
    219             short acceptNodeResult = acceptNode(node.get(), exceptionState);
    220             if (exceptionState.hadException())
    221                 return 0;
    222             if (acceptNodeResult == NodeFilter::FILTER_REJECT)
    223                 continue;
    224             while (Node* lastChild = node->lastChild()) {
    225                 node = lastChild;
    226                 acceptNodeResult = acceptNode(node.get(), exceptionState);
    227                 if (exceptionState.hadException())
    228                     return 0;
    229                 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
    230                     break;
    231             }
    232             if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
    233                 m_current = node.release();
    234                 return m_current.get();
    235             }
    236         }
    237         if (node == root())
    238             return 0;
    239         ContainerNode* parent = node->parentNode();
    240         if (!parent)
    241             return 0;
    242         node = parent;
    243         short acceptNodeResult = acceptNode(node.get(), exceptionState);
    244         if (exceptionState.hadException())
    245             return 0;
    246         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
    247             return setCurrent(node.release());
    248     }
    249     return 0;
    250 }
    251 
    252 Node* TreeWalker::nextNode(ExceptionState& exceptionState)
    253 {
    254     RefPtrWillBeRawPtr<Node> node = m_current;
    255 Children:
    256     while (Node* firstChild = node->firstChild()) {
    257         node = firstChild;
    258         short acceptNodeResult = acceptNode(node.get(), exceptionState);
    259         if (exceptionState.hadException())
    260             return 0;
    261         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
    262             return setCurrent(node.release());
    263         if (acceptNodeResult == NodeFilter::FILTER_REJECT)
    264             break;
    265     }
    266     while (Node* nextSibling = NodeTraversal::nextSkippingChildren(*node, root())) {
    267         node = nextSibling;
    268         short acceptNodeResult = acceptNode(node.get(), exceptionState);
    269         if (exceptionState.hadException())
    270             return 0;
    271         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
    272             return setCurrent(node.release());
    273         if (acceptNodeResult == NodeFilter::FILTER_SKIP)
    274             goto Children;
    275     }
    276     return 0;
    277 }
    278 
    279 void TreeWalker::trace(Visitor* visitor)
    280 {
    281     visitor->trace(m_current);
    282     NodeIteratorBase::trace(visitor);
    283 }
    284 
    285 } // namespace blink
    286