2 * Copyright (C) 2005, 2006, 2008, 2010, 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #ifndef WTF_StringHasher_h
23 #define WTF_StringHasher_h
25 #include "wtf/text/Unicode.h"
29 // Paul Hsieh's SuperFastHash
30 // http://www.azillionmonkeys.com/qed/hash.html
32 // LChar data is interpreted as Latin-1-encoded (zero extended to 16 bits).
34 // NOTE: The hash computation here must stay in sync with the create_hash_table script in
35 // JavaScriptCore and the CodeGeneratorJS.pm script in WebCore.
37 // Golden ratio. Arbitrary start value to avoid mapping all zeros to a hash value of zero.
38 static const unsigned stringHashingStartValue
= 0x9E3779B9U
;
42 static const unsigned flagCount
= 8; // Save 8 bits for StringImpl to use as flags.
45 : m_hash(stringHashingStartValue
)
46 , m_hasPendingCharacter(false)
47 , m_pendingCharacter(0)
51 // The hasher hashes two characters at a time, and thus an "aligned" hasher is one
52 // where an even number of characters have been added. Callers that always add
53 // characters two at a time can use the "assuming aligned" functions.
54 void addCharactersAssumingAligned(UChar a
, UChar b
)
56 ASSERT(!m_hasPendingCharacter
);
58 m_hash
= (m_hash
<< 16) ^ ((b
<< 11) ^ m_hash
);
59 m_hash
+= m_hash
>> 11;
62 void addCharacter(UChar character
)
64 if (m_hasPendingCharacter
) {
65 m_hasPendingCharacter
= false;
66 addCharactersAssumingAligned(m_pendingCharacter
, character
);
70 m_pendingCharacter
= character
;
71 m_hasPendingCharacter
= true;
74 void addCharacters(UChar a
, UChar b
)
76 if (m_hasPendingCharacter
) {
78 m_hasPendingCharacter
= false;
80 addCharactersAssumingAligned(m_pendingCharacter
, a
);
81 m_pendingCharacter
= b
;
83 m_hasPendingCharacter
= true;
88 addCharactersAssumingAligned(a
, b
);
91 template<typename T
, UChar
Converter(T
)> void addCharactersAssumingAligned(const T
* data
, unsigned length
)
93 ASSERT(!m_hasPendingCharacter
);
95 bool remainder
= length
& 1;
99 addCharactersAssumingAligned(Converter(data
[0]), Converter(data
[1]));
104 addCharacter(Converter(*data
));
107 template<typename T
> void addCharactersAssumingAligned(const T
* data
, unsigned length
)
109 addCharactersAssumingAligned
<T
, defaultConverter
>(data
, length
);
112 template<typename T
, UChar
Converter(T
)> void addCharacters(const T
* data
, unsigned length
)
114 if (m_hasPendingCharacter
&& length
) {
115 m_hasPendingCharacter
= false;
116 addCharactersAssumingAligned(m_pendingCharacter
, Converter(*data
++));
119 addCharactersAssumingAligned
<T
, Converter
>(data
, length
);
122 template<typename T
> void addCharacters(const T
* data
, unsigned length
)
124 addCharacters
<T
, defaultConverter
>(data
, length
);
127 unsigned hashWithTop8BitsMasked() const
129 unsigned result
= avalancheBits();
131 // Reserving space from the high bits for flags preserves most of the hash's
132 // value, since hash lookup typically masks out the high bits anyway.
133 result
&= (1U << (sizeof(result
) * 8 - flagCount
)) - 1;
135 // This avoids ever returning a hash code of 0, since that is used to
136 // signal "hash not computed yet". Setting the high bit maintains
137 // reasonable fidelity to a hash code of 0 because it is likely to yield
138 // exactly 0 when hash lookup masks out the high bits.
140 result
= 0x80000000 >> flagCount
;
145 unsigned hash() const
147 unsigned result
= avalancheBits();
149 // This avoids ever returning a hash code of 0, since that is used to
150 // signal "hash not computed yet". Setting the high bit maintains
151 // reasonable fidelity to a hash code of 0 because it is likely to yield
152 // exactly 0 when hash lookup masks out the high bits.
159 template<typename T
, UChar
Converter(T
)> static unsigned computeHashAndMaskTop8Bits(const T
* data
, unsigned length
)
162 hasher
.addCharactersAssumingAligned
<T
, Converter
>(data
, length
);
163 return hasher
.hashWithTop8BitsMasked();
166 template<typename T
> static unsigned computeHashAndMaskTop8Bits(const T
* data
, unsigned length
)
168 return computeHashAndMaskTop8Bits
<T
, defaultConverter
>(data
, length
);
171 template<typename T
, UChar
Converter(T
)> static unsigned computeHash(const T
* data
, unsigned length
)
174 hasher
.addCharactersAssumingAligned
<T
, Converter
>(data
, length
);
175 return hasher
.hash();
178 template<typename T
> static unsigned computeHash(const T
* data
, unsigned length
)
180 return computeHash
<T
, defaultConverter
>(data
, length
);
183 static unsigned hashMemory(const void* data
, unsigned length
)
185 // FIXME: Why does this function use the version of the hash that drops the top 8 bits?
186 // We want that for all string hashing so we can use those bits in StringImpl and hash
187 // strings consistently, but I don't see why we'd want that for general memory hashing.
188 ASSERT(!(length
% 2));
189 return computeHashAndMaskTop8Bits
<UChar
>(static_cast<const UChar
*>(data
), length
/ sizeof(UChar
));
192 template<size_t length
> static unsigned hashMemory(const void* data
)
194 static_assert(!(length
% 2), "length must be a multiple of two");
195 return hashMemory(data
, length
);
199 static UChar
defaultConverter(UChar character
)
204 static UChar
defaultConverter(LChar character
)
209 unsigned avalancheBits() const
211 unsigned result
= m_hash
;
214 if (m_hasPendingCharacter
) {
215 result
+= m_pendingCharacter
;
216 result
^= result
<< 11;
217 result
+= result
>> 17;
220 // Force "avalanching" of final 31 bits.
221 result
^= result
<< 3;
222 result
+= result
>> 5;
223 result
^= result
<< 2;
224 result
+= result
>> 15;
225 result
^= result
<< 10;
231 bool m_hasPendingCharacter
;
232 UChar m_pendingCharacter
;
237 using WTF::StringHasher
;
239 #endif // WTF_StringHasher_h