2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
34 #include "core/dom/Attribute.h"
35 #include "core/dom/SpaceSplitString.h"
36 #include "wtf/text/AtomicString.h"
41 class ShareableElementData;
42 class StylePropertySet;
43 class UniqueElementData;
45 class ElementData : public RefCounted<ElementData> {
46 WTF_MAKE_FAST_ALLOCATED;
48 // Override RefCounted's deref() to ensure operator delete is called on
49 // the appropriate subclass type.
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; }
56 const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
57 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
59 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
61 const StylePropertySet* presentationAttributeStyle() const;
63 size_t length() const;
64 bool isEmpty() const { return !length(); }
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;
72 bool hasID() const { return !m_idForStyleResolution.isNull(); }
73 bool hasClass() const { return !m_classNames.isNull(); }
75 bool isEquivalent(const ElementData* other) const;
77 bool isUnique() const { return m_isUnique; }
81 explicit ElementData(unsigned arraySize);
82 ElementData(const ElementData&, bool isUnique);
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;
90 mutable RefPtr<StylePropertySet> m_inlineStyle;
91 mutable SpaceSplitString m_classNames;
92 mutable AtomicString m_idForStyleResolution;
96 friend class ShareableElementData;
97 friend class UniqueElementData;
98 friend class SVGElement;
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;
104 PassRefPtr<UniqueElementData> makeUniqueCopy() const;
108 #pragma warning(push)
109 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
112 class ShareableElementData : public ElementData {
114 static PassRefPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&);
116 explicit ShareableElementData(const Vector<Attribute>&);
117 explicit ShareableElementData(const UniqueElementData&);
118 ~ShareableElementData();
120 Attribute m_attributeArray[0];
127 class UniqueElementData : public ElementData {
129 static PassRefPtr<UniqueElementData> create();
130 PassRefPtr<ShareableElementData> makeShareableCopy() const;
132 // These functions do no error/duplicate checking.
133 void addAttribute(const QualifiedName&, const AtomicString&);
134 void removeAttribute(size_t index);
136 Attribute* attributeItem(unsigned index);
137 Attribute* getAttributeItem(const QualifiedName&);
140 explicit UniqueElementData(const ShareableElementData&);
141 explicit UniqueElementData(const UniqueElementData&);
143 mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
144 Vector<Attribute, 4> m_attributeVector;
147 inline size_t ElementData::length() const
150 return static_cast<const UniqueElementData*>(this)->m_attributeVector.size();
154 inline const StylePropertySet* ElementData::presentationAttributeStyle() const
158 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get();
161 inline const Attribute* ElementData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
163 size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
164 if (index != kNotFound)
165 return attributeItem(index);
169 inline const Attribute* ElementData::attributeBase() const
172 return static_cast<const UniqueElementData*>(this)->m_attributeVector.begin();
173 return static_cast<const ShareableElementData*>(this)->m_attributeArray;
176 inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name, bool shouldIgnoreCase) const
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))
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
191 unsigned len = length();
192 bool doSlowCheck = shouldIgnoreAttributeCase;
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())
207 return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase);
211 inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const
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))
222 inline const Attribute* ElementData::attributeItem(unsigned index) const
224 RELEASE_ASSERT(index < length());
225 return attributeBase() + index;
228 } // namespace WebCore
230 #endif // ElementData_h