From 949200cd3e5a0bfdd45607df7dcda75d463abea1 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 13 Aug 2016 16:36:04 +0300 Subject: [PATCH] Type hacks removed --- Utilities/BEType.h | 470 ++++++++++++++----------------------------- Utilities/StrFmt.cpp | 91 +++++---- Utilities/StrFmt.h | 57 +++--- Utilities/StrUtil.h | 34 ++-- Utilities/types.h | 281 ++++++++++++++------------ 5 files changed, 403 insertions(+), 530 deletions(-) diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 1ffe22acd8..b55e013c0c 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -3,54 +3,57 @@ #include "types.h" #include "Platform.h" +// 128-bit vector type and also se_storage<> storage type union alignas(16) v128 { char _bytes[16]; - template + template struct masked_array_t // array type accessed as (index ^ M) { T m_data[N]; public: - T& operator [](std::size_t index) + T& operator[](std::size_t index) { return m_data[index ^ M]; } - const T& operator [](std::size_t index) const + const T& operator[](std::size_t index) const { return m_data[index ^ M]; } }; #if IS_LE_MACHINE == 1 - template using normal_array_t = masked_array_t; - template using reversed_array_t = masked_array_t; + template + using normal_array_t = masked_array_t; + template + using reversed_array_t = masked_array_t; #endif - normal_array_t _u64; - normal_array_t _s64; + normal_array_t _u64; + normal_array_t _s64; reversed_array_t u64r; reversed_array_t s64r; - normal_array_t _u32; - normal_array_t _s32; + normal_array_t _u32; + normal_array_t _s32; reversed_array_t u32r; reversed_array_t s32r; - normal_array_t _u16; - normal_array_t _s16; + normal_array_t _u16; + normal_array_t _s16; reversed_array_t u16r; reversed_array_t s16r; - normal_array_t _u8; - normal_array_t _s8; - reversed_array_t u8r; - reversed_array_t s8r; + normal_array_t _u8; + normal_array_t _s8; + reversed_array_t u8r; + reversed_array_t s8r; - normal_array_t _f; - normal_array_t _d; + normal_array_t _f; + normal_array_t _d; reversed_array_t fr; reversed_array_t dr; @@ -80,7 +83,7 @@ union alignas(16) v128 return (data & mask) != 0; } - bit_element& operator =(const bool right) + bit_element& operator=(const bool right) { if (right) { @@ -93,7 +96,7 @@ union alignas(16) v128 return *this; } - bit_element& operator =(const bit_element& right) + bit_element& operator=(const bit_element& right) { if (right) { @@ -108,7 +111,7 @@ union alignas(16) v128 }; // Index 0 returns the MSB and index 127 returns the LSB - bit_element operator [](u32 index) + bit_element operator[](u32 index) { #if IS_LE_MACHINE == 1 return bit_element(m_data[1 - (index >> 6)], 0x8000000000000000ull >> (index & 0x3F)); @@ -116,14 +119,13 @@ union alignas(16) v128 } // Index 0 returns the MSB and index 127 returns the LSB - bool operator [](u32 index) const + bool operator[](u32 index) const { #if IS_LE_MACHINE == 1 return (m_data[1 - (index >> 6)] & (0x8000000000000000ull >> (index & 0x3F))) != 0; #endif } - } - _bit; + } _bit; static v128 from64(u64 _0, u64 _1 = 0) { @@ -277,12 +279,12 @@ union alignas(16) v128 return fromV(_mm_cmpeq_epi32(left.vi, right.vi)); } - bool operator ==(const v128& right) const + bool operator==(const v128& right) const { return _u64[0] == right._u64[0] && _u64[1] == right._u64[1]; } - bool operator !=(const v128& right) const + bool operator!=(const v128& right) const { return _u64[0] != right._u64[0] || _u64[1] != right._u64[1]; } @@ -300,30 +302,27 @@ union alignas(16) v128 } }; -inline v128 operator |(const v128& left, const v128& right) +inline v128 operator|(const v128& left, const v128& right) { return v128::fromV(_mm_or_si128(left.vi, right.vi)); } -inline v128 operator &(const v128& left, const v128& right) +inline v128 operator&(const v128& left, const v128& right) { return v128::fromV(_mm_and_si128(left.vi, right.vi)); } -inline v128 operator ^(const v128& left, const v128& right) +inline v128 operator^(const v128& left, const v128& right) { return v128::fromV(_mm_xor_si128(left.vi, right.vi)); } -inline v128 operator ~(const v128& other) +inline v128 operator~(const v128& other) { return v128::from64(~other._u64[0], ~other._u64[1]); } -#define IS_INTEGER(t) (std::is_integral::value || std::is_enum::value) -#define IS_BINARY_COMPARABLE(t1, t2) (IS_INTEGER(t1) && IS_INTEGER(t2) && sizeof(t1) == sizeof(t2)) - -template +template struct se_storage { using type = std::aligned_storage_t; @@ -359,7 +358,7 @@ struct se_storage } }; -template +template struct se_storage { using type = u16; @@ -386,11 +385,11 @@ struct se_storage static inline T copy(const T& src) { - return src; + return src; } }; -template +template struct se_storage { using type = u32; @@ -417,11 +416,11 @@ struct se_storage static inline T copy(const T& src) { - return src; + return src; } }; -template +template struct se_storage { using type = u64; @@ -448,11 +447,11 @@ struct se_storage static inline T copy(const T& src) { - return src; + return src; } }; -template +template struct se_storage { using type = v128; @@ -475,14 +474,12 @@ struct se_storage static inline T copy(const T& src) { - return src; + return src; } }; -static struct se_raw_tag_t {} constexpr se_raw{}; - // Switched endianness -template +template class se_t { using type = typename std::remove_cv::type; @@ -496,24 +493,6 @@ class se_t static_assert(!std::is_array::value, "se_t<> error: invalid type (array)"); static_assert(sizeof(type) == alignof(type), "se_t<> error: unexpected alignment"); - template - struct bool_converter - { - static inline bool to_bool(const se_t& value) - { - return static_cast(value.value()); - } - }; - - template - struct bool_converter::value>> - { - static inline bool to_bool(const se_t& value) - { - return value.m_data != 0; - } - }; - public: se_t() = default; @@ -523,27 +502,15 @@ public: : m_data(storage::to(value)) { } - - // 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 { 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) { return m_data = storage::to(value), *this; } @@ -554,58 +521,10 @@ public: { return storage::from(m_data); } - - // Optimization - explicit operator bool() const - { - return bool_converter::to_bool(*this); - } - - // Optimization - template - std::enable_if_t operator &=(const se_t& right) - { - return m_data &= right.raw_data(), *this; - } - - // Optimization - template - std::enable_if_t::value && std::is_convertible::value, se_t&> operator &=(CT right) - { - return m_data &= storage::to(right), *this; - } - - // Optimization - template - std::enable_if_t operator |=(const se_t& right) - { - return m_data |= right.raw_data(), *this; - } - - // Optimization - template - std::enable_if_t::value && std::is_convertible::value, se_t&> operator |=(CT right) - { - return m_data |= storage::to(right), *this; - } - - // Optimization - template - std::enable_if_t operator ^=(const se_t& right) - { - return m_data ^= right.raw_data(), *this; - } - - // Optimization - template - std::enable_if_t::value && std::is_convertible::value, se_t&> operator ^=(CT right) - { - return m_data ^= storage::to(right), *this; - } }; // Native endianness -template +template class se_t { using type = typename std::remove_cv::type; @@ -627,26 +546,14 @@ 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 { return storage::copy(reinterpret_cast(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) { return m_data = reinterpret_cast(value), *this; } @@ -657,80 +564,84 @@ public: { return storage::copy(reinterpret_cast(m_data)); } - - template - std::enable_if_t::value && std::is_convertible::value, se_t&> operator &=(const CT& right) - { - return m_data &= right, *this; - } - - template - std::enable_if_t::value && std::is_convertible::value, se_t&> operator |=(const CT& right) - { - return m_data |= right, *this; - } - - template - std::enable_if_t::value && std::is_convertible::value, se_t&> operator ^=(const CT& right) - { - return m_data ^= right, *this; - } }; -// se_t with native endianness (alias) -template using nse_t = se_t; +// se_t<> with native endianness +template +using nse_t = se_t; -template -inline se_t& operator +=(se_t& left, const T1& right) +template +inline se_t& operator+=(se_t& left, const T1& right) { auto value = left.value(); return left = (value += right); } -template -inline se_t& operator -=(se_t& left, const T1& right) +template +inline se_t& operator-=(se_t& left, const T1& right) { auto value = left.value(); return left = (value -= right); } -template -inline se_t& operator *=(se_t& left, const T1& right) +template +inline se_t& operator*=(se_t& left, const T1& right) { auto value = left.value(); return left = (value *= right); } -template -inline se_t& operator /=(se_t& left, const T1& right) +template +inline se_t& operator/=(se_t& left, const T1& right) { auto value = left.value(); return left = (value /= right); } -template -inline se_t& operator %=(se_t& left, const T1& right) +template +inline se_t& operator%=(se_t& left, const T1& right) { auto value = left.value(); return left = (value %= right); } -template -inline se_t& operator <<=(se_t& left, const T1& right) +template +inline se_t& operator&=(se_t& left, const T1& right) +{ + auto value = left.value(); + return left = (value &= right); +} + +template +inline se_t& operator|=(se_t& left, const T1& right) +{ + auto value = left.value(); + return left = (value |= right); +} + +template +inline se_t& operator^=(se_t& left, const T1& right) +{ + auto value = left.value(); + return left = (value ^= right); +} + +template +inline se_t& operator<<=(se_t& left, const T1& right) { auto value = left.value(); return left = (value <<= right); } -template -inline se_t& operator >>=(se_t& left, const T1& right) +template +inline se_t& operator>>=(se_t& left, const T1& right) { auto value = left.value(); return left = (value >>= right); } -template -inline se_t operator ++(se_t& left, int) +template +inline se_t operator++(se_t& left, int) { auto value = left.value(); auto result = value++; @@ -738,8 +649,8 @@ inline se_t operator ++(se_t& left, int) return result; } -template -inline se_t operator --(se_t& left, int) +template +inline se_t operator--(se_t& left, int) { auto value = left.value(); auto result = value--; @@ -747,148 +658,38 @@ inline se_t operator --(se_t& left, int) return result; } -template -inline se_t& operator ++(se_t& right) +template +inline se_t& operator++(se_t& right) { auto value = right.value(); return right = ++value; } -template -inline se_t& operator --(se_t& right) +template +inline se_t& operator--(se_t& right) { auto value = right.value(); return right = --value; } -// Optimization -template -inline std::enable_if_t operator ==(const se_t& left, const se_t& right) -{ - return left.raw_data() == right.raw_data(); -} - -// Optimization -template -inline std::enable_if_t::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator ==(const se_t& left, T2 right) -{ - return left.raw_data() == se_storage::to(right); -} - -// Optimization -template -inline std::enable_if_t::value && sizeof(T1) <= sizeof(T2), bool> operator ==(T1 left, const se_t& right) -{ - return se_storage::to(left) == right.raw_data(); -} - -// Optimization -template -inline std::enable_if_t operator !=(const se_t& left, const se_t& right) -{ - return left.raw_data() != right.raw_data(); -} - -// Optimization -template -inline std::enable_if_t::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2), bool> operator !=(const se_t& left, T2 right) -{ - return left.raw_data() != se_storage::to(right); -} - -// Optimization -template -inline std::enable_if_t::value && sizeof(T1) <= sizeof(T2), bool> operator !=(T1 left, const se_t& right) -{ - return se_storage::to(left) != right.raw_data(); -} - -// Optimization -template -inline std::enable_if_t= 4, se_t> operator &(const se_t& left, const se_t& right) -{ - return{ left.raw_data() & right.raw_data(), se_raw }; -} - -// Optimization -template -inline std::enable_if_t::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t> operator &(const se_t& left, T2 right) -{ - return{ left.raw_data() & se_storage::to(right), se_raw }; -} - -// Optimization -template -inline std::enable_if_t::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t> operator &(T1 left, const se_t& right) -{ - return{ se_storage::to(left) & right.raw_data(), se_raw }; -} - -// Optimization -template -inline std::enable_if_t= 4, se_t> operator |(const se_t& left, const se_t& right) -{ - return{ left.raw_data() | right.raw_data(), se_raw }; -} - -// Optimization -template -inline std::enable_if_t::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t> operator |(const se_t& left, T2 right) -{ - return{ left.raw_data() | se_storage::to(right), se_raw }; -} - -// Optimization -template -inline std::enable_if_t::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t> operator |(T1 left, const se_t& right) -{ - return{ se_storage::to(left) | right.raw_data(), se_raw }; -} - -// Optimization -template -inline std::enable_if_t= 4, se_t> operator ^(const se_t& left, const se_t& right) -{ - return{ left.raw_data() ^ right.raw_data(), se_raw }; -} - -// Optimization -template -inline std::enable_if_t::value && IS_INTEGER(T2) && sizeof(T1) >= sizeof(T2) && sizeof(T1) >= 4, se_t> operator ^(const se_t& left, T2 right) -{ - return{ left.raw_data() ^ se_storage::to(right), se_raw }; -} - -// Optimization -template -inline std::enable_if_t::value && sizeof(T1) <= sizeof(T2) && sizeof(T2) >= 4, se_t> operator ^(T1 left, const se_t& right) -{ - return{ se_storage::to(left) ^ right.raw_data(), se_raw }; -} - -// Optimization -template -inline std::enable_if_t::value && sizeof(T) >= 4, se_t> operator ~(const se_t& right) -{ - return{ ~right.raw_data(), se_raw }; -} - #if IS_LE_MACHINE == 1 -template using be_t = se_t; -template using le_t = se_t; +template +using be_t = se_t; +template +using le_t = se_t; #endif // Type converter: converts native endianness arithmetic/enum types to appropriate se_t<> type -template +template struct to_se { - template + template struct to_se_ { using type = T2; }; - template + template struct to_se_::value || std::is_enum::value>> { using type = se_t; @@ -898,34 +699,70 @@ struct to_se using type = typename to_se_::type; }; -template struct to_se { using type = se_t; }; -template struct to_se { using type = bool; }; -template struct to_se { using type = char; }; -template struct to_se { using type = u8; }; -template struct to_se { using type = s8; }; +template +struct to_se +{ + using type = se_t; +}; -template -struct to_se::value>> +template +struct to_se +{ + using type = se_t; +}; + +template +struct to_se +{ + using type = se_t; +}; + +template +struct to_se +{ + using type = bool; +}; + +template +struct to_se +{ + using type = char; +}; + +template +struct to_se +{ + using type = u8; +}; + +template +struct to_se +{ + using type = s8; +}; + +template +struct to_se::value>> { // Move const qualifier using type = const typename to_se::type; }; -template +template struct to_se::value && !std::is_const::value>> { // Move volatile qualifier using type = volatile typename to_se::type; }; -template +template struct to_se { // Move array qualifier using type = typename to_se::type[]; }; -template +template struct to_se { // Move array qualifier @@ -934,17 +771,21 @@ struct to_se // BE/LE aliases for to_se<> #if IS_LE_MACHINE == 1 -template using to_be_t = typename to_se::type; -template using to_le_t = typename to_se::type; +template +using to_be_t = typename to_se::type; +template +using to_le_t = typename to_se::type; #endif // BE/LE aliases for atomic_t #if IS_LE_MACHINE == 1 -template using atomic_be_t = atomic_t>; -template using atomic_le_t = atomic_t>; +template +using atomic_be_t = atomic_t>; +template +using atomic_le_t = atomic_t>; #endif -template +template struct fmt_unveil, void> { using type = typename fmt_unveil::type; @@ -954,6 +795,3 @@ struct fmt_unveil, void> return fmt_unveil::get(arg); } }; - -#undef IS_BINARY_COMPARABLE -#undef IS_INTEGER diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index b65c56395b..36f05551b9 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -11,115 +11,109 @@ void fmt_class_string::format(std::string& out, u64 arg) fmt::append(out, "%p", reinterpret_cast(static_cast(arg))); } -template<> -void fmt_class_string::format(std::string& out, u64 arg) -{ - fmt::append(out, "%p", reinterpret_cast(static_cast(arg))); -} - void fmt_class_string::format(std::string& out, u64 arg) { out += reinterpret_cast(static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { out += get_object(arg).c_str(); // TODO? } -template<> +template <> void fmt_class_string>::format(std::string& out, u64 arg) { const std::vector& obj = get_object(arg); out.append(obj.cbegin(), obj.cend()); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#hhx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#hhx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#hhx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#hx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#hx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#x", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#x", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#lx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#lx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#llx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%#llx", static_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%gf", static_cast(reinterpret_cast(arg))); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { fmt::append(out, "%g", reinterpret_cast(arg)); } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { out += arg ? "true" : "false"; } -template<> +template <> void fmt_class_string::format(std::string& out, u64 arg) { const v128& vec = get_object(arg); @@ -130,21 +124,38 @@ namespace fmt { void raw_error(const char* msg) { - std::string out; + std::string out{"Error"}; - out += "Error: "; + out += ": "; 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) { - std::string out; + std::string out{"Narrow error"}; - out += "Narrow error: ("; + out += " ("; sup->fmt_string(out, arg); // Print value - out += ")"; + out += "): "; if (msg) { @@ -152,11 +163,11 @@ namespace fmt out += msg; } - throw std::range_error(out); + throw std::range_error{out}; } // Hidden template - template + template void raw_throw_exception(const char* fmt, const fmt_type_info* sup, const u64* args) { std::string out; @@ -193,7 +204,7 @@ struct fmt::cfmt_src return true; } - template + template T get(std::size_t index) const { return reinterpret_cast(args[index]); @@ -215,9 +226,9 @@ struct fmt::cfmt_src // Returns type size (0 if unknown, pointer, unsigned, assumed max) std::size_t type(std::size_t extra) const { - // Hack: use known function pointers to determine type -#define TYPE(type)\ - if (sup[extra].fmt_string == &fmt_class_string::format) return sizeof(type); +// Hack: use known function pointers to determine type +#define TYPE(type) \ + if (sup[extra].fmt_string == &fmt_class_string::format) return sizeof(type); TYPE(int); TYPE(llong); @@ -249,7 +260,7 @@ std::string fmt::replace_first(const std::string& src, const std::string& from, return (pos ? src.substr(0, pos) + to : to) + std::string(src.c_str() + pos + from.length()); } -std::string fmt::replace_all(const std::string &src, const std::string& from, const std::string& to) +std::string fmt::replace_all(const std::string& src, const std::string& from, const std::string& to) { std::string target = src; for (auto pos = target.find(from); pos != std::string::npos; pos = target.find(from, pos + 1)) @@ -269,7 +280,7 @@ std::vector fmt::split(const std::string& source, std::initializer_ for (size_t cursor_end = 0; cursor_end < source.length(); ++cursor_end) { - for (auto &separator : separators) + for (auto& separator : separators) { if (strncmp(source.c_str() + cursor_end, separator.c_str(), separator.length()) == 0) { @@ -278,7 +289,7 @@ std::vector fmt::split(const std::string& source, std::initializer_ result.push_back(candidate); cursor_begin = cursor_end + separator.length(); - cursor_end = cursor_begin - 1; + cursor_end = cursor_begin - 1; break; } } @@ -297,7 +308,7 @@ std::string fmt::trim(const std::string& source, const std::string& values) std::size_t begin = source.find_first_not_of(values); if (begin == source.npos) - return{}; + return {}; return source.substr(begin, source.find_last_not_of(values) + 1); } @@ -310,7 +321,7 @@ std::string fmt::to_upper(const std::string& string) return result; } -bool fmt::match(const std::string &source, const std::string &mask) +bool fmt::match(const std::string& source, const std::string& mask) { std::size_t source_position = 0, mask_position = 0; diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index c90db59914..3b283fcf7b 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -8,11 +8,11 @@ namespace fmt { - template + template static std::string format(const char*, const Args&...); } -template +template struct fmt_unveil { static_assert(sizeof(T) > 0, "fmt_unveil<>: cannot pass forward-declared object"); @@ -43,7 +43,7 @@ struct fmt_unveil } }; -template +template struct fmt_unveil::value && sizeof(T) <= 8 && alignof(T) <= 8>> { using type = T; @@ -54,7 +54,7 @@ struct fmt_unveil::value && sizeof(T) <= } }; -template +template struct fmt_unveil::value && sizeof(T) <= 8 && alignof(T) <= 8>> { using type = T; @@ -66,7 +66,7 @@ struct fmt_unveil::value && sizeof } }; -template +template struct fmt_unveil::value>> { using type = T; @@ -77,7 +77,7 @@ struct fmt_unveil::value>> } }; -template +template struct fmt_unveil { using type = const T*; @@ -88,7 +88,7 @@ struct fmt_unveil } }; -template +template struct fmt_unveil { using type = const T*; @@ -99,7 +99,7 @@ struct fmt_unveil } }; -template<> +template <> struct fmt_unveil { using type = bool; @@ -111,7 +111,7 @@ struct fmt_unveil }; // String type format provider, also type classifier (format() called if an argument is formatted as "%s") -template +template struct fmt_class_string { // Formatting function (must be explicitly specialized) @@ -127,7 +127,7 @@ struct fmt_class_string } // Helper function (safely converts arg to enum value) - static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, const char*(*get)(T value)) + static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, const char* (*get)(T value)) { const auto value = static_cast>(arg); @@ -146,7 +146,7 @@ struct fmt_class_string } // Helper function (bitset formatting) - static SAFE_BUFFERS FORCE_INLINE void format_bitset(std::string& out, u64 arg, const char* prefix, const char* delim, const char* suffix, void(*fmt)(std::string&, u64)) + static SAFE_BUFFERS FORCE_INLINE void format_bitset(std::string& out, u64 arg, const char* prefix, const char* delim, const char* suffix, void (*fmt)(std::string&, u64)) { // Start from raw value fmt_class_string::format(out, arg); @@ -175,25 +175,25 @@ struct fmt_class_string static constexpr const char* unknown = nullptr; }; -template<> +template <> struct fmt_class_string { static void format(std::string& out, u64 arg); }; -template +template struct fmt_class_string : fmt_class_string { // Classify all pointers as const void* }; -template<> +template <> struct fmt_class_string { static void format(std::string& out, u64 arg); }; -template<> +template <> struct fmt_class_string : fmt_class_string { // Classify char* as const char* @@ -203,7 +203,7 @@ struct fmt_type_info { decltype(&fmt_class_string::format) fmt_string; - template + template static constexpr fmt_type_info make() { return fmt_type_info @@ -213,23 +213,20 @@ struct fmt_type_info } }; -template +template using fmt_unveil_t = typename fmt_unveil::type; // Argument array type (each element generated via fmt_unveil<>) -template +template using fmt_args_t = const u64(&&)[sizeof...(Args) + 1]; namespace fmt { - template - const fmt_type_info* get_type_info() + template + SAFE_BUFFERS FORCE_INLINE const fmt_type_info* get_type_info() { // Constantly initialized null-terminated list of type-specific information - static constexpr fmt_type_info result[sizeof...(Args) + 1] - { - fmt_type_info::make()... - }; + static constexpr fmt_type_info result[sizeof...(Args) + 1]{fmt_type_info::make()...}; return result; } @@ -238,15 +235,15 @@ namespace fmt void raw_append(std::string& out, const char*, const fmt_type_info*, const u64*) noexcept; // Formatting function - template - static SAFE_BUFFERS void append(std::string& out, const char* fmt, const Args&... args) + template + SAFE_BUFFERS FORCE_INLINE void append(std::string& out, const char* fmt, const Args&... args) { raw_append(out, fmt, fmt::get_type_info...>(), fmt_args_t{fmt_unveil::get(args)...}); } // Formatting function - template - static SAFE_BUFFERS std::string format(const char* fmt, const Args&... args) + template + SAFE_BUFFERS FORCE_INLINE std::string format(const char* fmt, const Args&... args) { std::string result; append(result, fmt, args...); @@ -254,11 +251,11 @@ namespace fmt } // Internal exception message formatting template, must be explicitly specialized or instantiated in cpp to minimize code bloat - template + template [[noreturn]] void raw_throw_exception(const char*, const fmt_type_info*, const u64*); // Throw exception with formatting - template + template [[noreturn]] SAFE_BUFFERS FORCE_INLINE void throw_exception(const char* fmt, const Args&... args) { raw_throw_exception(fmt, fmt::get_type_info...>(), fmt_args_t{fmt_unveil::get(args)...}); diff --git a/Utilities/StrUtil.h b/Utilities/StrUtil.h index 7a38bd2891..12448f60cf 100644 --- a/Utilities/StrUtil.h +++ b/Utilities/StrUtil.h @@ -7,8 +7,8 @@ #include // Copy null-terminated string from std::string to char array with truncation -template -inline void strcpy_trunc(char(&dst)[N], const std::string& src) +template +inline void strcpy_trunc(char (&dst)[N], const std::string& src) { const std::size_t count = src.size() >= N ? N - 1 : src.size(); std::memcpy(dst, src.c_str(), count); @@ -16,8 +16,8 @@ inline void strcpy_trunc(char(&dst)[N], const std::string& src) } // Copy null-terminated string from char array to another char array with truncation -template -inline void strcpy_trunc(char(&dst)[N], const char(&src)[N2]) +template +inline void strcpy_trunc(char (&dst)[N], const char (&src)[N2]) { const std::size_t count = N2 >= N ? N - 1 : N2; std::memcpy(dst, src, count); @@ -27,10 +27,10 @@ inline void strcpy_trunc(char(&dst)[N], const char(&src)[N2]) namespace fmt { std::string replace_first(const std::string& src, const std::string& from, const std::string& to); - std::string replace_all(const std::string &src, const std::string& from, const std::string& to); + std::string replace_all(const std::string& src, const std::string& from, const std::string& to); - template - std::string replace_all(std::string src, const std::pair(&list)[list_size]) + template + std::string replace_all(std::string src, const std::pair (&list)[list_size]) { for (size_t pos = 0; pos < src.length(); ++pos) { @@ -53,8 +53,8 @@ namespace fmt return src; } - template - std::string replace_all(std::string src, const std::pair>(&list)[list_size]) + template + std::string replace_all(std::string src, const std::pair> (&list)[list_size]) { for (size_t pos = 0; pos < src.length(); ++pos) { @@ -80,17 +80,17 @@ namespace fmt std::vector split(const std::string& source, std::initializer_list separators, bool is_skip_empty = true); std::string trim(const std::string& source, const std::string& values = " \t"); - template + template std::string merge(const T& source, const std::string& separator) { if (!source.size()) { - return{}; + return {}; } std::string result; - auto it = source.begin(); + auto it = source.begin(); auto end = source.end(); for (--end; it != end; ++it) { @@ -100,23 +100,23 @@ namespace fmt return result + source.back(); } - template + template std::string merge(std::initializer_list sources, const std::string& separator) { if (!sources.size()) { - return{}; + return {}; } std::string result; bool first = true; - for (auto &v : sources) + for (auto& v : sources) { if (first) { result = fmt::merge(v, separator); - first = false; + first = false; } else { @@ -129,5 +129,5 @@ namespace fmt std::string to_upper(const std::string& string); - bool match(const std::string &source, const std::string &mask); + bool match(const std::string& source, const std::string& mask); } diff --git a/Utilities/types.h b/Utilities/types.h index 114042928f..3fe743f57f 100644 --- a/Utilities/types.h +++ b/Utilities/types.h @@ -4,20 +4,20 @@ #include #include -using schar = signed char; -using uchar = unsigned char; +using schar = signed char; +using uchar = unsigned char; using ushort = unsigned short; -using uint = unsigned int; -using ulong = unsigned long; +using uint = unsigned int; +using ulong = unsigned long; using ullong = unsigned long long; -using llong = long long; +using llong = long long; -using u8 = std::uint8_t; +using u8 = std::uint8_t; using u16 = std::uint16_t; using u32 = std::uint32_t; using u64 = std::uint64_t; -using s8 = std::int8_t; +using s8 = std::int8_t; using s16 = std::int16_t; using s32 = std::int32_t; using s64 = std::int64_t; @@ -28,63 +28,63 @@ namespace gsl } // Formatting helper, type-specific preprocessing for improving safety and functionality -template +template struct fmt_unveil; struct fmt_type_info; namespace fmt { - template + template const fmt_type_info* get_type_info(); } -template +template struct se_storage; -template +template class se_t; -template +template struct atomic_storage; -template +template struct atomic_add; -template +template struct atomic_sub; -template +template struct atomic_and; -template +template struct atomic_or; -template +template struct atomic_xor; -template +template struct atomic_pre_inc; -template +template struct atomic_post_inc; -template +template struct atomic_pre_dec; -template +template struct atomic_post_dec; -template +template struct atomic_test_and_set; -template +template struct atomic_test_and_reset; -template +template struct atomic_test_and_complement; -template +template class atomic_t; #ifdef _MSC_VER @@ -92,30 +92,32 @@ using std::void_t; #else namespace void_details { - template + template struct make_void { using type = void; }; } -template using void_t = typename void_details::make_void::type; +template +using void_t = typename void_details::make_void::type; #endif // Extract T::simple_type if available, remove cv qualifiers -template +template struct simple_type_helper { using type = typename std::remove_cv::type; }; -template +template struct simple_type_helper> { using type = typename T::simple_type; }; -template using simple_t = typename simple_type_helper::type; +template +using simple_t = typename simple_type_helper::type; // Bool type equivalent class b8 @@ -172,87 +174,87 @@ struct alignas(16) u128 { } - friend u128 operator +(const u128& l, const u128& r) + friend u128 operator+(const u128& l, const u128& r) { u128 value; _addcarry_u64(_addcarry_u64(0, r.lo, l.lo, &value.lo), r.hi, l.hi, &value.hi); return value; } - friend u128 operator +(const u128& l, u64 r) + friend u128 operator+(const u128& l, u64 r) { u128 value; _addcarry_u64(_addcarry_u64(0, r, l.lo, &value.lo), l.hi, 0, &value.hi); return value; } - friend u128 operator +(u64 l, const u128& r) + friend u128 operator+(u64 l, const u128& r) { u128 value; _addcarry_u64(_addcarry_u64(0, r.lo, l, &value.lo), 0, r.hi, &value.hi); return value; } - friend u128 operator -(const u128& l, const u128& r) + friend u128 operator-(const u128& l, const u128& r) { u128 value; _subborrow_u64(_subborrow_u64(0, r.lo, l.lo, &value.lo), r.hi, l.hi, &value.hi); return value; } - friend u128 operator -(const u128& l, u64 r) + friend u128 operator-(const u128& l, u64 r) { u128 value; _subborrow_u64(_subborrow_u64(0, r, l.lo, &value.lo), 0, l.hi, &value.hi); return value; } - friend u128 operator -(u64 l, const u128& r) + friend u128 operator-(u64 l, const u128& r) { u128 value; _subborrow_u64(_subborrow_u64(0, r.lo, l, &value.lo), r.hi, 0, &value.hi); return value; } - u128 operator +() const + u128 operator+() const { return *this; } - u128 operator -() const + u128 operator-() const { u128 value; _subborrow_u64(_subborrow_u64(0, lo, 0, &value.lo), hi, 0, &value.hi); return value; } - u128& operator ++() + u128& operator++() { _addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi); return *this; } - u128 operator ++(int) + u128 operator++(int) { u128 value = *this; _addcarry_u64(_addcarry_u64(0, 1, lo, &lo), 0, hi, &hi); return value; } - u128& operator --() + u128& operator--() { _subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi); return *this; } - u128 operator --(int) + u128 operator--(int) { u128 value = *this; _subborrow_u64(_subborrow_u64(0, 1, lo, &lo), 0, hi, &hi); return value; } - u128 operator ~() const + u128 operator~() const { u128 value; value.lo = ~lo; @@ -260,7 +262,7 @@ struct alignas(16) u128 return value; } - friend u128 operator &(const u128& l, const u128& r) + friend u128 operator&(const u128& l, const u128& r) { u128 value; value.lo = l.lo & r.lo; @@ -268,7 +270,7 @@ struct alignas(16) u128 return value; } - friend u128 operator |(const u128& l, const u128& r) + friend u128 operator|(const u128& l, const u128& r) { u128 value; value.lo = l.lo | r.lo; @@ -276,7 +278,7 @@ struct alignas(16) u128 return value; } - friend u128 operator ^(const u128& l, const u128& r) + friend u128 operator^(const u128& l, const u128& r) { u128 value; value.lo = l.lo ^ r.lo; @@ -284,33 +286,33 @@ struct alignas(16) u128 return value; } - u128& operator +=(const u128& r) + u128& operator+=(const u128& r) { _addcarry_u64(_addcarry_u64(0, r.lo, lo, &lo), r.hi, hi, &hi); return *this; } - u128& operator +=(uint64_t r) + u128& operator+=(uint64_t r) { _addcarry_u64(_addcarry_u64(0, r, lo, &lo), 0, hi, &hi); return *this; } - u128& operator &=(const u128& r) + u128& operator&=(const u128& r) { lo &= r.lo; hi &= r.hi; return *this; } - u128& operator |=(const u128& r) + u128& operator|=(const u128& r) { lo |= r.lo; hi |= r.hi; return *this; } - u128& operator ^=(const u128& r) + u128& operator^=(const u128& r) { lo ^= r.lo; hi ^= r.hi; @@ -340,47 +342,8 @@ struct alignas(16) s128 }; #endif -namespace std -{ - /* Let's hack. */ - - template<> - struct is_integral : true_type - { - }; - - template<> - struct is_integral : true_type - { - }; - - template<> - struct make_unsigned - { - using type = u128; - }; - - template<> - struct make_unsigned - { - using type = u128; - }; - - template<> - struct make_signed - { - using type = s128; - }; - - template<> - struct make_signed - { - using type = s128; - }; -} - -static_assert(std::is_arithmetic::value && std::is_integral::value && alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation"); -static_assert(std::is_arithmetic::value && std::is_integral::value && alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation"); +static_assert(alignof(u128) == 16 && sizeof(u128) == 16, "Wrong u128 implementation"); +static_assert(alignof(s128) == 16 && sizeof(s128) == 16, "Wrong s128 implementation"); union alignas(2) f16 { @@ -396,9 +359,9 @@ union alignas(2) f16 { // See http://stackoverflow.com/a/26779139 // The conversion doesn't handle NaN/Inf - u32 raw = ((_u16 & 0x8000) << 16) | // Sign (just moved) - (((_u16 & 0x7c00) + 0x1C000) << 13) | // Exponent ( exp - 15 + 127) - ((_u16 & 0x03FF) << 13); // Mantissa + u32 raw = ((_u16 & 0x8000) << 16) | // Sign (just moved) + (((_u16 & 0x7c00) + 0x1C000) << 13) | // Exponent ( exp - 15 + 127) + ((_u16 & 0x03FF) << 13); // Mantissa return (float&)raw; } }; @@ -408,13 +371,13 @@ using f64 = double; struct ignore { - template + template ignore(T) { } }; -template::value>> +template ::value>> constexpr T align(const T& value, std::uint64_t align) { return static_cast((value + (align - 1)) & ~(align - 1)); @@ -423,12 +386,74 @@ constexpr T align(const T& value, std::uint64_t align) namespace fmt { [[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); } +struct verify_func +{ + template + bool operator()(T&& value) const + { + if (std::forward(value)) + { + return true; + } + + return false; + } +}; + +template +struct verify_impl +{ + const char* cause; + + template + auto operator,(T&& value) const + { + // Verification (can be safely disabled) + if (!verify_func()(std::forward(value))) + { + fmt::raw_verify_error(cause, N); + } + + return verify_impl{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 +inline T verify(T&& value, const char* cause, F&& func = F()) +{ + if (!func(std::forward(value))) + { + fmt::raw_verify_error(cause, 0); + } + + return std::forward(value); +} + +// Verification helper (must be used in return expression or in place of std::move) +template +inline std::remove_reference_t&& verify_move(T&& value, const char* cause, F&& func = F()) +{ + if (!func(std::forward(value))) + { + fmt::raw_verify_error(cause, 0); + } + + return std::move(value); +} + // Narrow cast (throws on failure) -template(std::declval()))> +template (std::declval()))> inline To narrow(const From& value, const char* msg = nullptr) { // Allow "narrowing to void" and ensure it always fails in this case @@ -443,32 +468,32 @@ inline To narrow(const From& value, const char* msg = nullptr) } // Returns u32 size() for container -template(std::declval().size()))> +template (std::declval().size()))> inline u32 size32(const CT& container, const char* msg = nullptr) { return narrow(container.size(), msg); } // Returns u32 size for an array -template -constexpr u32 size32(const T(&)[Size], const char* msg = nullptr) +template +constexpr u32 size32(const T (&)[Size], const char* msg = nullptr) { return static_cast(Size); } -template::value>> +template ::value>> constexpr bool test(const T1& value) { return value != 0; } -template::value && std::is_integral::value>> +template ::value && std::is_integral::value>> constexpr bool test(const T1& lhs, const T2& rhs) { return (lhs & rhs) != 0; } -template::value && std::is_integral::value>> +template ::value && std::is_integral::value>> inline bool test_and_set(T& lhs, const T2& rhs) { const bool result = (lhs & rhs) != 0; @@ -476,7 +501,7 @@ inline bool test_and_set(T& lhs, const T2& rhs) return result; } -template::value && std::is_integral::value>> +template ::value && std::is_integral::value>> inline bool test_and_reset(T& lhs, const T2& rhs) { const bool result = (lhs & rhs) != 0; @@ -484,7 +509,7 @@ inline bool test_and_reset(T& lhs, const T2& rhs) return result; } -template::value && std::is_integral::value>> +template ::value && std::is_integral::value>> inline bool test_and_complement(T& lhs, const T2& rhs) { const bool result = (lhs & rhs) != 0; @@ -493,7 +518,7 @@ inline bool test_and_complement(T& lhs, const T2& rhs) } // Simplified hash algorithm for pointers. May be used in std::unordered_(map|set). -template +template struct pointer_hash { std::size_t operator()(T* ptr) const @@ -502,7 +527,7 @@ struct pointer_hash } }; -template +template struct value_hash { std::size_t operator()(T value) const @@ -513,26 +538,26 @@ struct value_hash // Contains value of any POD type with fixed size and alignment. TT<> is the type converter applied. // For example, `simple_t` may be used to remove endianness. -template class TT, std::size_t S, std::size_t A = S> +template