2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 // A 128-bit noncryptographic hash, for checksums and table lookup
19 // By Bob Jenkins. Public domain.
20 // Oct 31 2010: published framework, disclaimer ShortHash isn't right
21 // Nov 7 2010: disabled ShortHash
22 // Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again
23 // April 10 2012: buffer overflow on platforms without unaligned reads
24 // July 12 2012: was passing out variables in final to in/out in short
25 // July 30 2012: I reintroduced the buffer overflow
27 #include <folly/SpookyHashV1.h>
29 #include <folly/CppAttributes.h>
33 #define ALLOW_UNALIGNED_READS 1
39 // short hash ... it could be used on any message,
40 // but it's used by Spooky just for short messages.
42 void SpookyHashV1::Short(
48 uint64_t buf[2*sc_numVars];
57 u.p8 = (const uint8_t *)message;
59 if (!ALLOW_UNALIGNED_READS && (u.i & 0x7))
61 memcpy(buf, message, length);
65 size_t remainder = length%32;
73 const uint64_t *end = u.p64 + (length/32)*4;
75 // handle all complete sets of 32 bytes
76 for (; u.p64 < end; u.p64 += 4)
85 //Handle the case of 16+ remaining bytes.
96 // Handle the last 0..15 bytes, and its length
97 d = ((uint64_t)length) << 56;
101 d += ((uint64_t)u.p8[14]) << 48;
104 d += ((uint64_t)u.p8[13]) << 40;
107 d += ((uint64_t)u.p8[12]) << 32;
114 d += ((uint64_t)u.p8[10]) << 16;
117 d += ((uint64_t)u.p8[9]) << 8;
120 d += (uint64_t)u.p8[8];
126 c += ((uint64_t)u.p8[6]) << 48;
129 c += ((uint64_t)u.p8[5]) << 40;
132 c += ((uint64_t)u.p8[4]) << 32;
138 c += ((uint64_t)u.p8[2]) << 16;
141 c += ((uint64_t)u.p8[1]) << 8;
144 c += (uint64_t)u.p8[0];
158 // do the whole hash in one call
159 void SpookyHashV1::Hash128(
165 if (length < sc_bufSize)
167 Short(message, length, hash1, hash2);
171 uint64_t h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
172 uint64_t buf[sc_numVars];
182 h0=h3=h6=h9 = *hash1;
183 h1=h4=h7=h10 = *hash2;
184 h2=h5=h8=h11 = sc_const;
186 u.p8 = (const uint8_t *)message;
187 end = u.p64 + (length/sc_blockSize)*sc_numVars;
189 // handle all whole sc_blockSize blocks of bytes
190 if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0))
194 Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
202 memcpy(buf, u.p64, sc_blockSize);
203 Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
208 // handle the last partial block of sc_blockSize bytes
209 remainder = (length - ((const uint8_t *)end-(const uint8_t *)message));
210 memcpy(buf, end, remainder);
211 memset(((uint8_t *)buf)+remainder, 0, sc_blockSize-remainder);
212 ((uint8_t*)buf)[sc_blockSize - 1] = uint8_t(remainder);
213 Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
215 // do some final mixing
216 End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
224 void SpookyHashV1::Init(uint64_t seed1, uint64_t seed2)
233 // add a message fragment to the state
234 void SpookyHashV1::Update(const void *message, size_t length)
236 uint64_t h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11;
237 size_t newLength = length + m_remainder;
247 // Is this message fragment too short? If it is, stuff it away.
248 if (newLength < sc_bufSize)
250 memcpy(&((uint8_t *)m_data)[m_remainder], message, length);
251 m_length = length + m_length;
252 m_remainder = (uint8_t)newLength;
256 // init the variables
257 if (m_length < sc_bufSize)
259 h0=h3=h6=h9 = m_state[0];
260 h1=h4=h7=h10 = m_state[1];
261 h2=h5=h8=h11 = sc_const;
278 m_length = length + m_length;
280 // if we've got anything stuffed away, use it now
283 uint8_t prefix = sc_bufSize-m_remainder;
284 memcpy(&(((uint8_t *)m_data)[m_remainder]), message, prefix);
286 Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
287 Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
288 u.p8 = ((const uint8_t *)message) + prefix;
293 u.p8 = (const uint8_t *)message;
296 // handle all whole blocks of sc_blockSize bytes
297 end = u.p64 + (length/sc_blockSize)*sc_numVars;
298 remainder = (uint8_t)(length-((const uint8_t *)end-u.p8));
299 if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0)
303 Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
311 memcpy(m_data, u.p8, sc_blockSize);
312 Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
317 // stuff away the last few bytes
318 m_remainder = remainder;
319 memcpy(m_data, end, remainder);
321 // stuff away the variables
337 // report the hash for the concatenation of all message fragments so far
338 void SpookyHashV1::Final(uint64_t *hash1, uint64_t *hash2)
340 // init the variables
341 if (m_length < sc_bufSize)
345 Short( m_data, m_length, hash1, hash2);
349 const uint64_t *data = (const uint64_t *)m_data;
350 uint8_t remainder = m_remainder;
352 uint64_t h0 = m_state[0];
353 uint64_t h1 = m_state[1];
354 uint64_t h2 = m_state[2];
355 uint64_t h3 = m_state[3];
356 uint64_t h4 = m_state[4];
357 uint64_t h5 = m_state[5];
358 uint64_t h6 = m_state[6];
359 uint64_t h7 = m_state[7];
360 uint64_t h8 = m_state[8];
361 uint64_t h9 = m_state[9];
362 uint64_t h10 = m_state[10];
363 uint64_t h11 = m_state[11];
365 if (remainder >= sc_blockSize)
367 // m_data can contain two blocks; handle any whole first block
368 Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
370 remainder -= sc_blockSize;
373 // mix in the last partial block, and the length mod sc_blockSize
374 memset(&((uint8_t *)data)[remainder], 0, (sc_blockSize-remainder));
376 ((uint8_t *)data)[sc_blockSize-1] = remainder;
377 Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);
379 // do some final mixing
380 End(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11);