diff options
Diffstat (limited to 'Source/WebCore/dom/ElementAttributeData.cpp')
-rw-r--r-- | Source/WebCore/dom/ElementAttributeData.cpp | 97 |
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 |