Chromium Code Reviews| 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. | |
|
esprehn
2014/05/28 20:03:54
Do we really need to add Apple copyrights?
Inactive
2014/05/29 15:14:01
I don't know what the exact rules are but it seems
Inactive
2014/05/29 15:17:59
Also, this CL seems to hint that I am not the only
| |
| 3 * | 4 * |
| 4 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 6 * met: | 7 * met: |
| 7 * | 8 * |
| 8 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 11 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 12 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 13 * in the documentation and/or other materials provided with the |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 35 #include "core/dom/SpaceSplitString.h" | 36 #include "core/dom/SpaceSplitString.h" |
| 36 #include "wtf/text/AtomicString.h" | 37 #include "wtf/text/AtomicString.h" |
| 37 | 38 |
| 38 namespace WebCore { | 39 namespace WebCore { |
| 39 | 40 |
| 40 class Attr; | 41 class Attr; |
| 41 class ShareableElementData; | 42 class ShareableElementData; |
| 42 class StylePropertySet; | 43 class StylePropertySet; |
| 43 class UniqueElementData; | 44 class UniqueElementData; |
| 44 | 45 |
| 46 class AttributeConstIterator { | |
| 47 public: | |
| 48 AttributeConstIterator(const Attribute* array, unsigned index) | |
| 49 : m_array(array) | |
| 50 , m_index(index) | |
| 51 { } | |
| 52 | |
| 53 const Attribute* operator*() const { return &m_array[m_index]; } | |
| 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 { | |
|
esprehn
2014/05/28 20:03:54
This class seems unnecessary.
Inactive
2014/05/29 15:14:01
The main reason for this class (besides avoiding m
| |
| 68 public: | |
| 69 AttributeIteratorAccessor(const Attribute* array, unsigned size) | |
| 70 : m_array(array) | |
| 71 , m_size(size) | |
| 72 { } | |
| 73 | |
| 74 AttributeConstIterator begin() const { return AttributeConstIterator(m_array , 0); } | |
| 75 AttributeConstIterator end() const { return AttributeConstIterator(m_array, m_size); } | |
| 76 | |
| 77 unsigned size() const { return m_size; } | |
| 78 | |
| 79 private: | |
| 80 const Attribute* m_array; | |
| 81 unsigned m_size; | |
| 82 }; | |
| 83 | |
| 45 // ElementData represents very common, but not necessarily unique to an element, | 84 // ElementData represents very common, but not necessarily unique to an element, |
| 46 // data such as attributes, inline style, and parsed class names and ids. | 85 // data such as attributes, inline style, and parsed class names and ids. |
| 47 class ElementData : public RefCounted<ElementData> { | 86 class ElementData : public RefCounted<ElementData> { |
| 48 WTF_MAKE_FAST_ALLOCATED; | 87 WTF_MAKE_FAST_ALLOCATED; |
| 49 public: | 88 public: |
| 50 // Override RefCounted's deref() to ensure operator delete is called on | 89 // Override RefCounted's deref() to ensure operator delete is called on |
| 51 // the appropriate subclass type. | 90 // the appropriate subclass type. |
| 52 void deref(); | 91 void deref(); |
| 53 | 92 |
| 54 void clearClass() const { m_classNames.clear(); } | 93 void clearClass() const { m_classNames.clear(); } |
| 55 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_ classNames.set(className, shouldFoldCase); } | 94 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_ classNames.set(className, shouldFoldCase); } |
| 56 const SpaceSplitString& classNames() const { return m_classNames; } | 95 const SpaceSplitString& classNames() const { return m_classNames; } |
| 57 | 96 |
| 58 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu tion; } | 97 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu tion; } |
| 59 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle Resolution = newId; } | 98 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle Resolution = newId; } |
| 60 | 99 |
| 61 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } | 100 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } |
| 62 | 101 |
| 63 const StylePropertySet* presentationAttributeStyle() const; | 102 const StylePropertySet* presentationAttributeStyle() const; |
| 64 | 103 |
| 65 // This is not a trivial getter and its return value should be cached for pe rformance. | 104 // This is not a trivial getter and its return value should be cached for pe rformance. |
| 66 size_t length() const; | 105 size_t length() const; |
| 67 bool isEmpty() const { return !length(); } | 106 bool isEmpty() const { return !length(); } |
| 68 | 107 |
| 108 AttributeIteratorAccessor attributesIterator() const; | |
|
esprehn
2014/05/28 20:03:54
Can we just add attributesBegin() and attributesEn
Inactive
2014/05/29 15:14:01
If we do this then we will call ElementData::isUni
Inactive
2014/05/30 13:16:03
Note that we had issues before with callers not ca
| |
| 109 | |
| 69 const Attribute& attributeItem(unsigned index) const; | 110 const Attribute& attributeItem(unsigned index) const; |
| 70 const Attribute* getAttributeItem(const QualifiedName&) const; | 111 const Attribute* getAttributeItem(const QualifiedName&) const; |
| 71 size_t getAttributeItemIndex(const QualifiedName&, bool shouldIgnoreCase = f alse) const; | 112 size_t getAttributeItemIndex(const QualifiedName&, bool shouldIgnoreCase = f alse) const; |
| 72 size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttr ibuteCase) const; | 113 size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttr ibuteCase) const; |
| 73 size_t getAttrIndex(Attr*) const; | 114 size_t getAttrIndex(Attr*) const; |
| 74 | 115 |
| 75 bool hasID() const { return !m_idForStyleResolution.isNull(); } | 116 bool hasID() const { return !m_idForStyleResolution.isNull(); } |
| 76 bool hasClass() const { return !m_classNames.isNull(); } | 117 bool hasClass() const { return !m_classNames.isNull(); } |
| 77 | 118 |
| 78 bool isEquivalent(const ElementData* other) const; | 119 bool isEquivalent(const ElementData* other) const; |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 | 236 |
| 196 inline const Attribute* ElementData::attributeBase() const | 237 inline const Attribute* ElementData::attributeBase() const |
| 197 { | 238 { |
| 198 if (m_isUnique) | 239 if (m_isUnique) |
| 199 return static_cast<const UniqueElementData*>(this)->m_attributeVector.be gin(); | 240 return static_cast<const UniqueElementData*>(this)->m_attributeVector.be gin(); |
| 200 return static_cast<const ShareableElementData*>(this)->m_attributeArray; | 241 return static_cast<const ShareableElementData*>(this)->m_attributeArray; |
| 201 } | 242 } |
| 202 | 243 |
| 203 inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name, bool shouldIgnoreCase) const | 244 inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name, bool shouldIgnoreCase) const |
| 204 { | 245 { |
| 205 const Attribute* begin = attributeBase(); | 246 AttributeIteratorAccessor attributes = attributesIterator(); |
| 206 // Cache length for performance as ElementData::length() contains a conditio nal branch. | 247 AttributeConstIterator end = attributes.end(); |
| 207 unsigned length = this->length(); | 248 for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { |
| 208 for (unsigned i = 0; i < length; ++i) { | 249 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) |
| 209 const Attribute& attribute = begin[i]; | 250 return it.index(); |
| 210 if (attribute.name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase) ) | |
| 211 return i; | |
| 212 } | 251 } |
| 213 return kNotFound; | 252 return kNotFound; |
| 214 } | 253 } |
| 215 | 254 |
| 216 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th at the caller | 255 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th at the caller |
| 217 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). | 256 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). |
| 218 inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const | 257 inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const |
| 219 { | 258 { |
| 220 // Cache length for performance as ElementData::length() contains a conditio nal branch. | |
| 221 unsigned length = this->length(); | |
| 222 bool doSlowCheck = shouldIgnoreAttributeCase; | 259 bool doSlowCheck = shouldIgnoreAttributeCase; |
| 223 | 260 |
| 224 // Optimize for the case where the attribute exists and its name exactly mat ches. | 261 // Optimize for the case where the attribute exists and its name exactly mat ches. |
| 225 const Attribute* begin = attributeBase(); | 262 AttributeIteratorAccessor attributes = attributesIterator(); |
| 226 for (unsigned i = 0; i < length; ++i) { | 263 AttributeConstIterator end = attributes.end(); |
| 227 const Attribute& attribute = begin[i]; | 264 for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { |
| 228 // FIXME: Why check the prefix? Namespaces should be all that matter. | 265 // FIXME: Why check the prefix? Namespaces should be all that matter. |
| 229 // Most attributes (all of HTML and CSS) have no namespace. | 266 // Most attributes (all of HTML and CSS) have no namespace. |
| 230 if (!attribute.name().hasPrefix()) { | 267 if (!it->name().hasPrefix()) { |
| 231 if (name == attribute.localName()) | 268 if (name == it->localName()) |
| 232 return i; | 269 return it.index(); |
| 233 } else { | 270 } else { |
| 234 doSlowCheck = true; | 271 doSlowCheck = true; |
| 235 } | 272 } |
| 236 } | 273 } |
| 237 | 274 |
| 238 if (doSlowCheck) | 275 if (doSlowCheck) |
| 239 return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase); | 276 return getAttributeItemIndexSlowCase(name, shouldIgnoreAttributeCase); |
| 240 return kNotFound; | 277 return kNotFound; |
| 241 } | 278 } |
| 242 | 279 |
| 280 inline AttributeIteratorAccessor ElementData::attributesIterator() const | |
| 281 { | |
| 282 if (isUnique()) { | |
| 283 const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueEl ementData*>(this)->m_attributeVector; | |
| 284 return AttributeIteratorAccessor(attributeVector.data(), attributeVector .size()); | |
| 285 } | |
| 286 return AttributeIteratorAccessor(static_cast<const ShareableElementData*>(th is)->m_attributeArray, m_arraySize); | |
| 287 } | |
| 288 | |
| 243 inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const | 289 inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const |
| 244 { | 290 { |
| 245 const Attribute* begin = attributeBase(); | 291 AttributeIteratorAccessor attributes = attributesIterator(); |
| 246 unsigned length = this->length(); | 292 AttributeConstIterator end = attributes.end(); |
| 247 for (unsigned i = 0; i < length; ++i) { | 293 for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { |
| 248 const Attribute& attribute = begin[i]; | 294 if (it->name().matches(name)) |
| 249 if (attribute.name().matches(name)) | 295 return *it; |
| 250 return &attribute; | |
| 251 } | 296 } |
| 252 return 0; | 297 return 0; |
| 253 } | 298 } |
| 254 | 299 |
| 255 inline const Attribute& ElementData::attributeItem(unsigned index) const | 300 inline const Attribute& ElementData::attributeItem(unsigned index) const |
| 256 { | 301 { |
| 257 RELEASE_ASSERT(index < length()); | 302 RELEASE_ASSERT(index < length()); |
| 258 ASSERT(attributeBase() + index); | 303 ASSERT(attributeBase() + index); |
| 259 return *(attributeBase() + index); | 304 return *(attributeBase() + index); |
| 260 } | 305 } |
| 261 | 306 |
| 262 inline void UniqueElementData::addAttribute(const QualifiedName& attributeName, const AtomicString& value) | 307 inline void UniqueElementData::addAttribute(const QualifiedName& attributeName, const AtomicString& value) |
| 263 { | 308 { |
| 264 m_attributeVector.append(Attribute(attributeName, value)); | 309 m_attributeVector.append(Attribute(attributeName, value)); |
| 265 } | 310 } |
| 266 | 311 |
| 267 inline void UniqueElementData::removeAttribute(size_t index) | 312 inline void UniqueElementData::removeAttribute(size_t index) |
| 268 { | 313 { |
| 269 m_attributeVector.remove(index); | 314 m_attributeVector.remove(index); |
| 270 } | 315 } |
| 271 | 316 |
| 272 inline Attribute& UniqueElementData::attributeItem(unsigned index) | 317 inline Attribute& UniqueElementData::attributeItem(unsigned index) |
| 273 { | 318 { |
| 274 return m_attributeVector.at(index); | 319 return m_attributeVector.at(index); |
| 275 } | 320 } |
| 276 | 321 |
| 277 } // namespace WebCore | 322 } // namespace WebCore |
| 278 | 323 |
| 279 #endif // ElementData_h | 324 #endif // ElementData_h |
| OLD | NEW |