# XXHash

```cpp
#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;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://malwaresourcecode.com/home/string-hashing/xxhash.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
