summaryrefslogtreecommitdiff
path: root/Source/WebCore/dom/ElementAttributeData.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/dom/ElementAttributeData.cpp')
-rw-r--r--Source/WebCore/dom/ElementAttributeData.cpp97
1 files changed, 76 insertions, 21 deletions
diff --git a/Source/WebCore/dom/ElementAttributeData.cpp b/Source/WebCore/dom/ElementAttributeData.cpp
index cb8917a45..6527cf90a 100644
--- a/Source/WebCore/dom/ElementAttributeData.cpp
+++ b/Source/WebCore/dom/ElementAttributeData.cpp
@@ -32,47 +32,99 @@
namespace WebCore {
-typedef HashMap<pair<Element*, QualifiedName>, RefPtr<Attr> > AttrMap;
-static AttrMap& attrMap()
+typedef Vector<RefPtr<Attr> > AttrList;
+typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap;
+
+static AttrListMap& attrListMap()
{
- DEFINE_STATIC_LOCAL(AttrMap, map, ());
+ DEFINE_STATIC_LOCAL(AttrListMap, map, ());
return map;
}
-PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name)
+static AttrList* attrListForElement(Element* element)
{
- if (!m_attrCount)
+ ASSERT(element);
+ if (!element->hasAttrList())
return 0;
- return attrMap().get(std::make_pair(element, name)).get();
+ ASSERT(attrListMap().contains(element));
+ return attrListMap().get(element);
}
-PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name)
+static AttrList* ensureAttrListForElement(Element* element)
{
- AttrMap::AddResult result = attrMap().add(std::make_pair(element, name), 0);
- if (result.isNewEntry) {
- result.iterator->second = Attr::create(element, name);
- ++m_attrCount;
+ ASSERT(element);
+ if (element->hasAttrList()) {
+ ASSERT(attrListMap().contains(element));
+ return attrListMap().get(element);
}
+ ASSERT(!attrListMap().contains(element));
+ element->setHasAttrList();
+ AttrListMap::AddResult result = attrListMap().add(element, adoptPtr(new AttrList));
return result.iterator->second.get();
}
+static void removeAttrListForElement(Element* element)
+{
+ ASSERT(element);
+ ASSERT(element->hasAttrList());
+ ASSERT(attrListMap().contains(element));
+ attrListMap().remove(element);
+ element->clearHasAttrList();
+}
+
+static Attr* findAttrInList(AttrList* attrList, const QualifiedName& name)
+{
+ for (unsigned i = 0; i < attrList->size(); ++i) {
+ if (attrList->at(i)->qualifiedName() == name)
+ return attrList->at(i).get();
+ }
+ return 0;
+}
+
+PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name)
+{
+ if (AttrList* attrList = attrListForElement(element))
+ return findAttrInList(attrList, name);
+ return 0;
+}
+
+PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name)
+{
+ AttrList* attrList = ensureAttrListForElement(element);
+ RefPtr<Attr> attr = findAttrInList(attrList, name);
+ if (!attr) {
+ attr = Attr::create(element, name);
+ attrList->append(attr);
+ }
+ return attr.release();
+}
+
void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr)
{
- ASSERT(!attrMap().contains(std::make_pair(element, name)));
- attrMap().add(std::make_pair(element, name), attr);
+ AttrList* attrList = ensureAttrListForElement(element);
+
+ if (findAttrInList(attrList, name))
+ return;
+
+ attrList->append(attr);
attr->attachToElement(element);
- ++m_attrCount;
}
void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name)
{
- ASSERT(attrMap().contains(std::make_pair(element, name)));
- attrMap().remove(std::make_pair(element, name));
- --m_attrCount;
-}
+ AttrList* attrList = attrListForElement(element);
+ ASSERT(attrList);
+
+ for (unsigned i = 0; i < attrList->size(); ++i) {
+ if (attrList->at(i)->qualifiedName() == name) {
+ attrList->remove(i);
+ if (attrList->isEmpty())
+ removeAttrListForElement(element);
+ return;
+ }
+ }
-ElementAttributeData::~ElementAttributeData()
-{
+ ASSERT_NOT_REACHED();
}
void ElementAttributeData::setClass(const String& className, bool shouldFoldCase)
@@ -170,13 +222,16 @@ bool ElementAttributeData::isEquivalent(const ElementAttributeData* other) const
void ElementAttributeData::detachAttributesFromElement(Element* element)
{
- if (!m_attrCount)
+ if (!element->hasAttrList())
return;
for (unsigned i = 0; i < m_attributes.size(); ++i) {
if (RefPtr<Attr> attr = attrIfExists(element, m_attributes[i].name()))
attr->detachFromElementWithValue(m_attributes[i].value());
}
+
+ // The loop above should have cleaned out this element's Attr map.
+ ASSERT(!element->hasAttrList());
}
size_t ElementAttributeData::getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const