HTMLFormCollection::item and HTMLPropertiesCollection::item should share code
[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(CollectionType type, bool includeChildren)
43         : DynamicNodeListCacheBase(RootedAtNode, AlwaysInvalidate) // These two flags are never used
44         , m_cachedElementsArrayOffset(0)
45         , m_cacheTreeVersion(0)
46         , m_hasNameCache(false)
47         , m_type(type)
48         , m_includeChildren(includeChildren)
49     {
50         ASSERT(static_cast<CollectionType>(m_type) == type);
51     }
52
53     CollectionType type() const { return static_cast<CollectionType>(m_type); }
54
55 protected:
56     void clearCache(uint64_t currentDomTreeVersion) const
57     {
58         DynamicNodeListCacheBase::clearCache();
59         m_idCache.clear();
60         m_nameCache.clear();
61         m_cachedElementsArrayOffset = 0;
62         m_cacheTreeVersion = currentDomTreeVersion;
63         m_hasNameCache = false;
64     }
65
66     using DynamicNodeListCacheBase::setItemCache;
67     void setItemCache(Node* item, unsigned offset, unsigned elementsArrayOffset) const
68     {
69         setItemCache(item, offset);
70         m_cachedElementsArrayOffset = elementsArrayOffset;
71     }
72     unsigned cachedElementsArrayOffset() const { return m_cachedElementsArrayOffset; }
73
74     bool includeChildren() const { return m_includeChildren; }
75     uint64_t cacheTreeVersion() const { return m_cacheTreeVersion; }
76
77     typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<Element*> > > NodeCacheMap;
78     Vector<Element*>* idCache(const AtomicString& name) const { return m_idCache.get(name.impl()); }
79     Vector<Element*>* nameCache(const AtomicString& name) const { return m_nameCache.get(name.impl()); }
80     void appendIdCache(const AtomicString& name, Element* element) const { append(m_idCache, name, element); }
81     void appendNameCache(const AtomicString& name, Element* element) const { append(m_nameCache, name, element); }
82
83     bool hasNameCache() const { return m_hasNameCache; }
84     void setHasNameCache() const { m_hasNameCache = true; }
85
86     static void append(NodeCacheMap&, const AtomicString&, Element*);
87
88 private:
89     using DynamicNodeListCacheBase::isRootedAtDocument;
90     using DynamicNodeListCacheBase::shouldInvalidateOnAttributeChange;
91     using DynamicNodeListCacheBase::clearCache;
92
93     mutable NodeCacheMap m_idCache;
94     mutable NodeCacheMap m_nameCache;
95     mutable unsigned m_cachedElementsArrayOffset;
96     mutable uint64_t m_cacheTreeVersion;
97
98     // FIXME: Move these bit flags to DynamicNodeListCacheBase to pack them better.
99     mutable unsigned m_hasNameCache : 1;
100     const unsigned m_type : 5; // CollectionType
101     const unsigned m_includeChildren : 1;
102 };
103
104 class HTMLCollection : public RefCounted<HTMLCollection>, public HTMLCollectionCacheBase {
105 public:
106     static PassRefPtr<HTMLCollection> create(Node* base, CollectionType);
107     virtual ~HTMLCollection();
108
109     // DOM API
110     unsigned length() const;
111     virtual Node* item(unsigned index) const;
112     virtual Node* namedItem(const AtomicString& name) const;
113     PassRefPtr<NodeList> tags(const String&);
114
115     // Non-DOM API
116     virtual bool hasNamedItem(const AtomicString& name) const;
117     void namedItems(const AtomicString& name, Vector<RefPtr<Node> >&) const;
118     bool isEmpty() const
119     {
120         invalidateCacheIfNeeded();
121         if (isLengthCacheValid())
122             return !cachedLength();
123         if (isItemCacheValid())
124             return !cachedItem();
125         return !item(0);
126     }
127     bool hasExactlyOneItem() const
128     {
129         invalidateCacheIfNeeded();
130         if (isLengthCacheValid())
131             return cachedLength() == 1;
132         if (isItemCacheValid())
133             return cachedItem() && !cachedItemOffset() && !item(1);
134         return item(0) && !item(1);
135     }
136
137     Node* base() const { return m_base.get(); }
138
139     void invalidateCache() const;
140     void invalidateCacheIfNeeded() const;
141
142 protected:
143     HTMLCollection(Node* base, CollectionType);
144
145     virtual void updateNameCache() const;
146     virtual Element* itemAfter(Node*) const;
147
148 private:
149     bool checkForNameMatch(Element*, bool checkName, const AtomicString& name) const;
150
151     virtual unsigned calcLength() const;
152
153     bool isAcceptableElement(Element*) const;
154
155     RefPtr<Node> m_base;
156 };
157
158 class HTMLCollectionWithArrayStorage : public HTMLCollection {
159 public:
160     HTMLCollectionWithArrayStorage(Node* base, CollectionType type)
161         : HTMLCollection(base, type)
162     { }
163
164     virtual Node* item(unsigned index) const OVERRIDE;
165
166 private:
167     virtual HTMLElement* itemAfter(unsigned& offsetInArray, HTMLElement* previousItem) const = 0;
168 };
169
170 } // namespace
171
172 #endif