1 /**
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include "config.h"
24 #include "ChildNodeList.h"
25 
26 #include "Element.h"
27 
28 namespace WebCore {
29 
ChildNodeList(PassRefPtr<Node> rootNode,DynamicNodeList::Caches * info)30 ChildNodeList::ChildNodeList(PassRefPtr<Node> rootNode, DynamicNodeList::Caches* info)
31     : DynamicNodeList(rootNode, info)
32 {
33 }
34 
length() const35 unsigned ChildNodeList::length() const
36 {
37     if (m_caches->isLengthCacheValid)
38         return m_caches->cachedLength;
39 
40     unsigned len = 0;
41     for (Node* n = m_rootNode->firstChild(); n; n = n->nextSibling())
42         len++;
43 
44     m_caches->cachedLength = len;
45     m_caches->isLengthCacheValid = true;
46 
47     return len;
48 }
49 
item(unsigned index) const50 Node* ChildNodeList::item(unsigned index) const
51 {
52     unsigned int pos = 0;
53     Node* n = m_rootNode->firstChild();
54 
55     if (m_caches->isItemCacheValid) {
56         if (index == m_caches->lastItemOffset)
57             return m_caches->lastItem;
58 
59         int diff = index - m_caches->lastItemOffset;
60         unsigned dist = abs(diff);
61         if (dist < index) {
62             n = m_caches->lastItem;
63             pos = m_caches->lastItemOffset;
64         }
65     }
66 
67     if (m_caches->isLengthCacheValid) {
68         if (index >= m_caches->cachedLength)
69             return 0;
70 
71         int diff = index - pos;
72         unsigned dist = abs(diff);
73         if (dist > m_caches->cachedLength - 1 - index) {
74             n = m_rootNode->lastChild();
75             pos = m_caches->cachedLength - 1;
76         }
77     }
78 
79     if (pos <= index) {
80         while (n && pos < index) {
81             n = n->nextSibling();
82             ++pos;
83         }
84     } else {
85         while (n && pos > index) {
86             n = n->previousSibling();
87             --pos;
88         }
89     }
90 
91     if (n) {
92         m_caches->lastItem = n;
93         m_caches->lastItemOffset = pos;
94         m_caches->isItemCacheValid = true;
95         return n;
96     }
97 
98     return 0;
99 }
100 
nodeMatches(Element * testNode) const101 bool ChildNodeList::nodeMatches(Element* testNode) const
102 {
103     // Note: Due to the overrides of the length and item functions above,
104     // this function will be called only by DynamicNodeList::itemWithName,
105     // for an element that was located with getElementById.
106     return testNode->parentNode() == m_rootNode;
107 }
108 
109 } // namespace WebCore
110