Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: third_party/WebKit/Source/wtf/StringHasher.h

Issue 1436153002: Apply clang-format with Chromium-style without column limit. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2008, 2010, 2013 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2008, 2010, 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> 3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
(...skipping 20 matching lines...) Expand all
31 31
32 // LChar data is interpreted as Latin-1-encoded (zero extended to 16 bits). 32 // LChar data is interpreted as Latin-1-encoded (zero extended to 16 bits).
33 33
34 // NOTE: The hash computation here must stay in sync with the create_hash_table script in 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. 35 // JavaScriptCore and the CodeGeneratorJS.pm script in WebCore.
36 36
37 // Golden ratio. Arbitrary start value to avoid mapping all zeros to a hash valu e of zero. 37 // Golden ratio. Arbitrary start value to avoid mapping all zeros to a hash valu e of zero.
38 static const unsigned stringHashingStartValue = 0x9E3779B9U; 38 static const unsigned stringHashingStartValue = 0x9E3779B9U;
39 39
40 class StringHasher { 40 class StringHasher {
41 public: 41 public:
42 static const unsigned flagCount = 8; // Save 8 bits for StringImpl to use as flags. 42 static const unsigned flagCount = 8; // Save 8 bits for StringImpl to use as flags.
43 43
44 StringHasher() 44 StringHasher()
45 : m_hash(stringHashingStartValue) 45 : m_hash(stringHashingStartValue), m_hasPendingCharacter(false), m_pending Character(0) {
46 , m_hasPendingCharacter(false) 46 }
47 , m_pendingCharacter(0) 47
48 { 48 // The hasher hashes two characters at a time, and thus an "aligned" hasher is one
49 // where an even number of characters have been added. Callers that always add
50 // characters two at a time can use the "assuming aligned" functions.
51 void addCharactersAssumingAligned(UChar a, UChar b) {
52 ASSERT(!m_hasPendingCharacter);
53 m_hash += a;
54 m_hash = (m_hash << 16) ^ ((b << 11) ^ m_hash);
55 m_hash += m_hash >> 11;
56 }
57
58 void addCharacter(UChar character) {
59 if (m_hasPendingCharacter) {
60 m_hasPendingCharacter = false;
61 addCharactersAssumingAligned(m_pendingCharacter, character);
62 return;
49 } 63 }
50 64
51 // The hasher hashes two characters at a time, and thus an "aligned" hasher is one 65 m_pendingCharacter = character;
52 // where an even number of characters have been added. Callers that always a dd 66 m_hasPendingCharacter = true;
53 // characters two at a time can use the "assuming aligned" functions. 67 }
54 void addCharactersAssumingAligned(UChar a, UChar b) 68
55 { 69 void addCharacters(UChar a, UChar b) {
56 ASSERT(!m_hasPendingCharacter); 70 if (m_hasPendingCharacter) {
57 m_hash += a; 71 #if ENABLE(ASSERT)
58 m_hash = (m_hash << 16) ^ ((b << 11) ^ m_hash); 72 m_hasPendingCharacter = false;
59 m_hash += m_hash >> 11; 73 #endif
74 addCharactersAssumingAligned(m_pendingCharacter, a);
75 m_pendingCharacter = b;
76 #if ENABLE(ASSERT)
77 m_hasPendingCharacter = true;
78 #endif
79 return;
60 } 80 }
61 81
62 void addCharacter(UChar character) 82 addCharactersAssumingAligned(a, b);
63 { 83 }
64 if (m_hasPendingCharacter) {
65 m_hasPendingCharacter = false;
66 addCharactersAssumingAligned(m_pendingCharacter, character);
67 return;
68 }
69 84
70 m_pendingCharacter = character; 85 template <typename T, UChar Converter(T)>
71 m_hasPendingCharacter = true; 86 void addCharactersAssumingAligned(const T* data, unsigned length) {
87 ASSERT(!m_hasPendingCharacter);
88
89 bool remainder = length & 1;
90 length >>= 1;
91
92 while (length--) {
93 addCharactersAssumingAligned(Converter(data[0]), Converter(data[1]));
94 data += 2;
72 } 95 }
73 96
74 void addCharacters(UChar a, UChar b) 97 if (remainder)
75 { 98 addCharacter(Converter(*data));
76 if (m_hasPendingCharacter) { 99 }
77 #if ENABLE(ASSERT)
78 m_hasPendingCharacter = false;
79 #endif
80 addCharactersAssumingAligned(m_pendingCharacter, a);
81 m_pendingCharacter = b;
82 #if ENABLE(ASSERT)
83 m_hasPendingCharacter = true;
84 #endif
85 return;
86 }
87 100
88 addCharactersAssumingAligned(a, b); 101 template <typename T>
102 void addCharactersAssumingAligned(const T* data, unsigned length) {
103 addCharactersAssumingAligned<T, defaultConverter>(data, length);
104 }
105
106 template <typename T, UChar Converter(T)>
107 void addCharacters(const T* data, unsigned length) {
108 if (m_hasPendingCharacter && length) {
109 m_hasPendingCharacter = false;
110 addCharactersAssumingAligned(m_pendingCharacter, Converter(*data++));
111 --length;
112 }
113 addCharactersAssumingAligned<T, Converter>(data, length);
114 }
115
116 template <typename T>
117 void addCharacters(const T* data, unsigned length) {
118 addCharacters<T, defaultConverter>(data, length);
119 }
120
121 unsigned hashWithTop8BitsMasked() const {
122 unsigned result = avalancheBits();
123
124 // Reserving space from the high bits for flags preserves most of the hash's
125 // value, since hash lookup typically masks out the high bits anyway.
126 result &= (1U << (sizeof(result) * 8 - flagCount)) - 1;
127
128 // This avoids ever returning a hash code of 0, since that is used to
129 // signal "hash not computed yet". Setting the high bit maintains
130 // reasonable fidelity to a hash code of 0 because it is likely to yield
131 // exactly 0 when hash lookup masks out the high bits.
132 if (!result)
133 result = 0x80000000 >> flagCount;
134
135 return result;
136 }
137
138 unsigned hash() const {
139 unsigned result = avalancheBits();
140
141 // This avoids ever returning a hash code of 0, since that is used to
142 // signal "hash not computed yet". Setting the high bit maintains
143 // reasonable fidelity to a hash code of 0 because it is likely to yield
144 // exactly 0 when hash lookup masks out the high bits.
145 if (!result)
146 result = 0x80000000;
147
148 return result;
149 }
150
151 template <typename T, UChar Converter(T)>
152 static unsigned computeHashAndMaskTop8Bits(const T* data, unsigned length) {
153 StringHasher hasher;
154 hasher.addCharactersAssumingAligned<T, Converter>(data, length);
155 return hasher.hashWithTop8BitsMasked();
156 }
157
158 template <typename T>
159 static unsigned computeHashAndMaskTop8Bits(const T* data, unsigned length) {
160 return computeHashAndMaskTop8Bits<T, defaultConverter>(data, length);
161 }
162
163 template <typename T, UChar Converter(T)>
164 static unsigned computeHash(const T* data, unsigned length) {
165 StringHasher hasher;
166 hasher.addCharactersAssumingAligned<T, Converter>(data, length);
167 return hasher.hash();
168 }
169
170 template <typename T>
171 static unsigned computeHash(const T* data, unsigned length) {
172 return computeHash<T, defaultConverter>(data, length);
173 }
174
175 static unsigned hashMemory(const void* data, unsigned length) {
176 // FIXME: Why does this function use the version of the hash that drops the top 8 bits?
177 // We want that for all string hashing so we can use those bits in StringImp l and hash
178 // strings consistently, but I don't see why we'd want that for general memo ry hashing.
179 ASSERT(!(length % 2));
180 return computeHashAndMaskTop8Bits<UChar>(static_cast<const UChar*>(data), le ngth / sizeof(UChar));
181 }
182
183 template <size_t length>
184 static unsigned hashMemory(const void* data) {
185 static_assert(!(length % 2), "length must be a multiple of two");
186 return hashMemory(data, length);
187 }
188
189 private:
190 static UChar defaultConverter(UChar character) {
191 return character;
192 }
193
194 static UChar defaultConverter(LChar character) {
195 return character;
196 }
197
198 unsigned avalancheBits() const {
199 unsigned result = m_hash;
200
201 // Handle end case.
202 if (m_hasPendingCharacter) {
203 result += m_pendingCharacter;
204 result ^= result << 11;
205 result += result >> 17;
89 } 206 }
90 207
91 template<typename T, UChar Converter(T)> void addCharactersAssumingAligned(c onst T* data, unsigned length) 208 // Force "avalanching" of final 31 bits.
92 { 209 result ^= result << 3;
93 ASSERT(!m_hasPendingCharacter); 210 result += result >> 5;
211 result ^= result << 2;
212 result += result >> 15;
213 result ^= result << 10;
94 214
95 bool remainder = length & 1; 215 return result;
96 length >>= 1; 216 }
97 217
98 while (length--) { 218 unsigned m_hash;
99 addCharactersAssumingAligned(Converter(data[0]), Converter(data[1])) ; 219 bool m_hasPendingCharacter;
100 data += 2; 220 UChar m_pendingCharacter;
101 }
102
103 if (remainder)
104 addCharacter(Converter(*data));
105 }
106
107 template<typename T> void addCharactersAssumingAligned(const T* data, unsign ed length)
108 {
109 addCharactersAssumingAligned<T, defaultConverter>(data, length);
110 }
111
112 template<typename T, UChar Converter(T)> void addCharacters(const T* data, u nsigned length)
113 {
114 if (m_hasPendingCharacter && length) {
115 m_hasPendingCharacter = false;
116 addCharactersAssumingAligned(m_pendingCharacter, Converter(*data++)) ;
117 --length;
118 }
119 addCharactersAssumingAligned<T, Converter>(data, length);
120 }
121
122 template<typename T> void addCharacters(const T* data, unsigned length)
123 {
124 addCharacters<T, defaultConverter>(data, length);
125 }
126
127 unsigned hashWithTop8BitsMasked() const
128 {
129 unsigned result = avalancheBits();
130
131 // Reserving space from the high bits for flags preserves most of the ha sh's
132 // value, since hash lookup typically masks out the high bits anyway.
133 result &= (1U << (sizeof(result) * 8 - flagCount)) - 1;
134
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.
139 if (!result)
140 result = 0x80000000 >> flagCount;
141
142 return result;
143 }
144
145 unsigned hash() const
146 {
147 unsigned result = avalancheBits();
148
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.
153 if (!result)
154 result = 0x80000000;
155
156 return result;
157 }
158
159 template<typename T, UChar Converter(T)> static unsigned computeHashAndMaskT op8Bits(const T* data, unsigned length)
160 {
161 StringHasher hasher;
162 hasher.addCharactersAssumingAligned<T, Converter>(data, length);
163 return hasher.hashWithTop8BitsMasked();
164 }
165
166 template<typename T> static unsigned computeHashAndMaskTop8Bits(const T* dat a, unsigned length)
167 {
168 return computeHashAndMaskTop8Bits<T, defaultConverter>(data, length);
169 }
170
171 template<typename T, UChar Converter(T)> static unsigned computeHash(const T * data, unsigned length)
172 {
173 StringHasher hasher;
174 hasher.addCharactersAssumingAligned<T, Converter>(data, length);
175 return hasher.hash();
176 }
177
178 template<typename T> static unsigned computeHash(const T* data, unsigned len gth)
179 {
180 return computeHash<T, defaultConverter>(data, length);
181 }
182
183 static unsigned hashMemory(const void* data, unsigned length)
184 {
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 Strin gImpl 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));
190 }
191
192 template<size_t length> static unsigned hashMemory(const void* data)
193 {
194 static_assert(!(length % 2), "length must be a multiple of two");
195 return hashMemory(data, length);
196 }
197
198 private:
199 static UChar defaultConverter(UChar character)
200 {
201 return character;
202 }
203
204 static UChar defaultConverter(LChar character)
205 {
206 return character;
207 }
208
209 unsigned avalancheBits() const
210 {
211 unsigned result = m_hash;
212
213 // Handle end case.
214 if (m_hasPendingCharacter) {
215 result += m_pendingCharacter;
216 result ^= result << 11;
217 result += result >> 17;
218 }
219
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;
226
227 return result;
228 }
229
230 unsigned m_hash;
231 bool m_hasPendingCharacter;
232 UChar m_pendingCharacter;
233 }; 221 };
234 222
235 } // namespace WTF 223 } // namespace WTF
236 224
237 using WTF::StringHasher; 225 using WTF::StringHasher;
238 226
239 #endif // WTF_StringHasher_h 227 #endif // WTF_StringHasher_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/StringExtrasTest.cpp ('k') | third_party/WebKit/Source/wtf/StringHasherTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698