1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Peter Kelly (pmk (at) post.com) 5 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 6 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2010 Apple Inc. All rights reserved. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 25 #ifndef NamedNodeMap_h 26 #define NamedNodeMap_h 27 28 #include "Attribute.h" 29 #include "SpaceSplitString.h" 30 31 namespace WebCore { 32 33 class Node; 34 35 typedef int ExceptionCode; 36 37 class NamedNodeMap : public RefCounted<NamedNodeMap> { 38 friend class Element; 39 public: 40 static PassRefPtr<NamedNodeMap> create(Element* element = 0) 41 { 42 return adoptRef(new NamedNodeMap(element)); 43 } 44 45 ~NamedNodeMap(); 46 47 // Public DOM interface. 48 49 PassRefPtr<Node> getNamedItem(const String& name) const; 50 PassRefPtr<Node> removeNamedItem(const String& name, ExceptionCode&); 51 52 PassRefPtr<Node> getNamedItemNS(const String& namespaceURI, const String& localName) const; 53 PassRefPtr<Node> removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode&); 54 55 PassRefPtr<Node> getNamedItem(const QualifiedName& name) const; 56 PassRefPtr<Node> removeNamedItem(const QualifiedName& name, ExceptionCode&); 57 PassRefPtr<Node> setNamedItem(Node*, ExceptionCode&); 58 PassRefPtr<Node> setNamedItemNS(Node*, ExceptionCode&); 59 60 PassRefPtr<Node> item(unsigned index) const; 61 size_t length() const { return m_attributes.size(); } 62 bool isEmpty() const { return !length(); } 63 64 // Internal interface. 65 66 void setAttributes(const NamedNodeMap&); 67 68 Attribute* attributeItem(unsigned index) const { return m_attributes[index].get(); } 69 Attribute* getAttributeItem(const QualifiedName&) const; 70 71 void copyAttributesToVector(Vector<RefPtr<Attribute> >&); 72 73 void shrinkToLength() { m_attributes.shrinkCapacity(length()); } 74 void reserveInitialCapacity(unsigned capacity) { m_attributes.reserveInitialCapacity(capacity); } 75 76 // Used during parsing: only inserts if not already there. No error checking! 77 void insertAttribute(PassRefPtr<Attribute> newAttribute, bool allowDuplicates) 78 { 79 ASSERT(!m_element); 80 if (allowDuplicates || !getAttributeItem(newAttribute->name())) 81 addAttribute(newAttribute); 82 } 83 84 const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; } 85 void setIdForStyleResolution(const AtomicString& newId) { m_idForStyleResolution = newId; } 86 87 // FIXME: These two functions should be merged if possible. 88 bool mapsEquivalent(const NamedNodeMap* otherMap) const; 89 bool mappedMapsEquivalent(const NamedNodeMap* otherMap) const; 90 91 // These functions do no error checking. 92 void addAttribute(PassRefPtr<Attribute>); 93 void removeAttribute(const QualifiedName&); 94 95 Element* element() const { return m_element; } 96 97 void clearClass() { m_classNames.clear(); } 98 void setClass(const String&); 99 const SpaceSplitString& classNames() const { return m_classNames; } 100 101 bool hasMappedAttributes() const { return m_mappedAttributeCount > 0; } 102 void declRemoved() { m_mappedAttributeCount--; } 103 void declAdded() { m_mappedAttributeCount++; } 104 105 private: 106 NamedNodeMap(Element* element) 107 : m_mappedAttributeCount(0) 108 , m_element(element) 109 { 110 } 111 112 void detachAttributesFromElement(); 113 void detachFromElement(); 114 Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const; 115 Attribute* getAttributeItemSlowCase(const String& name, bool shouldIgnoreAttributeCase) const; 116 void clearAttributes(); 117 int declCount() const; 118 119 int m_mappedAttributeCount; 120 SpaceSplitString m_classNames; 121 Element* m_element; 122 Vector<RefPtr<Attribute> > m_attributes; 123 AtomicString m_idForStyleResolution; 124 }; 125 126 inline Attribute* NamedNodeMap::getAttributeItem(const QualifiedName& name) const 127 { 128 unsigned len = length(); 129 for (unsigned i = 0; i < len; ++i) { 130 if (m_attributes[i]->name().matches(name)) 131 return m_attributes[i].get(); 132 } 133 return 0; 134 } 135 136 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so that the caller 137 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is not). 138 inline Attribute* NamedNodeMap::getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const 139 { 140 unsigned len = length(); 141 bool doSlowCheck = shouldIgnoreAttributeCase; 142 143 // Optimize for the case where the attribute exists and its name exactly matches. 144 for (unsigned i = 0; i < len; ++i) { 145 const QualifiedName& attrName = m_attributes[i]->name(); 146 if (!attrName.hasPrefix()) { 147 if (name == attrName.localName()) 148 return m_attributes[i].get(); 149 } else 150 doSlowCheck = true; 151 } 152 153 if (doSlowCheck) 154 return getAttributeItemSlowCase(name, shouldIgnoreAttributeCase); 155 return 0; 156 } 157 158 } // namespace WebCore 159 160 #endif // NamedNodeMap_h 161