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() { deref(); } 62 #ifdef QNAME_DEFAULT_CONSTRUCTOR 63 QualifiedName() : m_impl(0) { } 64 #endif 65 66 QualifiedName(const QualifiedName& other) : m_impl(other.m_impl) { ref(); } 67 const QualifiedName& operator=(const QualifiedName& other) { other.ref(); deref(); m_impl = other.m_impl; return *this; } 68 69 bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; } 70 bool operator!=(const QualifiedName& other) const { return !(*this == other); } 71 72 bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); } 73 74 bool hasPrefix() const { return m_impl->m_prefix != nullAtom; } 75 void setPrefix(const AtomicString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); } 76 77 const AtomicString& prefix() const { return m_impl->m_prefix; } 78 const AtomicString& localName() const { return m_impl->m_localName; } 79 const AtomicString& namespaceURI() const { return m_impl->m_namespace; } 80 81 // Uppercased localName, cached for efficiency 82 const AtomicString& localNameUpper() const; 83 84 String toString() const; 85 86 QualifiedNameImpl* impl() const { return m_impl; } 87 88 // Init routine for globals 89 static void init(); 90 91 private: 92 void init(const AtomicString& prefix, const AtomicString& localName, const AtomicString& namespaceURI); 93 void ref() const { m_impl->ref(); } 94 void deref(); 95 96 QualifiedNameImpl* m_impl; 97 }; 98 99 #ifndef WEBCORE_QUALIFIEDNAME_HIDE_GLOBALS 100 extern const QualifiedName anyName; 101 inline const QualifiedName& anyQName() { return anyName; } 102 #endif 103 104 inline bool operator==(const AtomicString& a, const QualifiedName& q) { return a == q.localName(); } 105 inline bool operator!=(const AtomicString& a, const QualifiedName& q) { return a != q.localName(); } 106 inline bool operator==(const QualifiedName& q, const AtomicString& a) { return a == q.localName(); } 107 inline bool operator!=(const QualifiedName& q, const AtomicString& a) { return a != q.localName(); } 108 109 inline unsigned hashComponents(const QualifiedNameComponents& buf) 110 { 111 ASSERT(sizeof(QualifiedNameComponents) % (sizeof(uint16_t) * 2) == 0); 112 113 unsigned l = sizeof(QualifiedNameComponents) / (sizeof(uint16_t) * 2); 114 const uint16_t* s = reinterpret_cast<const uint16_t*>(&buf); 115 uint32_t hash = WTF::stringHashingStartValue; 116 117 // Main loop 118 for (; l > 0; l--) { 119 hash += s[0]; 120 uint32_t tmp = (s[1] << 11) ^ hash; 121 hash = (hash << 16) ^ tmp; 122 s += 2; 123 hash += hash >> 11; 124 } 125 126 // Force "avalanching" of final 127 bits 127 hash ^= hash << 3; 128 hash += hash >> 5; 129 hash ^= hash << 2; 130 hash += hash >> 15; 131 hash ^= hash << 10; 132 133 // this avoids ever returning a hash code of 0, since that is used to 134 // signal "hash not computed yet", using a value that is likely to be 135 // effectively the same as 0 when the low bits are masked 136 if (hash == 0) 137 hash = 0x80000000; 138 139 return hash; 140 } 141 142 struct QualifiedNameHash { 143 static unsigned hash(const QualifiedName& name) { return hash(name.impl()); } 144 145 static unsigned hash(const QualifiedName::QualifiedNameImpl* name) 146 { 147 QualifiedNameComponents c = { name->m_prefix.impl(), name->m_localName.impl(), name->m_namespace.impl() }; 148 return hashComponents(c); 149 } 150 151 static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; } 152 static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; } 153 154 static const bool safeToCompareToEmptyOrDeleted = false; 155 }; 156 157 } 158 159 namespace WTF { 160 161 template<typename T> struct DefaultHash; 162 163 template<> struct DefaultHash<WebCore::QualifiedName> { 164 typedef WebCore::QualifiedNameHash Hash; 165 }; 166 167 template<> struct HashTraits<WebCore::QualifiedName> : GenericHashTraits<WebCore::QualifiedName> { 168 static const bool emptyValueIsZero = false; 169 static WebCore::QualifiedName emptyValue() { return WebCore::QualifiedName(WebCore::nullAtom, WebCore::nullAtom, WebCore::nullAtom); } 170 static void constructDeletedValue(WebCore::QualifiedName& slot) { new (&slot) WebCore::QualifiedName(WebCore::nullAtom, WebCore::AtomicString(HashTableDeletedValue), WebCore::nullAtom); } 171 static bool isDeletedValue(const WebCore::QualifiedName& slot) { return slot.localName().isHashTableDeletedValue(); } 172 }; 173 } 174 175 #endif 176