177 lines
5.3 KiB
C++
177 lines
5.3 KiB
C++
/***
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: auFNV1Utils.hpp
|
|
Date: 2022-3-23
|
|
File: fnv1.hpp
|
|
Date: 2021-6-10
|
|
Author: Reece
|
|
***/
|
|
#pragma once
|
|
|
|
#include "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 ^= AuUInt32(AuReadU8(base, i)) * AuUInt32(kFnv1MagicPrime32);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
inline AuUInt64 AuFnv1a64Runtime(const void *base, AuUInt length) noexcept
|
|
{
|
|
AuUInt64 result {kFnv1MagicVal64};
|
|
|
|
AuUInt i {};
|
|
for (; i < length; i++)
|
|
{
|
|
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);
|
|
}
|
|
|
|
#undef _AU_FNV1_32
|
|
|
|
#if defined(_AU_HASH_RETARD_COMPILER)
|
|
#pragma optimize("", on)
|
|
//#pragma GCC optimize ("fast-math")
|
|
#undef _AU_HASH_RETARD_COMPILER
|
|
#endif |