mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 13:31:27 +12:00
Type hacks removed
This commit is contained in:
parent
2d512121f1
commit
949200cd3e
5 changed files with 403 additions and 530 deletions
|
@ -3,6 +3,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
|
// 128-bit vector type and also se_storage<> storage type
|
||||||
union alignas(16) v128
|
union alignas(16) v128
|
||||||
{
|
{
|
||||||
char _bytes[16];
|
char _bytes[16];
|
||||||
|
@ -25,8 +26,10 @@ union alignas(16) v128
|
||||||
};
|
};
|
||||||
|
|
||||||
#if IS_LE_MACHINE == 1
|
#if IS_LE_MACHINE == 1
|
||||||
template<typename T, std::size_t N = 16 / sizeof(T)> using normal_array_t = masked_array_t<T, N, 0>;
|
template <typename T, std::size_t N = 16 / sizeof(T)>
|
||||||
template<typename T, std::size_t N = 16 / sizeof(T)> using reversed_array_t = masked_array_t<T, N, N - 1>;
|
using normal_array_t = masked_array_t<T, N, 0>;
|
||||||
|
template <typename T, std::size_t N = 16 / sizeof(T)>
|
||||||
|
using reversed_array_t = masked_array_t<T, N, N - 1>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
normal_array_t<u64> _u64;
|
normal_array_t<u64> _u64;
|
||||||
|
@ -122,8 +125,7 @@ union alignas(16) v128
|
||||||
return (m_data[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
|
return (m_data[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
} _bit;
|
||||||
_bit;
|
|
||||||
|
|
||||||
static v128 from64(u64 _0, u64 _1 = 0)
|
static v128 from64(u64 _0, u64 _1 = 0)
|
||||||
{
|
{
|
||||||
|
@ -320,9 +322,6 @@ inline v128 operator ~(const v128& other)
|
||||||
return v128::from64(~other._u64[0], ~other._u64[1]);
|
return v128::from64(~other._u64[0], ~other._u64[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_INTEGER(t) (std::is_integral<t>::value || std::is_enum<t>::value)
|
|
||||||
#define IS_BINARY_COMPARABLE(t1, t2) (IS_INTEGER(t1) && IS_INTEGER(t2) && sizeof(t1) == sizeof(t2))
|
|
||||||
|
|
||||||
template <typename T, std::size_t Align, std::size_t Size>
|
template <typename T, std::size_t Align, std::size_t Size>
|
||||||
struct se_storage
|
struct se_storage
|
||||||
{
|
{
|
||||||
|
@ -479,8 +478,6 @@ struct se_storage<T, 16, 16>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct se_raw_tag_t {} constexpr se_raw{};
|
|
||||||
|
|
||||||
// Switched endianness
|
// Switched endianness
|
||||||
template <typename T, std::size_t Align>
|
template <typename T, std::size_t Align>
|
||||||
class se_t<T, true, Align>
|
class se_t<T, true, Align>
|
||||||
|
@ -496,24 +493,6 @@ class se_t<T, true, Align>
|
||||||
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
|
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
|
||||||
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
|
static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment");
|
||||||
|
|
||||||
template<typename T2, typename = void>
|
|
||||||
struct bool_converter
|
|
||||||
{
|
|
||||||
static inline bool to_bool(const se_t<T2>& value)
|
|
||||||
{
|
|
||||||
return static_cast<bool>(value.value());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T2>
|
|
||||||
struct bool_converter<T2, std::enable_if_t<std::is_integral<T2>::value>>
|
|
||||||
{
|
|
||||||
static inline bool to_bool(const se_t<T2>& value)
|
|
||||||
{
|
|
||||||
return value.m_data != 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
se_t() = default;
|
se_t() = default;
|
||||||
|
|
||||||
|
@ -524,23 +503,11 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct directly from raw data (don't use)
|
|
||||||
constexpr se_t(const stype& raw_value, const se_raw_tag_t&)
|
|
||||||
: m_data(raw_value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
type value() const
|
type value() const
|
||||||
{
|
{
|
||||||
return storage::from(m_data);
|
return storage::from(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Access underlying raw data (don't use)
|
|
||||||
constexpr const stype& raw_data() const noexcept
|
|
||||||
{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
se_t& operator=(const se_t&) = default;
|
se_t& operator=(const se_t&) = default;
|
||||||
|
|
||||||
se_t& operator=(type value)
|
se_t& operator=(type value)
|
||||||
|
@ -554,54 +521,6 @@ public:
|
||||||
{
|
{
|
||||||
return storage::from(m_data);
|
return storage::from(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimization
|
|
||||||
explicit operator bool() const
|
|
||||||
{
|
|
||||||
return bool_converter<type>::to_bool(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T2>
|
|
||||||
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator &=(const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return m_data &= right.raw_data(), *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename CT>
|
|
||||||
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator &=(CT right)
|
|
||||||
{
|
|
||||||
return m_data &= storage::to(right), *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T2>
|
|
||||||
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator |=(const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return m_data |= right.raw_data(), *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename CT>
|
|
||||||
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator |=(CT right)
|
|
||||||
{
|
|
||||||
return m_data |= storage::to(right), *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T2>
|
|
||||||
std::enable_if_t<IS_BINARY_COMPARABLE(T, T2), se_t&> operator ^=(const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return m_data ^= right.raw_data(), *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename CT>
|
|
||||||
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator ^=(CT right)
|
|
||||||
{
|
|
||||||
return m_data ^= storage::to(right), *this;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Native endianness
|
// Native endianness
|
||||||
|
@ -627,23 +546,11 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct directly from raw data (don't use)
|
|
||||||
constexpr se_t(const stype& raw_value, const se_raw_tag_t&)
|
|
||||||
: m_data(raw_value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
type value() const
|
type value() const
|
||||||
{
|
{
|
||||||
return storage::copy(reinterpret_cast<const type&>(m_data));
|
return storage::copy(reinterpret_cast<const type&>(m_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Access underlying raw data (don't use)
|
|
||||||
constexpr const stype& raw_data() const noexcept
|
|
||||||
{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
se_t& operator=(const se_t& value) = default;
|
se_t& operator=(const se_t& value) = default;
|
||||||
|
|
||||||
se_t& operator=(type value)
|
se_t& operator=(type value)
|
||||||
|
@ -657,28 +564,11 @@ public:
|
||||||
{
|
{
|
||||||
return storage::copy(reinterpret_cast<const type&>(m_data));
|
return storage::copy(reinterpret_cast<const type&>(m_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CT>
|
|
||||||
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator &=(const CT& right)
|
|
||||||
{
|
|
||||||
return m_data &= right, *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CT>
|
|
||||||
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator |=(const CT& right)
|
|
||||||
{
|
|
||||||
return m_data |= right, *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CT>
|
|
||||||
std::enable_if_t<std::is_integral<T>::value && std::is_convertible<CT, T>::value, se_t&> operator ^=(const CT& right)
|
|
||||||
{
|
|
||||||
return m_data ^= right, *this;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// se_t with native endianness (alias)
|
// se_t<> with native endianness
|
||||||
template<typename T, std::size_t Align = alignof(T)> using nse_t = se_t<T, false, Align>;
|
template <typename T, std::size_t Align = alignof(T)>
|
||||||
|
using nse_t = se_t<T, false, Align>;
|
||||||
|
|
||||||
template <typename T, bool Se, std::size_t Align, typename T1>
|
template <typename T, bool Se, std::size_t Align, typename T1>
|
||||||
inline se_t<T, Se, Align>& operator+=(se_t<T, Se, Align>& left, const T1& right)
|
inline se_t<T, Se, Align>& operator+=(se_t<T, Se, Align>& left, const T1& right)
|
||||||
|
@ -715,6 +605,27 @@ inline se_t<T, Se, Align>& operator %=(se_t<T, Se, Align>& left, const T1& right
|
||||||
return left = (value %= right);
|
return left = (value %= right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T, bool Se, std::size_t Align, typename T1>
|
||||||
|
inline se_t<T, Se, Align>& operator&=(se_t<T, Se, Align>& left, const T1& right)
|
||||||
|
{
|
||||||
|
auto value = left.value();
|
||||||
|
return left = (value &= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool Se, std::size_t Align, typename T1>
|
||||||
|
inline se_t<T, Se, Align>& operator|=(se_t<T, Se, Align>& left, const T1& right)
|
||||||
|
{
|
||||||
|
auto value = left.value();
|
||||||
|
return left = (value |= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool Se, std::size_t Align, typename T1>
|
||||||
|
inline se_t<T, Se, Align>& operator^=(se_t<T, Se, Align>& left, const T1& right)
|
||||||
|
{
|
||||||
|
auto value = left.value();
|
||||||
|
return left = (value ^= right);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, bool Se, std::size_t Align, typename T1>
|
template <typename T, bool Se, std::size_t Align, typename T1>
|
||||||
inline se_t<T, Se, Align>& operator<<=(se_t<T, Se, Align>& left, const T1& right)
|
inline se_t<T, Se, Align>& operator<<=(se_t<T, Se, Align>& left, const T1& right)
|
||||||
{
|
{
|
||||||
|
@ -761,121 +672,11 @@ inline se_t<T, Se, Align>& operator --(se_t<T, Se, Align>& right)
|
||||||
return right = --value;
|
return right = --value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator ==(const se_t<T1>& left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return left.raw_data() == right.raw_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator ==(const se_t<T1>& left, T2 right)
|
|
||||||
{
|
|
||||||
return left.raw_data() == se_storage<T1>::to(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2), bool> operator ==(T1 left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return se_storage<T2>::to(left) == right.raw_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2), bool> operator !=(const se_t<T1>& left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return left.raw_data() != right.raw_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator !=(const se_t<T1>& left, T2 right)
|
|
||||||
{
|
|
||||||
return left.raw_data() != se_storage<T1>::to(right);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2), bool> operator !=(T1 left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return se_storage<T2>::to(left) != right.raw_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return{ left.raw_data() & right.raw_data(), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() & T2())>> operator &(const se_t<T1>& left, T2 right)
|
|
||||||
{
|
|
||||||
return{ left.raw_data() & se_storage<T1>::to(right), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() & T2())>> operator &(T1 left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return{ se_storage<T2>::to(left) & right.raw_data(), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return{ left.raw_data() | right.raw_data(), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() | T2())>> operator |(const se_t<T1>& left, T2 right)
|
|
||||||
{
|
|
||||||
return{ left.raw_data() | se_storage<T1>::to(right), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() | T2())>> operator |(T1 left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return{ se_storage<T2>::to(left) | right.raw_data(), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_BINARY_COMPARABLE(T1, T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return{ left.raw_data() ^ right.raw_data(), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<std::is_integral<T1>::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(const se_t<T1>& left, T2 right)
|
|
||||||
{
|
|
||||||
return{ left.raw_data() ^ se_storage<T1>::to(right), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T1, typename T2>
|
|
||||||
inline std::enable_if_t<IS_INTEGER(T1) && std::is_integral<T2>::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t<decltype(T1() ^ T2())>> operator ^(T1 left, const se_t<T2>& right)
|
|
||||||
{
|
|
||||||
return{ se_storage<T2>::to(left) ^ right.raw_data(), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optimization
|
|
||||||
template<typename T>
|
|
||||||
inline std::enable_if_t<std::is_integral<T>::value && sizeof(T) >= 4, se_t<decltype(~T())>> operator ~(const se_t<T>& right)
|
|
||||||
{
|
|
||||||
return{ ~right.raw_data(), se_raw };
|
|
||||||
}
|
|
||||||
|
|
||||||
#if IS_LE_MACHINE == 1
|
#if IS_LE_MACHINE == 1
|
||||||
template<typename T, std::size_t Align = alignof(T)> using be_t = se_t<T, true, Align>;
|
template <typename T, std::size_t Align = alignof(T)>
|
||||||
template<typename T, std::size_t Align = alignof(T)> using le_t = se_t<T, false, Align>;
|
using be_t = se_t<T, true, Align>;
|
||||||
|
template <typename T, std::size_t Align = alignof(T)>
|
||||||
|
using le_t = se_t<T, false, Align>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type
|
// Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type
|
||||||
|
@ -898,11 +699,47 @@ struct to_se
|
||||||
using type = typename to_se_<T>::type;
|
using type = typename to_se_<T>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool Se> struct to_se<v128, Se> { using type = se_t<v128, Se>; };
|
template <bool Se>
|
||||||
template<bool Se> struct to_se<bool, Se> { using type = bool; };
|
struct to_se<v128, Se>
|
||||||
template<bool Se> struct to_se<char, Se> { using type = char; };
|
{
|
||||||
template<bool Se> struct to_se<u8, Se> { using type = u8; };
|
using type = se_t<v128, Se>;
|
||||||
template<bool Se> struct to_se<s8, Se> { using type = s8; };
|
};
|
||||||
|
|
||||||
|
template <bool Se>
|
||||||
|
struct to_se<u128, Se>
|
||||||
|
{
|
||||||
|
using type = se_t<u128, Se>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool Se>
|
||||||
|
struct to_se<s128, Se>
|
||||||
|
{
|
||||||
|
using type = se_t<s128, Se>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool Se>
|
||||||
|
struct to_se<bool, Se>
|
||||||
|
{
|
||||||
|
using type = bool;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool Se>
|
||||||
|
struct to_se<char, Se>
|
||||||
|
{
|
||||||
|
using type = char;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool Se>
|
||||||
|
struct to_se<u8, Se>
|
||||||
|
{
|
||||||
|
using type = u8;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <bool Se>
|
||||||
|
struct to_se<s8, Se>
|
||||||
|
{
|
||||||
|
using type = s8;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, bool Se>
|
template <typename T, bool Se>
|
||||||
struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>>
|
struct to_se<const T, Se, std::enable_if_t<!std::is_array<T>::value>>
|
||||||
|
@ -934,14 +771,18 @@ struct to_se<T[N], Se>
|
||||||
|
|
||||||
// BE/LE aliases for to_se<>
|
// BE/LE aliases for to_se<>
|
||||||
#if IS_LE_MACHINE == 1
|
#if IS_LE_MACHINE == 1
|
||||||
template<typename T> using to_be_t = typename to_se<T, true>::type;
|
template <typename T>
|
||||||
template<typename T> using to_le_t = typename to_se<T, false>::type;
|
using to_be_t = typename to_se<T, true>::type;
|
||||||
|
template <typename T>
|
||||||
|
using to_le_t = typename to_se<T, false>::type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BE/LE aliases for atomic_t
|
// BE/LE aliases for atomic_t
|
||||||
#if IS_LE_MACHINE == 1
|
#if IS_LE_MACHINE == 1
|
||||||
template<typename T> using atomic_be_t = atomic_t<be_t<T>>;
|
template <typename T>
|
||||||
template<typename T> using atomic_le_t = atomic_t<le_t<T>>;
|
using atomic_be_t = atomic_t<be_t<T>>;
|
||||||
|
template <typename T>
|
||||||
|
using atomic_le_t = atomic_t<le_t<T>>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T, bool Se, std::size_t Align>
|
template <typename T, bool Se, std::size_t Align>
|
||||||
|
@ -954,6 +795,3 @@ struct fmt_unveil<se_t<T, Se, Align>, void>
|
||||||
return fmt_unveil<T>::get(arg);
|
return fmt_unveil<T>::get(arg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef IS_BINARY_COMPARABLE
|
|
||||||
#undef IS_INTEGER
|
|
||||||
|
|
|
@ -11,12 +11,6 @@ void fmt_class_string<const void*>::format(std::string& out, u64 arg)
|
||||||
fmt::append(out, "%p", reinterpret_cast<const void*>(static_cast<std::uintptr_t>(arg)));
|
fmt::append(out, "%p", reinterpret_cast<const void*>(static_cast<std::uintptr_t>(arg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
|
||||||
void fmt_class_string<std::nullptr_t>::format(std::string& out, u64 arg)
|
|
||||||
{
|
|
||||||
fmt::append(out, "%p", reinterpret_cast<const void*>(static_cast<std::uintptr_t>(arg)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void fmt_class_string<const char*>::format(std::string& out, u64 arg)
|
void fmt_class_string<const char*>::format(std::string& out, u64 arg)
|
||||||
{
|
{
|
||||||
out += reinterpret_cast<const char*>(static_cast<std::uintptr_t>(arg));
|
out += reinterpret_cast<const char*>(static_cast<std::uintptr_t>(arg));
|
||||||
|
@ -130,21 +124,38 @@ namespace fmt
|
||||||
{
|
{
|
||||||
void raw_error(const char* msg)
|
void raw_error(const char* msg)
|
||||||
{
|
{
|
||||||
std::string out;
|
std::string out{"Error"};
|
||||||
|
|
||||||
out += "Error: ";
|
out += ": ";
|
||||||
out += msg;
|
out += msg;
|
||||||
|
|
||||||
throw std::runtime_error(out);
|
throw std::runtime_error{out};
|
||||||
|
}
|
||||||
|
|
||||||
|
void raw_verify_error(const char* msg, uint position)
|
||||||
|
{
|
||||||
|
std::string out{"Verification failed"};
|
||||||
|
|
||||||
|
if (position)
|
||||||
|
{
|
||||||
|
out += " (+";
|
||||||
|
out += std::to_string(position);
|
||||||
|
out += ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
out += ": ";
|
||||||
|
out += msg;
|
||||||
|
|
||||||
|
throw std::runtime_error{out};
|
||||||
}
|
}
|
||||||
|
|
||||||
void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg)
|
void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg)
|
||||||
{
|
{
|
||||||
std::string out;
|
std::string out{"Narrow error"};
|
||||||
|
|
||||||
out += "Narrow error: (";
|
out += " (";
|
||||||
sup->fmt_string(out, arg); // Print value
|
sup->fmt_string(out, arg); // Print value
|
||||||
out += ")";
|
out += "): ";
|
||||||
|
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
|
@ -152,7 +163,7 @@ namespace fmt
|
||||||
out += msg;
|
out += msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::range_error(out);
|
throw std::range_error{out};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hidden template
|
// Hidden template
|
||||||
|
|
|
@ -223,13 +223,10 @@ using fmt_args_t = const u64(&&)[sizeof...(Args) + 1];
|
||||||
namespace fmt
|
namespace fmt
|
||||||
{
|
{
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
const fmt_type_info* get_type_info()
|
SAFE_BUFFERS FORCE_INLINE const fmt_type_info* get_type_info()
|
||||||
{
|
{
|
||||||
// Constantly initialized null-terminated list of type-specific information
|
// Constantly initialized null-terminated list of type-specific information
|
||||||
static constexpr fmt_type_info result[sizeof...(Args) + 1]
|
static constexpr fmt_type_info result[sizeof...(Args) + 1]{fmt_type_info::make<Args>()...};
|
||||||
{
|
|
||||||
fmt_type_info::make<Args>()...
|
|
||||||
};
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -239,14 +236,14 @@ namespace fmt
|
||||||
|
|
||||||
// Formatting function
|
// Formatting function
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static SAFE_BUFFERS void append(std::string& out, const char* fmt, const Args&... args)
|
SAFE_BUFFERS FORCE_INLINE void append(std::string& out, const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
raw_append(out, fmt, fmt::get_type_info<fmt_unveil_t<Args>...>(), fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
|
raw_append(out, fmt, fmt::get_type_info<fmt_unveil_t<Args>...>(), fmt_args_t<Args...>{fmt_unveil<Args>::get(args)...});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatting function
|
// Formatting function
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static SAFE_BUFFERS std::string format(const char* fmt, const Args&... args)
|
SAFE_BUFFERS FORCE_INLINE std::string format(const char* fmt, const Args&... args)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
append<Args...>(result, fmt, args...);
|
append<Args...>(result, fmt, args...);
|
||||||
|
|
|
@ -92,14 +92,15 @@ using std::void_t;
|
||||||
#else
|
#else
|
||||||
namespace void_details
|
namespace void_details
|
||||||
{
|
{
|
||||||
template<class... >
|
template <typename...>
|
||||||
struct make_void
|
struct make_void
|
||||||
{
|
{
|
||||||
using type = void;
|
using type = void;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class... T> using void_t = typename void_details::make_void<T...>::type;
|
template <typename... T>
|
||||||
|
using void_t = typename void_details::make_void<T...>::type;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Extract T::simple_type if available, remove cv qualifiers
|
// Extract T::simple_type if available, remove cv qualifiers
|
||||||
|
@ -115,7 +116,8 @@ struct simple_type_helper<T, void_t<typename T::simple_type>>
|
||||||
using type = typename T::simple_type;
|
using type = typename T::simple_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> using simple_t = typename simple_type_helper<T>::type;
|
template <typename T>
|
||||||
|
using simple_t = typename simple_type_helper<T>::type;
|
||||||
|
|
||||||
// Bool type equivalent
|
// Bool type equivalent
|
||||||
class b8
|
class b8
|
||||||
|
@ -340,47 +342,8 @@ struct alignas(16) s128
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace std
|
static_assert(alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation");
|
||||||
{
|
static_assert(alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation");
|
||||||
/* Let's hack. */
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct is_integral<u128> : true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct is_integral<s128> : true_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct make_unsigned<u128>
|
|
||||||
{
|
|
||||||
using type = u128;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct make_unsigned<s128>
|
|
||||||
{
|
|
||||||
using type = u128;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct make_signed<u128>
|
|
||||||
{
|
|
||||||
using type = s128;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct make_signed<s128>
|
|
||||||
{
|
|
||||||
using type = s128;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static_assert(std::is_arithmetic<u128>::value && std::is_integral<u128>::value && alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation");
|
|
||||||
static_assert(std::is_arithmetic<s128>::value && std::is_integral<s128>::value && alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation");
|
|
||||||
|
|
||||||
union alignas(2) f16
|
union alignas(2) f16
|
||||||
{
|
{
|
||||||
|
@ -423,10 +386,72 @@ constexpr T align(const T& value, std::uint64_t align)
|
||||||
namespace fmt
|
namespace fmt
|
||||||
{
|
{
|
||||||
[[noreturn]] void raw_error(const char* msg);
|
[[noreturn]] void raw_error(const char* msg);
|
||||||
|
[[noreturn]] void raw_verify_error(const char* msg, uint position);
|
||||||
[[noreturn]] void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg);
|
[[noreturn]] void raw_narrow_error(const char* msg, const fmt_type_info* sup, u64 arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct verify_func
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
bool operator()(T&& value) const
|
||||||
|
{
|
||||||
|
if (std::forward<T>(value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <uint N>
|
||||||
|
struct verify_impl
|
||||||
|
{
|
||||||
|
const char* cause;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto operator,(T&& value) const
|
||||||
|
{
|
||||||
|
// Verification (can be safely disabled)
|
||||||
|
if (!verify_func()(std::forward<T>(value)))
|
||||||
|
{
|
||||||
|
fmt::raw_verify_error(cause, N);
|
||||||
|
}
|
||||||
|
|
||||||
|
return verify_impl<N + 1>{cause};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Verification helper, checks several conditions delimited with comma operator
|
||||||
|
inline auto verify(const char* cause)
|
||||||
|
{
|
||||||
|
return verify_impl<0>{cause};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verification helper (returns value or lvalue reference, may require to use verify_move instead)
|
||||||
|
template <typename F = verify_func, typename T>
|
||||||
|
inline T verify(T&& value, const char* cause, F&& func = F())
|
||||||
|
{
|
||||||
|
if (!func(std::forward<T>(value)))
|
||||||
|
{
|
||||||
|
fmt::raw_verify_error(cause, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::forward<T>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verification helper (must be used in return expression or in place of std::move)
|
||||||
|
template <typename F = verify_func, typename T>
|
||||||
|
inline std::remove_reference_t<T>&& verify_move(T&& value, const char* cause, F&& func = F())
|
||||||
|
{
|
||||||
|
if (!func(std::forward<T>(value)))
|
||||||
|
{
|
||||||
|
fmt::raw_verify_error(cause, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(value);
|
||||||
|
}
|
||||||
|
|
||||||
// Narrow cast (throws on failure)
|
// Narrow cast (throws on failure)
|
||||||
template <typename To = void, typename From, typename = decltype(static_cast<To>(std::declval<From>()))>
|
template <typename To = void, typename From, typename = decltype(static_cast<To>(std::declval<From>()))>
|
||||||
inline To narrow(const From& value, const char* msg = nullptr)
|
inline To narrow(const From& value, const char* msg = nullptr)
|
||||||
|
@ -642,7 +667,9 @@ class id_value
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr id_value() {}
|
constexpr id_value()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Get the value
|
// Get the value
|
||||||
operator ID() const
|
operator ID() const
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue