1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#ifndef HTMLCollection_h
24#define HTMLCollection_h
25
26#include "CollectionType.h"
27#include "LiveNodeList.h"
28#include "ScriptWrappable.h"
29#include <wtf/Forward.h>
30#include <wtf/HashMap.h>
31#include <wtf/PassOwnPtr.h>
32#include <wtf/Vector.h>
33
34namespace WebCore {
35
36class HTMLCollection : public LiveNodeListBase {
37public:
38    static PassRefPtr<HTMLCollection> create(Node* base, CollectionType);
39    virtual ~HTMLCollection();
40
41    // DOM API
42    virtual Node* namedItem(const AtomicString& name) const;
43    PassRefPtr<NodeList> tags(const String&);
44
45    // Non-DOM API
46    virtual bool hasNamedItem(const AtomicString& name) const;
47    void namedItems(const AtomicString& name, Vector<RefPtr<Node> >&) const;
48    bool isEmpty() const
49    {
50        if (isLengthCacheValid())
51            return !cachedLength();
52        if (isItemCacheValid())
53            return !cachedItem();
54        return !item(0);
55    }
56    bool hasExactlyOneItem() const
57    {
58        if (isLengthCacheValid())
59            return cachedLength() == 1;
60        if (isItemCacheValid())
61            return cachedItem() && !cachedItemOffset() && !item(1);
62        return item(0) && !item(1);
63    }
64
65    virtual Element* virtualItemAfter(unsigned& offsetInArray, Element*) const;
66
67    Element* traverseFirstElement(unsigned& offsetInArray, ContainerNode* root) const;
68    Element* traverseForwardToOffset(unsigned offset, Element* currentElement, unsigned& currentOffset, unsigned& offsetInArray, ContainerNode* root) const;
69
70protected:
71    HTMLCollection(Node* base, CollectionType, ItemAfterOverrideType);
72
73    virtual void updateNameCache() const;
74
75    typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<Element*> > > NodeCacheMap;
76    Vector<Element*>* idCache(const AtomicString& name) const { return m_idCache.get(name.impl()); }
77    Vector<Element*>* nameCache(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
78    void appendIdCache(const AtomicString& name, Element* element) const { append(m_idCache, name, element); }
79    void appendNameCache(const AtomicString& name, Element* element) const { append(m_nameCache, name, element); }
80
81private:
82    Element* traverseNextElement(unsigned& offsetInArray, Element* previous, ContainerNode* root) const;
83
84    virtual bool isLiveNodeList() const OVERRIDE { ASSERT_NOT_REACHED(); return true; }
85
86    static void append(NodeCacheMap&, const AtomicString&, Element*);
87
88    mutable NodeCacheMap m_idCache;
89    mutable NodeCacheMap m_nameCache;
90    mutable unsigned m_cachedElementsArrayOffset;
91
92    friend class LiveNodeListBase;
93};
94
95} // namespace
96
97#endif
98