// Copyright Keysight Technologies 2012-2019
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
|
/*
|
This code is public domain.
|
The MurmurHash3 algorithm was created by Austin Appleby and put into the public domain. See http://code.google.com/p/smhasher/
|
This C# variant was authored by
|
Elliott B. Edwards and was placed into the public domain as a gist
|
*/
|
using System.IO;
|
using System.Text;
|
|
namespace Tap.Shared
|
{
|
internal static class MurMurHash3
|
{
|
//Change to suit your needs
|
const uint seed = 144;
|
|
public static int Hash(byte[] bytes)
|
{
|
using (var stream = new MemoryStream(bytes))
|
return Hash(stream);
|
}
|
|
public static int Hash(string uniqueString)
|
{
|
byte[] input = Encoding.UTF8.GetBytes(uniqueString);
|
using (var stream = new MemoryStream(input))
|
return Hash(stream);
|
}
|
|
public static int Hash(Stream stream)
|
{
|
const uint c1 = 0xcc9e2d51;
|
const uint c2 = 0x1b873593;
|
|
uint h1 = seed;
|
uint k1 = 0;
|
uint streamLength = 0;
|
|
var reader = stream;
|
byte[] chunk = new byte[4];
|
{
|
|
while (true)
|
{
|
int len = reader.Read(chunk, 0, 4);
|
if (len <= 0) break;
|
streamLength += (uint)len;
|
switch (len)
|
{
|
case 4:
|
/* Get four bytes from the input into an uint */
|
k1 = (uint)
|
(chunk[0]
|
| chunk[1] << 8
|
| chunk[2] << 16
|
| chunk[3] << 24);
|
|
/* bitmagic hash */
|
k1 *= c1;
|
k1 = rotl32(k1, 15);
|
k1 *= c2;
|
|
h1 ^= k1;
|
h1 = rotl32(h1, 13);
|
h1 = h1 * 5 + 0xe6546b64;
|
break;
|
case 3:
|
k1 = (uint)
|
(chunk[0]
|
| chunk[1] << 8
|
| chunk[2] << 16);
|
k1 *= c1;
|
k1 = rotl32(k1, 15);
|
k1 *= c2;
|
h1 ^= k1;
|
break;
|
case 2:
|
k1 = (uint)
|
(chunk[0]
|
| chunk[1] << 8);
|
k1 *= c1;
|
k1 = rotl32(k1, 15);
|
k1 *= c2;
|
h1 ^= k1;
|
break;
|
case 1:
|
k1 = (uint)(chunk[0]);
|
k1 *= c1;
|
k1 = rotl32(k1, 15);
|
k1 *= c2;
|
h1 ^= k1;
|
break;
|
|
}
|
}
|
}
|
|
// finalization, magic chants to wrap it all up
|
h1 ^= streamLength;
|
h1 = fmix(h1);
|
|
unchecked //ignore overflow
|
{
|
return (int)h1;
|
}
|
}
|
|
private static uint rotl32(uint x, byte r)
|
{
|
return (x << r) | (x >> (32 - r));
|
}
|
|
private static uint fmix(uint h)
|
{
|
h ^= h >> 16;
|
h *= 0x85ebca6b;
|
h ^= h >> 13;
|
h *= 0xc2b2ae35;
|
h ^= h >> 16;
|
return h;
|
}
|
}
|
}
|