|
1 /* |
|
2 * Copyright (C) 2005, 2006, 2009 Apple Inc. All rights reserved. |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public License |
|
15 * along with this library; see the file COPYING.LIB. If not, write to |
|
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
17 * Boston, MA 02110-1301, USA. |
|
18 * |
|
19 */ |
|
20 |
|
21 #ifndef QualifiedName_h |
|
22 #define QualifiedName_h |
|
23 |
|
24 #include "AtomicString.h" |
|
25 #include <wtf/HashTraits.h> |
|
26 |
|
27 namespace WebCore { |
|
28 |
|
29 struct QualifiedNameComponents { |
|
30 StringImpl* m_prefix; |
|
31 StringImpl* m_localName; |
|
32 StringImpl* m_namespace; |
|
33 }; |
|
34 |
|
35 class QualifiedName : public FastAllocBase { |
|
36 public: |
|
37 class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> { |
|
38 public: |
|
39 static PassRefPtr<QualifiedNameImpl> create(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI) |
|
40 { |
|
41 return adoptRef(new QualifiedNameImpl(prefix, localName, namespaceURI)); |
|
42 } |
|
43 |
|
44 const AtomicString m_prefix; |
|
45 const AtomicString m_localName; |
|
46 const AtomicString m_namespace; |
|
47 mutable AtomicString m_localNameUpper; |
|
48 |
|
49 private: |
|
50 QualifiedNameImpl(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI) |
|
51 : m_prefix(prefix) |
|
52 , m_localName(localName) |
|
53 , m_namespace(namespaceURI) |
|
54 { |
|
55 ASSERT(!namespaceURI.isEmpty() || namespaceURI.isNull()); |
|
56 } |
|
57 }; |
|
58 |
|
59 QualifiedName(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); |
|
60 QualifiedName(const AtomicString& prefix, const char* localName, const AtomicString& namespaceURI); |
|
61 QualifiedName(WTF::HashTableDeletedValueType) : m_impl(hashTableDeletedValue()) { } |
|
62 bool isHashTableDeletedValue() const { return m_impl == hashTableDeletedValue(); } |
|
63 ~QualifiedName() { deref(); } |
|
64 #ifdef QNAME_DEFAULT_CONSTRUCTOR |
|
65 QualifiedName() : m_impl(0) { } |
|
66 #endif |
|
67 |
|
68 QualifiedName(const QualifiedName& other) : m_impl(other.m_impl) { ref(); } |
|
69 const QualifiedName& operator=(const QualifiedName& other) { other.ref(); deref(); m_impl = other.m_impl; return *this; } |
|
70 |
|
71 bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; } |
|
72 bool operator!=(const QualifiedName& other) const { return !(*this == other); } |
|
73 |
|
74 bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); } |
|
75 |
|
76 bool hasPrefix() const { return m_impl->m_prefix != nullAtom; } |
|
77 void setPrefix(const AtomicString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); } |
|
78 |
|
79 const AtomicString& prefix() const { return m_impl->m_prefix; } |
|
80 const AtomicString& localName() const { return m_impl->m_localName; } |
|
81 const AtomicString& namespaceURI() const { return m_impl->m_namespace; } |
|
82 |
|
83 // Uppercased localName, cached for efficiency |
|
84 const AtomicString& localNameUpper() const; |
|
85 |
|
86 String toString() const; |
|
87 |
|
88 QualifiedNameImpl* impl() const { return m_impl; } |
|
89 |
|
90 // Init routine for globals |
|
91 static void init(); |
|
92 |
|
93 private: |
|
94 void init(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); |
|
95 void ref() const { m_impl->ref(); } |
|
96 void deref(); |
|
97 |
|
98 static QualifiedNameImpl* hashTableDeletedValue() { return RefPtr<QualifiedNameImpl>::hashTableDeletedValue(); } |
|
99 |
|
100 QualifiedNameImpl* m_impl; |
|
101 }; |
|
102 |
|
103 #ifndef WEBCORE_QUALIFIEDNAME_HIDE_GLOBALS |
|
104 extern const QualifiedName anyName; |
|
105 inline const QualifiedName& anyQName() { return anyName; } |
|
106 #endif |
|
107 |
|
108 inline bool operator==(const AtomicString& a, const QualifiedName& q) { return a == q.localName(); } |
|
109 inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a != q.localName(); } |
|
110 inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); } |
|
111 inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a != q.localName(); } |
|
112 |
|
113 inline unsigned hashComponents(const QualifiedNameComponents& buf) |
|
114 { |
|
115 ASSERT(sizeof(QualifiedNameComponents) % (sizeof(uint16_t) * 2) == 0); |
|
116 |
|
117 unsigned l = sizeof(QualifiedNameComponents) / (sizeof(uint16_t) * 2); |
|
118 const uint16_t* s = reinterpret_cast<const uint16_t*>(&buf); |
|
119 uint32_t hash = WTF::stringHashingStartValue; |
|
120 |
|
121 // Main loop |
|
122 for (; l > 0; l--) { |
|
123 hash += s[0]; |
|
124 uint32_t tmp = (s[1] << 11) ^ hash; |
|
125 hash = (hash << 16) ^ tmp; |
|
126 s += 2; |
|
127 hash += hash >> 11; |
|
128 } |
|
129 |
|
130 // Force "avalanching" of final 127 bits |
|
131 hash ^= hash << 3; |
|
132 hash += hash >> 5; |
|
133 hash ^= hash << 2; |
|
134 hash += hash >> 15; |
|
135 hash ^= hash << 10; |
|
136 |
|
137 // this avoids ever returning a hash code of 0, since that is used to |
|
138 // signal "hash not computed yet", using a value that is likely to be |
|
139 // effectively the same as 0 when the low bits are masked |
|
140 if (hash == 0) |
|
141 hash = 0x80000000; |
|
142 |
|
143 return hash; |
|
144 } |
|
145 |
|
146 struct QualifiedNameHash { |
|
147 static unsigned hash(const QualifiedName& name) { return hash(name.impl()); } |
|
148 |
|
149 static unsigned hash(const QualifiedName::QualifiedNameImpl* name) |
|
150 { |
|
151 QualifiedNameComponents c = { name->m_prefix.impl(), name->m_localName.impl(), name->m_namespace.impl() }; |
|
152 return hashComponents(c); |
|
153 } |
|
154 |
|
155 static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; } |
|
156 static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; } |
|
157 |
|
158 static const bool safeToCompareToEmptyOrDeleted = false; |
|
159 }; |
|
160 |
|
161 } |
|
162 |
|
163 namespace WTF { |
|
164 |
|
165 template<typename T> struct DefaultHash; |
|
166 |
|
167 template<> struct DefaultHash<WebCore::QualifiedName> { |
|
168 typedef WebCore::QualifiedNameHash Hash; |
|
169 }; |
|
170 |
|
171 template<> struct HashTraits<WebCore::QualifiedName> : GenericHashTraits<WebCore::QualifiedName> { |
|
172 static const bool emptyValueIsZero = false; |
|
173 static WebCore::QualifiedName emptyValue() { return WebCore::QualifiedName(WebCore::nullAtom, WebCore::nullAtom, WebCore::nullAtom); } |
|
174 static void constructDeletedValue(WebCore::QualifiedName& slot) { new (&slot) WebCore::QualifiedName(WTF::HashTableDeletedValue); } |
|
175 static bool isDeletedValue(const WebCore::QualifiedName& slot) { return slot.isHashTableDeletedValue(); } |
|
176 }; |
|
177 } |
|
178 |
|
179 #endif |