2017-11-01 20:14:23 +01:00
|
|
|
/******************************************************************************/
|
|
|
|
/* VARIOUS UTILITIES - INLINE CODE ********************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2017-11-01 21:44:54 +01:00
|
|
|
#ifndef _H_EBCL_INLINE_UTILITIES
|
|
|
|
#define _H_EBCL_INLINE_UTILITIES
|
|
|
|
#include <ebcl/Utilities.hh>
|
|
|
|
namespace ebcl {
|
2017-11-01 20:14:23 +01:00
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
inline constexpr bool IsPowerOf2( T value )
|
|
|
|
{
|
|
|
|
static_assert( std::is_integral< T >( ) , "integer type only" );
|
|
|
|
return value > 0 && ( value & ( value - 1 ) ) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*= ENDIAN DETECTION =========================================================*/
|
|
|
|
|
|
|
|
inline static constexpr bool IsBigEndian( )
|
|
|
|
{
|
|
|
|
return E_Endian::NATIVE == E_Endian::BIG;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline static constexpr bool IsLittleEndian( )
|
|
|
|
{
|
|
|
|
return E_Endian::NATIVE == E_Endian::LITTLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static_assert( IsBigEndian( ) || IsLittleEndian( ) ,
|
|
|
|
"unsupported endianness" );
|
|
|
|
|
|
|
|
|
|
|
|
/*= ENDIAN CONVERSION ========================================================*/
|
|
|
|
|
|
|
|
template<
|
|
|
|
typename T ,
|
|
|
|
uint32_t S = sizeof( T ) ,
|
|
|
|
typename = std::enable_if_t<
|
|
|
|
std::is_integral< T >::value
|
|
|
|
|| std::is_floating_point< T >::value
|
|
|
|
>
|
|
|
|
>
|
|
|
|
struct T_ByteSwapper_ { };
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_ByteSwapper_< T , 1 >
|
|
|
|
{
|
|
|
|
static constexpr T swap( T value )
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_ByteSwapper_< T , 2 >
|
|
|
|
{
|
|
|
|
static T swap( T value )
|
|
|
|
{
|
|
|
|
union { T v;
|
|
|
|
uint16_t i;
|
|
|
|
} u = { value };
|
|
|
|
u.i = __builtin_bswap16( u.i );
|
|
|
|
return u.v;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_ByteSwapper_< T , 4 >
|
|
|
|
{
|
|
|
|
static T swap( T value )
|
|
|
|
{
|
|
|
|
union { T v;
|
|
|
|
uint32_t i;
|
|
|
|
} u = { value };
|
|
|
|
u.i = __builtin_bswap32( u.i );
|
|
|
|
return u.v;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_ByteSwapper_< T , 8 >
|
|
|
|
{
|
|
|
|
static T swap( T value );
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
inline T T_ByteSwapper_< T , 8 >::swap( T value )
|
|
|
|
{
|
|
|
|
union { T v;
|
|
|
|
uint64_t i;
|
|
|
|
} u = { value };
|
|
|
|
u.i = __builtin_bswap64( u.i );
|
|
|
|
return u.v;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_LittleEndian< T , E_Endian::LITTLE >
|
|
|
|
{
|
|
|
|
static T convert( T value )
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_LittleEndian< T , E_Endian::BIG >
|
|
|
|
{
|
|
|
|
static T convert( T value )
|
|
|
|
{
|
|
|
|
return T_ByteSwapper_< T >::swap( value );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_BigEndian< T , E_Endian::LITTLE >
|
|
|
|
{
|
|
|
|
static T convert( T value )
|
|
|
|
{
|
|
|
|
return T_ByteSwapper_< T >::swap( value );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_BigEndian< T , E_Endian::BIG >
|
|
|
|
{
|
|
|
|
static T convert( T value )
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*= COMPARATORS AND SORTING ==================================================*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
inline int T_Comparator< T >::compare( T const& a , T const& b )
|
|
|
|
{
|
|
|
|
if ( a < b ) return -1;
|
|
|
|
if ( a > b ) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
// T_Sorter_ - "Plumbing" for Sort
|
|
|
|
struct T_Sorter_
|
|
|
|
{
|
|
|
|
typedef std::function< void ( uint8_t* a , uint8_t* b ) > F_Swap;
|
|
|
|
typedef std::function< int ( uint8_t const* a , uint8_t const* b ) > F_Cmp;
|
|
|
|
static void sort( uint8_t* data , uint32_t itemSize , uint32_t items , F_Swap swap , F_Cmp cmp );
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
void Sort( T* array , uint32_t items , F_Comparator< T > comparator )
|
|
|
|
{
|
|
|
|
T_Sorter_::sort( reinterpret_cast< uint8_t* >( array ) ,
|
|
|
|
sizeof( T ) , items ,
|
|
|
|
[]( uint8_t* a , uint8_t* b ) {
|
|
|
|
using std::swap;
|
|
|
|
swap( *reinterpret_cast< T* >( a ) ,
|
|
|
|
*reinterpret_cast< T* >( b ) );
|
|
|
|
} ,
|
|
|
|
[comparator]( uint8_t const* a , uint8_t const* b ) {
|
|
|
|
return comparator(
|
|
|
|
*reinterpret_cast< T const* >( a ) ,
|
|
|
|
*reinterpret_cast< T const* >( b ) );
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*= HASHING ==================================================================*/
|
|
|
|
|
|
|
|
template< typename T , int S >
|
|
|
|
inline uint32_t T_HashFunction< T , S >::hash( T const& item )
|
|
|
|
{
|
|
|
|
return HashData( reinterpret_cast< uint8_t const* >( &item ) , sizeof( T ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
inline uint32_t ComputeHash( T const& item )
|
|
|
|
{
|
|
|
|
return T_HashFunction< T >::hash( item );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
// Hash function specializations for data sizes 1, 2, 4 and 8.
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_HashFunction< T , 1 >
|
|
|
|
{
|
|
|
|
static uint32_t hash( T const& item )
|
|
|
|
{
|
|
|
|
return *reinterpret_cast< uint8_t const* >( &item );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_HashFunction< T , 2 >
|
|
|
|
{
|
|
|
|
static uint32_t hash( T const& item )
|
|
|
|
{
|
|
|
|
return *reinterpret_cast< uint16_t const* >( &item );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_HashFunction< T , 4 >
|
|
|
|
{
|
|
|
|
static uint32_t hash( T const& item )
|
|
|
|
{
|
|
|
|
return *reinterpret_cast< uint32_t const* >( &item );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
struct T_HashFunction< T , 8 >
|
|
|
|
{
|
|
|
|
static uint32_t hash( T const& item )
|
|
|
|
{
|
|
|
|
uint64_t v = *reinterpret_cast< uint64_t const* >( &item );
|
|
|
|
return ( v >> 32 ) ^ v;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*= PRIVATE IMPLEMENTATION BASE ==============================================*/
|
|
|
|
|
|
|
|
inline A_PrivateImplementation::A_PrivateImplementation( void* p , T_Destructor_ destructor )
|
|
|
|
: p_( p ) , piDestructor_( destructor )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
inline A_PrivateImplementation::A_PrivateImplementation( T* p )
|
|
|
|
: A_PrivateImplementation( p , []( void* ptr ) {
|
|
|
|
reinterpret_cast< T* >( ptr )->~T( );
|
|
|
|
} )
|
|
|
|
{ }
|
|
|
|
|
|
|
|
inline A_PrivateImplementation::A_PrivateImplementation( A_PrivateImplementation&& other ) noexcept
|
|
|
|
: p_( other.p_ ) , piDestructor_( other.piDestructor_ )
|
|
|
|
{
|
|
|
|
other.p_ = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline A_PrivateImplementation& A_PrivateImplementation::operator=( A_PrivateImplementation&& other ) noexcept
|
|
|
|
{
|
|
|
|
callPrivateDestructor( );
|
|
|
|
p_ = other.p_;
|
|
|
|
piDestructor_ = other.piDestructor_;
|
|
|
|
other.p_ = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline A_PrivateImplementation::~A_PrivateImplementation( )
|
|
|
|
{
|
|
|
|
callPrivateDestructor( );
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T >
|
|
|
|
inline T& A_PrivateImplementation::p( ) const
|
|
|
|
{
|
|
|
|
return *reinterpret_cast< T* >( p_ );
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void A_PrivateImplementation::callPrivateDestructor( ) noexcept
|
|
|
|
{
|
|
|
|
if ( p_ && piDestructor_ ) {
|
|
|
|
piDestructor_( p_ );
|
|
|
|
::operator delete( p_ );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2017-11-01 21:44:54 +01:00
|
|
|
#endif // _H_EBCL_INLINE_UTILITIES
|