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

Unified Diff: Source/core/dom/ElementData.h

Issue 298253009: Add iterator object to iterate efficiently over an Element's attributes (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 6 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/dom/Element.cpp ('k') | Source/core/dom/ElementData.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
*
* 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 {
+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;
+
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;
}
« 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