| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright (C) 2013 Google Inc. All rights reserved. | 2  * Copyright (C) 2013 Google Inc. All rights reserved. | 
| 3  * Copyright (C) 2014 Apple Inc. All rights reserved. | 3  * Copyright (C) 2014 Apple Inc. All rights reserved. | 
| 4  * Copyright (C) 2014 Samsung Electronics. All rights reserved. | 4  * Copyright (C) 2014 Samsung Electronics. All rights reserved. | 
| 5  * | 5  * | 
| 6  * Redistribution and use in source and binary forms, with or without | 6  * Redistribution and use in source and binary forms, with or without | 
| 7  * modification, are permitted provided that the following conditions are | 7  * modification, are permitted provided that the following conditions are | 
| 8  * met: | 8  * met: | 
| 9  * | 9  * | 
| 10  *     * Redistributions of source code must retain the above copyright | 10  *     * Redistributions of source code must retain the above copyright | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| 27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 31  */ | 31  */ | 
| 32 | 32 | 
| 33 #ifndef AttributeCollection_h | 33 #ifndef AttributeCollection_h | 
| 34 #define AttributeCollection_h | 34 #define AttributeCollection_h | 
| 35 | 35 | 
|  | 36 #include "core/dom/Attr.h" | 
| 36 #include "core/dom/Attribute.h" | 37 #include "core/dom/Attribute.h" | 
|  | 38 #include "wtf/Vector.h" | 
| 37 | 39 | 
| 38 namespace blink { | 40 namespace blink { | 
| 39 | 41 | 
| 40 class Attr; | 42 template <typename Container, typename ContainerMemberType = Container> | 
|  | 43 class AttributeCollectionGeneric { | 
|  | 44 public: | 
|  | 45     typedef typename Container::ValueType ValueType; | 
|  | 46     typedef ValueType* iterator; | 
| 41 | 47 | 
| 42 class AttributeCollection { | 48     AttributeCollectionGeneric(Container& attributes) | 
|  | 49         : m_attributes(attributes) | 
|  | 50     { } | 
|  | 51 | 
|  | 52     ValueType& operator[](unsigned index) const { return at(index); } | 
|  | 53     ValueType& at(unsigned index) const | 
|  | 54     { | 
|  | 55         RELEASE_ASSERT(index < size()); | 
|  | 56         return begin()[index]; | 
|  | 57     } | 
|  | 58 | 
|  | 59     iterator begin() const { return m_attributes.data(); } | 
|  | 60     iterator end() const { return begin() + size(); } | 
|  | 61 | 
|  | 62     unsigned size() const { return m_attributes.size(); } | 
|  | 63     bool isEmpty() const { return !size(); } | 
|  | 64 | 
|  | 65     iterator find(const QualifiedName&) const; | 
|  | 66     iterator find(const AtomicString& name, bool shouldIgnoreCase) const; | 
|  | 67     size_t findIndex(const QualifiedName&, bool shouldIgnoreCase = false) const; | 
|  | 68     size_t findIndex(const AtomicString& name, bool shouldIgnoreCase) const; | 
|  | 69     size_t findIndex(Attr*) const; | 
|  | 70 | 
|  | 71 protected: | 
|  | 72     size_t findSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase
     ) const; | 
|  | 73 | 
|  | 74     ContainerMemberType m_attributes; | 
|  | 75 }; | 
|  | 76 | 
|  | 77 class AttributeArray { | 
| 43 public: | 78 public: | 
| 44     typedef const Attribute* const_iterator; | 79     typedef const Attribute ValueType; | 
| 45 | 80 | 
| 46     AttributeCollection(const Attribute* array, unsigned size) | 81     AttributeArray(const Attribute* array, unsigned size) | 
| 47         : m_array(array) | 82         : m_array(array) | 
| 48         , m_size(size) | 83         , m_size(size) | 
| 49     { } | 84     { } | 
| 50 | 85 | 
| 51     const Attribute& operator[](unsigned index) const { return at(index); } | 86     const Attribute* data() const { return m_array; } | 
| 52     const Attribute& at(unsigned index) const |  | 
| 53     { |  | 
| 54         RELEASE_ASSERT(index < m_size); |  | 
| 55         return m_array[index]; |  | 
| 56     } |  | 
| 57 |  | 
| 58     const Attribute* find(const QualifiedName&) const; |  | 
| 59     const Attribute* find(const AtomicString& name, bool shouldIgnoreCase) const
     ; |  | 
| 60     size_t findIndex(const QualifiedName&, bool shouldIgnoreCase = false) const; |  | 
| 61     size_t findIndex(const AtomicString& name, bool shouldIgnoreCase) const; |  | 
| 62     size_t findIndex(Attr*) const; |  | 
| 63 |  | 
| 64     const_iterator begin() const { return m_array; } |  | 
| 65     const_iterator end() const { return m_array + m_size; } |  | 
| 66 |  | 
| 67     unsigned size() const { return m_size; } | 87     unsigned size() const { return m_size; } | 
| 68     bool isEmpty() const { return !m_size; } |  | 
| 69 | 88 | 
| 70 private: | 89 private: | 
| 71     size_t findSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase
     ) const; |  | 
| 72 |  | 
| 73     const Attribute* m_array; | 90     const Attribute* m_array; | 
| 74     unsigned m_size; | 91     unsigned m_size; | 
| 75 }; | 92 }; | 
| 76 | 93 | 
| 77 inline const Attribute* AttributeCollection::find(const AtomicString& name, bool
      shouldIgnoreCase) const | 94 class AttributeCollection : public AttributeCollectionGeneric<const AttributeArr
     ay> { | 
|  | 95 public: | 
|  | 96     typedef iterator const_iterator; | 
|  | 97 | 
|  | 98     AttributeCollection(const Attribute* array, unsigned size) | 
|  | 99         : AttributeCollectionGeneric<const AttributeArray>(AttributeArray(array,
      size)) | 
|  | 100     { } | 
|  | 101 }; | 
|  | 102 | 
|  | 103 typedef Vector<Attribute, 4> AttributeVector; | 
|  | 104 class MutableAttributeCollection : public AttributeCollectionGeneric<AttributeVe
     ctor, AttributeVector&> { | 
|  | 105 public: | 
|  | 106     explicit MutableAttributeCollection(AttributeVector& attributes) | 
|  | 107         : AttributeCollectionGeneric<AttributeVector, AttributeVector&>(attribut
     es) | 
|  | 108     { } | 
|  | 109 | 
|  | 110     // These functions do no error/duplicate checking. | 
|  | 111     void append(const QualifiedName&, const AtomicString& value); | 
|  | 112     void remove(unsigned index); | 
|  | 113 }; | 
|  | 114 | 
|  | 115 inline void MutableAttributeCollection::append(const QualifiedName& name, const 
     AtomicString& value) | 
|  | 116 { | 
|  | 117     m_attributes.append(Attribute(name, value)); | 
|  | 118 } | 
|  | 119 | 
|  | 120 inline void MutableAttributeCollection::remove(unsigned index) | 
|  | 121 { | 
|  | 122     m_attributes.remove(index); | 
|  | 123 } | 
|  | 124 | 
|  | 125 template <typename Container, typename ContainerMemberType> | 
|  | 126 inline typename AttributeCollectionGeneric<Container, ContainerMemberType>::iter
     ator AttributeCollectionGeneric<Container, ContainerMemberType>::find(const Atom
     icString& name, bool shouldIgnoreCase) const | 
| 78 { | 127 { | 
| 79     size_t index = findIndex(name, shouldIgnoreCase); | 128     size_t index = findIndex(name, shouldIgnoreCase); | 
| 80     return index != kNotFound ? &at(index) : 0; | 129     return index != kNotFound ? &at(index) : 0; | 
| 81 } | 130 } | 
| 82 | 131 | 
| 83 inline size_t AttributeCollection::findIndex(const QualifiedName& name, bool sho
     uldIgnoreCase) const | 132 template <typename Container, typename ContainerMemberType> | 
|  | 133 inline size_t AttributeCollectionGeneric<Container, ContainerMemberType>::findIn
     dex(const QualifiedName& name, bool shouldIgnoreCase) const | 
| 84 { | 134 { | 
| 85     const_iterator end = this->end(); | 135     iterator end = this->end(); | 
| 86     unsigned index = 0; | 136     unsigned index = 0; | 
| 87     for (const_iterator it = begin(); it != end; ++it, ++index) { | 137     for (iterator it = begin(); it != end; ++it, ++index) { | 
| 88         if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) | 138         if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) | 
| 89             return index; | 139             return index; | 
| 90     } | 140     } | 
| 91     return kNotFound; | 141     return kNotFound; | 
| 92 } | 142 } | 
| 93 | 143 | 
| 94 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th
     at the caller | 144 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th
     at the caller | 
| 95 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is
      not). | 145 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is
      not). | 
| 96 inline size_t AttributeCollection::findIndex(const AtomicString& name, bool shou
     ldIgnoreCase) const | 146 template <typename Container, typename ContainerMemberType> | 
|  | 147 inline size_t AttributeCollectionGeneric<Container, ContainerMemberType>::findIn
     dex(const AtomicString& name, bool shouldIgnoreCase) const | 
| 97 { | 148 { | 
| 98     bool doSlowCheck = shouldIgnoreCase; | 149     bool doSlowCheck = shouldIgnoreCase; | 
| 99 | 150 | 
| 100     // Optimize for the case where the attribute exists and its name exactly mat
     ches. | 151     // Optimize for the case where the attribute exists and its name exactly mat
     ches. | 
| 101     const_iterator end = this->end(); | 152     iterator end = this->end(); | 
| 102     unsigned index = 0; | 153     unsigned index = 0; | 
| 103     for (const_iterator it = begin(); it != end; ++it, ++index) { | 154     for (iterator it = begin(); it != end; ++it, ++index) { | 
| 104         // FIXME: Why check the prefix? Namespaces should be all that matter. | 155         // FIXME: Why check the prefix? Namespaces should be all that matter. | 
| 105         // Most attributes (all of HTML and CSS) have no namespace. | 156         // Most attributes (all of HTML and CSS) have no namespace. | 
| 106         if (!it->name().hasPrefix()) { | 157         if (!it->name().hasPrefix()) { | 
| 107             if (name == it->localName()) | 158             if (name == it->localName()) | 
| 108                 return index; | 159                 return index; | 
| 109         } else { | 160         } else { | 
| 110             doSlowCheck = true; | 161             doSlowCheck = true; | 
| 111         } | 162         } | 
| 112     } | 163     } | 
| 113 | 164 | 
| 114     if (doSlowCheck) | 165     if (doSlowCheck) | 
| 115         return findSlowCase(name, shouldIgnoreCase); | 166         return findSlowCase(name, shouldIgnoreCase); | 
| 116     return kNotFound; | 167     return kNotFound; | 
| 117 } | 168 } | 
| 118 | 169 | 
| 119 inline const Attribute* AttributeCollection::find(const QualifiedName& name) con
     st | 170 template <typename Container, typename ContainerMemberType> | 
|  | 171 inline typename AttributeCollectionGeneric<Container, ContainerMemberType>::iter
     ator AttributeCollectionGeneric<Container, ContainerMemberType>::find(const Qual
     ifiedName& name) const | 
| 120 { | 172 { | 
| 121     const_iterator end = this->end(); | 173     iterator end = this->end(); | 
| 122     for (const_iterator it = begin(); it != end; ++it) { | 174     for (iterator it = begin(); it != end; ++it) { | 
| 123         if (it->name().matches(name)) | 175         if (it->name().matches(name)) | 
| 124             return it; | 176             return it; | 
| 125     } | 177     } | 
| 126     return 0; | 178     return 0; | 
| 127 } | 179 } | 
| 128 | 180 | 
|  | 181 template <typename Container, typename ContainerMemberType> | 
|  | 182 size_t AttributeCollectionGeneric<Container, ContainerMemberType>::findIndex(Att
     r* attr) const | 
|  | 183 { | 
|  | 184     // This relies on the fact that Attr's QualifiedName == the Attribute's name
     . | 
|  | 185     iterator end = this->end(); | 
|  | 186     unsigned index = 0; | 
|  | 187     for (iterator it = begin(); it != end; ++it, ++index) { | 
|  | 188         if (it->name() == attr->qualifiedName()) | 
|  | 189             return index; | 
|  | 190     } | 
|  | 191     return kNotFound; | 
|  | 192 } | 
|  | 193 | 
|  | 194 template <typename Container, typename ContainerMemberType> | 
|  | 195 size_t AttributeCollectionGeneric<Container, ContainerMemberType>::findSlowCase(
     const AtomicString& name, bool shouldIgnoreAttributeCase) const | 
|  | 196 { | 
|  | 197     // Continue to checking case-insensitively and/or full namespaced names if n
     ecessary: | 
|  | 198     iterator end = this->end(); | 
|  | 199     unsigned index = 0; | 
|  | 200     for (iterator it = begin(); it != end; ++it, ++index) { | 
|  | 201         // FIXME: Why check the prefix? Namespace is all that should matter | 
|  | 202         // and all HTML/SVG attributes have a null namespace! | 
|  | 203         if (!it->name().hasPrefix()) { | 
|  | 204             if (shouldIgnoreAttributeCase && equalIgnoringCase(name, it->localNa
     me())) | 
|  | 205                 return index; | 
|  | 206         } else { | 
|  | 207             // FIXME: Would be faster to do this comparison without calling toSt
     ring, which | 
|  | 208             // generates a temporary string by concatenation. But this branch is
      only reached | 
|  | 209             // if the attribute name has a prefix, which is rare in HTML. | 
|  | 210             if (equalPossiblyIgnoringCase(name, it->name().toString(), shouldIgn
     oreAttributeCase)) | 
|  | 211                 return index; | 
|  | 212         } | 
|  | 213     } | 
|  | 214     return kNotFound; | 
|  | 215 } | 
|  | 216 | 
| 129 } // namespace blink | 217 } // namespace blink | 
| 130 | 218 | 
| 131 #endif // AttributeCollection_h | 219 #endif // AttributeCollection_h | 
| OLD | NEW | 
|---|