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
28namespace WebCore {
29
30ChildNodeList::ChildNodeList(PassRefPtr<Node> rootNode, DynamicNodeList::Caches* info)
31    : DynamicNodeList(rootNode, info)
32{
33}
34
35unsigned 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
50Node* 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
101bool 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