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
27namespace WebCore {
28
29struct QualifiedNameComponents {
30 StringImpl* m_prefix;
31 StringImpl* m_localName;
32 StringImpl* m_namespace;
33};
34
35class QualifiedName {
36 WTF_MAKE_FAST_ALLOCATED;
37public:
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
102private:
103 static QualifiedNameImpl* hashTableDeletedValue() { return RefPtr<QualifiedNameImpl>::hashTableDeletedValue(); }
104
105 RefPtr<QualifiedNameImpl> m_impl;
106};
107
108extern LazyNeverDestroyed<const QualifiedName> anyName;
109inline const QualifiedName& anyQName() { return anyName; }
110
111const QualifiedName& nullQName();
112
113inline bool operator==(const AtomString& a, const QualifiedName& q) { return a == q.localName(); }
114inline bool operator!=(const AtomString& a, const QualifiedName& q) { return a != q.localName(); }
115inline bool operator==(const QualifiedName& q, const AtomString& a) { return a == q.localName(); }
116inline bool operator!=(const QualifiedName& q, const AtomString& a) { return a != q.localName(); }
117
118inline unsigned hashComponents(const QualifiedNameComponents& buf)
119{
120 return StringHasher::hashMemory<sizeof(QualifiedNameComponents)>(&buf);
121}
122
123struct 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
139inline String QualifiedName::toString() const
140{
141 if (!hasPrefix())
142 return localName();
143
144 return prefix().string() + ':' + localName().string();
145}
146
147} // namespace WebCore
148
149namespace 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