1/*
2 * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <wtf/HashSet.h>
29#include <wtf/text/StringHash.h>
30#include <wtf/text/SymbolImpl.h>
31#include <wtf/text/WTFString.h>
32
33namespace WTF {
34
35// Since StringImpl* used for Symbol uid doesn't have a hash value reflecting the string content,
36// to compare with an external string in string contents, introduce SymbolRegistryKey.
37// SymbolRegistryKey holds a hash value reflecting the string content additionally.
38class SymbolRegistryKey {
39public:
40 SymbolRegistryKey() = default;
41 explicit SymbolRegistryKey(StringImpl* uid);
42 SymbolRegistryKey(WTF::HashTableDeletedValueType);
43
44 unsigned hash() const { return m_hash; }
45 StringImpl* impl() const { return m_impl; }
46
47 bool isHashTableDeletedValue() const { return m_impl == hashTableDeletedValue(); }
48
49private:
50 static StringImpl* hashTableDeletedValue() { return reinterpret_cast<StringImpl*>(-1); }
51
52 StringImpl* m_impl { nullptr };
53 unsigned m_hash { 0 };
54};
55
56template<typename T> struct DefaultHash;
57template<> struct DefaultHash<SymbolRegistryKey> {
58 struct Hash : StringHash {
59 static unsigned hash(const SymbolRegistryKey& key)
60 {
61 return key.hash();
62 }
63 static bool equal(const SymbolRegistryKey& a, const SymbolRegistryKey& b)
64 {
65 return StringHash::equal(a.impl(), b.impl());
66 }
67 };
68};
69
70template<> struct HashTraits<SymbolRegistryKey> : SimpleClassHashTraits<SymbolRegistryKey> {
71 static const bool hasIsEmptyValueFunction = true;
72 static bool isEmptyValue(const SymbolRegistryKey& key)
73 {
74 return key.impl() == nullptr;
75 }
76};
77
78class SymbolRegistry {
79 WTF_MAKE_NONCOPYABLE(SymbolRegistry);
80public:
81 SymbolRegistry() = default;
82 WTF_EXPORT_PRIVATE ~SymbolRegistry();
83
84 WTF_EXPORT_PRIVATE Ref<RegisteredSymbolImpl> symbolForKey(const String&);
85
86 void remove(RegisteredSymbolImpl&);
87
88private:
89 HashSet<SymbolRegistryKey> m_table;
90};
91
92inline SymbolRegistryKey::SymbolRegistryKey(StringImpl* uid)
93 : m_impl(uid)
94{
95 if (uid->isSymbol()) {
96 if (uid->is8Bit())
97 m_hash = StringHasher::computeHashAndMaskTop8Bits(uid->characters8(), uid->length());
98 else
99 m_hash = StringHasher::computeHashAndMaskTop8Bits(uid->characters16(), uid->length());
100 } else
101 m_hash = uid->hash();
102}
103
104inline SymbolRegistryKey::SymbolRegistryKey(WTF::HashTableDeletedValueType)
105 : m_impl(hashTableDeletedValue())
106{
107}
108
109}
110