Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(858)

Side by Side Diff: Source/core/dom/ElementData.h

Issue 354023008: Move attributes-related methods from ElementData to AttributeCollection (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/dom/Element.cpp ('k') | Source/core/dom/ElementData.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * Copyright (C) 2014 Apple Inc. All rights reserved. 3 * Copyright (C) 2014 Apple Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 26 matching lines...) Expand all
37 #include "platform/heap/Handle.h" 37 #include "platform/heap/Handle.h"
38 #include "wtf/text/AtomicString.h" 38 #include "wtf/text/AtomicString.h"
39 39
40 namespace WebCore { 40 namespace WebCore {
41 41
42 class Attr; 42 class Attr;
43 class ShareableElementData; 43 class ShareableElementData;
44 class StylePropertySet; 44 class StylePropertySet;
45 class UniqueElementData; 45 class UniqueElementData;
46 46
47 class AttributeCollection { 47 class AttributeCollection {
Inactive 2014/06/26 22:16:40 Ok, I'll move this to a separate file since it is
48 public: 48 public:
49 typedef const Attribute* const_iterator; 49 typedef const Attribute* const_iterator;
50 50
51 AttributeCollection(const Attribute* array, unsigned size) 51 AttributeCollection(const Attribute* array, unsigned size)
52 : m_array(array) 52 : m_array(array)
53 , m_size(size) 53 , m_size(size)
54 { } 54 { }
55 55
56 const Attribute& operator[](unsigned index) const { return at(index); }
57 const Attribute& at(unsigned index) const
58 {
59 RELEASE_ASSERT(index < m_size);
60 return m_array[index];
61 }
62
63 const Attribute* get(const QualifiedName&) const;
64 const Attribute* get(const AtomicString& name, bool shouldIgnoreCase) const;
65 size_t find(const QualifiedName&, bool shouldIgnoreCase = false) const;
66 size_t find(const AtomicString& name, bool shouldIgnoreCase) const;
67 size_t find(Attr*) const;
esprehn 2014/06/26 22:03:58 We're going to have to be really careful here, ori
Inactive 2014/06/26 22:16:40 To be fair, they were called getAttributeItem() /
68
56 const_iterator begin() const { return m_array; } 69 const_iterator begin() const { return m_array; }
57 const_iterator end() const { return m_array + m_size; } 70 const_iterator end() const { return m_array + m_size; }
58 71
59 unsigned size() const { return m_size; } 72 unsigned size() const { return m_size; }
73 bool isEmpty() const { return !m_size; }
60 74
61 private: 75 private:
76 size_t findSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase ) const;
77
62 const Attribute* m_array; 78 const Attribute* m_array;
63 unsigned m_size; 79 unsigned m_size;
64 }; 80 };
65 81
66 // ElementData represents very common, but not necessarily unique to an element, 82 // ElementData represents very common, but not necessarily unique to an element,
67 // data such as attributes, inline style, and parsed class names and ids. 83 // data such as attributes, inline style, and parsed class names and ids.
68 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData > { 84 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData > {
69 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; 85 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
70 public: 86 public:
71 #if ENABLE(OILPAN) 87 #if ENABLE(OILPAN)
(...skipping 10 matching lines...) Expand all
82 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_ classNames.set(className, shouldFoldCase); } 98 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_ classNames.set(className, shouldFoldCase); }
83 const SpaceSplitString& classNames() const { return m_classNames; } 99 const SpaceSplitString& classNames() const { return m_classNames; }
84 100
85 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu tion; } 101 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu tion; }
86 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle Resolution = newId; } 102 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle Resolution = newId; }
87 103
88 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } 104 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
89 105
90 const StylePropertySet* presentationAttributeStyle() const; 106 const StylePropertySet* presentationAttributeStyle() const;
91 107
92 // This is not a trivial getter and its return value should be cached for pe rformance.
93 size_t attributeCount() const;
94 bool hasAttributes() const { return !!attributeCount(); }
95
96 AttributeCollection attributes() const; 108 AttributeCollection attributes() const;
97 109
98 const Attribute& attributeAt(unsigned index) const;
99 const Attribute* findAttributeByName(const QualifiedName&) const;
100 size_t findAttributeIndexByName(const QualifiedName&, bool shouldIgnoreCase = false) const;
101 size_t findAttributeIndexByName(const AtomicString& name, bool shouldIgnoreA ttributeCase) const;
102 size_t findAttrNodeIndex(Attr*) const;
103
104 bool hasID() const { return !m_idForStyleResolution.isNull(); } 110 bool hasID() const { return !m_idForStyleResolution.isNull(); }
105 bool hasClass() const { return !m_classNames.isNull(); } 111 bool hasClass() const { return !m_classNames.isNull(); }
106 112
107 bool isEquivalent(const ElementData* other) const; 113 bool isEquivalent(const ElementData* other) const;
108 114
109 bool isUnique() const { return m_isUnique; } 115 bool isUnique() const { return m_isUnique; }
110 116
111 void traceAfterDispatch(Visitor*); 117 void traceAfterDispatch(Visitor*);
112 void trace(Visitor*); 118 void trace(Visitor*);
113 119
(...skipping 16 matching lines...) Expand all
130 private: 136 private:
131 friend class Element; 137 friend class Element;
132 friend class ShareableElementData; 138 friend class ShareableElementData;
133 friend class UniqueElementData; 139 friend class UniqueElementData;
134 friend class SVGElement; 140 friend class SVGElement;
135 141
136 #if !ENABLE(OILPAN) 142 #if !ENABLE(OILPAN)
137 void destroy(); 143 void destroy();
138 #endif 144 #endif
139 145
140 const Attribute* attributeBase() const;
141 const Attribute* findAttributeByName(const AtomicString& name, bool shouldIg noreAttributeCase) const;
142 size_t findAttributeIndexByNameSlowCase(const AtomicString& name, bool shoul dIgnoreAttributeCase) const;
143
144 PassRefPtrWillBeRawPtr<UniqueElementData> makeUniqueCopy() const; 146 PassRefPtrWillBeRawPtr<UniqueElementData> makeUniqueCopy() const;
145 }; 147 };
146 148
147 #if COMPILER(MSVC) 149 #if COMPILER(MSVC)
148 #pragma warning(push) 150 #pragma warning(push)
149 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" war ning 151 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" war ning
150 #endif 152 #endif
151 153
152 // SharableElementData is managed by ElementDataCache and is produced by 154 // SharableElementData is managed by ElementDataCache and is produced by
153 // the parser during page load for elements that have identical attributes. This 155 // the parser during page load for elements that have identical attributes. This
(...skipping 12 matching lines...) Expand all
166 // Add support for placement new as ShareableElementData is not allocated 168 // Add support for placement new as ShareableElementData is not allocated
167 // with a fixed size. Instead the allocated memory size is computed based on 169 // with a fixed size. Instead the allocated memory size is computed based on
168 // the number of attributes. This requires us to use Heap::allocate directly 170 // the number of attributes. This requires us to use Heap::allocate directly
169 // with the computed size and subsequently call placement new with the 171 // with the computed size and subsequently call placement new with the
170 // allocated memory address. 172 // allocated memory address.
171 void* operator new(std::size_t, void* location) 173 void* operator new(std::size_t, void* location)
172 { 174 {
173 return location; 175 return location;
174 } 176 }
175 177
178 AttributeCollection attributes() const;
179
176 Attribute m_attributeArray[0]; 180 Attribute m_attributeArray[0];
177 }; 181 };
178 182
179 #if COMPILER(MSVC) 183 #if COMPILER(MSVC)
180 #pragma warning(pop) 184 #pragma warning(pop)
181 #endif 185 #endif
182 186
183 // UniqueElementData is created when an element needs to mutate its attributes 187 // UniqueElementData is created when an element needs to mutate its attributes
184 // or gains presentation attribute style (ex. width="10"). It does not need to 188 // or gains presentation attribute style (ex. width="10"). It does not need to
185 // be created to fill in values in the ElementData that are derived from 189 // be created to fill in values in the ElementData that are derived from
186 // attributes. For example populating the m_inlineStyle from the style attribute 190 // attributes. For example populating the m_inlineStyle from the style attribute
187 // doesn't require a UniqueElementData as all elements with the same style 191 // doesn't require a UniqueElementData as all elements with the same style
188 // attribute will have the same inline style. 192 // attribute will have the same inline style.
189 class UniqueElementData FINAL : public ElementData { 193 class UniqueElementData FINAL : public ElementData {
190 public: 194 public:
191 static PassRefPtrWillBeRawPtr<UniqueElementData> create(); 195 static PassRefPtrWillBeRawPtr<UniqueElementData> create();
192 PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const; 196 PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const;
193 197
194 // These functions do no error/duplicate checking. 198 // These functions do no error/duplicate checking.
195 void appendAttribute(const QualifiedName&, const AtomicString&); 199 void appendAttribute(const QualifiedName&, const AtomicString&);
196 void removeAttributeAt(size_t index); 200 void removeAttributeAt(size_t index);
197 201
202 AttributeCollection attributes() const;
203
198 Attribute& attributeAt(unsigned index); 204 Attribute& attributeAt(unsigned index);
199 Attribute* findAttributeByName(const QualifiedName&); 205 Attribute* findAttributeByName(const QualifiedName&);
200 206
201 UniqueElementData(); 207 UniqueElementData();
202 explicit UniqueElementData(const ShareableElementData&); 208 explicit UniqueElementData(const ShareableElementData&);
203 explicit UniqueElementData(const UniqueElementData&); 209 explicit UniqueElementData(const UniqueElementData&);
204 210
205 void traceAfterDispatch(Visitor*); 211 void traceAfterDispatch(Visitor*);
206 212
207 // FIXME: We might want to support sharing element data for elements with 213 // FIXME: We might want to support sharing element data for elements with
208 // presentation attribute style. Lots of table cells likely have the same 214 // presentation attribute style. Lots of table cells likely have the same
209 // attributes. Most modern pages don't use presentation attributes though 215 // attributes. Most modern pages don't use presentation attributes though
210 // so this might not make sense. 216 // so this might not make sense.
211 mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle; 217 mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle;
212 Vector<Attribute, 4> m_attributeVector; 218 Vector<Attribute, 4> m_attributeVector;
213 }; 219 };
214 220
215 #if !ENABLE(OILPAN) 221 #if !ENABLE(OILPAN)
216 inline void ElementData::deref() 222 inline void ElementData::deref()
217 { 223 {
218 if (!derefBase()) 224 if (!derefBase())
219 return; 225 return;
220 destroy(); 226 destroy();
221 } 227 }
222 #endif 228 #endif
223 229
224 inline size_t ElementData::attributeCount() const
225 {
226 if (isUnique())
227 return static_cast<const UniqueElementData*>(this)->m_attributeVector.si ze();
228 return m_arraySize;
229 }
230
231 inline const StylePropertySet* ElementData::presentationAttributeStyle() const 230 inline const StylePropertySet* ElementData::presentationAttributeStyle() const
232 { 231 {
233 if (!m_isUnique) 232 if (!m_isUnique)
234 return 0; 233 return 0;
235 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeS tyle.get(); 234 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeS tyle.get();
236 } 235 }
237 236
238 inline const Attribute* ElementData::findAttributeByName(const AtomicString& nam e, bool shouldIgnoreAttributeCase) const 237 inline const Attribute* AttributeCollection::get(const AtomicString& name, bool shouldIgnoreCase) const
239 { 238 {
240 size_t index = findAttributeIndexByName(name, shouldIgnoreAttributeCase); 239 size_t index = find(name, shouldIgnoreCase);
241 if (index != kNotFound) 240 return index != kNotFound ? &at(index) : 0;
242 return &attributeAt(index);
243 return 0;
244 } 241 }
245 242
246 inline const Attribute* ElementData::attributeBase() const 243 inline size_t AttributeCollection::find(const QualifiedName& name, bool shouldIg noreCase) const
247 { 244 {
248 if (m_isUnique) 245 const_iterator end = this->end();
249 return static_cast<const UniqueElementData*>(this)->m_attributeVector.be gin();
250 return static_cast<const ShareableElementData*>(this)->m_attributeArray;
251 }
252
253 inline size_t ElementData::findAttributeIndexByName(const QualifiedName& name, b ool shouldIgnoreCase) const
254 {
255 AttributeCollection attributes = this->attributes();
256 AttributeCollection::const_iterator end = attributes.end();
257 unsigned index = 0; 246 unsigned index = 0;
258 for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it, ++index) { 247 for (const_iterator it = begin(); it != end; ++it, ++index) {
259 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) 248 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase))
260 return index; 249 return index;
261 } 250 }
262 return kNotFound; 251 return kNotFound;
263 } 252 }
264 253
265 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th at the caller 254 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th at the caller
266 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). 255 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not).
267 inline size_t ElementData::findAttributeIndexByName(const AtomicString& name, bo ol shouldIgnoreAttributeCase) const 256 inline size_t AttributeCollection::find(const AtomicString& name, bool shouldIgn oreCase) const
268 { 257 {
269 bool doSlowCheck = shouldIgnoreAttributeCase; 258 bool doSlowCheck = shouldIgnoreCase;
270 259
271 // Optimize for the case where the attribute exists and its name exactly mat ches. 260 // Optimize for the case where the attribute exists and its name exactly mat ches.
272 AttributeCollection attributes = this->attributes(); 261 const_iterator end = this->end();
273 AttributeCollection::const_iterator end = attributes.end();
274 unsigned index = 0; 262 unsigned index = 0;
275 for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it, ++index) { 263 for (const_iterator it = begin(); it != end; ++it, ++index) {
276 // FIXME: Why check the prefix? Namespaces should be all that matter. 264 // FIXME: Why check the prefix? Namespaces should be all that matter.
277 // Most attributes (all of HTML and CSS) have no namespace. 265 // Most attributes (all of HTML and CSS) have no namespace.
278 if (!it->name().hasPrefix()) { 266 if (!it->name().hasPrefix()) {
279 if (name == it->localName()) 267 if (name == it->localName())
280 return index; 268 return index;
281 } else { 269 } else {
282 doSlowCheck = true; 270 doSlowCheck = true;
283 } 271 }
284 } 272 }
285 273
286 if (doSlowCheck) 274 if (doSlowCheck)
287 return findAttributeIndexByNameSlowCase(name, shouldIgnoreAttributeCase) ; 275 return findSlowCase(name, shouldIgnoreCase);
288 return kNotFound; 276 return kNotFound;
289 } 277 }
290 278
291 inline AttributeCollection ElementData::attributes() const 279 inline AttributeCollection ElementData::attributes() const
292 { 280 {
293 if (isUnique()) { 281 if (isUnique())
294 const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueEl ementData*>(this)->m_attributeVector; 282 return static_cast<const UniqueElementData*>(this)->attributes();
295 return AttributeCollection(attributeVector.data(), attributeVector.size( )); 283 return static_cast<const ShareableElementData*>(this)->attributes();
296 }
297 return AttributeCollection(static_cast<const ShareableElementData*>(this)->m _attributeArray, m_arraySize);
298 } 284 }
299 285
300 inline const Attribute* ElementData::findAttributeByName(const QualifiedName& na me) const 286 inline AttributeCollection ShareableElementData::attributes() const
301 { 287 {
302 AttributeCollection attributes = this->attributes(); 288 return AttributeCollection(m_attributeArray, m_arraySize);
303 AttributeCollection::const_iterator end = attributes.end(); 289 }
304 for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { 290
291 inline AttributeCollection UniqueElementData::attributes() const
292 {
293 return AttributeCollection(m_attributeVector.data(), m_attributeVector.size( ));
294 }
295
296 inline const Attribute* AttributeCollection::get(const QualifiedName& name) cons t
297 {
298 const_iterator end = this->end();
299 for (const_iterator it = begin(); it != end; ++it) {
305 if (it->name().matches(name)) 300 if (it->name().matches(name))
306 return it; 301 return it;
307 } 302 }
308 return 0; 303 return 0;
309 } 304 }
310 305
311 inline const Attribute& ElementData::attributeAt(unsigned index) const
312 {
313 RELEASE_ASSERT(index < attributeCount());
314 ASSERT(attributeBase() + index);
315 return *(attributeBase() + index);
316 }
317
318 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam e, const AtomicString& value) 306 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam e, const AtomicString& value)
319 { 307 {
320 m_attributeVector.append(Attribute(attributeName, value)); 308 m_attributeVector.append(Attribute(attributeName, value));
321 } 309 }
322 310
323 inline void UniqueElementData::removeAttributeAt(size_t index) 311 inline void UniqueElementData::removeAttributeAt(size_t index)
324 { 312 {
325 m_attributeVector.remove(index); 313 m_attributeVector.remove(index);
326 } 314 }
327 315
328 inline Attribute& UniqueElementData::attributeAt(unsigned index) 316 inline Attribute& UniqueElementData::attributeAt(unsigned index)
329 { 317 {
330 return m_attributeVector.at(index); 318 return m_attributeVector.at(index);
331 } 319 }
332 320
333 } // namespace WebCore 321 } // namespace WebCore
334 322
335 #endif // ElementData_h 323 #endif // ElementData_h
OLDNEW
« no previous file with comments | « Source/core/dom/Element.cpp ('k') | Source/core/dom/ElementData.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698