303 lines
9.8 KiB
C++
303 lines
9.8 KiB
C++
/***
|
|
Copyright (C) 2022-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: auFNV1.hpp
|
|
File: auFNV1Utils.hpp
|
|
Date: 2022-3-23
|
|
File: fnv1.hpp
|
|
Date: 2021-6-10
|
|
Author: Reece
|
|
***/
|
|
#pragma once
|
|
|
|
#include <auROXTL/auTypeUtils.hpp>
|
|
|
|
// Note: we're too early for AuroraEnv.hpp w/ AuroraEnums
|
|
#if defined(AURORA_IS_32BIT)
|
|
#define _AU_FNV1_32 1
|
|
#else
|
|
#define _AU_FNV1_32 0
|
|
#endif
|
|
|
|
#if defined(AURORA_COMPILER_CLANG) && !defined(AURORA_BUG_CLANG_SUPPORT_HASH_OVERFLOW)
|
|
#define _AU_HASH_RETARD_COMPILER
|
|
#pragma optimize("", off)
|
|
//#pragma GCC optimize ("no-fast-math")
|
|
#endif
|
|
|
|
constexpr AuUInt64 kFnv1MagicVal64 = 0xcbf29ce484222325ull;
|
|
constexpr AuUInt64 kFnv1MagicPrime64 = 0x100000001b3ull;
|
|
constexpr AuUInt32 kFnv1MagicVal32 = 0x811c9dc5;
|
|
constexpr AuUInt32 kFnv1MagicPrime32 = 0x01000193;
|
|
|
|
constexpr auto kFnv1MagicValPlatform = _AU_FNV1_32 ? kFnv1MagicVal32 : kFnv1MagicVal64;
|
|
constexpr auto kFnv1MagicPrimePlatform = _AU_FNV1_32 ? kFnv1MagicPrime32 : kFnv1MagicPrime64;
|
|
|
|
inline constexpr AuUInt64 AuFnv1a64(const char *const str, const AuUInt64 value = kFnv1MagicVal64) noexcept
|
|
{
|
|
return (str[0] == '\0') ? value : AuFnv1a64(&str[1], (value ^ AuUInt64(str[0])) * kFnv1MagicPrime64);
|
|
}
|
|
|
|
inline constexpr AuUInt32 AuFnv1aTrunc(const char *const str) noexcept
|
|
{
|
|
return static_cast<AuUInt32>(AuFnv1a64(str));
|
|
}
|
|
|
|
inline constexpr AuUInt32 AuFnv1a32(const char *const str, const AuUInt32 value = kFnv1MagicVal32) noexcept
|
|
{
|
|
return (str[0] == '\0') ? value : AuFnv1a32(&str[1], (value ^ AuUInt32(str[0])) * kFnv1MagicPrime32);
|
|
}
|
|
|
|
inline constexpr AuUInt AuFnv1aType(const char *const type, AuUInt size, AuUInt index, const AuUInt value) noexcept
|
|
{
|
|
return (index == size) ? value : AuFnv1aType(type + 1, size, index + 1, (value ^ AuUInt(*type)) * kFnv1MagicPrimePlatform);
|
|
}
|
|
|
|
inline constexpr AuUInt32 AuFnv1aType32(const char *const type, AuUInt size, AuUInt index, const AuUInt32 value) noexcept
|
|
{
|
|
return (index == size) ? value : AuFnv1aType32(type + 1, size, index + 1, (value ^ AuUInt32(*type)) * kFnv1MagicPrime32);
|
|
}
|
|
|
|
inline constexpr AuUInt64 AuFnv1aType64(const char *const type, AuUInt size, AuUInt index, const AuUInt64 value) noexcept
|
|
{
|
|
return (index == size) ? value : AuFnv1aType64(type + 1, size, index + 1, (value ^ AuUInt64(*type)) * kFnv1MagicPrime64);
|
|
}
|
|
|
|
#if !defined(_AU_HASH_RETARD_COMPILER)
|
|
template <class T>
|
|
inline constexpr AuUInt32 AuFnv1aType32(T type, const AuUInt32 value = kFnv1MagicVal32) noexcept
|
|
{
|
|
#if defined(AURORA_COMPILER_CLANG)
|
|
static_assert(false, "Unsupported constexpr hash on type");
|
|
#else
|
|
return AuFnv1aType32(((const char *)&type) + 1, sizeof(T), 1, (value ^ (AuUInt32(*(const char *)&type)) * kFnv1MagicPrime32));
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if !defined(_AU_HASH_RETARD_COMPILER)
|
|
template <class T>
|
|
inline constexpr AuUInt64 AuFnv1aType64(T type, const AuUInt64 value = kFnv1MagicVal64) noexcept
|
|
{
|
|
#if defined(AURORA_COMPILER_CLANG)
|
|
static_assert(false, "Unsupported constexpr hash on type");
|
|
#else
|
|
return AuFnv1aType64(((const char *)&type) + 1, sizeof(T), 1, (value ^ (AuUInt64(*(const char *)&type)) * kFnv1MagicPrime64));
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if !defined(_AU_HASH_RETARD_COMPILER)
|
|
template <class T>
|
|
inline constexpr AuUInt AuFnv1aType(const T &type, const AuUInt value = kFnv1MagicValPlatform) noexcept
|
|
{
|
|
#if _AU_FNV1_32
|
|
return AuFnv1aType32(type, value);
|
|
#else
|
|
return AuFnv1aType64(type, value);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
template <class T>
|
|
inline constexpr AuUInt AuFnv1aPtr(const T *const type, AuUInt length, const AuUInt value = kFnv1MagicValPlatform) noexcept
|
|
{
|
|
return AuFnv1aType((const char *)type,
|
|
length,
|
|
0,
|
|
value);
|
|
}
|
|
|
|
template <class T>
|
|
inline constexpr AuUInt32 AuFnv1aPtr32(const T *const type, AuUInt length, const AuUInt32 value = kFnv1MagicVal32) noexcept
|
|
{
|
|
return AuFnv1aType32((const char *)type,
|
|
length,
|
|
0,
|
|
value);
|
|
}
|
|
|
|
template <class T>
|
|
inline constexpr AuUInt64 AuFnv1aPtr64(const T *const type, AuUInt length, const AuUInt64 value = kFnv1MagicVal64) noexcept
|
|
{
|
|
return AuFnv1aType64((const char *)type,
|
|
length,
|
|
0,
|
|
value);
|
|
}
|
|
|
|
inline constexpr auto AuFnv1a(const char *const str) noexcept
|
|
{
|
|
return _AU_FNV1_32 ? AuFnv1a32(str) : AuFnv1a64(str);
|
|
}
|
|
|
|
inline constexpr auto AuFnv1a(const char *const str, AuUInt length) noexcept
|
|
{
|
|
return AuFnv1aPtr(str, length);
|
|
}
|
|
|
|
inline AuUInt32 AuFnv1a32Runtime(const void *base, AuUInt length) noexcept
|
|
{
|
|
AuUInt32 result {kFnv1MagicVal32};
|
|
|
|
AuUInt i {};
|
|
for (; i < length; i++)
|
|
{
|
|
result = (result ^ AuUInt32(AuReadU8(base, i))) * AuUInt64(kFnv1MagicPrime32);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
inline AuUInt64 AuFnv1a64Runtime(const void *base, AuUInt length) noexcept
|
|
{
|
|
AuUInt64 result {kFnv1MagicVal64};
|
|
|
|
AuUInt i {};
|
|
for (; i < length; i++)
|
|
{
|
|
result = (result ^ AuUInt64(AuReadU8(base, i))) * AuUInt64(kFnv1MagicPrime64);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
inline auto AuFnv1aRuntime(const void *base, AuUInt length) noexcept
|
|
{
|
|
return _AU_FNV1_32 ?
|
|
AuFnv1a32Runtime(base, length) :
|
|
AuFnv1a64Runtime(base, length);
|
|
}
|
|
|
|
template <AuUInt uCount>
|
|
inline AuUInt64 AuFnv1a64Runtime(const void *base) noexcept
|
|
{
|
|
AuUInt64 result { kFnv1MagicVal64 };
|
|
|
|
AuUInt i {};
|
|
for (; i < uCount; i++)
|
|
{
|
|
result = (result ^ AuUInt64(AuReadU8(base, i))) * AuUInt64(kFnv1MagicPrime64);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
template <AuUInt uCount>
|
|
inline AuUInt32 AuFnv1a32Runtime(const void *base) noexcept
|
|
{
|
|
AuUInt32 result { kFnv1MagicVal32 };
|
|
|
|
AuUInt i {};
|
|
for (; i < uCount; i++)
|
|
{
|
|
result = (result ^ AuUInt32(AuReadU8(base, i))) * AuUInt32(kFnv1MagicPrime32);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
#if defined(AU_CPU_ENDIAN_LITTLE)
|
|
|
|
template <>
|
|
inline AuUInt32 AuFnv1a32Runtime<2>(const void *base) noexcept
|
|
{
|
|
AuUInt32 result { kFnv1MagicVal32 };
|
|
|
|
auto uWord16 = AuReadU16(base, 0);
|
|
result = (result ^ AuUInt32((uWord16 & 0xFF) >> 0)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord16 & 0xFF00) >> 8)) * AuUInt32(kFnv1MagicPrime32);
|
|
return result;
|
|
}
|
|
|
|
template <>
|
|
inline AuUInt32 AuFnv1a32Runtime<4>(const void *base) noexcept
|
|
{
|
|
AuUInt32 result { kFnv1MagicVal32 };
|
|
|
|
auto uWord32 = AuReadU32(base, 0);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF) >> 0)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF00) >> 8)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF0000) >> 16)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF000000) >> 24)) * AuUInt32(kFnv1MagicPrime32);
|
|
return result;
|
|
}
|
|
|
|
template <>
|
|
inline AuUInt32 AuFnv1a32Runtime<8>(const void *base) noexcept
|
|
{
|
|
AuUInt32 result { kFnv1MagicVal32 };
|
|
|
|
auto uWord32 = AuReadU32(base, 0);
|
|
auto uWord32Hi = AuReadU32(base, 4);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF) >> 0)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF00) >> 8)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF0000) >> 16)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32 & 0xFF000000) >> 24)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32Hi & 0xFF) >> 0)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32Hi & 0xFF00) >> 8)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32Hi & 0xFF0000) >> 16)) * AuUInt32(kFnv1MagicPrime32);
|
|
result = (result ^ AuUInt32((uWord32Hi & 0xFF000000) >> 24)) * AuUInt32(kFnv1MagicPrime32);
|
|
return result;
|
|
}
|
|
|
|
template <>
|
|
inline AuUInt64 AuFnv1a64Runtime<2>(const void *base) noexcept
|
|
{
|
|
AuUInt64 result { kFnv1MagicVal64 };
|
|
|
|
auto uWord16 = AuReadU16(base, 0);
|
|
result = (result ^ AuUInt64((uWord16 & 0xFF) >> 0)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord16 & 0xFF00) >> 8)) * AuUInt64(kFnv1MagicPrime64);
|
|
return result;
|
|
}
|
|
|
|
template <>
|
|
inline AuUInt64 AuFnv1a64Runtime<4>(const void *base) noexcept
|
|
{
|
|
AuUInt64 result { kFnv1MagicVal64 };
|
|
|
|
auto uWord64 = AuReadU32(base, 0);
|
|
result = (result ^ AuUInt64((uWord64 & 0xFF) >> 0)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord64 & 0xFF00) >> 8)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord64 & 0xFF0000) >> 16)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord64 & 0xFF000000) >> 24)) * AuUInt64(kFnv1MagicPrime64);
|
|
return result;
|
|
}
|
|
|
|
template <>
|
|
inline AuUInt64 AuFnv1a64Runtime<8>(const void *base) noexcept
|
|
{
|
|
AuUInt64 result { kFnv1MagicVal64 };
|
|
|
|
auto uWord32 = AuReadU32(base, 0);
|
|
auto uWord32Hi = AuReadU32(base, 4);
|
|
result = (result ^ AuUInt64((uWord32 & 0xFF) >> 0)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord32 & 0xFF00) >> 8)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord32 & 0xFF0000) >> 16)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord32 & 0xFF000000) >> 24)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord32Hi & 0xFF) >> 0)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord32Hi & 0xFF00) >> 8)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord32Hi & 0xFF0000) >> 16)) * AuUInt64(kFnv1MagicPrime64);
|
|
result = (result ^ AuUInt64((uWord32Hi & 0xFF000000) >> 24)) * AuUInt64(kFnv1MagicPrime64);
|
|
return result;
|
|
}
|
|
|
|
#endif
|
|
|
|
template <AuUInt uCount>
|
|
inline auto AuFnv1aRuntime(const void *base) noexcept
|
|
{
|
|
return _AU_FNV1_32 ?
|
|
AuFnv1a32Runtime<uCount>(base) :
|
|
AuFnv1a64Runtime<uCount>(base);
|
|
}
|
|
|
|
#undef _AU_FNV1_32
|
|
|
|
#if defined(_AU_HASH_RETARD_COMPILER)
|
|
#pragma optimize("", on)
|
|
//#pragma GCC optimize ("fast-math")
|
|
#undef _AU_HASH_RETARD_COMPILER
|
|
#endif |