diff options
Diffstat (limited to 'WebCore/dom/NamedAttrMap.cpp')
-rw-r--r-- | WebCore/dom/NamedAttrMap.cpp | 195 |
1 files changed, 72 insertions, 123 deletions
diff --git a/WebCore/dom/NamedAttrMap.cpp b/WebCore/dom/NamedAttrMap.cpp index d1a39a7..8944b79 100644 --- a/WebCore/dom/NamedAttrMap.cpp +++ b/WebCore/dom/NamedAttrMap.cpp @@ -3,7 +3,7 @@ * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2001 Peter Kelly (pmk@post.com) * (C) 2001 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * (C) 2007 Eric Seidel (eric@webkit.org) * * This library is free software; you can redistribute it and/or @@ -39,16 +39,9 @@ static inline bool shouldIgnoreAttributeCase(const Element* e) return e && e->document()->isHTMLDocument() && e->isHTMLElement(); } -NamedAttrMap::NamedAttrMap(Element *e) - : element(e) - , attrs(0) - , len(0) -{ -} - NamedAttrMap::~NamedAttrMap() { - NamedAttrMap::clearAttributes(); // virtual method, so qualify just to be explicit + NamedAttrMap::clearAttributes(); // virtual function, qualify to be explicit and slightly faster } bool NamedAttrMap::isMappedAttributeMap() const @@ -58,12 +51,11 @@ bool NamedAttrMap::isMappedAttributeMap() const PassRefPtr<Node> NamedAttrMap::getNamedItem(const String& name) const { - String localName = shouldIgnoreAttributeCase(element) ? name.lower() : name; - Attribute* a = getAttributeItem(localName); + Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); if (!a) return 0; - return a->createAttrIfNeeded(element); + return a->createAttrIfNeeded(m_element); } PassRefPtr<Node> NamedAttrMap::getNamedItemNS(const String& namespaceURI, const String& localName) const @@ -73,8 +65,7 @@ PassRefPtr<Node> NamedAttrMap::getNamedItemNS(const String& namespaceURI, const PassRefPtr<Node> NamedAttrMap::removeNamedItem(const String& name, ExceptionCode& ec) { - String localName = shouldIgnoreAttributeCase(element) ? name.lower() : name; - Attribute* a = getAttributeItem(localName); + Attribute* a = getAttributeItem(name, shouldIgnoreAttributeCase(m_element)); if (!a) { ec = NOT_FOUND_ERR; return 0; @@ -94,28 +85,18 @@ PassRefPtr<Node> NamedAttrMap::getNamedItem(const QualifiedName& name) const if (!a) return 0; - return a->createAttrIfNeeded(element); + return a->createAttrIfNeeded(m_element); } PassRefPtr<Node> NamedAttrMap::setNamedItem(Node* arg, ExceptionCode& ec) { -#ifdef ANDROID_FIX - if (!element || !arg) { -#else - if (!element) { -#endif + if (!m_element || !arg) { ec = NOT_FOUND_ERR; return 0; } - // NO_MODIFICATION_ALLOWED_ERR: Raised if this map is readonly. - if (isReadOnlyNode()) { - ec = NO_MODIFICATION_ALLOWED_ERR; - return 0; - } - // WRONG_DOCUMENT_ERR: Raised if arg was created from a different document than the one that created this map. - if (arg->document() != element->document()) { + if (arg->document() != m_element->document()) { ec = WRONG_DOCUMENT_ERR; return 0; } @@ -140,12 +121,12 @@ PassRefPtr<Node> NamedAttrMap::setNamedItem(Node* arg, ExceptionCode& ec) } if (a->name() == idAttr) - element->updateId(old ? old->value() : nullAtom, a->value()); + m_element->updateId(old ? old->value() : nullAtom, a->value()); // ### slightly inefficient - resizes attribute array twice. RefPtr<Node> r; if (old) { - r = old->createAttrIfNeeded(element); + r = old->createAttrIfNeeded(m_element); removeAttribute(a->name()); } @@ -158,183 +139,155 @@ PassRefPtr<Node> NamedAttrMap::setNamedItem(Node* arg, ExceptionCode& ec) // because of removeNamedItem, removeNamedItemNS, and removeAttributeNode. PassRefPtr<Node> NamedAttrMap::removeNamedItem(const QualifiedName& name, ExceptionCode& ec) { - // ### should this really be raised when the attribute to remove isn't there at all? - // NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly - if (isReadOnlyNode()) { - ec = NO_MODIFICATION_ALLOWED_ERR; - return 0; - } - Attribute* a = getAttributeItem(name); if (!a) { ec = NOT_FOUND_ERR; return 0; } - RefPtr<Node> r = a->createAttrIfNeeded(element); + RefPtr<Node> r = a->createAttrIfNeeded(m_element); if (name == idAttr) - element->updateId(a->value(), nullAtom); + m_element->updateId(a->value(), nullAtom); removeAttribute(name); return r.release(); } -PassRefPtr<Node> NamedAttrMap::item ( unsigned index ) const +PassRefPtr<Node> NamedAttrMap::item (unsigned index) const { - if (index >= len) + if (index >= length()) return 0; - return attrs[index]->createAttrIfNeeded(element); + return m_attributes[index]->createAttrIfNeeded(m_element); } -Attribute* NamedAttrMap::getAttributeItem(const String& name) const +// We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller +// can tune the behaviour (hasAttribute is case sensitive whereas getAttribute is not). +Attribute* NamedAttrMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const { + unsigned len = length(); for (unsigned i = 0; i < len; ++i) { - if (!attrs[i]->name().hasPrefix() && - attrs[i]->name().localName() == name) - return attrs[i]; - - if (attrs[i]->name().toString() == name) - return attrs[i]; + if (!m_attributes[i]->name().hasPrefix() && + m_attributes[i]->name().localName() == name) + return m_attributes[i].get(); + + if (shouldIgnoreAttributeCase ? equalIgnoringCase(m_attributes[i]->name().toString(), name) : name == m_attributes[i]->name().toString()) + return m_attributes[i].get(); } return 0; } Attribute* NamedAttrMap::getAttributeItem(const QualifiedName& name) const { + unsigned len = length(); for (unsigned i = 0; i < len; ++i) { - if (attrs[i]->name().matches(name)) - return attrs[i]; + if (m_attributes[i]->name().matches(name)) + return m_attributes[i].get(); } return 0; } void NamedAttrMap::clearAttributes() { - if (attrs) { - for (unsigned i = 0; i < len; i++) { - if (attrs[i]->attr()) - attrs[i]->attr()->m_element = 0; - attrs[i]->deref(); - } - fastFree(attrs); - attrs = 0; - } - len = 0; + unsigned len = length(); + for (unsigned i = 0; i < len; i++) + if (Attr* attr = m_attributes[i]->attr()) + attr->m_element = 0; + + m_attributes.clear(); } void NamedAttrMap::detachFromElement() { // we allow a NamedAttrMap w/o an element in case someone still has a reference // to if after the element gets deleted - but the map is now invalid - element = 0; + m_element = 0; clearAttributes(); } -NamedAttrMap& NamedAttrMap::operator=(const NamedAttrMap& other) +void NamedAttrMap::setAttributes(const NamedAttrMap& other) { // clone all attributes in the other map, but attach to our element - if (!element) - return *this; + if (!m_element) + return; // If assigning the map changes the id attribute, we need to call // updateId. - Attribute *oldId = getAttributeItem(idAttr); Attribute *newId = other.getAttributeItem(idAttr); if (oldId || newId) - element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); + m_element->updateId(oldId ? oldId->value() : nullAtom, newId ? newId->value() : nullAtom); clearAttributes(); - len = other.len; - attrs = static_cast<Attribute **>(fastMalloc(len * sizeof(Attribute *))); - - // first initialize attrs vector, then call attributeChanged on it - // this allows attributeChanged to use getAttribute - for (unsigned i = 0; i < len; i++) { - attrs[i] = other.attrs[i]->clone(); - attrs[i]->ref(); - } + unsigned newLength = other.length(); + m_attributes.resize(newLength); + for (unsigned i = 0; i < newLength; i++) + m_attributes[i] = other.m_attributes[i]->clone(); // FIXME: This is wasteful. The class list could be preserved on a copy, and we // wouldn't have to waste time reparsing the attribute. // The derived class, HTMLNamedAttrMap, which manages a parsed class list for the CLASS attribute, // will update its member variable when parse attribute is called. - for(unsigned i = 0; i < len; i++) - element->attributeChanged(attrs[i], true); - - return *this; + for (unsigned i = 0; i < newLength; i++) + m_element->attributeChanged(m_attributes[i].get(), true); } void NamedAttrMap::addAttribute(PassRefPtr<Attribute> prpAttribute) { - Attribute* attribute = prpAttribute.releaseRef(); // The attrs array will own this pointer. - + RefPtr<Attribute> attribute = prpAttribute; + // Add the attribute to the list - attrs = static_cast<Attribute**>(fastRealloc(attrs, (len + 1) * sizeof(Attribute*))); - attrs[len++] = attribute; + m_attributes.append(attribute); if (Attr* attr = attribute->attr()) - attr->m_element = element; + attr->m_element = m_element; // Notify the element that the attribute has been added, and dispatch appropriate mutation events // Note that element may be null here if we are called from insertAttr() during parsing - if (element) { - element->attributeChanged(attribute); - // Because of our updateStyleAttributeIfNeeded() style modification events are never sent at the right time, so don't bother sending them. + if (m_element) { + m_element->attributeChanged(attribute.get()); + // Because of our updateStyleAttribute() style modification events are never sent at the right time, so don't bother sending them. if (attribute->name() != styleAttr) { - element->dispatchAttrAdditionEvent(attribute); - element->dispatchSubtreeModifiedEvent(false); + m_element->dispatchAttrAdditionEvent(attribute.get()); + m_element->dispatchSubtreeModifiedEvent(); } } } void NamedAttrMap::removeAttribute(const QualifiedName& name) { - unsigned index = len+1; + unsigned len = length(); + unsigned index = len + 1; for (unsigned i = 0; i < len; ++i) - if (attrs[i]->name().matches(name)) { + if (m_attributes[i]->name().matches(name)) { index = i; break; } - if (index >= len) return; + if (index >= len) + return; // Remove the attribute from the list - Attribute* attr = attrs[index]; - if (attrs[index]->attr()) - attrs[index]->attr()->m_element = 0; - if (len == 1) { - fastFree(attrs); - attrs = 0; - len = 0; - } else { - Attribute **newAttrs = static_cast<Attribute **>(fastMalloc((len - 1) * sizeof(Attribute *))); - unsigned i; - for (i = 0; i < unsigned(index); i++) - newAttrs[i] = attrs[i]; - len--; - for (; i < len; i++) - newAttrs[i] = attrs[i+1]; - fastFree(attrs); - attrs = newAttrs; - } + RefPtr<Attribute> attr = m_attributes[index].get(); + if (Attr* a = m_attributes[index]->attr()) + a->m_element = 0; + + m_attributes.remove(index); // Notify the element that the attribute has been removed // dispatch appropriate mutation events - if (element && !attr->m_value.isNull()) { + if (m_element && !attr->m_value.isNull()) { AtomicString value = attr->m_value; attr->m_value = nullAtom; - element->attributeChanged(attr); + m_element->attributeChanged(attr.get()); attr->m_value = value; } - if (element) { - element->dispatchAttrRemovalEvent(attr); - element->dispatchSubtreeModifiedEvent(false); + if (m_element) { + m_element->dispatchAttrRemovalEvent(attr.get()); + m_element->dispatchSubtreeModifiedEvent(); } - attr->deref(); } bool NamedAttrMap::mapsEquivalent(const NamedAttrMap* otherMap) const @@ -342,10 +295,11 @@ bool NamedAttrMap::mapsEquivalent(const NamedAttrMap* otherMap) const if (!otherMap) return false; - if (length() != otherMap->length()) + unsigned len = length(); + if (len != otherMap->length()) return false; - for (unsigned i = 0; i < length(); i++) { + for (unsigned i = 0; i < len; i++) { Attribute *attr = attributeItem(i); Attribute *otherAttr = otherMap->getAttributeItem(attr->name()); @@ -356,9 +310,4 @@ bool NamedAttrMap::mapsEquivalent(const NamedAttrMap* otherMap) const return true; } -bool NamedAttrMap::isReadOnlyNode() -{ - return element && element->isReadOnlyNode(); -} - } |