1 | /* |
2 | * Copyright (C) 2005-2017 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 | #pragma once |
22 | |
23 | #include <wtf/HashTraits.h> |
24 | #include <wtf/NeverDestroyed.h> |
25 | #include <wtf/text/AtomString.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 { |
36 | WTF_MAKE_FAST_ALLOCATED; |
37 | public: |
38 | class QualifiedNameImpl : public RefCounted<QualifiedNameImpl> { |
39 | public: |
40 | static Ref<QualifiedNameImpl> create(const AtomString& prefix, const AtomString& localName, const AtomString& namespaceURI) |
41 | { |
42 | return adoptRef(*new QualifiedNameImpl(prefix, localName, namespaceURI)); |
43 | } |
44 | |
45 | WEBCORE_EXPORT ~QualifiedNameImpl(); |
46 | |
47 | unsigned computeHash() const; |
48 | |
49 | mutable unsigned m_existingHash { 0 }; |
50 | const AtomString m_prefix; |
51 | const AtomString m_localName; |
52 | const AtomString m_namespace; |
53 | mutable AtomString m_localNameUpper; |
54 | |
55 | #if ENABLE(JIT) |
56 | static ptrdiff_t localNameMemoryOffset() { return OBJECT_OFFSETOF(QualifiedNameImpl, m_localName); } |
57 | static ptrdiff_t namespaceMemoryOffset() { return OBJECT_OFFSETOF(QualifiedNameImpl, m_namespace); } |
58 | #endif |
59 | |
60 | private: |
61 | QualifiedNameImpl(const AtomString& prefix, const AtomString& localName, const AtomString& namespaceURI) |
62 | : m_prefix(prefix) |
63 | , m_localName(localName) |
64 | , m_namespace(namespaceURI) |
65 | { |
66 | ASSERT(!namespaceURI.isEmpty() || namespaceURI.isNull()); |
67 | } |
68 | }; |
69 | |
70 | WEBCORE_EXPORT QualifiedName(const AtomString& prefix, const AtomString& localName, const AtomString& namespaceURI); |
71 | explicit QualifiedName(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } |
72 | bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } |
73 | #ifdef QNAME_DEFAULT_CONSTRUCTOR |
74 | QualifiedName() { } |
75 | #endif |
76 | |
77 | bool operator==(const QualifiedName& other) const { return m_impl == other.m_impl; } |
78 | bool operator!=(const QualifiedName& other) const { return !(*this == other); } |
79 | |
80 | bool matches(const QualifiedName& other) const { return m_impl == other.m_impl || (localName() == other.localName() && namespaceURI() == other.namespaceURI()); } |
81 | |
82 | bool hasPrefix() const { return !m_impl->m_prefix.isNull(); } |
83 | void setPrefix(const AtomString& prefix) { *this = QualifiedName(prefix, localName(), namespaceURI()); } |
84 | |
85 | const AtomString& prefix() const { return m_impl->m_prefix; } |
86 | const AtomString& localName() const { return m_impl->m_localName; } |
87 | const AtomString& namespaceURI() const { return m_impl->m_namespace; } |
88 | |
89 | // Uppercased localName, cached for efficiency |
90 | const AtomString& localNameUpper() const; |
91 | |
92 | String toString() const; |
93 | |
94 | QualifiedNameImpl* impl() const { return m_impl.get(); } |
95 | #if ENABLE(JIT) |
96 | static ptrdiff_t implMemoryOffset() { return OBJECT_OFFSETOF(QualifiedName, m_impl); } |
97 | #endif |
98 | |
99 | // Init routine for globals |
100 | WEBCORE_EXPORT static void init(); |
101 | |
102 | private: |
103 | static QualifiedNameImpl* hashTableDeletedValue() { return RefPtr<QualifiedNameImpl>::hashTableDeletedValue(); } |
104 | |
105 | RefPtr<QualifiedNameImpl> m_impl; |
106 | }; |
107 | |
108 | extern LazyNeverDestroyed<const QualifiedName> anyName; |
109 | inline const QualifiedName& anyQName() { return anyName; } |
110 | |
111 | const QualifiedName& nullQName(); |
112 | |
113 | inline bool operator==(const AtomString& a, const QualifiedName& q) { return a == q.localName(); } |
114 | inline bool operator!=(const AtomString& a, const QualifiedName& q) { return a != q.localName(); } |
115 | inline bool operator==(const QualifiedName& q, const AtomString& a) { return a == q.localName(); } |
116 | inline bool operator!=(const QualifiedName& q, const AtomString& a) { return a != q.localName(); } |
117 | |
118 | inline unsigned hashComponents(const QualifiedNameComponents& buf) |
119 | { |
120 | return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf); |
121 | } |
122 | |
123 | struct QualifiedNameHash { |
124 | static unsigned hash(const QualifiedName& name) { return hash(name.impl()); } |
125 | |
126 | static unsigned hash(const QualifiedName::QualifiedNameImpl* name) |
127 | { |
128 | if (!name->m_existingHash) |
129 | name->m_existingHash = name->computeHash(); |
130 | return name->m_existingHash; |
131 | } |
132 | |
133 | static bool equal(const QualifiedName& a, const QualifiedName& b) { return a == b; } |
134 | static bool equal(const QualifiedName::QualifiedNameImpl* a, const QualifiedName::QualifiedNameImpl* b) { return a == b; } |
135 | |
136 | static const bool safeToCompareToEmptyOrDeleted = false; |
137 | }; |
138 | |
139 | inline String QualifiedName::toString() const |
140 | { |
141 | if (!hasPrefix()) |
142 | return localName(); |
143 | |
144 | return prefix().string() + ':' + localName().string(); |
145 | } |
146 | |
147 | } // namespace WebCore |
148 | |
149 | namespace WTF { |
150 | |
151 | template<typename T> struct DefaultHash; |
152 | |
153 | template<> struct DefaultHash<WebCore::QualifiedName> { |
154 | typedef WebCore::QualifiedNameHash Hash; |
155 | }; |
156 | |
157 | template<> struct HashTraits<WebCore::QualifiedName> : SimpleClassHashTraits<WebCore::QualifiedName> { |
158 | static const bool emptyValueIsZero = false; |
159 | static WebCore::QualifiedName emptyValue() { return WebCore::nullQName(); } |
160 | }; |
161 | |
162 | } // namespace WTF |
163 | |