2022-03-23 16:03:48 +00:00
/***
Copyright ( C ) 2022 J Reece Wilson ( a / k / a " Reece " ) . All rights reserved .
File : auHashUtils . hpp
Date : 2022 - 3 - 23
Author : Reece
* * */
# pragma once
# include "auFNV1Utils.hpp"
# define _AU_HASH_UTILS_HAS_STD
// Thy shall pollute me, not std:: or any other namespace
// ...namespace
// ...namespace
// Has the penny dropped yet?
// It's amazing how every other language with a similar concept has conventions or other limitations on overloading packages/namespaces/modules, but C++ morons took the stance of the FSB on Chechnya, Crimea and Ukraine.
// We could potentially be even nicer with a dedicated namespace (`AuUserHashes`?) for user-defined overloads and substitution-is-often-compiler-crash behavior on a nicer template (Static? ::Hashcode() instead of operator?), so that AuHash doesn't get invaded.
template < typename T >
struct AuHasHashCode
{
template < typename C > static constexpr AuTrueType Test ( decltype ( & C : : HashCode ) ) ;
template < typename C > static constexpr AuFalseType Test ( . . . ) ;
using type = decltype ( Test < T > ( 0 ) ) ;
} ;
template < typename T >
constexpr inline bool AuHasHashCode_v = AuHasHashCode < T > : : type : : value ;
namespace AuHash
{
template < class Key >
struct hash
{
# if defined(_AU_HASH_UTILS_HAS_STD)
AuConditional_t < AuHasHashCode_v < Key > , AuUInt8 , std : : hash < Key > > trashHasher ;
# endif
AuUInt operator ( ) ( const Key & ref ) const
{
if constexpr ( AuHasHashCode_v < Key > )
{
return ref . HashCode ( ) ;
}
# if defined(_AU_HASH_UTILS_HAS_STD)
else
{
return trashHasher ( ref ) ;
}
# endif
}
} ;
# define _HASH_F_CPP(type) \
template < > struct hash < type > \
{ \
AuUInt operator ( ) ( type b ) const \
{ \
return AuFnv1aType < type > ( b ) ; \
} \
} ;
_HASH_F_CPP ( bool ) ;
_HASH_F_CPP ( char ) ;
_HASH_F_CPP ( signed char ) ;
_HASH_F_CPP ( unsigned char ) ;
_HASH_F_CPP ( char8_t ) ;
_HASH_F_CPP ( char16_t ) ;
_HASH_F_CPP ( char32_t ) ;
_HASH_F_CPP ( wchar_t ) ;
_HASH_F_CPP ( short ) ;
_HASH_F_CPP ( unsigned short ) ;
_HASH_F_CPP ( int ) ;
_HASH_F_CPP ( unsigned int ) ;
_HASH_F_CPP ( long ) ;
_HASH_F_CPP ( long long ) ;
_HASH_F_CPP ( unsigned long ) ;
_HASH_F_CPP ( unsigned long long ) ;
_HASH_F_CPP ( float ) ;
_HASH_F_CPP ( double ) ;
_HASH_F_CPP ( long double ) ;
_HASH_F_CPP ( std : : nullptr_t ) ;
# undef _HASH_F_CPP
template < class T > struct hash < T * >
{
AuUInt operator ( ) ( T * ptr ) const
{
2022-03-23 19:51:10 +00:00
# if defined(AURORA_IS_32BIT)
return AuFnv1a32Runtime ( & ptr , sizeof ( T * ) ) ;
# else
return AuFnv1a64Runtime ( & ptr , sizeof ( T * ) ) ;
# endif
2022-03-23 16:03:48 +00:00
}
} ;
template < class T >
struct less
{
constexpr bool operator ( ) ( const T & lhs , const T & rhs ) const
{
if constexpr ( AuHasHashCode_v < T > )
{
return lhs . HashCode ( ) < rhs . HashCode ( ) ;
}
else
{
return lhs < rhs ;
}
}
} ;
template < class T >
struct equal
{
constexpr bool operator ( ) ( const T & lhs , const T & rhs ) const
{
return lhs = = rhs ;
}
} ;
}
template < typename T , AU_TEMPLATE_ENABLE_WHEN ( AuHasHashCode_v < T > ) >
inline AuUInt AuHashCode ( const T & ref )
{
return ref . HashCode ( ) ;
}
template < typename T , AU_TEMPLATE_ENABLE_WHEN ( ! AuHasHashCode_v < T > ) >
inline AuUInt AuHashCode ( const T & ref )
{
return AuHash : : hash < T > ( ) ( ref ) ;
}
template < typename T >
struct AuEnableHashCodeOnData
{
AuUInt HashCode ( ) const
{
2022-03-23 19:32:33 +00:00
# if defined(AURORA_IS_32BIT)
return AuFnv1a32Runtime ( AuStaticCast < T > ( this ) , sizeof ( T ) ) ;
# else
return AuFnv1a64Runtime ( AuStaticCast < T > ( this ) , sizeof ( T ) ) ;
# endif
2022-03-23 16:03:48 +00:00
}
} ;