6343e8edf6faeacee753bf336676836bd6680ea9
[WebKit-https.git] / Source / WebCore / html / HTMLCollection.h
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 "Node.h"
27 #include "CollectionType.h"
28 #include "DynamicNodeList.h"
29 #include <wtf/Forward.h>
30 #include <wtf/HashMap.h>
31 #include <wtf/PassOwnPtr.h>
32 #include <wtf/Vector.h>
33
34 namespace WebCore {
35
36 class Document;
37 class Element;
38 class NodeList;
39
40 class HTMLCollectionCacheBase : public DynamicNodeListCacheBase {
41 public:
42     HTMLCollectionCacheBase(NodeListRootType rootType, NodeListInvalidationType invalidationType, CollectionType collectionType, ItemBeforeSupportType itemBeforeSupportType)
43         : DynamicNodeListCacheBase(rootType, invalidationType, collectionType, itemBeforeSupportType)
44         , m_cachedElementsArrayOffset(0)
45     {
46     }
47
48 protected:
49     void setItemCache(Node* item, unsigned offset, unsigned elementsArrayOffset) const
50     {
51         setItemCache(item, offset);
52         m_cachedElementsArrayOffset = elementsArrayOffset;
53     }
54     unsigned cachedElementsArrayOffset() const { return m_cachedElementsArrayOffset; }
55
56     typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<Element*> > > NodeCacheMap;
57     Vector<Element*>* idCache(const AtomicString& name) const { return m_idCache.get(name.impl()); }
58     Vector<Element*>* nameCache(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
59     void appendIdCache(const AtomicString& name, Element* element) const { append(m_idCache, name, element); }
60     void appendNameCache(const AtomicString& name, Element* element) const { append(m_nameCache, name, element); }
61
62     static void append(NodeCacheMap&, const AtomicString&, Element*);
63
64 private:
65     using DynamicNodeListCacheBase::isRootedAtDocument;
66     using DynamicNodeListCacheBase::setItemCache;
67
68     mutable NodeCacheMap m_idCache;
69     mutable NodeCacheMap m_nameCache;
70     mutable unsigned m_cachedElementsArrayOffset;
71
72     friend void DynamicNodeListCacheBase::invalidateCache() const;
73 };
74
75 class HTMLCollection : public RefCounted<HTMLCollection>, public HTMLCollectionCacheBase {
76 public:
77     static PassRefPtr<HTMLCollection> create(Node* base, CollectionType);
78     virtual ~HTMLCollection();
79
80     // DOM API
81     unsigned length() const;
82     Node* item(unsigned index) const;
83     virtual Node* namedItem(const AtomicString& name) const;
84     PassRefPtr<NodeList> tags(const String&);
85
86     // Non-DOM API
87     virtual bool hasNamedItem(const AtomicString& name) const;
88     void namedItems(const AtomicString& name, Vector<RefPtr<Node> >&) const;
89     bool isEmpty() const
90     {
91         if (isLengthCacheValid())
92             return !cachedLength();
93         if (isItemCacheValid())
94             return !cachedItem();
95         return !item(0);
96     }
97     bool hasExactlyOneItem() const
98     {
99         if (isLengthCacheValid())
100             return cachedLength() == 1;
101         if (isItemCacheValid())
102             return cachedItem() && !cachedItemOffset() && !item(1);
103         return item(0) && !item(1);
104     }
105
106     Node* base() const { return m_base.get(); }
107
108 protected:
109     HTMLCollection(Node* base, CollectionType, ItemBeforeSupportType);
110
111     virtual void updateNameCache() const;
112     virtual Element* itemAfter(unsigned& offsetInArray, Element*) const;
113
114 private:
115     bool checkForNameMatch(Element*, bool checkName, const AtomicString& name) const;
116
117     Element* itemBefore(unsigned& offsetInArray, Element*) const;
118     bool isLastItemCloserThanLastOrCachedItem(unsigned offset) const;
119     bool isFirstItemCloserThanCachedItem(unsigned offset) const;
120     Element* itemBeforeOrAfterCachedItem(unsigned offset) const;
121
122     RefPtr<Node> m_base;
123 };
124
125 } // namespace
126
127 #endif