]> git.saurik.com Git - apple/javascriptcore.git/blob - wtf/StringHashFunctions.h
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / wtf / StringHashFunctions.h
1 /*
2 * Copyright (C) 2005, 2006, 2008, 2010 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 #ifndef WTF_StringHashFunctions_h
21 #define WTF_StringHashFunctions_h
22
23 #include <wtf/unicode/Unicode.h>
24
25 namespace WTF {
26
27 // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
28 static const unsigned stringHashingStartValue = 0x9e3779b9U;
29
30 // stringHash methods based on Paul Hsieh's SuperFastHash.
31 // http://www.azillionmonkeys.com/qed/hash.html
32 // char* data is interpreted as latin-encoded (zero extended to 16 bits).
33
34 inline unsigned stringHash(const UChar* data, unsigned length)
35 {
36 unsigned hash = WTF::stringHashingStartValue;
37 unsigned rem = length & 1;
38 length >>= 1;
39
40 // Main loop
41 for (; length > 0; length--) {
42 hash += data[0];
43 unsigned tmp = (data[1] << 11) ^ hash;
44 hash = (hash << 16) ^ tmp;
45 data += 2;
46 hash += hash >> 11;
47 }
48
49 // Handle end case
50 if (rem) {
51 hash += data[0];
52 hash ^= hash << 11;
53 hash += hash >> 17;
54 }
55
56 // Force "avalanching" of final 127 bits
57 hash ^= hash << 3;
58 hash += hash >> 5;
59 hash ^= hash << 2;
60 hash += hash >> 15;
61 hash ^= hash << 10;
62
63 hash &= 0x7fffffff;
64
65 // this avoids ever returning a hash code of 0, since that is used to
66 // signal "hash not computed yet", using a value that is likely to be
67 // effectively the same as 0 when the low bits are masked
68 if (hash == 0)
69 hash = 0x40000000;
70
71 return hash;
72 }
73
74 inline unsigned stringHash(const char* data, unsigned length)
75 {
76 unsigned hash = WTF::stringHashingStartValue;
77 unsigned rem = length & 1;
78 length >>= 1;
79
80 // Main loop
81 for (; length > 0; length--) {
82 hash += static_cast<unsigned char>(data[0]);
83 unsigned tmp = (static_cast<unsigned char>(data[1]) << 11) ^ hash;
84 hash = (hash << 16) ^ tmp;
85 data += 2;
86 hash += hash >> 11;
87 }
88
89 // Handle end case
90 if (rem) {
91 hash += static_cast<unsigned char>(data[0]);
92 hash ^= hash << 11;
93 hash += hash >> 17;
94 }
95
96 // Force "avalanching" of final 127 bits
97 hash ^= hash << 3;
98 hash += hash >> 5;
99 hash ^= hash << 2;
100 hash += hash >> 15;
101 hash ^= hash << 10;
102
103 hash &= 0x7fffffff;
104
105 // this avoids ever returning a hash code of 0, since that is used to
106 // signal "hash not computed yet", using a value that is likely to be
107 // effectively the same as 0 when the low bits are masked
108 if (hash == 0)
109 hash = 0x40000000;
110
111 return hash;
112 }
113
114 inline unsigned stringHash(const char* data)
115 {
116 unsigned hash = WTF::stringHashingStartValue;
117
118 // Main loop
119 for (;;) {
120 unsigned char b0 = data[0];
121 if (!b0)
122 break;
123 unsigned char b1 = data[1];
124 if (!b1) {
125 hash += b0;
126 hash ^= hash << 11;
127 hash += hash >> 17;
128 break;
129 }
130 hash += b0;
131 unsigned tmp = (b1 << 11) ^ hash;
132 hash = (hash << 16) ^ tmp;
133 data += 2;
134 hash += hash >> 11;
135 }
136
137 // Force "avalanching" of final 127 bits.
138 hash ^= hash << 3;
139 hash += hash >> 5;
140 hash ^= hash << 2;
141 hash += hash >> 15;
142 hash ^= hash << 10;
143
144 hash &= 0x7fffffff;
145
146 // This avoids ever returning a hash code of 0, since that is used to
147 // signal "hash not computed yet", using a value that is likely to be
148 // effectively the same as 0 when the low bits are masked.
149 if (hash == 0)
150 hash = 0x40000000;
151
152 return hash;
153 }
154
155 } // namespace WTF
156
157 #endif // WTF_StringHashFunctions_h