OLD | NEW |
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 25 matching lines...) Expand all Loading... |
36 #include "core/dom/SpaceSplitString.h" | 36 #include "core/dom/SpaceSplitString.h" |
37 #include "wtf/text/AtomicString.h" | 37 #include "wtf/text/AtomicString.h" |
38 | 38 |
39 namespace WebCore { | 39 namespace WebCore { |
40 | 40 |
41 class Attr; | 41 class Attr; |
42 class ShareableElementData; | 42 class ShareableElementData; |
43 class StylePropertySet; | 43 class StylePropertySet; |
44 class UniqueElementData; | 44 class UniqueElementData; |
45 | 45 |
46 class AttributeConstIterator { | 46 class AttributeCollection { |
47 public: | 47 public: |
48 AttributeConstIterator(const Attribute* array, unsigned index) | 48 typedef const Attribute* const_iterator; |
49 : m_array(array) | |
50 , m_index(index) | |
51 { } | |
52 | 49 |
53 const Attribute* operator*() const { return &m_array[m_index]; } | 50 AttributeCollection(const Attribute* array, unsigned size) |
54 const Attribute* operator->() const { return &m_array[m_index]; } | |
55 AttributeConstIterator& operator++() { ++m_index; return *this; } | |
56 | |
57 bool operator==(const AttributeConstIterator& other) const { return m_index
== other.m_index; } | |
58 bool operator!=(const AttributeConstIterator& other) const { return !(*this
== other); } | |
59 | |
60 unsigned index() const { return m_index; } | |
61 | |
62 private: | |
63 const Attribute* m_array; | |
64 unsigned m_index; | |
65 }; | |
66 | |
67 class AttributeIteratorAccessor { | |
68 public: | |
69 AttributeIteratorAccessor(const Attribute* array, unsigned size) | |
70 : m_array(array) | 51 : m_array(array) |
71 , m_size(size) | 52 , m_size(size) |
72 { } | 53 { } |
73 | 54 |
74 AttributeConstIterator begin() const { return AttributeConstIterator(m_array
, 0); } | 55 const_iterator begin() const { return m_array; } |
75 AttributeConstIterator end() const { return AttributeConstIterator(m_array,
m_size); } | 56 const_iterator end() const { return m_array + m_size; } |
76 | 57 |
77 unsigned size() const { return m_size; } | 58 unsigned size() const { return m_size; } |
78 | 59 |
79 private: | 60 private: |
80 const Attribute* m_array; | 61 const Attribute* m_array; |
81 unsigned m_size; | 62 unsigned m_size; |
82 }; | 63 }; |
83 | 64 |
84 // ElementData represents very common, but not necessarily unique to an element, | 65 // ElementData represents very common, but not necessarily unique to an element, |
85 // data such as attributes, inline style, and parsed class names and ids. | 66 // data such as attributes, inline style, and parsed class names and ids. |
(...skipping 12 matching lines...) Expand all Loading... |
98 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle
Resolution = newId; } | 79 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle
Resolution = newId; } |
99 | 80 |
100 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } | 81 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } |
101 | 82 |
102 const StylePropertySet* presentationAttributeStyle() const; | 83 const StylePropertySet* presentationAttributeStyle() const; |
103 | 84 |
104 // This is not a trivial getter and its return value should be cached for pe
rformance. | 85 // This is not a trivial getter and its return value should be cached for pe
rformance. |
105 size_t attributeCount() const; | 86 size_t attributeCount() const; |
106 bool hasAttributes() const { return !!attributeCount(); } | 87 bool hasAttributes() const { return !!attributeCount(); } |
107 | 88 |
108 AttributeIteratorAccessor attributesIterator() const; | 89 AttributeCollection attributes() const; |
109 | 90 |
110 const Attribute& attributeAt(unsigned index) const; | 91 const Attribute& attributeAt(unsigned index) const; |
111 const Attribute* findAttributeByName(const QualifiedName&) const; | 92 const Attribute* findAttributeByName(const QualifiedName&) const; |
112 size_t findAttributeIndexByName(const QualifiedName&, bool shouldIgnoreCase
= false) const; | 93 size_t findAttributeIndexByName(const QualifiedName&, bool shouldIgnoreCase
= false) const; |
113 size_t findAttributeIndexByName(const AtomicString& name, bool shouldIgnoreA
ttributeCase) const; | 94 size_t findAttributeIndexByName(const AtomicString& name, bool shouldIgnoreA
ttributeCase) const; |
114 size_t findAttrNodeIndex(Attr*) const; | 95 size_t findAttrNodeIndex(Attr*) const; |
115 | 96 |
116 bool hasID() const { return !m_idForStyleResolution.isNull(); } | 97 bool hasID() const { return !m_idForStyleResolution.isNull(); } |
117 bool hasClass() const { return !m_classNames.isNull(); } | 98 bool hasClass() const { return !m_classNames.isNull(); } |
118 | 99 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 | 217 |
237 inline const Attribute* ElementData::attributeBase() const | 218 inline const Attribute* ElementData::attributeBase() const |
238 { | 219 { |
239 if (m_isUnique) | 220 if (m_isUnique) |
240 return static_cast<const UniqueElementData*>(this)->m_attributeVector.be
gin(); | 221 return static_cast<const UniqueElementData*>(this)->m_attributeVector.be
gin(); |
241 return static_cast<const ShareableElementData*>(this)->m_attributeArray; | 222 return static_cast<const ShareableElementData*>(this)->m_attributeArray; |
242 } | 223 } |
243 | 224 |
244 inline size_t ElementData::findAttributeIndexByName(const QualifiedName& name, b
ool shouldIgnoreCase) const | 225 inline size_t ElementData::findAttributeIndexByName(const QualifiedName& name, b
ool shouldIgnoreCase) const |
245 { | 226 { |
246 AttributeIteratorAccessor attributes = attributesIterator(); | 227 AttributeCollection attributes = this->attributes(); |
247 AttributeConstIterator end = attributes.end(); | 228 AttributeCollection::const_iterator end = attributes.end(); |
248 for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { | 229 unsigned index = 0; |
| 230 for (AttributeCollection::const_iterator it = attributes.begin(); it != end;
++it, ++index) { |
249 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) | 231 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) |
250 return it.index(); | 232 return index; |
251 } | 233 } |
252 return kNotFound; | 234 return kNotFound; |
253 } | 235 } |
254 | 236 |
255 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th
at the caller | 237 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th
at the caller |
256 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is
not). | 238 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is
not). |
257 inline size_t ElementData::findAttributeIndexByName(const AtomicString& name, bo
ol shouldIgnoreAttributeCase) const | 239 inline size_t ElementData::findAttributeIndexByName(const AtomicString& name, bo
ol shouldIgnoreAttributeCase) const |
258 { | 240 { |
259 bool doSlowCheck = shouldIgnoreAttributeCase; | 241 bool doSlowCheck = shouldIgnoreAttributeCase; |
260 | 242 |
261 // Optimize for the case where the attribute exists and its name exactly mat
ches. | 243 // Optimize for the case where the attribute exists and its name exactly mat
ches. |
262 AttributeIteratorAccessor attributes = attributesIterator(); | 244 AttributeCollection attributes = this->attributes(); |
263 AttributeConstIterator end = attributes.end(); | 245 AttributeCollection::const_iterator end = attributes.end(); |
264 for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { | 246 unsigned index = 0; |
| 247 for (AttributeCollection::const_iterator it = attributes.begin(); it != end;
++it, ++index) { |
265 // FIXME: Why check the prefix? Namespaces should be all that matter. | 248 // FIXME: Why check the prefix? Namespaces should be all that matter. |
266 // Most attributes (all of HTML and CSS) have no namespace. | 249 // Most attributes (all of HTML and CSS) have no namespace. |
267 if (!it->name().hasPrefix()) { | 250 if (!it->name().hasPrefix()) { |
268 if (name == it->localName()) | 251 if (name == it->localName()) |
269 return it.index(); | 252 return index; |
270 } else { | 253 } else { |
271 doSlowCheck = true; | 254 doSlowCheck = true; |
272 } | 255 } |
273 } | 256 } |
274 | 257 |
275 if (doSlowCheck) | 258 if (doSlowCheck) |
276 return findAttributeIndexByNameSlowCase(name, shouldIgnoreAttributeCase)
; | 259 return findAttributeIndexByNameSlowCase(name, shouldIgnoreAttributeCase)
; |
277 return kNotFound; | 260 return kNotFound; |
278 } | 261 } |
279 | 262 |
280 inline AttributeIteratorAccessor ElementData::attributesIterator() const | 263 inline AttributeCollection ElementData::attributes() const |
281 { | 264 { |
282 if (isUnique()) { | 265 if (isUnique()) { |
283 const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueEl
ementData*>(this)->m_attributeVector; | 266 const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueEl
ementData*>(this)->m_attributeVector; |
284 return AttributeIteratorAccessor(attributeVector.data(), attributeVector
.size()); | 267 return AttributeCollection(attributeVector.data(), attributeVector.size(
)); |
285 } | 268 } |
286 return AttributeIteratorAccessor(static_cast<const ShareableElementData*>(th
is)->m_attributeArray, m_arraySize); | 269 return AttributeCollection(static_cast<const ShareableElementData*>(this)->m
_attributeArray, m_arraySize); |
287 } | 270 } |
288 | 271 |
289 inline const Attribute* ElementData::findAttributeByName(const QualifiedName& na
me) const | 272 inline const Attribute* ElementData::findAttributeByName(const QualifiedName& na
me) const |
290 { | 273 { |
291 AttributeIteratorAccessor attributes = attributesIterator(); | 274 AttributeCollection attributes = this->attributes(); |
292 AttributeConstIterator end = attributes.end(); | 275 AttributeCollection::const_iterator end = attributes.end(); |
293 for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { | 276 for (AttributeCollection::const_iterator it = attributes.begin(); it != end;
++it) { |
294 if (it->name().matches(name)) | 277 if (it->name().matches(name)) |
295 return *it; | 278 return it; |
296 } | 279 } |
297 return 0; | 280 return 0; |
298 } | 281 } |
299 | 282 |
300 inline const Attribute& ElementData::attributeAt(unsigned index) const | 283 inline const Attribute& ElementData::attributeAt(unsigned index) const |
301 { | 284 { |
302 RELEASE_ASSERT(index < attributeCount()); | 285 RELEASE_ASSERT(index < attributeCount()); |
303 ASSERT(attributeBase() + index); | 286 ASSERT(attributeBase() + index); |
304 return *(attributeBase() + index); | 287 return *(attributeBase() + index); |
305 } | 288 } |
306 | 289 |
307 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam
e, const AtomicString& value) | 290 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam
e, const AtomicString& value) |
308 { | 291 { |
309 m_attributeVector.append(Attribute(attributeName, value)); | 292 m_attributeVector.append(Attribute(attributeName, value)); |
310 } | 293 } |
311 | 294 |
312 inline void UniqueElementData::removeAttributeAt(size_t index) | 295 inline void UniqueElementData::removeAttributeAt(size_t index) |
313 { | 296 { |
314 m_attributeVector.remove(index); | 297 m_attributeVector.remove(index); |
315 } | 298 } |
316 | 299 |
317 inline Attribute& UniqueElementData::attributeAt(unsigned index) | 300 inline Attribute& UniqueElementData::attributeAt(unsigned index) |
318 { | 301 { |
319 return m_attributeVector.at(index); | 302 return m_attributeVector.at(index); |
320 } | 303 } |
321 | 304 |
322 } // namespace WebCore | 305 } // namespace WebCore |
323 | 306 |
324 #endif // ElementData_h | 307 #endif // ElementData_h |
OLD | NEW |