| 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 |