- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / dom / ElementData.h
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #ifndef ElementData_h
32 #define ElementData_h
33
34 #include "core/dom/Attribute.h"
35 #include "core/dom/SpaceSplitString.h"
36 #include "wtf/text/AtomicString.h"
37
38 namespace WebCore {
39
40 class Attr;
41 class ShareableElementData;
42 class StylePropertySet;
43 class UniqueElementData;
44
45 class ElementData : public RefCounted<ElementData> {
46     WTF_MAKE_FAST_ALLOCATED;
47 public:
48     // Override RefCounted's deref() to ensure operator delete is called on
49     // the appropriate subclass type.
50     void deref();
51
52     void clearClass() const { m_classNames.clear(); }
53     void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
54     const SpaceSplitString& classNames() const { return m_classNames; }
55
56     const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
57     void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
58
59     const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
60
61     const StylePropertySet* presentationAttributeStyle() const;
62
63     size_t length() const;
64     bool isEmpty() const { return !length(); }
65
66     const Attribute* attributeItem(unsigned index) const;
67     const Attribute* getAttributeItem(const QualifiedName&) const;
68     size_t getAttributeItemIndex(const QualifiedName&, bool shouldIgnoreCase = false) const;
69     size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
70     size_t getAttrIndex(Attr*) const;
71
72     bool hasID() const { return !m_idForStyleResolution.isNull(); }
73     bool hasClass() const { return !m_classNames.isNull(); }
74
75     bool isEquivalent(const ElementData* other) const;
76
77     bool isUnique() const { return m_isUnique; }
78
79 protected:
80     ElementData();
81     explicit ElementData(unsigned arraySize);
82     ElementData(const ElementData&, bool isUnique);
83
84     unsigned m_isUnique : 1;
85     unsigned m_arraySize : 28;
86     mutable unsigned m_presentationAttributeStyleIsDirty : 1;
87     mutable unsigned m_styleAttributeIsDirty : 1;
88     mutable unsigned m_animatedSVGAttributesAreDirty : 1;
89
90     mutable RefPtr<StylePropertySet> m_inlineStyle;
91     mutable SpaceSplitString m_classNames;
92     mutable AtomicString m_idForStyleResolution;
93
94 private:
95     friend class Element;
96     friend class ShareableElementData;
97     friend class UniqueElementData;
98     friend class SVGElement;
99
100     const Attribute* attributeBase() const;
101     const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
102     size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
103
104     PassRefPtr<UniqueElementData> makeUniqueCopy() const;
105 };
106
107 #if COMPILER(MSVC)
108 #pragma warning(push)
109 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
110 #endif
111
112 class ShareableElementData : public ElementData {
113 public:
114     static PassRefPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&);
115
116     explicit ShareableElementData(const Vector<Attribute>&);
117     explicit ShareableElementData(const UniqueElementData&);
118     ~ShareableElementData();
119
120     Attribute m_attributeArray[0];
121 };
122
123 #if COMPILER(MSVC)
124 #pragma warning(pop)
125 #endif
126
127 class UniqueElementData : public ElementData {
128 public:
129     static PassRefPtr<UniqueElementData> create();
130     PassRefPtr<ShareableElementData> makeShareableCopy() const;
131
132     // These functions do no error/duplicate checking.
133     void addAttribute(const QualifiedName&, const AtomicString&);
134     void removeAttribute(size_t index);
135
136     Attribute* attributeItem(unsigned index);
137     Attribute* getAttributeItem(const QualifiedName&);
138
139     UniqueElementData();
140     explicit UniqueElementData(const ShareableElementData&);
141     explicit UniqueElementData(const UniqueElementData&);
142
143     mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
144     Vector<Attribute, 4> m_attributeVector;
145 };
146
147 inline size_t ElementData::length() const
148 {
149     if (isUnique())
150         return static_cast<const UniqueElementData*>(this)->m_attributeVector.size();
151     return m_arraySize;
152 }
153
154 inline const StylePropertySet* ElementData::presentationAttributeStyle() const
155 {
156     if (!m_isUnique)
157         return 0;
158     return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get();
159 }
160
161 inline const Attribute* ElementData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
162 {
163     size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
164     if (index != kNotFound)
165         return attributeItem(index);
166     return 0;
167 }
168
169 inline const Attribute* ElementData::attributeBase() const
170 {
171     if (m_isUnique)
172         return static_cast<const UniqueElementData*>(this)->m_attributeVector.begin();
173     return static_cast<const ShareableElementData*>(this)->m_attributeArray;
174 }
175
176 inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name, bool shouldIgnoreCase) const
177 {
178     const Attribute* begin = attributeBase();
179     for (unsigned i = 0; i < length(); ++i) {
180         const Attribute& attribute = begin[i];
181         if (attribute.name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase))
182             return i;
183     }
184     return kNotFound;
185 }
186
187 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller
188 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
189 inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const
190 {
191     unsigned len = length();
192     bool doSlowCheck = shouldIgnoreAttributeCase;
193
194     // Optimize for the case where the attribute exists and its name exactly matches.
195     const Attribute* begin = attributeBase();
196     for (unsigned i = 0; i < len; ++i) {
197         const Attribute& attribute = begin[i];
198         if (!attribute.name().hasPrefix()) {
199             if (name == attribute.localName())
200                 return i;
201         } else {
202             doSlowCheck = true;
203         }
204     }
205
206     if (doSlowCheck)
207         return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
208     return kNotFound;
209 }
210
211 inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const
212 {
213     const Attribute* begin = attributeBase();
214     for (unsigned i = 0; i < length(); ++i) {
215         const Attribute& attribute = begin[i];
216         if (attribute.name().matches(name))
217             return &attribute;
218     }
219     return 0;
220 }
221
222 inline const Attribute* ElementData::attributeItem(unsigned index) const
223 {
224     RELEASE_ASSERT(index < length());
225     return attributeBase() + index;
226 }
227
228 } // namespace WebCore
229
230 #endif // ElementData_h