2019-12-03 20:23:33 +01:00
# ifndef UTILITY_H
# define UTILITY_H
# include <algorithm>
# include <condition_variable>
2021-05-17 21:21:57 +02:00
# include <memory>
# include <mutex>
# include <optional>
2019-12-03 20:23:33 +01:00
# include <string_view>
2021-05-17 21:21:57 +02:00
# include <type_traits>
# include <variant>
# include <vector>
2020-02-09 17:30:11 +01:00
2021-05-17 21:21:57 +02:00
# define KITTY_WHILE_LOOP(x, y, z) \
{ \
x ; \
while ( y ) z \
}
2021-06-04 21:12:06 +02:00
template < typename T >
struct argument_type ;
template < typename T , typename U >
struct argument_type < T ( U ) > { typedef U type ; } ;
# define KITTY_USING_MOVE_T(move_t, t, init_val, z) \
class move_t { \
public : \
using element_type = typename argument_type < void ( t ) > : : type ; \
\
move_t ( ) : el { init_val } { } \
template < class . . . Args > \
move_t ( Args & & . . . args ) : el { std : : forward < Args > ( args ) . . . } { } \
move_t ( const move_t & ) = delete ; \
\
2021-06-06 20:57:42 +02:00
move_t ( move_t & & other ) noexcept : el { std : : move ( other . el ) } { \
2021-06-04 21:12:06 +02:00
other . el = element_type { init_val } ; \
} \
\
move_t & operator = ( const move_t & ) = delete ; \
\
move_t & operator = ( move_t & & other ) { \
std : : swap ( el , other . el ) ; \
return * this ; \
} \
element_type * operator - > ( ) { return & el ; } \
const element_type * operator - > ( ) const { return & el ; } \
\
2021-09-01 14:22:41 +02:00
inline element_type release ( ) { \
element_type val = std : : move ( el ) ; \
el = element_type { init_val } ; \
return val ; \
} \
\
2021-06-04 21:12:06 +02:00
~ move_t ( ) z \
\
element_type el ; \
}
2021-05-17 21:21:57 +02:00
# define KITTY_DECL_CONSTR(x) \
x ( x & & ) noexcept = default ; \
x & operator = ( x & & ) noexcept = default ; \
2019-12-26 22:44:09 +01:00
x ( ) ;
2019-12-03 20:23:33 +01:00
2022-02-16 18:23:56 -05:00
# define KITTY_DEFAULT_CONSTR_MOVE(x) \
x ( x & & ) noexcept = default ; \
2021-09-14 11:58:21 +02:00
x & operator = ( x & & ) noexcept = default ;
2021-05-17 21:21:57 +02:00
2021-07-18 11:05:34 +02:00
# define KITTY_DEFAULT_CONSTR_MOVE_THROW(x) \
x ( x & & ) = default ; \
x & operator = ( x & & ) = default ; \
2021-05-17 21:21:57 +02:00
x ( ) = default ;
2021-07-18 11:05:34 +02:00
# define KITTY_DEFAULT_CONSTR(x) \
KITTY_DEFAULT_CONSTR_MOVE ( x ) \
x ( const x & ) noexcept = default ; \
x & operator = ( const x & ) = default ;
2021-05-17 21:21:57 +02:00
# define TUPLE_2D(a, b, expr) \
decltype ( expr ) a # # _ # # b = expr ; \
auto & a = std : : get < 0 > ( a # # _ # # b ) ; \
auto & b = std : : get < 1 > ( a # # _ # # b )
# define TUPLE_2D_REF(a, b, expr) \
auto & a # # _ # # b = expr ; \
auto & a = std : : get < 0 > ( a # # _ # # b ) ; \
auto & b = std : : get < 1 > ( a # # _ # # b )
# define TUPLE_3D(a, b, c, expr) \
decltype ( expr ) a # # _ # # b # # _ # # c = expr ; \
auto & a = std : : get < 0 > ( a # # _ # # b # # _ # # c ) ; \
auto & b = std : : get < 1 > ( a # # _ # # b # # _ # # c ) ; \
auto & c = std : : get < 2 > ( a # # _ # # b # # _ # # c )
# define TUPLE_3D_REF(a, b, c, expr) \
auto & a # # _ # # b # # _ # # c = expr ; \
auto & a = std : : get < 0 > ( a # # _ # # b # # _ # # c ) ; \
auto & b = std : : get < 1 > ( a # # _ # # b # # _ # # c ) ; \
auto & c = std : : get < 2 > ( a # # _ # # b # # _ # # c )
2019-12-03 20:23:33 +01:00
2021-05-18 13:36:12 +02:00
# define TUPLE_EL(a, b, expr) \
decltype ( expr ) a # # _ = expr ; \
auto & a = std : : get < b > ( a # # _ )
2021-06-04 21:12:06 +02:00
# define TUPLE_EL_REF(a, b, expr) \
auto & a = std : : get < b > ( expr )
2019-12-03 20:23:33 +01:00
namespace util {
2021-05-17 21:21:57 +02:00
template < template < typename . . . > class X , class . . . Y >
2019-12-03 20:23:33 +01:00
struct __instantiation_of : public std : : false_type { } ;
template < template < typename . . . > class X , class . . . Y >
struct __instantiation_of < X , X < Y . . . > > : public std : : true_type { } ;
2021-05-17 21:21:57 +02:00
template < template < typename . . . > class X , class T , class . . . Y >
2019-12-03 20:23:33 +01:00
static constexpr auto instantiation_of_v = __instantiation_of < X , T , Y . . . > : : value ;
template < bool V , class X , class Y >
struct __either ;
template < class X , class Y >
struct __either < true , X , Y > {
using type = X ;
} ;
template < class X , class Y >
struct __either < false , X , Y > {
using type = Y ;
} ;
template < bool V , class X , class Y >
using either_t = typename __either < V , X , Y > : : type ;
2021-05-17 21:21:57 +02:00
template < class . . . Ts >
struct overloaded : Ts . . . { using Ts : : operator ( ) . . . ; } ;
template < class . . . Ts >
overloaded ( Ts . . . ) - > overloaded < Ts . . . > ;
2020-03-31 23:48:07 +02:00
2019-12-03 20:23:33 +01:00
template < class T >
class FailGuard {
public :
FailGuard ( ) = delete ;
2021-05-17 21:21:57 +02:00
FailGuard ( T & & f ) noexcept : _func { std : : forward < T > ( f ) } { }
2019-12-03 20:23:33 +01:00
FailGuard ( FailGuard & & other ) noexcept : _func { std : : move ( other . _func ) } {
this - > failure = other . failure ;
other . failure = false ;
}
FailGuard ( const FailGuard & ) = delete ;
FailGuard & operator = ( const FailGuard & ) = delete ;
FailGuard & operator = ( FailGuard & & other ) = delete ;
~ FailGuard ( ) noexcept {
if ( failure ) {
_func ( ) ;
}
}
void disable ( ) { failure = false ; }
bool failure { true } ;
2021-05-17 21:21:57 +02:00
2019-12-03 20:23:33 +01:00
private :
T _func ;
} ;
template < class T >
2021-05-17 21:21:57 +02:00
[ [ nodiscard ] ] auto fail_guard ( T & & f ) {
2019-12-03 20:23:33 +01:00
return FailGuard < T > { std : : forward < T > ( f ) } ;
}
template < class T >
void append_struct ( std : : vector < uint8_t > & buf , const T & _struct ) {
constexpr size_t data_len = sizeof ( _struct ) ;
buf . reserve ( data_len ) ;
2021-05-17 21:21:57 +02:00
auto * data = ( uint8_t * ) & _struct ;
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
for ( size_t x = 0 ; x < data_len ; + + x ) {
2019-12-03 20:23:33 +01:00
buf . push_back ( data [ x ] ) ;
}
}
template < class T >
class Hex {
public :
typedef T elem_type ;
2021-05-17 21:21:57 +02:00
2019-12-03 20:23:33 +01:00
private :
const char _bits [ 16 ] {
' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F '
} ;
char _hex [ sizeof ( elem_type ) * 2 ] ;
2021-05-17 21:21:57 +02:00
2019-12-03 20:23:33 +01:00
public :
Hex ( const elem_type & elem , bool rev ) {
if ( ! rev ) {
const uint8_t * data = reinterpret_cast < const uint8_t * > ( & elem ) + sizeof ( elem_type ) - 1 ;
2021-05-17 21:21:57 +02:00
for ( auto it = begin ( ) ; it < cend ( ) ; ) {
2019-12-03 20:23:33 +01:00
* it + + = _bits [ * data / 16 ] ;
* it + + = _bits [ * data - - % 16 ] ;
}
}
else {
const uint8_t * data = reinterpret_cast < const uint8_t * > ( & elem ) ;
2021-05-17 21:21:57 +02:00
for ( auto it = begin ( ) ; it < cend ( ) ; ) {
2019-12-03 20:23:33 +01:00
* it + + = _bits [ * data / 16 ] ;
* it + + = _bits [ * data + + % 16 ] ;
}
}
}
char * begin ( ) { return _hex ; }
char * end ( ) { return _hex + sizeof ( elem_type ) * 2 ; }
const char * begin ( ) const { return _hex ; }
const char * end ( ) const { return _hex + sizeof ( elem_type ) * 2 ; }
const char * cbegin ( ) const { return _hex ; }
const char * cend ( ) const { return _hex + sizeof ( elem_type ) * 2 ; }
std : : string to_string ( ) const {
return { begin ( ) , end ( ) } ;
}
std : : string_view to_string_view ( ) const {
return { begin ( ) , sizeof ( elem_type ) * 2 } ;
}
} ;
template < class T >
Hex < T > hex ( const T & elem , bool rev = false ) {
return Hex < T > ( elem , rev ) ;
}
template < class It >
std : : string hex_vec ( It begin , It end , bool rev = false ) {
2021-05-17 21:21:57 +02:00
auto str_size = 2 * std : : distance ( begin , end ) ;
2019-12-03 20:23:33 +01:00
std : : string hex ;
hex . resize ( str_size ) ;
const char _bits [ 16 ] {
' 0 ' , ' 1 ' , ' 2 ' , ' 3 ' , ' 4 ' , ' 5 ' , ' 6 ' , ' 7 ' , ' 8 ' , ' 9 ' , ' A ' , ' B ' , ' C ' , ' D ' , ' E ' , ' F '
} ;
if ( rev ) {
2021-05-17 21:21:57 +02:00
for ( auto it = std : : begin ( hex ) ; it < std : : end ( hex ) ; ) {
2019-12-03 20:23:33 +01:00
* it + + = _bits [ ( ( uint8_t ) * begin ) / 16 ] ;
* it + + = _bits [ ( ( uint8_t ) * begin + + ) % 16 ] ;
}
}
else {
- - end ;
2021-05-17 21:21:57 +02:00
for ( auto it = std : : begin ( hex ) ; it < std : : end ( hex ) ; ) {
2019-12-03 20:23:33 +01:00
* it + + = _bits [ ( ( uint8_t ) * end ) / 16 ] ;
* it + + = _bits [ ( ( uint8_t ) * end - - ) % 16 ] ;
}
}
return hex ;
}
template < class C >
2021-05-17 21:21:57 +02:00
std : : string hex_vec ( C & & c , bool rev = false ) {
2019-12-03 20:23:33 +01:00
return hex_vec ( std : : begin ( c ) , std : : end ( c ) , rev ) ;
}
template < class T >
2021-08-03 15:24:04 +02:00
T from_hex ( const std : : string_view & hex , bool rev = false ) {
2019-12-03 20:23:33 +01:00
std : : uint8_t buf [ sizeof ( T ) ] ;
static char constexpr shift_bit = ' a ' - ' A ' ;
2021-08-03 15:24:04 +02:00
auto is_convertable = [ ] ( char ch ) - > bool {
2019-12-03 20:23:33 +01:00
if ( isdigit ( ch ) ) {
return true ;
}
ch | = shift_bit ;
if ( ' a ' > ch | | ch > ' z ' ) {
return false ;
}
return true ;
} ;
auto buf_size = std : : count_if ( std : : begin ( hex ) , std : : end ( hex ) , is_convertable ) / 2 ;
2021-08-03 15:24:04 +02:00
auto padding = sizeof ( T ) - buf_size ;
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
const char * data = hex . data ( ) + hex . size ( ) - 1 ;
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
auto convert = [ ] ( char ch ) - > std : : uint8_t {
2019-12-03 20:23:33 +01:00
if ( ch > = ' 0 ' & & ch < = ' 9 ' ) {
return ( std : : uint8_t ) ch - ' 0 ' ;
}
return ( std : : uint8_t ) ( ch | ( char ) 32 ) - ' a ' + ( char ) 10 ;
} ;
2021-08-03 15:24:04 +02:00
std : : fill_n ( buf + buf_size , padding , 0 ) ;
std : : for_each_n ( buf , buf_size , [ & ] ( auto & el ) {
2019-12-03 20:23:33 +01:00
while ( ! is_convertable ( * data ) ) { - - data ; }
std : : uint8_t ch_r = convert ( * data - - ) ;
while ( ! is_convertable ( * data ) ) { - - data ; }
std : : uint8_t ch_l = convert ( * data - - ) ;
el = ( ch_l < < 4 ) | ch_r ;
2021-08-03 15:24:04 +02:00
} ) ;
2019-12-03 20:23:33 +01:00
if ( rev ) {
std : : reverse ( std : : begin ( buf ) , std : : end ( buf ) ) ;
}
return * reinterpret_cast < T * > ( buf ) ;
}
inline std : : string from_hex_vec ( const std : : string & hex , bool rev = false ) {
std : : string buf ;
static char constexpr shift_bit = ' a ' - ' A ' ;
2021-05-17 21:21:57 +02:00
auto is_convertable = [ ] ( char ch ) - > bool {
2019-12-03 20:23:33 +01:00
if ( isdigit ( ch ) ) {
return true ;
}
ch | = shift_bit ;
if ( ' a ' > ch | | ch > ' z ' ) {
return false ;
}
return true ;
} ;
auto buf_size = std : : count_if ( std : : begin ( hex ) , std : : end ( hex ) , is_convertable ) / 2 ;
buf . resize ( buf_size ) ;
2021-05-17 21:21:57 +02:00
const char * data = hex . data ( ) + hex . size ( ) - 1 ;
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
auto convert = [ ] ( char ch ) - > std : : uint8_t {
2019-12-03 20:23:33 +01:00
if ( ch > = ' 0 ' & & ch < = ' 9 ' ) {
return ( std : : uint8_t ) ch - ' 0 ' ;
}
return ( std : : uint8_t ) ( ch | ( char ) 32 ) - ' a ' + ( char ) 10 ;
} ;
for ( auto & el : buf ) {
while ( ! is_convertable ( * data ) ) { - - data ; }
std : : uint8_t ch_r = convert ( * data - - ) ;
while ( ! is_convertable ( * data ) ) { - - data ; }
std : : uint8_t ch_l = convert ( * data - - ) ;
el = ( ch_l < < 4 ) | ch_r ;
}
if ( rev ) {
std : : reverse ( std : : begin ( buf ) , std : : end ( buf ) ) ;
}
return buf ;
}
template < class T >
class hash {
public :
using value_type = T ;
std : : size_t operator ( ) ( const value_type & value ) const {
const auto * p = reinterpret_cast < const char * > ( & value ) ;
2021-05-17 21:21:57 +02:00
return std : : hash < std : : string_view > { } ( std : : string_view { p , sizeof ( value_type ) } ) ;
2019-12-03 20:23:33 +01:00
}
} ;
template < class T >
2021-05-17 21:21:57 +02:00
auto enm ( const T & val ) - > const std : : underlying_type_t < T > & {
return * reinterpret_cast < const std : : underlying_type_t < T > * > ( & val ) ;
2019-12-03 20:23:33 +01:00
}
template < class T >
2021-05-17 21:21:57 +02:00
auto enm ( T & val ) - > std : : underlying_type_t < T > & {
return * reinterpret_cast < std : : underlying_type_t < T > * > ( & val ) ;
2019-12-03 20:23:33 +01:00
}
inline std : : int64_t from_chars ( const char * begin , const char * end ) {
2021-08-08 13:59:43 +02:00
if ( begin = = end ) {
return 0 ;
}
2019-12-03 20:23:33 +01:00
std : : int64_t res { } ;
std : : int64_t mul = 1 ;
while ( begin ! = - - end ) {
res + = ( std : : int64_t ) ( * end - ' 0 ' ) * mul ;
mul * = 10 ;
}
return * begin ! = ' - ' ? res + ( std : : int64_t ) ( * begin - ' 0 ' ) * mul : - res ;
}
inline std : : int64_t from_view ( const std : : string_view & number ) {
return from_chars ( std : : begin ( number ) , std : : end ( number ) ) ;
}
template < class X , class Y >
2021-09-14 11:58:21 +02:00
class Either : public std : : variant < std : : monostate , X , Y > {
2019-12-03 20:23:33 +01:00
public :
2021-09-14 11:58:21 +02:00
using std : : variant < std : : monostate , X , Y > : : variant ;
2019-12-03 20:23:33 +01:00
constexpr bool has_left ( ) const {
return std : : holds_alternative < X > ( * this ) ;
}
constexpr bool has_right ( ) const {
return std : : holds_alternative < Y > ( * this ) ;
}
X & left ( ) {
return std : : get < X > ( * this ) ;
}
Y & right ( ) {
return std : : get < Y > ( * this ) ;
}
const X & left ( ) const {
return std : : get < X > ( * this ) ;
}
const Y & right ( ) const {
return std : : get < Y > ( * this ) ;
}
} ;
2021-05-09 11:40:12 +02:00
// Compared to std::unique_ptr, it adds the ability to get the address of the pointer itself
2021-05-17 21:21:57 +02:00
template < typename T , typename D = std : : default_delete < T > >
2021-05-09 11:40:12 +02:00
class uniq_ptr {
public :
using element_type = T ;
2021-05-17 21:21:57 +02:00
using pointer = element_type * ;
2021-05-09 11:40:12 +02:00
using deleter_type = D ;
constexpr uniq_ptr ( ) noexcept : _p { nullptr } { }
constexpr uniq_ptr ( std : : nullptr_t ) noexcept : _p { nullptr } { }
uniq_ptr ( const uniq_ptr & other ) noexcept = delete ;
uniq_ptr & operator = ( const uniq_ptr & other ) noexcept = delete ;
template < class V >
uniq_ptr ( V * p ) noexcept : _p { p } {
static_assert ( std : : is_same_v < element_type , void > | | std : : is_same_v < element_type , V > | | std : : is_base_of_v < element_type , V > , " element_type must be base class of V " ) ;
}
template < class V >
uniq_ptr ( std : : unique_ptr < V , deleter_type > & & uniq ) noexcept : _p { uniq . release ( ) } {
static_assert ( std : : is_same_v < element_type , void > | | std : : is_same_v < T , V > | | std : : is_base_of_v < element_type , V > , " element_type must be base class of V " ) ;
}
template < class V >
uniq_ptr ( uniq_ptr < V , deleter_type > & & other ) noexcept : _p { other . release ( ) } {
static_assert ( std : : is_same_v < element_type , void > | | std : : is_same_v < T , V > | | std : : is_base_of_v < element_type , V > , " element_type must be base class of V " ) ;
}
template < class V >
uniq_ptr & operator = ( uniq_ptr < V , deleter_type > & & other ) noexcept {
static_assert ( std : : is_same_v < element_type , void > | | std : : is_same_v < T , V > | | std : : is_base_of_v < element_type , V > , " element_type must be base class of V " ) ;
reset ( other . release ( ) ) ;
return * this ;
}
template < class V >
uniq_ptr & operator = ( std : : unique_ptr < V , deleter_type > & & uniq ) noexcept {
static_assert ( std : : is_same_v < element_type , void > | | std : : is_same_v < T , V > | | std : : is_base_of_v < element_type , V > , " element_type must be base class of V " ) ;
reset ( uniq . release ( ) ) ;
return * this ;
}
~ uniq_ptr ( ) {
reset ( ) ;
}
void reset ( pointer p = pointer ( ) ) {
if ( _p ) {
_deleter ( _p ) ;
}
_p = p ;
}
pointer release ( ) {
auto tmp = _p ;
2021-05-17 21:21:57 +02:00
_p = nullptr ;
2021-05-09 11:40:12 +02:00
return tmp ;
}
pointer get ( ) {
return _p ;
}
const pointer get ( ) const {
return _p ;
}
const std : : add_lvalue_reference_t < element_type > operator * ( ) const {
return * _p ;
}
std : : add_lvalue_reference_t < element_type > operator * ( ) {
return * _p ;
}
const pointer operator - > ( ) const {
return _p ;
}
pointer operator - > ( ) {
return _p ;
}
pointer * operator & ( ) const {
return & _p ;
}
pointer * operator & ( ) {
return & _p ;
}
2021-05-17 21:21:57 +02:00
deleter_type & get_deleter ( ) {
2021-05-09 11:40:12 +02:00
return _deleter ;
}
2021-05-17 21:21:57 +02:00
const deleter_type & get_deleter ( ) const {
2021-05-09 11:40:12 +02:00
return _deleter ;
}
explicit operator bool ( ) const {
return _p ! = nullptr ;
}
2021-05-17 21:21:57 +02:00
2021-05-09 11:40:12 +02:00
protected :
pointer _p ;
deleter_type _deleter ;
} ;
template < class T1 , class D1 , class T2 , class D2 >
2021-05-17 21:21:57 +02:00
bool operator = = ( const uniq_ptr < T1 , D1 > & x , const uniq_ptr < T2 , D2 > & y ) {
2021-05-09 11:40:12 +02:00
return x . get ( ) = = y . get ( ) ;
}
template < class T1 , class D1 , class T2 , class D2 >
2021-05-17 21:21:57 +02:00
bool operator ! = ( const uniq_ptr < T1 , D1 > & x , const uniq_ptr < T2 , D2 > & y ) {
2021-05-09 11:40:12 +02:00
return x . get ( ) ! = y . get ( ) ;
}
template < class T1 , class D1 , class T2 , class D2 >
2021-05-17 21:21:57 +02:00
bool operator = = ( const std : : unique_ptr < T1 , D1 > & x , const uniq_ptr < T2 , D2 > & y ) {
2021-05-09 11:40:12 +02:00
return x . get ( ) = = y . get ( ) ;
}
template < class T1 , class D1 , class T2 , class D2 >
2021-05-17 21:21:57 +02:00
bool operator ! = ( const std : : unique_ptr < T1 , D1 > & x , const uniq_ptr < T2 , D2 > & y ) {
2021-05-09 11:40:12 +02:00
return x . get ( ) ! = y . get ( ) ;
}
template < class T1 , class D1 , class T2 , class D2 >
2021-05-17 21:21:57 +02:00
bool operator = = ( const uniq_ptr < T1 , D1 > & x , const std : : unique_ptr < T1 , D1 > & y ) {
2021-05-09 11:40:12 +02:00
return x . get ( ) = = y . get ( ) ;
}
template < class T1 , class D1 , class T2 , class D2 >
2021-05-17 21:21:57 +02:00
bool operator ! = ( const uniq_ptr < T1 , D1 > & x , const std : : unique_ptr < T1 , D1 > & y ) {
2021-05-09 11:40:12 +02:00
return x . get ( ) ! = y . get ( ) ;
}
template < class T , class D >
2021-05-17 21:21:57 +02:00
bool operator = = ( const uniq_ptr < T , D > & x , std : : nullptr_t ) {
2021-05-09 11:40:12 +02:00
return ! ( bool ) x ;
}
template < class T , class D >
2021-05-17 21:21:57 +02:00
bool operator ! = ( const uniq_ptr < T , D > & x , std : : nullptr_t ) {
2021-05-09 11:40:12 +02:00
return ( bool ) x ;
}
template < class T , class D >
2021-05-17 21:21:57 +02:00
bool operator = = ( std : : nullptr_t , const uniq_ptr < T , D > & y ) {
2021-05-09 11:40:12 +02:00
return ! ( bool ) y ;
}
template < class T , class D >
2021-05-17 21:21:57 +02:00
bool operator ! = ( std : : nullptr_t , const uniq_ptr < T , D > & y ) {
2021-05-09 11:40:12 +02:00
return ( bool ) y ;
}
2020-04-15 19:16:20 +02:00
2021-08-06 15:55:38 +02:00
template < class P >
using shared_t = std : : shared_ptr < typename P : : element_type > ;
template < class P , class T >
shared_t < P > make_shared ( T * pointer ) {
return shared_t < P > ( reinterpret_cast < typename P : : pointer > ( pointer ) , typename P : : deleter_type ( ) ) ;
}
2020-04-15 19:16:20 +02:00
template < class T >
class wrap_ptr {
public :
using element_type = T ;
2021-05-17 21:21:57 +02:00
using pointer = element_type * ;
using reference = element_type & ;
2020-04-15 19:16:20 +02:00
wrap_ptr ( ) : _own_ptr { false } , _p { nullptr } { }
wrap_ptr ( pointer p ) : _own_ptr { false } , _p { p } { }
wrap_ptr ( std : : unique_ptr < element_type > & & uniq_p ) : _own_ptr { true } , _p { uniq_p . release ( ) } { }
wrap_ptr ( wrap_ptr & & other ) : _own_ptr { other . _own_ptr } , _p { other . _p } {
other . _own_ptr = false ;
}
2020-04-17 18:42:55 +02:00
wrap_ptr & operator = ( wrap_ptr & & other ) noexcept {
2020-04-15 19:16:20 +02:00
if ( _own_ptr ) {
delete _p ;
}
_p = other . _p ;
2021-05-17 21:21:57 +02:00
_own_ptr = other . _own_ptr ;
2020-04-15 19:16:20 +02:00
other . _own_ptr = false ;
return * this ;
}
template < class V >
wrap_ptr & operator = ( std : : unique_ptr < V > & & uniq_ptr ) {
static_assert ( std : : is_base_of_v < element_type , V > , " element_type must be base class of V " ) ;
_own_ptr = true ;
2021-05-17 21:21:57 +02:00
_p = uniq_ptr . release ( ) ;
2020-04-15 19:16:20 +02:00
return * this ;
}
wrap_ptr & operator = ( pointer p ) {
if ( _own_ptr ) {
delete _p ;
}
2021-05-17 21:21:57 +02:00
_p = p ;
2020-04-15 19:16:20 +02:00
_own_ptr = false ;
return * this ;
}
2020-04-17 18:42:55 +02:00
~ wrap_ptr ( ) {
if ( _own_ptr ) {
delete _p ;
}
_own_ptr = false ;
}
2020-04-15 19:16:20 +02:00
const reference operator * ( ) const {
return * _p ;
}
reference operator * ( ) {
return * _p ;
}
const pointer operator - > ( ) const {
return _p ;
}
pointer operator - > ( ) {
return _p ;
}
private :
bool _own_ptr ;
pointer _p ;
} ;
2021-06-04 21:12:06 +02:00
template < class T >
constexpr bool is_pointer_v =
instantiation_of_v < std : : unique_ptr , T > | |
instantiation_of_v < std : : shared_ptr , T > | |
instantiation_of_v < uniq_ptr , T > | |
std : : is_pointer_v < T > ;
2021-05-09 11:40:12 +02:00
template < class T , class V = void >
struct __false_v ;
template < class T >
struct __false_v < T , std : : enable_if_t < instantiation_of_v < std : : optional , T > > > {
static constexpr std : : nullopt_t value = std : : nullopt ;
} ;
template < class T >
2021-06-04 21:12:06 +02:00
struct __false_v < T , std : : enable_if_t < is_pointer_v < T > > > {
2021-05-09 11:40:12 +02:00
static constexpr std : : nullptr_t value = nullptr ;
} ;
template < class T >
struct __false_v < T , std : : enable_if_t < std : : is_same_v < T , bool > > > {
static constexpr bool value = false ;
} ;
template < class T >
static constexpr auto false_v = __false_v < T > : : value ;
template < class T >
using optional_t = either_t <
2021-06-04 21:12:06 +02:00
( std : : is_same_v < T , bool > | | is_pointer_v < T > ) ,
2021-05-09 11:40:12 +02:00
T , std : : optional < T > > ;
2019-12-03 20:23:33 +01:00
template < class T >
class buffer_t {
public :
buffer_t ( ) : _els { 0 } { } ;
2021-06-13 21:29:32 +02:00
buffer_t ( buffer_t & & o ) noexcept : _els { o . _els } , _buf { std : : move ( o . _buf ) } {
o . _els = 0 ;
}
buffer_t & operator = ( buffer_t & & o ) noexcept {
std : : swap ( _els , o . _els ) ;
std : : swap ( _buf , o . _buf ) ;
return * this ;
} ;
2019-12-03 20:23:33 +01:00
explicit buffer_t ( size_t elements ) : _els { elements } , _buf { std : : make_unique < T [ ] > ( elements ) } { }
explicit buffer_t ( size_t elements , const T & t ) : _els { elements } , _buf { std : : make_unique < T [ ] > ( elements ) } {
std : : fill_n ( _buf . get ( ) , elements , t ) ;
}
T & operator [ ] ( size_t el ) {
return _buf [ el ] ;
}
const T & operator [ ] ( size_t el ) const {
return _buf [ el ] ;
}
size_t size ( ) const {
return _els ;
}
void fake_resize ( std : : size_t els ) {
_els = els ;
}
T * begin ( ) {
return _buf . get ( ) ;
}
const T * begin ( ) const {
return _buf . get ( ) ;
}
T * end ( ) {
return _buf . get ( ) + _els ;
}
const T * end ( ) const {
return _buf . get ( ) + _els ;
}
private :
size_t _els ;
std : : unique_ptr < T [ ] > _buf ;
} ;
template < class T >
T either ( std : : optional < T > & & l , T & & r ) {
if ( l ) {
return std : : move ( * l ) ;
}
return std : : forward < T > ( r ) ;
}
2021-05-17 21:21:57 +02:00
template < class ReturnType , class . . . Args >
2021-05-09 11:40:12 +02:00
struct Function {
typedef ReturnType ( * type ) ( Args . . . ) ;
} ;
template < class T , class ReturnType , typename Function < ReturnType , T > : : type function >
struct Destroy {
typedef T pointer ;
2021-05-17 21:21:57 +02:00
2021-05-09 11:40:12 +02:00
void operator ( ) ( pointer p ) {
function ( p ) ;
}
} ;
2021-05-17 21:21:57 +02:00
template < class T , typename Function < void , T * > : : type function >
using safe_ptr = uniq_ptr < T , Destroy < T * , void , function > > ;
2021-05-09 11:40:12 +02:00
// You cannot specialize an alias
2021-05-17 21:21:57 +02:00
template < class T , class ReturnType , typename Function < ReturnType , T * > : : type function >
using safe_ptr_v2 = uniq_ptr < T , Destroy < T * , ReturnType , function > > ;
2021-05-09 11:40:12 +02:00
template < class T >
void c_free ( T * p ) {
free ( p ) ;
}
2021-06-04 21:12:06 +02:00
template < class T , class ReturnType , ReturnType ( * * function ) ( T * ) >
void dynamic ( T * p ) {
( * function ) ( p ) ;
}
template < class T , void ( * * function ) ( T * ) >
using dyn_safe_ptr = safe_ptr < T , dynamic < T , void , function > > ;
template < class T , class ReturnType , ReturnType ( * * function ) ( T * ) >
using dyn_safe_ptr_v2 = safe_ptr < T , dynamic < T , ReturnType , function > > ;
2021-05-09 11:40:12 +02:00
template < class T >
using c_ptr = safe_ptr < T , c_free < T > > ;
2021-06-04 21:12:06 +02:00
template < class It >
std : : string_view view ( It begin , It end ) {
return std : : string_view { ( const char * ) begin , ( std : : size_t ) ( end - begin ) } ;
}
template < class T >
std : : string_view view ( const T & data ) {
return std : : string_view ( ( const char * ) & data , sizeof ( T ) ) ;
}
2019-12-03 20:23:33 +01:00
namespace endian {
template < class T = void >
struct endianness {
enum : bool {
# if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
2021-05-17 21:21:57 +02:00
defined ( __BIG_ENDIAN__ ) | | \
defined ( __ARMEB__ ) | | \
defined ( __THUMBEB__ ) | | \
defined ( __AARCH64EB__ ) | | \
defined ( _MIBSEB ) | | defined ( __MIBSEB ) | | defined ( __MIBSEB__ )
2019-12-03 20:23:33 +01:00
// It's a big-endian target architecture
little = false ,
# elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
2021-05-17 21:21:57 +02:00
defined ( __LITTLE_ENDIAN__ ) | | \
defined ( __ARMEL__ ) | | \
defined ( __THUMBEL__ ) | | \
defined ( __AARCH64EL__ ) | | \
defined ( _MIPSEL ) | | defined ( __MIPSEL ) | | defined ( __MIPSEL__ ) | | \
defined ( _WIN32 )
2019-12-03 20:23:33 +01:00
// It's a little-endian target architecture
2021-05-17 21:21:57 +02:00
little = true ,
2019-12-03 20:23:33 +01:00
# else
# error "Unknown Endianness"
# endif
big = ! little
} ;
} ;
template < class T , class S = void >
2021-05-17 21:21:57 +02:00
struct endian_helper { } ;
2019-12-03 20:23:33 +01:00
template < class T >
struct endian_helper < T , std : : enable_if_t <
2021-05-17 21:21:57 +02:00
! ( instantiation_of_v < std : : optional , T > ) > > {
2019-12-03 20:23:33 +01:00
static inline T big ( T x ) {
2021-05-17 21:21:57 +02:00
if constexpr ( endianness < T > : : little ) {
uint8_t * data = reinterpret_cast < uint8_t * > ( & x ) ;
2019-12-03 20:23:33 +01:00
std : : reverse ( data , data + sizeof ( x ) ) ;
}
return x ;
}
static inline T little ( T x ) {
2021-05-17 21:21:57 +02:00
if constexpr ( endianness < T > : : big ) {
uint8_t * data = reinterpret_cast < uint8_t * > ( & x ) ;
2019-12-03 20:23:33 +01:00
std : : reverse ( data , data + sizeof ( x ) ) ;
}
return x ;
}
} ;
template < class T >
struct endian_helper < T , std : : enable_if_t <
2021-05-17 21:21:57 +02:00
instantiation_of_v < std : : optional , T > > > {
static inline T little ( T x ) {
if ( ! x ) return x ;
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
if constexpr ( endianness < T > : : big ) {
auto * data = reinterpret_cast < uint8_t * > ( & * x ) ;
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
std : : reverse ( data , data + sizeof ( * x ) ) ;
}
return x ;
2019-12-03 20:23:33 +01:00
}
2021-05-17 21:21:57 +02:00
static inline T big ( T x ) {
if ( ! x ) return x ;
2019-12-03 20:23:33 +01:00
2021-07-05 20:58:53 +02:00
if constexpr ( endianness < T > : : little ) {
2021-05-17 21:21:57 +02:00
auto * data = reinterpret_cast < uint8_t * > ( & * x ) ;
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
std : : reverse ( data , data + sizeof ( * x ) ) ;
}
2019-12-03 20:23:33 +01:00
2021-05-17 21:21:57 +02:00
return x ;
2019-12-03 20:23:33 +01:00
}
} ;
template < class T >
inline auto little ( T x ) { return endian_helper < T > : : little ( x ) ; }
template < class T >
inline auto big ( T x ) { return endian_helper < T > : : big ( x ) ; }
2021-05-17 21:21:57 +02:00
} // namespace endian
} // namespace util
2019-12-03 20:23:33 +01:00
# endif