Chromium Code Reviews| Index: Source/core/dom/ElementData.h |
| diff --git a/Source/core/dom/ElementData.h b/Source/core/dom/ElementData.h |
| index e209f7fb1b8d76c4ed606df990128f10ce8e1580..99f2115f0f4afdccfa5e3b36fd7ba1d95613cafd 100644 |
| --- a/Source/core/dom/ElementData.h |
| +++ b/Source/core/dom/ElementData.h |
| @@ -1,5 +1,6 @@ |
| /* |
| * Copyright (C) 2013 Google Inc. All rights reserved. |
| + * 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
|
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| @@ -42,6 +43,44 @@ class ShareableElementData; |
| class StylePropertySet; |
| class UniqueElementData; |
| +class AttributeConstIterator { |
| +public: |
| + AttributeConstIterator(const Attribute* array, unsigned index) |
| + : m_array(array) |
| + , m_index(index) |
| + { } |
| + |
| + const Attribute* operator*() const { return &m_array[m_index]; } |
| + const Attribute* operator->() const { return &m_array[m_index]; } |
| + AttributeConstIterator& operator++() { ++m_index; return *this; } |
| + |
| + bool operator==(const AttributeConstIterator& other) const { return m_index == other.m_index; } |
| + bool operator!=(const AttributeConstIterator& other) const { return !(*this == other); } |
| + |
| + unsigned index() const { return m_index; } |
| + |
| +private: |
| + const Attribute* m_array; |
| + unsigned m_index; |
| +}; |
| + |
| +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
|
| +public: |
| + AttributeIteratorAccessor(const Attribute* array, unsigned size) |
| + : m_array(array) |
| + , m_size(size) |
| + { } |
| + |
| + AttributeConstIterator begin() const { return AttributeConstIterator(m_array, 0); } |
| + AttributeConstIterator end() const { return AttributeConstIterator(m_array, m_size); } |
| + |
| + unsigned size() const { return m_size; } |
| + |
| +private: |
| + const Attribute* m_array; |
| + unsigned m_size; |
| +}; |
| + |
| // ElementData represents very common, but not necessarily unique to an element, |
| // data such as attributes, inline style, and parsed class names and ids. |
| class ElementData : public RefCounted<ElementData> { |
| @@ -66,6 +105,8 @@ public: |
| size_t length() const; |
| bool isEmpty() const { return !length(); } |
| + 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
|
| + |
| const Attribute& attributeItem(unsigned index) const; |
| const Attribute* getAttributeItem(const QualifiedName&) const; |
| size_t getAttributeItemIndex(const QualifiedName&, bool shouldIgnoreCase = false) const; |
| @@ -202,13 +243,11 @@ inline const Attribute* ElementData::attributeBase() const |
| inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name, bool shouldIgnoreCase) const |
| { |
| - const Attribute* begin = attributeBase(); |
| - // Cache length for performance as ElementData::length() contains a conditional branch. |
| - unsigned length = this->length(); |
| - for (unsigned i = 0; i < length; ++i) { |
| - const Attribute& attribute = begin[i]; |
| - if (attribute.name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) |
| - return i; |
| + AttributeIteratorAccessor attributes = attributesIterator(); |
| + AttributeConstIterator end = attributes.end(); |
| + for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { |
| + if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) |
| + return it.index(); |
| } |
| return kNotFound; |
| } |
| @@ -217,19 +256,17 @@ inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name, bool |
| // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). |
| inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const |
| { |
| - // Cache length for performance as ElementData::length() contains a conditional branch. |
| - unsigned length = this->length(); |
| bool doSlowCheck = shouldIgnoreAttributeCase; |
| // Optimize for the case where the attribute exists and its name exactly matches. |
| - const Attribute* begin = attributeBase(); |
| - for (unsigned i = 0; i < length; ++i) { |
| - const Attribute& attribute = begin[i]; |
| + AttributeIteratorAccessor attributes = attributesIterator(); |
| + AttributeConstIterator end = attributes.end(); |
| + for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { |
| // FIXME: Why check the prefix? Namespaces should be all that matter. |
| // Most attributes (all of HTML and CSS) have no namespace. |
| - if (!attribute.name().hasPrefix()) { |
| - if (name == attribute.localName()) |
| - return i; |
| + if (!it->name().hasPrefix()) { |
| + if (name == it->localName()) |
| + return it.index(); |
| } else { |
| doSlowCheck = true; |
| } |
| @@ -240,14 +277,22 @@ inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool |
| return kNotFound; |
| } |
| +inline AttributeIteratorAccessor ElementData::attributesIterator() const |
| +{ |
| + if (isUnique()) { |
| + const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueElementData*>(this)->m_attributeVector; |
| + return AttributeIteratorAccessor(attributeVector.data(), attributeVector.size()); |
| + } |
| + return AttributeIteratorAccessor(static_cast<const ShareableElementData*>(this)->m_attributeArray, m_arraySize); |
| +} |
| + |
| inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const |
| { |
| - const Attribute* begin = attributeBase(); |
| - unsigned length = this->length(); |
| - for (unsigned i = 0; i < length; ++i) { |
| - const Attribute& attribute = begin[i]; |
| - if (attribute.name().matches(name)) |
| - return &attribute; |
| + AttributeIteratorAccessor attributes = attributesIterator(); |
| + AttributeConstIterator end = attributes.end(); |
| + for (AttributeConstIterator it = attributes.begin(); it != end; ++it) { |
| + if (it->name().matches(name)) |
| + return *it; |
| } |
| return 0; |
| } |