<ClInclude Include="..\..\..\tests\cppunit\cppunit_mini.h" />\r
<ClInclude Include="..\..\..\tests\cppunit\cppunit_proxy.h" />\r
<ClInclude Include="..\..\..\tests\cppunit\file_reporter.h" />\r
+ <ClInclude Include="..\..\..\tests\hashing\city.h" />\r
+ <ClInclude Include="..\..\..\tests\hashing\hash_func.h" />\r
+ <ClInclude Include="..\..\..\tests\hashing\md5.h" />\r
+ <ClInclude Include="..\..\..\tests\hashing\sha256.h" />\r
<ClInclude Include="..\..\..\tests\unit\ellen_bintree_update_desc_pool.h" />\r
<ClInclude Include="..\..\..\tests\unit\michael_alloc.h" />\r
<ClInclude Include="..\..\..\tests\cppunit\test_beans.h" />\r
<ClInclude Include="..\..\..\tests\cppunit\thread.h" />\r
</ItemGroup>\r
<ItemGroup>\r
+ <ClCompile Include="..\..\..\tests\hashing\city.cc" />\r
+ <ClCompile Include="..\..\..\tests\hashing\md5.cpp" />\r
+ <ClCompile Include="..\..\..\tests\hashing\sha256.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\ellen_bintree_update_desc_pool.cpp" />\r
<ClCompile Include="..\..\..\tests\unit\michael_alloc.cpp" />\r
<ClCompile Include="..\..\..\tests\cppunit\test_main.cpp">\r
tests/cppunit/test_main.cpp \
tests/cppunit/thread.cpp \
tests/unit/michael_alloc.cpp \
- tests/unit/ellen_bintree_update_desc_pool.cpp
+ tests/unit/ellen_bintree_update_desc_pool.cpp \
+ tests/hashing/city.cc \
+ tests/hashing/md5.cpp \
+ tests/hashing/sha256.cpp
+
+
set(SOURCES cppunit/test_main.cpp
cppunit/thread.cpp
unit/michael_alloc.cpp
- unit/ellen_bintree_update_desc_pool.cpp)
+ unit/ellen_bintree_update_desc_pool.cpp
+ hashing/city.cc
+ hashing/md5.cpp
+ hashing/sha256.cpp)
add_library(${TEST_COMMON} OBJECT ${SOURCES})
--- /dev/null
+// Copyright (c) 2011 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// CityHash, by Geoff Pike and Jyrki Alakuijala
+//
+// This file provides CityHash64() and related functions.
+//
+// It's probably possible to create even faster hash functions by
+// writing a program that systematically explores some of the space of
+// possible hash functions, by using SIMD instructions, or by
+// compromising on hash quality.
+
+//#include "config.h"
+#include "city.h"
+
+#include <algorithm>
+#include <string.h> // for memcpy and memset
+
+using namespace std;
+
+static uint64 UNALIGNED_LOAD64(const char *p) {
+ uint64 result;
+ memcpy(&result, p, sizeof(result));
+ return result;
+}
+
+static uint32 UNALIGNED_LOAD32(const char *p) {
+ uint32 result;
+ memcpy(&result, p, sizeof(result));
+ return result;
+}
+
+#ifdef _MSC_VER
+
+#include <stdlib.h>
+#define bswap_32(x) _byteswap_ulong(x)
+#define bswap_64(x) _byteswap_uint64(x)
+
+#elif defined(__APPLE__)
+
+// Mac OS X / Darwin features
+#include <libkern/OSByteOrder.h>
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+
+#elif defined(__NetBSD__)
+
+#include <sys/types.h>
+#include <machine/bswap.h>
+#if defined(__BSWAP_RENAME) && !defined(__bswap_32)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+#endif
+
+#else
+
+#include <byteswap.h>
+
+#endif
+
+#ifdef WORDS_BIGENDIAN
+#define uint32_in_expected_order(x) (bswap_32(x))
+#define uint64_in_expected_order(x) (bswap_64(x))
+#else
+#define uint32_in_expected_order(x) (x)
+#define uint64_in_expected_order(x) (x)
+#endif
+
+#if !defined(LIKELY)
+#if HAVE_BUILTIN_EXPECT
+#define LIKELY(x) (__builtin_expect(!!(x), 1))
+#else
+#define LIKELY(x) (x)
+#endif
+#endif
+
+static uint64 Fetch64(const char *p) {
+ return uint64_in_expected_order(UNALIGNED_LOAD64(p));
+}
+
+static uint32 Fetch32(const char *p) {
+ return uint32_in_expected_order(UNALIGNED_LOAD32(p));
+}
+
+// Some primes between 2^63 and 2^64 for various uses.
+static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
+static const uint64 k1 = 0xb492b66fbe98f273ULL;
+static const uint64 k2 = 0x9ae16a3b2f90404fULL;
+
+// Magic numbers for 32-bit hashing. Copied from Murmur3.
+static const uint32_t c1 = 0xcc9e2d51;
+static const uint32_t c2 = 0x1b873593;
+
+// A 32-bit to 32-bit integer hash copied from Murmur3.
+static uint32 fmix(uint32 h)
+{
+ h ^= h >> 16;
+ h *= 0x85ebca6b;
+ h ^= h >> 13;
+ h *= 0xc2b2ae35;
+ h ^= h >> 16;
+ return h;
+}
+
+static uint32 Rotate32(uint32 val, int shift) {
+ // Avoid shifting by 32: doing so yields an undefined result.
+ return shift == 0 ? val : ((val >> shift) | (val << (32 - shift)));
+}
+
+#undef PERMUTE3
+#define PERMUTE3(a, b, c) do { std::swap(a, b); std::swap(a, c); } while (0)
+
+static uint32 Mur(uint32 a, uint32 h) {
+ // Helper from Murmur3 for combining two 32-bit values.
+ a *= c1;
+ a = Rotate32(a, 17);
+ a *= c2;
+ h ^= a;
+ h = Rotate32(h, 19);
+ return h * 5 + 0xe6546b64;
+}
+
+static uint32 Hash32Len13to24(const char *s, size_t len) {
+ uint32 a = Fetch32(s - 4 + (len >> 1));
+ uint32 b = Fetch32(s + 4);
+ uint32 c = Fetch32(s + len - 8);
+ uint32 d = Fetch32(s + (len >> 1));
+ uint32 e = Fetch32(s);
+ uint32 f = Fetch32(s + len - 4);
+ uint32 h = len;
+
+ return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h)))))));
+}
+
+static uint32 Hash32Len0to4(const char *s, size_t len) {
+ uint32 b = 0;
+ uint32 c = 9;
+ for (int i = 0; i < len; i++) {
+ signed char v = s[i];
+ b = b * c1 + v;
+ c ^= b;
+ }
+ return fmix(Mur(b, Mur(len, c)));
+}
+
+static uint32 Hash32Len5to12(const char *s, size_t len) {
+ uint32 a = len, b = len * 5, c = 9, d = b;
+ a += Fetch32(s);
+ b += Fetch32(s + len - 4);
+ c += Fetch32(s + ((len >> 1) & 4));
+ return fmix(Mur(c, Mur(b, Mur(a, d))));
+}
+
+uint32 CityHash32(const char *s, size_t len) {
+ if (len <= 24) {
+ return len <= 12 ?
+ (len <= 4 ? Hash32Len0to4(s, len) : Hash32Len5to12(s, len)) :
+ Hash32Len13to24(s, len);
+ }
+
+ // len > 24
+ uint32 h = len, g = c1 * len, f = g;
+ uint32 a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2;
+ uint32 a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2;
+ uint32 a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2;
+ uint32 a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2;
+ uint32 a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2;
+ h ^= a0;
+ h = Rotate32(h, 19);
+ h = h * 5 + 0xe6546b64;
+ h ^= a2;
+ h = Rotate32(h, 19);
+ h = h * 5 + 0xe6546b64;
+ g ^= a1;
+ g = Rotate32(g, 19);
+ g = g * 5 + 0xe6546b64;
+ g ^= a3;
+ g = Rotate32(g, 19);
+ g = g * 5 + 0xe6546b64;
+ f += a4;
+ f = Rotate32(f, 19);
+ f = f * 5 + 0xe6546b64;
+ size_t iters = (len - 1) / 20;
+ do {
+ uint32 a0 = Rotate32(Fetch32(s) * c1, 17) * c2;
+ uint32 a1 = Fetch32(s + 4);
+ uint32 a2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2;
+ uint32 a3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2;
+ uint32 a4 = Fetch32(s + 16);
+ h ^= a0;
+ h = Rotate32(h, 18);
+ h = h * 5 + 0xe6546b64;
+ f += a1;
+ f = Rotate32(f, 19);
+ f = f * c1;
+ g += a2;
+ g = Rotate32(g, 18);
+ g = g * 5 + 0xe6546b64;
+ h ^= a3 + a1;
+ h = Rotate32(h, 19);
+ h = h * 5 + 0xe6546b64;
+ g ^= a4;
+ g = bswap_32(g) * 5;
+ h += a4 * 5;
+ h = bswap_32(h);
+ f += a0;
+ PERMUTE3(f, h, g);
+ s += 20;
+ } while (--iters != 0);
+ g = Rotate32(g, 11) * c1;
+ g = Rotate32(g, 17) * c1;
+ f = Rotate32(f, 11) * c1;
+ f = Rotate32(f, 17) * c1;
+ h = Rotate32(h + g, 19);
+ h = h * 5 + 0xe6546b64;
+ h = Rotate32(h, 17) * c1;
+ h = Rotate32(h + f, 19);
+ h = h * 5 + 0xe6546b64;
+ h = Rotate32(h, 17) * c1;
+ return h;
+}
+
+// Bitwise right rotate. Normally this will compile to a single
+// instruction, especially if the shift is a manifest constant.
+static uint64 Rotate(uint64 val, int shift) {
+ // Avoid shifting by 64: doing so yields an undefined result.
+ return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
+}
+
+static uint64 ShiftMix(uint64 val) {
+ return val ^ (val >> 47);
+}
+
+static uint64 HashLen16(uint64 u, uint64 v) {
+ return Hash128to64(uint128(u, v));
+}
+
+static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) {
+ // Murmur-inspired hashing.
+ uint64 a = (u ^ v) * mul;
+ a ^= (a >> 47);
+ uint64 b = (v ^ a) * mul;
+ b ^= (b >> 47);
+ b *= mul;
+ return b;
+}
+
+static uint64 HashLen0to16(const char *s, size_t len) {
+ if (len >= 8) {
+ uint64 mul = k2 + len * 2;
+ uint64 a = Fetch64(s) + k2;
+ uint64 b = Fetch64(s + len - 8);
+ uint64 c = Rotate(b, 37) * mul + a;
+ uint64 d = (Rotate(a, 25) + b) * mul;
+ return HashLen16(c, d, mul);
+ }
+ if (len >= 4) {
+ uint64 mul = k2 + len * 2;
+ uint64 a = Fetch32(s);
+ return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
+ }
+ if (len > 0) {
+ uint8 a = s[0];
+ uint8 b = s[len >> 1];
+ uint8 c = s[len - 1];
+ uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
+ uint32 z = len + (static_cast<uint32>(c) << 2);
+ return ShiftMix(y * k2 ^ z * k0) * k2;
+ }
+ return k2;
+}
+
+// This probably works well for 16-byte strings as well, but it may be overkill
+// in that case.
+static uint64 HashLen17to32(const char *s, size_t len) {
+ uint64 mul = k2 + len * 2;
+ uint64 a = Fetch64(s) * k1;
+ uint64 b = Fetch64(s + 8);
+ uint64 c = Fetch64(s + len - 8) * mul;
+ uint64 d = Fetch64(s + len - 16) * k2;
+ return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d,
+ a + Rotate(b + k2, 18) + c, mul);
+}
+
+// Return a 16-byte hash for 48 bytes. Quick and dirty.
+// Callers do best to use "random-looking" values for a and b.
+static pair<uint64, uint64> WeakHashLen32WithSeeds(
+ uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) {
+ a += w;
+ b = Rotate(b + a + z, 21);
+ uint64 c = a;
+ a += x;
+ a += y;
+ b += Rotate(a, 44);
+ return make_pair(a + z, b + c);
+}
+
+// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
+static pair<uint64, uint64> WeakHashLen32WithSeeds(
+ const char* s, uint64 a, uint64 b) {
+ return WeakHashLen32WithSeeds(Fetch64(s),
+ Fetch64(s + 8),
+ Fetch64(s + 16),
+ Fetch64(s + 24),
+ a,
+ b);
+}
+
+// Return an 8-byte hash for 33 to 64 bytes.
+static uint64 HashLen33to64(const char *s, size_t len) {
+ uint64 mul = k2 + len * 2;
+ uint64 a = Fetch64(s) * k2;
+ uint64 b = Fetch64(s + 8);
+ uint64 c = Fetch64(s + len - 24);
+ uint64 d = Fetch64(s + len - 32);
+ uint64 e = Fetch64(s + 16) * k2;
+ uint64 f = Fetch64(s + 24) * 9;
+ uint64 g = Fetch64(s + len - 8);
+ uint64 h = Fetch64(s + len - 16) * mul;
+ uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
+ uint64 v = ((a + g) ^ d) + f + 1;
+ uint64 w = bswap_64((u + v) * mul) + h;
+ uint64 x = Rotate(e + f, 42) + c;
+ uint64 y = (bswap_64((v + w) * mul) + g) * mul;
+ uint64 z = e + f + c;
+ a = bswap_64((x + z) * mul + y) + b;
+ b = ShiftMix((z + a) * mul + d + h) * mul;
+ return b + x;
+}
+
+uint64 CityHash64(const char *s, size_t len) {
+ if (len <= 32) {
+ if (len <= 16) {
+ return HashLen0to16(s, len);
+ } else {
+ return HashLen17to32(s, len);
+ }
+ } else if (len <= 64) {
+ return HashLen33to64(s, len);
+ }
+
+ // For strings over 64 bytes we hash the end first, and then as we
+ // loop we keep 56 bytes of state: v, w, x, y, and z.
+ uint64 x = Fetch64(s + len - 40);
+ uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
+ uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
+ pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
+ pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
+ x = x * k1 + Fetch64(s);
+
+ // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
+ len = (len - 1) & ~static_cast<size_t>(63);
+ do {
+ x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
+ y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
+ x ^= w.second;
+ y += v.first + Fetch64(s + 40);
+ z = Rotate(z + w.first, 33) * k1;
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
+ std::swap(z, x);
+ s += 64;
+ len -= 64;
+ } while (len != 0);
+ return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
+ HashLen16(v.second, w.second) + x);
+}
+
+uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) {
+ return CityHash64WithSeeds(s, len, k2, seed);
+}
+
+uint64 CityHash64WithSeeds(const char *s, size_t len,
+ uint64 seed0, uint64 seed1) {
+ return HashLen16(CityHash64(s, len) - seed0, seed1);
+}
+
+// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
+// of any length representable in signed long. Based on City and Murmur.
+static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
+ uint64 a = Uint128Low64(seed);
+ uint64 b = Uint128High64(seed);
+ uint64 c = 0;
+ uint64 d = 0;
+ signed long l = len - 16;
+ if (l <= 0) { // len <= 16
+ a = ShiftMix(a * k1) * k1;
+ c = b * k1 + HashLen0to16(s, len);
+ d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
+ } else { // len > 16
+ c = HashLen16(Fetch64(s + len - 8) + k1, a);
+ d = HashLen16(b + len, c + Fetch64(s + len - 16));
+ a += d;
+ do {
+ a ^= ShiftMix(Fetch64(s) * k1) * k1;
+ a *= k1;
+ b ^= a;
+ c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
+ c *= k1;
+ d ^= c;
+ s += 16;
+ l -= 16;
+ } while (l > 0);
+ }
+ a = HashLen16(a, c);
+ b = HashLen16(d, b);
+ return uint128(a ^ b, HashLen16(b, a));
+}
+
+uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
+ if (len < 128) {
+ return CityMurmur(s, len, seed);
+ }
+
+ // We expect len >= 128 to be the common case. Keep 56 bytes of state:
+ // v, w, x, y, and z.
+ pair<uint64, uint64> v, w;
+ uint64 x = Uint128Low64(seed);
+ uint64 y = Uint128High64(seed);
+ uint64 z = len * k1;
+ v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
+ v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
+ w.first = Rotate(y + z, 35) * k1 + x;
+ w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
+
+ // This is the same inner loop as CityHash64(), manually unrolled.
+ do {
+ x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
+ y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
+ x ^= w.second;
+ y += v.first + Fetch64(s + 40);
+ z = Rotate(z + w.first, 33) * k1;
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
+ std::swap(z, x);
+ s += 64;
+ x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
+ y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
+ x ^= w.second;
+ y += v.first + Fetch64(s + 40);
+ z = Rotate(z + w.first, 33) * k1;
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
+ std::swap(z, x);
+ s += 64;
+ len -= 128;
+ } while (LIKELY(len >= 128));
+ x += Rotate(v.first + z, 49) * k0;
+ y = y * k0 + Rotate(w.second, 37);
+ z = z * k0 + Rotate(w.first, 27);
+ w.first *= 9;
+ v.first *= k0;
+ // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
+ for (size_t tail_done = 0; tail_done < len; ) {
+ tail_done += 32;
+ y = Rotate(x + y, 42) * k0 + v.second;
+ w.first += Fetch64(s + len - tail_done + 16);
+ x = x * k0 + w.first;
+ z += w.second + Fetch64(s + len - tail_done);
+ w.second += v.first;
+ v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
+ v.first *= k0;
+ }
+ // At this point our 56 bytes of state should contain more than
+ // enough information for a strong 128-bit hash. We use two
+ // different 56-byte-to-8-byte hashes to get a 16-byte final result.
+ x = HashLen16(x, v.first);
+ y = HashLen16(y + z, w.first);
+ return uint128(HashLen16(x + v.second, w.second) + y,
+ HashLen16(x + w.second, y + v.second));
+}
+
+uint128 CityHash128(const char *s, size_t len) {
+ return len >= 16 ?
+ CityHash128WithSeed(s + 16, len - 16,
+ uint128(Fetch64(s), Fetch64(s + 8) + k0)) :
+ CityHash128WithSeed(s, len, uint128(k0, k1));
+}
+
+#ifdef __SSE4_2__
+#include <citycrc.h>
+#include <nmmintrin.h>
+
+// Requires len >= 240.
+static void CityHashCrc256Long(const char *s, size_t len,
+ uint32 seed, uint64 *result) {
+ uint64 a = Fetch64(s + 56) + k0;
+ uint64 b = Fetch64(s + 96) + k0;
+ uint64 c = result[0] = HashLen16(b, len);
+ uint64 d = result[1] = Fetch64(s + 120) * k0 + len;
+ uint64 e = Fetch64(s + 184) + seed;
+ uint64 f = 0;
+ uint64 g = 0;
+ uint64 h = c + d;
+ uint64 x = seed;
+ uint64 y = 0;
+ uint64 z = 0;
+
+ // 240 bytes of input per iter.
+ size_t iters = len / 240;
+ len -= iters * 240;
+ do {
+#undef CHUNK
+#define CHUNK(r) \
+ PERMUTE3(x, z, y); \
+ b += Fetch64(s); \
+ c += Fetch64(s + 8); \
+ d += Fetch64(s + 16); \
+ e += Fetch64(s + 24); \
+ f += Fetch64(s + 32); \
+ a += b; \
+ h += f; \
+ b += c; \
+ f += d; \
+ g += e; \
+ e += z; \
+ g += x; \
+ z = _mm_crc32_u64(z, b + g); \
+ y = _mm_crc32_u64(y, e + h); \
+ x = _mm_crc32_u64(x, f + a); \
+ e = Rotate(e, r); \
+ c += e; \
+ s += 40
+
+ CHUNK(0); PERMUTE3(a, h, c);
+ CHUNK(33); PERMUTE3(a, h, f);
+ CHUNK(0); PERMUTE3(b, h, f);
+ CHUNK(42); PERMUTE3(b, h, d);
+ CHUNK(0); PERMUTE3(b, h, e);
+ CHUNK(33); PERMUTE3(a, h, e);
+ } while (--iters > 0);
+
+ while (len >= 40) {
+ CHUNK(29);
+ e ^= Rotate(a, 20);
+ h += Rotate(b, 30);
+ g ^= Rotate(c, 40);
+ f += Rotate(d, 34);
+ PERMUTE3(c, h, g);
+ len -= 40;
+ }
+ if (len > 0) {
+ s = s + len - 40;
+ CHUNK(33);
+ e ^= Rotate(a, 43);
+ h += Rotate(b, 42);
+ g ^= Rotate(c, 41);
+ f += Rotate(d, 40);
+ }
+ result[0] ^= h;
+ result[1] ^= g;
+ g += h;
+ a = HashLen16(a, g + z);
+ x += y << 32;
+ b += x;
+ c = HashLen16(c, z) + h;
+ d = HashLen16(d, e + result[0]);
+ g += e;
+ h += HashLen16(x, f);
+ e = HashLen16(a, d) + g;
+ z = HashLen16(b, c) + a;
+ y = HashLen16(g, h) + c;
+ result[0] = e + z + y + x;
+ a = ShiftMix((a + y) * k0) * k0 + b;
+ result[1] += a + result[0];
+ a = ShiftMix(a * k0) * k0 + c;
+ result[2] = a + result[1];
+ a = ShiftMix((a + e) * k0) * k0;
+ result[3] = a + result[2];
+}
+
+// Requires len < 240.
+static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) {
+ char buf[240];
+ memcpy(buf, s, len);
+ memset(buf + len, 0, 240 - len);
+ CityHashCrc256Long(buf, 240, ~static_cast<uint32>(len), result);
+}
+
+void CityHashCrc256(const char *s, size_t len, uint64 *result) {
+ if (LIKELY(len >= 240)) {
+ CityHashCrc256Long(s, len, 0, result);
+ } else {
+ CityHashCrc256Short(s, len, result);
+ }
+}
+
+uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
+ if (len <= 900) {
+ return CityHash128WithSeed(s, len, seed);
+ } else {
+ uint64 result[4];
+ CityHashCrc256(s, len, result);
+ uint64 u = Uint128High64(seed) + result[0];
+ uint64 v = Uint128Low64(seed) + result[1];
+ return uint128(HashLen16(u, v + result[2]),
+ HashLen16(Rotate(v, 32), u * k0 + result[3]));
+ }
+}
+
+uint128 CityHashCrc128(const char *s, size_t len) {
+ if (len <= 900) {
+ return CityHash128(s, len);
+ } else {
+ uint64 result[4];
+ CityHashCrc256(s, len, result);
+ return uint128(result[2], result[3]);
+ }
+}
+
+#endif
--- /dev/null
+// Copyright (c) 2011 Google, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+// CityHash, by Geoff Pike and Jyrki Alakuijala
+//
+// http://code.google.com/p/cityhash/
+//
+// This file provides a few functions for hashing strings. All of them are
+// high-quality functions in the sense that they pass standard tests such
+// as Austin Appleby's SMHasher. They are also fast.
+//
+// For 64-bit x86 code, on short strings, we don't know of anything faster than
+// CityHash64 that is of comparable quality. We believe our nearest competitor
+// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
+// tables and most other hashing (excluding cryptography).
+//
+// For 64-bit x86 code, on long strings, the picture is more complicated.
+// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
+// CityHashCrc128 appears to be faster than all competitors of comparable
+// quality. CityHash128 is also good but not quite as fast. We believe our
+// nearest competitor is Bob Jenkins' Spooky. We don't have great data for
+// other 64-bit CPUs, but for long strings we know that Spooky is slightly
+// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
+// Note that CityHashCrc128 is declared in citycrc.h.
+//
+// For 32-bit x86 code, we don't know of anything faster than CityHash32 that
+// is of comparable quality. We believe our nearest competitor is Murmur3A.
+// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
+//
+// Functions in the CityHash family are not suitable for cryptography.
+//
+// Please see CityHash's README file for more details on our performance
+// measurements and so on.
+//
+// WARNING: This code has been only lightly tested on big-endian platforms!
+// It is known to work well on little-endian platforms that have a small penalty
+// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
+// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
+// bug reports are welcome.
+//
+// By the way, for some hash functions, given strings a and b, the hash
+// of a+b is easily derived from the hashes of a and b. This property
+// doesn't hold for any hash functions in this file.
+
+#ifndef CITY_HASH_H_
+#define CITY_HASH_H_
+
+#include <stdlib.h> // for size_t.
+#include <stdint.h>
+#include <utility>
+
+typedef uint8_t uint8;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+typedef std::pair<uint64, uint64> uint128;
+
+inline uint64 Uint128Low64(const uint128& x) { return x.first; }
+inline uint64 Uint128High64(const uint128& x) { return x.second; }
+
+// Hash function for a byte array.
+uint64 CityHash64(const char *buf, size_t len);
+
+// Hash function for a byte array. For convenience, a 64-bit seed is also
+// hashed into the result.
+uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed);
+
+// Hash function for a byte array. For convenience, two seeds are also
+// hashed into the result.
+uint64 CityHash64WithSeeds(const char *buf, size_t len,
+ uint64 seed0, uint64 seed1);
+
+// Hash function for a byte array.
+uint128 CityHash128(const char *s, size_t len);
+
+// Hash function for a byte array. For convenience, a 128-bit seed is also
+// hashed into the result.
+uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed);
+
+// Hash function for a byte array. Most useful in 32-bit binaries.
+uint32 CityHash32(const char *buf, size_t len);
+
+// Hash 128 input bits down to 64 bits of output.
+// This is intended to be a reasonably good hash function.
+inline uint64 Hash128to64(const uint128& x) {
+ // Murmur-inspired hashing.
+ const uint64 kMul = 0x9ddfea08eb382d69ULL;
+ uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
+ a ^= (a >> 47);
+ uint64 b = (Uint128High64(x) ^ a) * kMul;
+ b ^= (b >> 47);
+ b *= kMul;
+ return b;
+}
+
+#endif // CITY_HASH_H_
--- /dev/null
+//$$CDS-header$$
+
+#ifndef CDSUNIT_HASH_FUNC_H
+#define CDSUNIT_HASH_FUNC_H
+
+#include "hashing/sha256.h"
+#include "hashing/md5.h"
+#include "hashing/city.h"
+
+namespace hashing {
+
+ template <class Hasher>
+ class hasher {
+ typedef Hasher hasher_type;
+ hasher_type m_hasher;
+ public:
+ struct hash_type {
+ uint8_t h[hasher_type::HashBytes];
+ };
+
+ hash_type operator()( void const * pBuf, size_t len )
+ {
+ m_hasher.reset();
+ m_hasher.add(pBuf, len);
+ hash_type result;
+ m_hasher.getHash( result.h );
+ return result;
+ }
+
+ hash_type operator()( std::string const& s )
+ {
+ return operator()( reinterpret_cast<void const *>(s.c_str()), s.length());
+ }
+
+ template <typename T>
+ hash_type operator()( T const& s )
+ {
+ return operator()( reinterpret_cast<void const *>(&s), sizeof(s));
+ }
+ };
+
+ typedef hasher<SHA256> sha256;
+ typedef hasher<MD5> md5;
+
+ class city32 {
+ public:
+ typedef uint32_t hash_type;
+
+ hash_type operator()( void const * pBuf, size_t len )
+ {
+ return CityHash32( reinterpret_cast<char const *>( pBuf ), len );
+ }
+
+ hash_type operator()( std::string const& s )
+ {
+ return CityHash32( s.c_str(), s.length() );
+ }
+
+ template <typename T>
+ hash_type operator()( T const& s )
+ {
+ return CityHash32( reinterpret_cast<char const *>( &s ), sizeof(s));
+ }
+ };
+
+ class city64 {
+ public:
+ typedef uint64_t hash_type;
+
+ hash_type operator()( void const * pBuf, size_t len )
+ {
+ return CityHash64( reinterpret_cast<char const *>( pBuf ), len );
+ }
+
+ hash_type operator()( std::string const& s )
+ {
+ return CityHash64( s.c_str(), s.length() );
+ }
+
+ template <typename T>
+ hash_type operator()( T const& s )
+ {
+ return CityHash64( reinterpret_cast<char const *>( &s ), sizeof(s));
+ }
+ };
+
+ class city128 {
+ public:
+ typedef uint128 hash_type;
+
+ hash_type operator()( void const * pBuf, size_t len )
+ {
+ return CityHash128( reinterpret_cast<char const *>( pBuf ), len );
+ }
+
+ hash_type operator()( std::string const& s )
+ {
+ return CityHash128( s.c_str(), s.length() );
+ }
+
+ template <typename T>
+ hash_type operator()( T const& s )
+ {
+ return CityHash128( reinterpret_cast<char const *>( &s ), sizeof(s));
+ }
+ };
+
+} // namespace hashing
+
+#endif // #ifndef CDSUNIT_HASH_FUNC_H
--- /dev/null
+// //////////////////////////////////////////////////////////
+// md5.cpp
+// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
+// see http://create.stephan-brumme.com/disclaimer.html
+//
+
+#include "md5.h"
+
+#ifndef _MSC_VER
+#include <endian.h>
+#endif
+
+
+/// same as reset()
+MD5::MD5()
+{
+ reset();
+}
+
+
+/// restart
+void MD5::reset()
+{
+ m_numBytes = 0;
+ m_bufferSize = 0;
+
+ // according to RFC 1321
+ m_hash[0] = 0x67452301;
+ m_hash[1] = 0xefcdab89;
+ m_hash[2] = 0x98badcfe;
+ m_hash[3] = 0x10325476;
+}
+
+
+namespace
+{
+ // mix functions for processBlock()
+ inline uint32_t f1(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return d ^ (b & (c ^ d)); // original: f = (b & c) | ((~b) & d);
+ }
+
+ inline uint32_t f2(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return c ^ (d & (b ^ c)); // original: f = (b & d) | (c & (~d));
+ }
+
+ inline uint32_t f3(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return b ^ c ^ d;
+ }
+
+ inline uint32_t f4(uint32_t b, uint32_t c, uint32_t d)
+ {
+ return c ^ (b | ~d);
+ }
+
+ inline uint32_t rotate(uint32_t a, uint32_t c)
+ {
+ return (a << c) | (a >> (32 - c));
+ }
+
+#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
+ inline uint32_t swap(uint32_t x)
+ {
+#if defined(__GNUC__) || defined(__clang__)
+ return __builtin_bswap32(x);
+#endif
+#ifdef MSC_VER
+ return _byteswap_ulong(x);
+#endif
+
+ return (x >> 24) |
+ ((x >> 8) & 0x0000FF00) |
+ ((x << 8) & 0x00FF0000) |
+ (x << 24);
+ }
+#endif
+}
+
+
+/// process 64 bytes
+void MD5::processBlock(const void* data)
+{
+ // get last hash
+ uint32_t a = m_hash[0];
+ uint32_t b = m_hash[1];
+ uint32_t c = m_hash[2];
+ uint32_t d = m_hash[3];
+
+ // data represented as 16x 32-bit words
+ const uint32_t* words = (uint32_t*) data;
+
+ // computations are little endian, swap data if necessary
+#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
+#define LITTLEENDIAN(x) swap(x)
+#else
+#define LITTLEENDIAN(x) (x)
+#endif
+
+ // first round
+ uint32_t word0 = LITTLEENDIAN(words[ 0]);
+ a = rotate(a + f1(b,c,d) + word0 + 0xd76aa478, 7) + b;
+ uint32_t word1 = LITTLEENDIAN(words[ 1]);
+ d = rotate(d + f1(a,b,c) + word1 + 0xe8c7b756, 12) + a;
+ uint32_t word2 = LITTLEENDIAN(words[ 2]);
+ c = rotate(c + f1(d,a,b) + word2 + 0x242070db, 17) + d;
+ uint32_t word3 = LITTLEENDIAN(words[ 3]);
+ b = rotate(b + f1(c,d,a) + word3 + 0xc1bdceee, 22) + c;
+
+ uint32_t word4 = LITTLEENDIAN(words[ 4]);
+ a = rotate(a + f1(b,c,d) + word4 + 0xf57c0faf, 7) + b;
+ uint32_t word5 = LITTLEENDIAN(words[ 5]);
+ d = rotate(d + f1(a,b,c) + word5 + 0x4787c62a, 12) + a;
+ uint32_t word6 = LITTLEENDIAN(words[ 6]);
+ c = rotate(c + f1(d,a,b) + word6 + 0xa8304613, 17) + d;
+ uint32_t word7 = LITTLEENDIAN(words[ 7]);
+ b = rotate(b + f1(c,d,a) + word7 + 0xfd469501, 22) + c;
+
+ uint32_t word8 = LITTLEENDIAN(words[ 8]);
+ a = rotate(a + f1(b,c,d) + word8 + 0x698098d8, 7) + b;
+ uint32_t word9 = LITTLEENDIAN(words[ 9]);
+ d = rotate(d + f1(a,b,c) + word9 + 0x8b44f7af, 12) + a;
+ uint32_t word10 = LITTLEENDIAN(words[10]);
+ c = rotate(c + f1(d,a,b) + word10 + 0xffff5bb1, 17) + d;
+ uint32_t word11 = LITTLEENDIAN(words[11]);
+ b = rotate(b + f1(c,d,a) + word11 + 0x895cd7be, 22) + c;
+
+ uint32_t word12 = LITTLEENDIAN(words[12]);
+ a = rotate(a + f1(b,c,d) + word12 + 0x6b901122, 7) + b;
+ uint32_t word13 = LITTLEENDIAN(words[13]);
+ d = rotate(d + f1(a,b,c) + word13 + 0xfd987193, 12) + a;
+ uint32_t word14 = LITTLEENDIAN(words[14]);
+ c = rotate(c + f1(d,a,b) + word14 + 0xa679438e, 17) + d;
+ uint32_t word15 = LITTLEENDIAN(words[15]);
+ b = rotate(b + f1(c,d,a) + word15 + 0x49b40821, 22) + c;
+
+ // second round
+ a = rotate(a + f2(b,c,d) + word1 + 0xf61e2562, 5) + b;
+ d = rotate(d + f2(a,b,c) + word6 + 0xc040b340, 9) + a;
+ c = rotate(c + f2(d,a,b) + word11 + 0x265e5a51, 14) + d;
+ b = rotate(b + f2(c,d,a) + word0 + 0xe9b6c7aa, 20) + c;
+
+ a = rotate(a + f2(b,c,d) + word5 + 0xd62f105d, 5) + b;
+ d = rotate(d + f2(a,b,c) + word10 + 0x02441453, 9) + a;
+ c = rotate(c + f2(d,a,b) + word15 + 0xd8a1e681, 14) + d;
+ b = rotate(b + f2(c,d,a) + word4 + 0xe7d3fbc8, 20) + c;
+
+ a = rotate(a + f2(b,c,d) + word9 + 0x21e1cde6, 5) + b;
+ d = rotate(d + f2(a,b,c) + word14 + 0xc33707d6, 9) + a;
+ c = rotate(c + f2(d,a,b) + word3 + 0xf4d50d87, 14) + d;
+ b = rotate(b + f2(c,d,a) + word8 + 0x455a14ed, 20) + c;
+
+ a = rotate(a + f2(b,c,d) + word13 + 0xa9e3e905, 5) + b;
+ d = rotate(d + f2(a,b,c) + word2 + 0xfcefa3f8, 9) + a;
+ c = rotate(c + f2(d,a,b) + word7 + 0x676f02d9, 14) + d;
+ b = rotate(b + f2(c,d,a) + word12 + 0x8d2a4c8a, 20) + c;
+
+ // third round
+ a = rotate(a + f3(b,c,d) + word5 + 0xfffa3942, 4) + b;
+ d = rotate(d + f3(a,b,c) + word8 + 0x8771f681, 11) + a;
+ c = rotate(c + f3(d,a,b) + word11 + 0x6d9d6122, 16) + d;
+ b = rotate(b + f3(c,d,a) + word14 + 0xfde5380c, 23) + c;
+
+ a = rotate(a + f3(b,c,d) + word1 + 0xa4beea44, 4) + b;
+ d = rotate(d + f3(a,b,c) + word4 + 0x4bdecfa9, 11) + a;
+ c = rotate(c + f3(d,a,b) + word7 + 0xf6bb4b60, 16) + d;
+ b = rotate(b + f3(c,d,a) + word10 + 0xbebfbc70, 23) + c;
+
+ a = rotate(a + f3(b,c,d) + word13 + 0x289b7ec6, 4) + b;
+ d = rotate(d + f3(a,b,c) + word0 + 0xeaa127fa, 11) + a;
+ c = rotate(c + f3(d,a,b) + word3 + 0xd4ef3085, 16) + d;
+ b = rotate(b + f3(c,d,a) + word6 + 0x04881d05, 23) + c;
+
+ a = rotate(a + f3(b,c,d) + word9 + 0xd9d4d039, 4) + b;
+ d = rotate(d + f3(a,b,c) + word12 + 0xe6db99e5, 11) + a;
+ c = rotate(c + f3(d,a,b) + word15 + 0x1fa27cf8, 16) + d;
+ b = rotate(b + f3(c,d,a) + word2 + 0xc4ac5665, 23) + c;
+
+ // fourth round
+ a = rotate(a + f4(b,c,d) + word0 + 0xf4292244, 6) + b;
+ d = rotate(d + f4(a,b,c) + word7 + 0x432aff97, 10) + a;
+ c = rotate(c + f4(d,a,b) + word14 + 0xab9423a7, 15) + d;
+ b = rotate(b + f4(c,d,a) + word5 + 0xfc93a039, 21) + c;
+
+ a = rotate(a + f4(b,c,d) + word12 + 0x655b59c3, 6) + b;
+ d = rotate(d + f4(a,b,c) + word3 + 0x8f0ccc92, 10) + a;
+ c = rotate(c + f4(d,a,b) + word10 + 0xffeff47d, 15) + d;
+ b = rotate(b + f4(c,d,a) + word1 + 0x85845dd1, 21) + c;
+
+ a = rotate(a + f4(b,c,d) + word8 + 0x6fa87e4f, 6) + b;
+ d = rotate(d + f4(a,b,c) + word15 + 0xfe2ce6e0, 10) + a;
+ c = rotate(c + f4(d,a,b) + word6 + 0xa3014314, 15) + d;
+ b = rotate(b + f4(c,d,a) + word13 + 0x4e0811a1, 21) + c;
+
+ a = rotate(a + f4(b,c,d) + word4 + 0xf7537e82, 6) + b;
+ d = rotate(d + f4(a,b,c) + word11 + 0xbd3af235, 10) + a;
+ c = rotate(c + f4(d,a,b) + word2 + 0x2ad7d2bb, 15) + d;
+ b = rotate(b + f4(c,d,a) + word9 + 0xeb86d391, 21) + c;
+
+ // update hash
+ m_hash[0] += a;
+ m_hash[1] += b;
+ m_hash[2] += c;
+ m_hash[3] += d;
+}
+
+
+/// add arbitrary number of bytes
+void MD5::add(const void* data, size_t numBytes)
+{
+ const uint8_t* current = (const uint8_t*) data;
+
+ if (m_bufferSize > 0)
+ {
+ while (numBytes > 0 && m_bufferSize < BlockSize)
+ {
+ m_buffer[m_bufferSize++] = *current++;
+ numBytes--;
+ }
+ }
+
+ // full buffer
+ if (m_bufferSize == BlockSize)
+ {
+ processBlock(m_buffer);
+ m_numBytes += BlockSize;
+ m_bufferSize = 0;
+ }
+
+ // no more data ?
+ if (numBytes == 0)
+ return;
+
+ // process full blocks
+ while (numBytes >= BlockSize)
+ {
+ processBlock(current);
+ current += BlockSize;
+ m_numBytes += BlockSize;
+ numBytes -= BlockSize;
+ }
+
+ // keep remaining bytes in buffer
+ while (numBytes > 0)
+ {
+ m_buffer[m_bufferSize++] = *current++;
+ numBytes--;
+ }
+}
+
+
+/// process final block, less than 64 bytes
+void MD5::processBuffer()
+{
+ // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
+
+ // - append "1" bit to message
+ // - append "0" bits until message length in bit mod 512 is 448
+ // - append length as 64 bit integer
+
+ // number of bits
+ size_t paddedLength = m_bufferSize * 8;
+
+ // plus one bit set to 1 (always appended)
+ paddedLength++;
+
+ // number of bits must be (numBits % 512) = 448
+ size_t lower11Bits = paddedLength & 511;
+ if (lower11Bits <= 448)
+ paddedLength += 448 - lower11Bits;
+ else
+ paddedLength += 512 + 448 - lower11Bits;
+ // convert from bits to bytes
+ paddedLength /= 8;
+
+ // only needed if additional data flows over into a second block
+ unsigned char extra[BlockSize];
+
+ // append a "1" bit, 128 => binary 10000000
+ if (m_bufferSize < BlockSize)
+ m_buffer[m_bufferSize] = 128;
+ else
+ extra[0] = 128;
+
+ size_t i;
+ for (i = m_bufferSize + 1; i < BlockSize; i++)
+ m_buffer[i] = 0;
+ for (; i < paddedLength; i++)
+ extra[i - BlockSize] = 0;
+
+ // add message length in bits as 64 bit number
+ uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
+ // find right position
+ unsigned char* addLength;
+ if (paddedLength < BlockSize)
+ addLength = m_buffer + paddedLength;
+ else
+ addLength = extra + paddedLength - BlockSize;
+
+ // must be little endian
+ *addLength++ = msgBits & 0xFF; msgBits >>= 8;
+ *addLength++ = msgBits & 0xFF; msgBits >>= 8;
+ *addLength++ = msgBits & 0xFF; msgBits >>= 8;
+ *addLength++ = msgBits & 0xFF; msgBits >>= 8;
+ *addLength++ = msgBits & 0xFF; msgBits >>= 8;
+ *addLength++ = msgBits & 0xFF; msgBits >>= 8;
+ *addLength++ = msgBits & 0xFF; msgBits >>= 8;
+ *addLength++ = msgBits & 0xFF;
+
+ // process blocks
+ processBlock(m_buffer);
+ // flowed over into a second block ?
+ if (paddedLength > BlockSize)
+ processBlock(extra);
+}
+
+
+/// return latest hash as 32 hex characters
+std::string MD5::getHash()
+{
+ // compute hash (as raw bytes)
+ unsigned char rawHash[HashBytes];
+ getHash(rawHash);
+
+ // convert to hex string
+ std::string result;
+ result.reserve(2 * HashBytes);
+ for (int i = 0; i < HashBytes; i++)
+ {
+ static const char dec2hex[16+1] = "0123456789abcdef";
+ result += dec2hex[(rawHash[i] >> 4) & 15];
+ result += dec2hex[ rawHash[i] & 15];
+ }
+
+ return result;
+}
+
+
+/// return latest hash as bytes
+void MD5::getHash(unsigned char buffer[MD5::HashBytes])
+{
+ // save old hash if buffer is partially filled
+ uint32_t oldHash[HashValues];
+ for (int i = 0; i < HashValues; i++)
+ oldHash[i] = m_hash[i];
+
+ // process remaining bytes
+ processBuffer();
+
+ unsigned char* current = buffer;
+ for (int i = 0; i < HashValues; i++)
+ {
+ *current++ = m_hash[i] & 0xFF;
+ *current++ = (m_hash[i] >> 8) & 0xFF;
+ *current++ = (m_hash[i] >> 16) & 0xFF;
+ *current++ = (m_hash[i] >> 24) & 0xFF;
+
+ // restore old hash
+ m_hash[i] = oldHash[i];
+ }
+}
+
+
+/// compute MD5 of a memory block
+std::string MD5::operator()(const void* data, size_t numBytes)
+{
+ reset();
+ add(data, numBytes);
+ return getHash();
+}
+
+
+/// compute MD5 of a string, excluding final zero
+std::string MD5::operator()(const std::string& text)
+{
+ reset();
+ add(text.c_str(), text.size());
+ return getHash();
+}
--- /dev/null
+// //////////////////////////////////////////////////////////
+// md5.h
+// Copyright (c) 2014 Stephan Brumme. All rights reserved.
+// see http://create.stephan-brumme.com/disclaimer.html
+//
+
+#pragma once
+
+//#include "hash.h"
+#include <string>
+
+// define fixed size integer types
+#ifdef _MSC_VER
+// Windows
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#else
+// GCC
+#include <stdint.h>
+#endif
+
+
+/// compute MD5 hash
+/** Usage:
+ MD5 md5;
+ std::string myHash = md5("Hello World"); // std::string
+ std::string myHash2 = md5("How are you", 11); // arbitrary data, 11 bytes
+
+ // or in a streaming fashion:
+
+ MD5 md5;
+ while (more data available)
+ md5.add(pointer to fresh data, number of new bytes);
+ std::string myHash3 = md5.getHash();
+ */
+class MD5 //: public Hash
+{
+public:
+ /// split into 64 byte blocks (=> 512 bits), hash is 16 bytes long
+ enum { BlockSize = 512 / 8, HashBytes = 16 };
+
+ /// same as reset()
+ MD5();
+
+ /// compute MD5 of a memory block
+ std::string operator()(const void* data, size_t numBytes);
+ /// compute MD5 of a string, excluding final zero
+ std::string operator()(const std::string& text);
+
+ /// add arbitrary number of bytes
+ void add(const void* data, size_t numBytes);
+
+ /// return latest hash as 32 hex characters
+ std::string getHash();
+ /// return latest hash as bytes
+ void getHash(unsigned char buffer[HashBytes]);
+
+ /// restart
+ void reset();
+
+private:
+ /// process 64 bytes
+ void processBlock(const void* data);
+ /// process everything left in the internal buffer
+ void processBuffer();
+
+ /// size of processed data in bytes
+ uint64_t m_numBytes;
+ /// valid bytes in m_buffer
+ size_t m_bufferSize;
+ /// bytes not processed yet
+ uint8_t m_buffer[BlockSize];
+
+ enum { HashValues = HashBytes / 4 };
+ /// hash, stored as integers
+ uint32_t m_hash[HashValues];
+};
--- /dev/null
+// //////////////////////////////////////////////////////////
+// sha256.cpp
+// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
+// see http://create.stephan-brumme.com/disclaimer.html
+//
+
+#include "sha256.h"
+
+// big endian architectures need #define __BYTE_ORDER __BIG_ENDIAN
+#ifndef _MSC_VER
+#include <endian.h>
+#endif
+
+
+/// same as reset()
+SHA256::SHA256()
+{
+ reset();
+}
+
+
+/// restart
+void SHA256::reset()
+{
+ m_numBytes = 0;
+ m_bufferSize = 0;
+
+ // according to RFC 1321
+ m_hash[0] = 0x6a09e667;
+ m_hash[1] = 0xbb67ae85;
+ m_hash[2] = 0x3c6ef372;
+ m_hash[3] = 0xa54ff53a;
+ m_hash[4] = 0x510e527f;
+ m_hash[5] = 0x9b05688c;
+ m_hash[6] = 0x1f83d9ab;
+ m_hash[7] = 0x5be0cd19;
+}
+
+
+namespace
+{
+ inline uint32_t rotate(uint32_t a, uint32_t c)
+ {
+ return (a >> c) | (a << (32 - c));
+ }
+
+ inline uint32_t swap(uint32_t x)
+ {
+#if defined(__GNUC__) || defined(__clang__)
+ return __builtin_bswap32(x);
+#endif
+#ifdef MSC_VER
+ return _byteswap_ulong(x);
+#endif
+
+ return (x >> 24) |
+ ((x >> 8) & 0x0000FF00) |
+ ((x << 8) & 0x00FF0000) |
+ (x << 24);
+ }
+
+ // mix functions for processBlock()
+ inline uint32_t f1(uint32_t e, uint32_t f, uint32_t g)
+ {
+ uint32_t term1 = rotate(e, 6) ^ rotate(e, 11) ^ rotate(e, 25);
+ uint32_t term2 = (e & f) ^ (~e & g); //(g ^ (e & (f ^ g)))
+ return term1 + term2;
+ }
+
+ inline uint32_t f2(uint32_t a, uint32_t b, uint32_t c)
+ {
+ uint32_t term1 = rotate(a, 2) ^ rotate(a, 13) ^ rotate(a, 22);
+ uint32_t term2 = ((a | b) & c) | (a & b); //(a & (b ^ c)) ^ (b & c);
+ return term1 + term2;
+ }
+}
+
+
+/// process 64 bytes
+void SHA256::processBlock(const void* data)
+{
+ // get last hash
+ uint32_t a = m_hash[0];
+ uint32_t b = m_hash[1];
+ uint32_t c = m_hash[2];
+ uint32_t d = m_hash[3];
+ uint32_t e = m_hash[4];
+ uint32_t f = m_hash[5];
+ uint32_t g = m_hash[6];
+ uint32_t h = m_hash[7];
+
+ // data represented as 16x 32-bit words
+ const uint32_t* input = (uint32_t*) data;
+ // convert to big endian
+ uint32_t words[64];
+ int i;
+ for (i = 0; i < 16; i++)
+#if defined(__BYTE_ORDER) && (__BYTE_ORDER != 0) && (__BYTE_ORDER == __BIG_ENDIAN)
+ words[i] = input[i];
+#else
+ words[i] = swap(input[i]);
+#endif
+
+ uint32_t x,y; // temporaries
+
+ // first round
+ x = h + f1(e,f,g) + 0x428a2f98 + words[ 0]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0x71374491 + words[ 1]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0xb5c0fbcf + words[ 2]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0xe9b5dba5 + words[ 3]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0x3956c25b + words[ 4]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0x59f111f1 + words[ 5]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0x923f82a4 + words[ 6]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0xab1c5ed5 + words[ 7]; y = f2(b,c,d); e += x; a = x + y;
+
+ // secound round
+ x = h + f1(e,f,g) + 0xd807aa98 + words[ 8]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0x12835b01 + words[ 9]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0x243185be + words[10]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0x550c7dc3 + words[11]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0x72be5d74 + words[12]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0x80deb1fe + words[13]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0x9bdc06a7 + words[14]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0xc19bf174 + words[15]; y = f2(b,c,d); e += x; a = x + y;
+
+ // extend to 24 words
+ for (; i < 24; i++)
+ words[i] = words[i-16] +
+ (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
+ words[i-7] +
+ (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
+
+ // third round
+ x = h + f1(e,f,g) + 0xe49b69c1 + words[16]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0xefbe4786 + words[17]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0x0fc19dc6 + words[18]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0x240ca1cc + words[19]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0x2de92c6f + words[20]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0x4a7484aa + words[21]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0x5cb0a9dc + words[22]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0x76f988da + words[23]; y = f2(b,c,d); e += x; a = x + y;
+
+ // extend to 32 words
+ for (; i < 32; i++)
+ words[i] = words[i-16] +
+ (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
+ words[i-7] +
+ (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
+
+ // fourth round
+ x = h + f1(e,f,g) + 0x983e5152 + words[24]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0xa831c66d + words[25]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0xb00327c8 + words[26]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0xbf597fc7 + words[27]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0xc6e00bf3 + words[28]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0xd5a79147 + words[29]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0x06ca6351 + words[30]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0x14292967 + words[31]; y = f2(b,c,d); e += x; a = x + y;
+
+ // extend to 40 words
+ for (; i < 40; i++)
+ words[i] = words[i-16] +
+ (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
+ words[i-7] +
+ (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
+
+ // fifth round
+ x = h + f1(e,f,g) + 0x27b70a85 + words[32]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0x2e1b2138 + words[33]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0x4d2c6dfc + words[34]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0x53380d13 + words[35]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0x650a7354 + words[36]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0x766a0abb + words[37]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0x81c2c92e + words[38]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0x92722c85 + words[39]; y = f2(b,c,d); e += x; a = x + y;
+
+ // extend to 48 words
+ for (; i < 48; i++)
+ words[i] = words[i-16] +
+ (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
+ words[i-7] +
+ (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
+
+ // sixth round
+ x = h + f1(e,f,g) + 0xa2bfe8a1 + words[40]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0xa81a664b + words[41]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0xc24b8b70 + words[42]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0xc76c51a3 + words[43]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0xd192e819 + words[44]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0xd6990624 + words[45]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0xf40e3585 + words[46]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0x106aa070 + words[47]; y = f2(b,c,d); e += x; a = x + y;
+
+ // extend to 56 words
+ for (; i < 56; i++)
+ words[i] = words[i-16] +
+ (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
+ words[i-7] +
+ (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
+
+ // seventh round
+ x = h + f1(e,f,g) + 0x19a4c116 + words[48]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0x1e376c08 + words[49]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0x2748774c + words[50]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0x34b0bcb5 + words[51]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0x391c0cb3 + words[52]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0x4ed8aa4a + words[53]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0x5b9cca4f + words[54]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0x682e6ff3 + words[55]; y = f2(b,c,d); e += x; a = x + y;
+
+ // extend to 64 words
+ for (; i < 64; i++)
+ words[i] = words[i-16] +
+ (rotate(words[i-15], 7) ^ rotate(words[i-15], 18) ^ (words[i-15] >> 3)) +
+ words[i-7] +
+ (rotate(words[i- 2], 17) ^ rotate(words[i- 2], 19) ^ (words[i- 2] >> 10));
+
+ // eigth round
+ x = h + f1(e,f,g) + 0x748f82ee + words[56]; y = f2(a,b,c); d += x; h = x + y;
+ x = g + f1(d,e,f) + 0x78a5636f + words[57]; y = f2(h,a,b); c += x; g = x + y;
+ x = f + f1(c,d,e) + 0x84c87814 + words[58]; y = f2(g,h,a); b += x; f = x + y;
+ x = e + f1(b,c,d) + 0x8cc70208 + words[59]; y = f2(f,g,h); a += x; e = x + y;
+ x = d + f1(a,b,c) + 0x90befffa + words[60]; y = f2(e,f,g); h += x; d = x + y;
+ x = c + f1(h,a,b) + 0xa4506ceb + words[61]; y = f2(d,e,f); g += x; c = x + y;
+ x = b + f1(g,h,a) + 0xbef9a3f7 + words[62]; y = f2(c,d,e); f += x; b = x + y;
+ x = a + f1(f,g,h) + 0xc67178f2 + words[63]; y = f2(b,c,d); e += x; a = x + y;
+
+ // update hash
+ m_hash[0] += a;
+ m_hash[1] += b;
+ m_hash[2] += c;
+ m_hash[3] += d;
+ m_hash[4] += e;
+ m_hash[5] += f;
+ m_hash[6] += g;
+ m_hash[7] += h;
+}
+
+
+/// add arbitrary number of bytes
+void SHA256::add(const void* data, size_t numBytes)
+{
+ const uint8_t* current = (const uint8_t*) data;
+
+ if (m_bufferSize > 0)
+ {
+ while (numBytes > 0 && m_bufferSize < BlockSize)
+ {
+ m_buffer[m_bufferSize++] = *current++;
+ numBytes--;
+ }
+ }
+
+ // full buffer
+ if (m_bufferSize == BlockSize)
+ {
+ processBlock(m_buffer);
+ m_numBytes += BlockSize;
+ m_bufferSize = 0;
+ }
+
+ // no more data ?
+ if (numBytes == 0)
+ return;
+
+ // process full blocks
+ while (numBytes >= BlockSize)
+ {
+ processBlock(current);
+ current += BlockSize;
+ m_numBytes += BlockSize;
+ numBytes -= BlockSize;
+ }
+
+ // keep remaining bytes in buffer
+ while (numBytes > 0)
+ {
+ m_buffer[m_bufferSize++] = *current++;
+ numBytes--;
+ }
+}
+
+
+/// process final block, less than 64 bytes
+void SHA256::processBuffer()
+{
+ // the input bytes are considered as bits strings, where the first bit is the most significant bit of the byte
+
+ // - append "1" bit to message
+ // - append "0" bits until message length in bit mod 512 is 448
+ // - append length as 64 bit integer
+
+ // number of bits
+ size_t paddedLength = m_bufferSize * 8;
+
+ // plus one bit set to 1 (always appended)
+ paddedLength++;
+
+ // number of bits must be (numBits % 512) = 448
+ size_t lower11Bits = paddedLength & 511;
+ if (lower11Bits <= 448)
+ paddedLength += 448 - lower11Bits;
+ else
+ paddedLength += 512 + 448 - lower11Bits;
+ // convert from bits to bytes
+ paddedLength /= 8;
+
+ // only needed if additional data flows over into a second block
+ unsigned char extra[BlockSize];
+
+ // append a "1" bit, 128 => binary 10000000
+ if (m_bufferSize < BlockSize)
+ m_buffer[m_bufferSize] = 128;
+ else
+ extra[0] = 128;
+
+ size_t i;
+ for (i = m_bufferSize + 1; i < BlockSize; i++)
+ m_buffer[i] = 0;
+ for (; i < paddedLength; i++)
+ extra[i - BlockSize] = 0;
+
+ // add message length in bits as 64 bit number
+ uint64_t msgBits = 8 * (m_numBytes + m_bufferSize);
+ // find right position
+ unsigned char* addLength;
+ if (paddedLength < BlockSize)
+ addLength = m_buffer + paddedLength;
+ else
+ addLength = extra + paddedLength - BlockSize;
+
+ // must be big endian
+ *addLength++ = (unsigned char)((msgBits >> 56) & 0xFF);
+ *addLength++ = (unsigned char)((msgBits >> 48) & 0xFF);
+ *addLength++ = (unsigned char)((msgBits >> 40) & 0xFF);
+ *addLength++ = (unsigned char)((msgBits >> 32) & 0xFF);
+ *addLength++ = (unsigned char)((msgBits >> 24) & 0xFF);
+ *addLength++ = (unsigned char)((msgBits >> 16) & 0xFF);
+ *addLength++ = (unsigned char)((msgBits >> 8) & 0xFF);
+ *addLength = (unsigned char)( msgBits & 0xFF);
+
+ // process blocks
+ processBlock(m_buffer);
+ // flowed over into a second block ?
+ if (paddedLength > BlockSize)
+ processBlock(extra);
+}
+
+
+/// return latest hash as 64 hex characters
+std::string SHA256::getHash()
+{
+ // compute hash (as raw bytes)
+ unsigned char rawHash[HashBytes];
+ getHash(rawHash);
+
+ // convert to hex string
+ std::string result;
+ result.reserve(2 * HashBytes);
+ for (int i = 0; i < HashBytes; i++)
+ {
+ static const char dec2hex[16+1] = "0123456789abcdef";
+ result += dec2hex[(rawHash[i] >> 4) & 15];
+ result += dec2hex[ rawHash[i] & 15];
+ }
+
+ return result;
+}
+
+
+/// return latest hash as bytes
+void SHA256::getHash(unsigned char buffer[SHA256::HashBytes])
+{
+ // save old hash if buffer is partially filled
+ uint32_t oldHash[HashValues];
+ for (int i = 0; i < HashValues; i++)
+ oldHash[i] = m_hash[i];
+
+ // process remaining bytes
+ processBuffer();
+
+ unsigned char* current = buffer;
+ for (int i = 0; i < HashValues; i++)
+ {
+ *current++ = (m_hash[i] >> 24) & 0xFF;
+ *current++ = (m_hash[i] >> 16) & 0xFF;
+ *current++ = (m_hash[i] >> 8) & 0xFF;
+ *current++ = m_hash[i] & 0xFF;
+
+ // restore old hash
+ m_hash[i] = oldHash[i];
+ }
+}
+
+
+/// compute SHA256 of a memory block
+std::string SHA256::operator()(const void* data, size_t numBytes)
+{
+ reset();
+ add(data, numBytes);
+ return getHash();
+}
+
+
+/// compute SHA256 of a string, excluding final zero
+std::string SHA256::operator()(const std::string& text)
+{
+ reset();
+ add(text.c_str(), text.size());
+ return getHash();
+}
--- /dev/null
+// //////////////////////////////////////////////////////////
+// sha256.h
+// Copyright (c) 2014,2015 Stephan Brumme. All rights reserved.
+// see http://create.stephan-brumme.com/disclaimer.html
+//
+
+#pragma once
+
+//#include "hash.h"
+#include <string>
+
+// define fixed size integer types
+#ifdef _MSC_VER
+// Windows
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#else
+// GCC
+#include <stdint.h>
+#endif
+
+
+/// compute SHA256 hash
+/** Usage:
+ SHA256 sha256;
+ std::string myHash = sha256("Hello World"); // std::string
+ std::string myHash2 = sha256("How are you", 11); // arbitrary data, 11 bytes
+
+ // or in a streaming fashion:
+
+ SHA256 sha256;
+ while (more data available)
+ sha256.add(pointer to fresh data, number of new bytes);
+ std::string myHash3 = sha256.getHash();
+ */
+class SHA256 //: public Hash
+{
+public:
+ /// split into 64 byte blocks (=> 512 bits), hash is 32 bytes long
+ enum { BlockSize = 512 / 8, HashBytes = 32 };
+
+ /// same as reset()
+ SHA256();
+
+ /// compute SHA256 of a memory block
+ std::string operator()(const void* data, size_t numBytes);
+ /// compute SHA256 of a string, excluding final zero
+ std::string operator()(const std::string& text);
+
+ /// add arbitrary number of bytes
+ void add(const void* data, size_t numBytes);
+
+ /// return latest hash as 64 hex characters
+ std::string getHash();
+ /// return latest hash as bytes
+ void getHash(unsigned char buffer[HashBytes]);
+
+ /// restart
+ void reset();
+
+private:
+ /// process 64 bytes
+ void processBlock(const void* data);
+ /// process everything left in the internal buffer
+ void processBuffer();
+
+ /// size of processed data in bytes
+ uint64_t m_numBytes;
+ /// valid bytes in m_buffer
+ size_t m_bufferSize;
+ /// bytes not processed yet
+ uint8_t m_buffer[BlockSize];
+
+ enum { HashValues = HashBytes / 4 };
+ /// hash, stored as integers
+ uint32_t m_hash[HashValues];
+};
TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_stdhash) \
TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_stdhash_stat) \
TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_stdhash) \
- TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_stdhash_stat)
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_stdhash_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_md5) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_md5_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_md5) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_md5_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_sha256) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_sha256_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_sha256) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_sha256_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city64) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city64_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city64) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city64_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city128) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_hp_city128_stat) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city128) \
+ TEST_CASE(tag_MultiLevelHashMap, MultiLevelHashMap_dhp_city128_stat) \
+
#undef CDSUNIT_TEST_MultiLevelHashMap
#define CDSUNIT_TEST_MultiLevelHashMap \
CPPUNIT_TEST(MultiLevelHashMap_hp_stdhash) \
CPPUNIT_TEST(MultiLevelHashMap_hp_stdhash_stat) \
CPPUNIT_TEST(MultiLevelHashMap_dhp_stdhash) \
- CPPUNIT_TEST(MultiLevelHashMap_dhp_stdhash_stat)
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_stdhash_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_md5) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_md5_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_md5) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_md5_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_sha256) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_sha256_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_sha256) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_sha256_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_city64) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_city64_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_city64) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_city64_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_city128) \
+ CPPUNIT_TEST(MultiLevelHashMap_hp_city128_stat) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_city128) \
+ CPPUNIT_TEST(MultiLevelHashMap_dhp_city128_stat) \
#include <cds/container/multilevel_hashmap_dhp.h>
#include "print_multilevel_hashset_stat.h"
+#include "hashing/hash_func.h"
namespace map2 {
typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_hp_stdhash_stat;
typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_stat > MultiLevelHashMap_dhp_stdhash_stat;
+
+ // SHA256
+ struct traits_MultiLevelHashMap_sha256 : public cc::multilevel_hashmap::traits
+ {
+ typedef ::hashing::sha256 hash;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_hp_sha256;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_sha256 > MultiLevelHashMap_dhp_sha256;
+
+ struct traits_MultiLevelHashMap_sha256_stat : public traits_MultiLevelHashMap_sha256
+ {
+ typedef cc::multilevel_hashmap::stat<> stat;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_hp_sha256_stat;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_sha256_stat > MultiLevelHashMap_dhp_sha256_stat;
+
+ //MD5
+ struct traits_MultiLevelHashMap_md5 : public cc::multilevel_hashmap::traits
+ {
+ typedef ::hashing::md5 hash;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_hp_md5;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_md5 > MultiLevelHashMap_dhp_md5;
+
+ struct traits_MultiLevelHashMap_md5_stat : public traits_MultiLevelHashMap_md5
+ {
+ typedef cc::multilevel_hashmap::stat<> stat;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_hp_md5_stat;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_md5_stat > MultiLevelHashMap_dhp_md5_stat;
+
+ // CityHash
+ struct traits_MultiLevelHashMap_city64 : public cc::multilevel_hashmap::traits
+ {
+ typedef ::hashing::city64 hash;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_hp_city64;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city64 > MultiLevelHashMap_dhp_city64;
+
+ struct traits_MultiLevelHashMap_city64_stat : public traits_MultiLevelHashMap_city64
+ {
+ typedef cc::multilevel_hashmap::stat<> stat;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_hp_city64_stat;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city64_stat > MultiLevelHashMap_dhp_city64_stat;
+
+ struct traits_MultiLevelHashMap_city128 : public cc::multilevel_hashmap::traits
+ {
+ typedef ::hashing::city128 hash;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_hp_city128;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city128 > MultiLevelHashMap_dhp_city128;
+
+ struct traits_MultiLevelHashMap_city128_stat : public traits_MultiLevelHashMap_city128
+ {
+ typedef cc::multilevel_hashmap::stat<> stat;
+ };
+ typedef MultiLevelHashMap< cds::gc::HP, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_hp_city128_stat;
+ typedef MultiLevelHashMap< cds::gc::DHP, Key, Value, traits_MultiLevelHashMap_city128_stat > MultiLevelHashMap_dhp_city128_stat;
+
};
template <typename GC, typename K, typename T, typename Traits >