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 |