XXHash

#include <Windows.h>

#define XXH64_PRIME1 0x9E3779B185EBCA87ULL
#define XXH64_PRIME2 0xC2B2AE3D27D4EB4FULL
#define XXH64_PRIME3 0x165667B19E3779F9ULL
#define XXH64_PRIME4 0x85EBCA77C2B2AE63ULL
#define XXH64_PRIME5 0x27D4EB2F165667C5ULL

SIZE_T StringLengthW(_In_ LPCWSTR String)
{
	LPCWSTR String2;

	for (String2 = String; *String2; ++String2);

	return (String2 - String);
}

UINT64 RotateToLeft64(UINT64 x, UINT64 Rotate)
{
	return (x << Rotate) | (x >> (64 - Rotate));
}

UINT64 Read8BytesFrom64ByteValue(PVOID Pointer)
{
	return *(PUINT64)Pointer;
}

UINT64 XXHash64String(PVOID Input, SIZE_T Length, UINT64 Seed)
{
	PBYTE Pointer = (PBYTE)Input;
	PBYTE InputEnd = Pointer + Length;
	UINT64 Hash;

	if (Length >= 32)
	{
		PUINT8 Limit = InputEnd - 32;

		UINT64 Offset8Bytes1 = Seed + XXH64_PRIME1 + XXH64_PRIME2;
		UINT64 Offset8Bytes2 = Seed + XXH64_PRIME2;
		UINT64 Offset8Bytes3 = Seed + 0;
		UINT64 Offset8Bytes4 = Seed - XXH64_PRIME1;

		do {
			Offset8Bytes1 = RotateToLeft64(Offset8Bytes1 + Read8BytesFrom64ByteValue(Pointer) * XXH64_PRIME2, 31) * XXH64_PRIME1;
			Pointer += 8;

			Offset8Bytes2 = RotateToLeft64(Offset8Bytes2 + Read8BytesFrom64ByteValue(Pointer) * XXH64_PRIME2, 31) * XXH64_PRIME1;
			Pointer += 8;

			Offset8Bytes3 = RotateToLeft64(Offset8Bytes3 + Read8BytesFrom64ByteValue(Pointer) * XXH64_PRIME2, 31) * XXH64_PRIME1;
			Pointer += 8;

			Offset8Bytes4 = RotateToLeft64(Offset8Bytes4 + Read8BytesFrom64ByteValue(Pointer) * XXH64_PRIME2, 31) * XXH64_PRIME1;
			Pointer += 8;
		} while (Pointer <= Limit);

		Hash = RotateToLeft64(Offset8Bytes1, 1);
		Hash += RotateToLeft64(Offset8Bytes2, 7);
		Hash += RotateToLeft64(Offset8Bytes3, 12);
		Hash += RotateToLeft64(Offset8Bytes4, 18);

		Offset8Bytes1 = RotateToLeft64(Offset8Bytes1 * XXH64_PRIME2, 31) * XXH64_PRIME1;
		Offset8Bytes2 = RotateToLeft64(Offset8Bytes2 * XXH64_PRIME2, 31) * XXH64_PRIME1;
		Offset8Bytes3 = RotateToLeft64(Offset8Bytes3 * XXH64_PRIME2, 31) * XXH64_PRIME1;
		Offset8Bytes4 = RotateToLeft64(Offset8Bytes4 * XXH64_PRIME2, 31) * XXH64_PRIME1;

		Hash ^= Offset8Bytes1;
		Hash = Hash * XXH64_PRIME1 + XXH64_PRIME4;

		Hash ^= Offset8Bytes2;
		Hash = Hash * XXH64_PRIME1 + XXH64_PRIME4;

		Hash ^= Offset8Bytes3;
		Hash = Hash * XXH64_PRIME1 + XXH64_PRIME4;

		Hash ^= Offset8Bytes4;
		Hash = Hash * XXH64_PRIME1 + XXH64_PRIME4;
	}
	else
		Hash = Seed + XXH64_PRIME5;

	Hash += Length;

	while (Pointer + 8 <= InputEnd)
	{
		Hash ^= RotateToLeft64(Read8BytesFrom64ByteValue(Pointer) * XXH64_PRIME2, 31) * XXH64_PRIME1;
		Hash = RotateToLeft64(Hash, 27) * XXH64_PRIME1 + XXH64_PRIME4;
		Pointer += 8;
	}

	if (Pointer + 4 <= InputEnd) 
	{
		Hash ^= (UINT64)(*(PUINT32)Pointer) * XXH64_PRIME1;
		Hash = RotateToLeft64(Hash, 23) * XXH64_PRIME2 + XXH64_PRIME3;
		Pointer += 4;
	}

	while (Pointer < InputEnd)
	{
		Hash ^= (*Pointer++) * XXH64_PRIME5;
		Hash = RotateToLeft64(Hash, 11) * XXH64_PRIME1;
	}

	Hash ^= Hash >> 33;
	Hash *= XXH64_PRIME2;
	Hash ^= Hash >> 29;
	Hash *= XXH64_PRIME3;
	Hash ^= Hash >> 32;

	return Hash;
}

INT main(VOID)
{
	WCHAR StringHashExample[] = L"Hash This String";
	ULONGLONG Hash = 0;

	Hash = XXHash64String(StringHashExample, (StringLengthW(StringHashExample) * sizeof(WCHAR)), 100); //100 should be seed, random number

	return ERROR_SUCCESS;
}

Last updated