diff --git a/src/common/logging/formatter.h b/src/common/logging/formatter.h index 07efba9c27..343174a0c7 100644 --- a/src/common/logging/formatter.h +++ b/src/common/logging/formatter.h @@ -1,11 +1,14 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include - #include +#include "common/swap.h" // adapted from https://github.com/fmtlib/fmt/issues/2704 // a generic formatter for enum classes @@ -20,3 +23,14 @@ struct fmt::formatter, char>> } }; #endif + +template +struct fmt::formatter> { + constexpr auto parse(format_parse_context& ctx) { + return ctx.begin(); + } + template + auto format(const SwapStructT& reg, FormatContext& ctx) const { + return fmt::format_to(ctx.out(), "{}", T(reg)); + } +}; diff --git a/src/common/swap.h b/src/common/swap.h index fde343e452..1cf8a6ba39 100644 --- a/src/common/swap.h +++ b/src/common/swap.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2012 PPSSPP Project // SPDX-FileCopyrightText: 2012 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -17,7 +20,17 @@ namespace Common { -#ifdef _MSC_VER +#if defined(__Bitrig__) || defined(__OpenBSD__) +// We'll redefine swap16, swap32, swap64 as inline functions +// but OpenBSD is like "wow I bring my own stuff" +// It would be nice if we could use them without C++ namespace shenanigans +// But alas :) +#undef swap16 +#undef swap32 +#undef swap64 +#endif + +#if defined(_MSC_VER) [[nodiscard]] inline u16 swap16(u16 data) noexcept { return _byteswap_ushort(data); } @@ -28,12 +41,6 @@ namespace Common { return _byteswap_uint64(data); } #elif defined(__clang__) || defined(__GNUC__) -#if defined(__Bitrig__) || defined(__OpenBSD__) -// redefine swap16, swap32, swap64 as inline functions -#undef swap16 -#undef swap32 -#undef swap64 -#endif [[nodiscard]] inline u16 swap16(u16 data) noexcept { return __builtin_bswap16(data); } @@ -44,7 +51,9 @@ namespace Common { return __builtin_bswap64(data); } #else -// Generic implementation. +// Generic implementation - compiler will optimise these into their respective +// __builtin_byteswapXX() and such; if not, the compiler is stupid and we probably +// have bigger problems to worry about :) [[nodiscard]] inline u16 swap16(u16 data) noexcept { return (data >> 8) | (data << 8); } @@ -62,33 +71,27 @@ namespace Common { [[nodiscard]] inline float swapf(float f) noexcept { static_assert(sizeof(u32) == sizeof(float), "float must be the same size as uint32_t."); - u32 value; std::memcpy(&value, &f, sizeof(u32)); - value = swap32(value); std::memcpy(&f, &value, sizeof(u32)); - return f; } [[nodiscard]] inline double swapd(double f) noexcept { static_assert(sizeof(u64) == sizeof(double), "double must be the same size as uint64_t."); - u64 value; std::memcpy(&value, &f, sizeof(u64)); - value = swap64(value); std::memcpy(&f, &value, sizeof(u64)); - return f; } } // Namespace Common template -struct swap_struct_t { - using swapped_t = swap_struct_t; +struct SwapStructT { + using SwappedT = SwapStructT; protected: T value; @@ -101,137 +104,137 @@ public: T swap() const { return swap(value); } - swap_struct_t() = default; - swap_struct_t(const T& v) : value(swap(v)) {} + SwapStructT() = default; + SwapStructT(const T& v) : value(swap(v)) {} template - swapped_t& operator=(const S& source) { - value = swap(static_cast(source)); + SwappedT& operator=(const S& source) { + value = swap(T(source)); return *this; } operator s8() const { - return static_cast(swap()); + return s8(swap()); } operator u8() const { - return static_cast(swap()); + return u8(swap()); } operator s16() const { - return static_cast(swap()); + return s16(swap()); } operator u16() const { - return static_cast(swap()); + return u16(swap()); } operator s32() const { - return static_cast(swap()); + return s32(swap()); } operator u32() const { - return static_cast(swap()); + return u32(swap()); } operator s64() const { - return static_cast(swap()); + return s64(swap()); } operator u64() const { - return static_cast(swap()); + return u64(swap()); } operator float() const { - return static_cast(swap()); + return float(swap()); } operator double() const { - return static_cast(swap()); + return double(swap()); } // +v - swapped_t operator+() const { + SwappedT operator+() const { return +swap(); } // -v - swapped_t operator-() const { + SwappedT operator-() const { return -swap(); } // v / 5 - swapped_t operator/(const swapped_t& i) const { + SwappedT operator/(const SwappedT& i) const { return swap() / i.swap(); } template - swapped_t operator/(const S& i) const { + SwappedT operator/(const S& i) const { return swap() / i; } // v * 5 - swapped_t operator*(const swapped_t& i) const { + SwappedT operator*(const SwappedT& i) const { return swap() * i.swap(); } template - swapped_t operator*(const S& i) const { + SwappedT operator*(const S& i) const { return swap() * i; } // v + 5 - swapped_t operator+(const swapped_t& i) const { + SwappedT operator+(const SwappedT& i) const { return swap() + i.swap(); } template - swapped_t operator+(const S& i) const { - return swap() + static_cast(i); + SwappedT operator+(const S& i) const { + return swap() + T(i); } // v - 5 - swapped_t operator-(const swapped_t& i) const { + SwappedT operator-(const SwappedT& i) const { return swap() - i.swap(); } template - swapped_t operator-(const S& i) const { - return swap() - static_cast(i); + SwappedT operator-(const S& i) const { + return swap() - T(i); } // v += 5 - swapped_t& operator+=(const swapped_t& i) { + SwappedT& operator+=(const SwappedT& i) { value = swap(swap() + i.swap()); return *this; } template - swapped_t& operator+=(const S& i) { - value = swap(swap() + static_cast(i)); + SwappedT& operator+=(const S& i) { + value = swap(swap() + T(i)); return *this; } // v -= 5 - swapped_t& operator-=(const swapped_t& i) { + SwappedT& operator-=(const SwappedT& i) { value = swap(swap() - i.swap()); return *this; } template - swapped_t& operator-=(const S& i) { - value = swap(swap() - static_cast(i)); + SwappedT& operator-=(const S& i) { + value = swap(swap() - T(i)); return *this; } // ++v - swapped_t& operator++() { + SwappedT& operator++() { value = swap(swap() + 1); return *this; } // --v - swapped_t& operator--() { + SwappedT& operator--() { value = swap(swap() - 1); return *this; } // v++ - swapped_t operator++(int) { - swapped_t old = *this; + SwappedT operator++(int) { + SwappedT old = *this; value = swap(swap() + 1); return old; } // v-- - swapped_t operator--(int) { - swapped_t old = *this; + SwappedT operator--(int) { + SwappedT old = *this; value = swap(swap() - 1); return old; } // Comparison // v == i - bool operator==(const swapped_t& i) const { + bool operator==(const SwappedT& i) const { return swap() == i.swap(); } template @@ -240,7 +243,7 @@ public: } // v != i - bool operator!=(const swapped_t& i) const { + bool operator!=(const SwappedT& i) const { return swap() != i.swap(); } template @@ -249,7 +252,7 @@ public: } // v > i - bool operator>(const swapped_t& i) const { + bool operator>(const SwappedT& i) const { return swap() > i.swap(); } template @@ -258,7 +261,7 @@ public: } // v < i - bool operator<(const swapped_t& i) const { + bool operator<(const SwappedT& i) const { return swap() < i.swap(); } template @@ -267,7 +270,7 @@ public: } // v >= i - bool operator>=(const swapped_t& i) const { + bool operator>=(const SwappedT& i) const { return swap() >= i.swap(); } template @@ -276,7 +279,7 @@ public: } // v <= i - bool operator<=(const swapped_t& i) const { + bool operator<=(const SwappedT& i) const { return swap() <= i.swap(); } template @@ -285,82 +288,82 @@ public: } // logical - swapped_t operator!() const { + SwappedT operator!() const { return !swap(); } // bitmath - swapped_t operator~() const { + SwappedT operator~() const { return ~swap(); } - swapped_t operator&(const swapped_t& b) const { + SwappedT operator&(const SwappedT& b) const { return swap() & b.swap(); } template - swapped_t operator&(const S& b) const { + SwappedT operator&(const S& b) const { return swap() & b; } - swapped_t& operator&=(const swapped_t& b) { + SwappedT& operator&=(const SwappedT& b) { value = swap(swap() & b.swap()); return *this; } template - swapped_t& operator&=(const S b) { + SwappedT& operator&=(const S b) { value = swap(swap() & b); return *this; } - swapped_t operator|(const swapped_t& b) const { + SwappedT operator|(const SwappedT& b) const { return swap() | b.swap(); } template - swapped_t operator|(const S& b) const { + SwappedT operator|(const S& b) const { return swap() | b; } - swapped_t& operator|=(const swapped_t& b) { + SwappedT& operator|=(const SwappedT& b) { value = swap(swap() | b.swap()); return *this; } template - swapped_t& operator|=(const S& b) { + SwappedT& operator|=(const S& b) { value = swap(swap() | b); return *this; } - swapped_t operator^(const swapped_t& b) const { + SwappedT operator^(const SwappedT& b) const { return swap() ^ b.swap(); } template - swapped_t operator^(const S& b) const { + SwappedT operator^(const S& b) const { return swap() ^ b; } - swapped_t& operator^=(const swapped_t& b) { + SwappedT& operator^=(const SwappedT& b) { value = swap(swap() ^ b.swap()); return *this; } template - swapped_t& operator^=(const S& b) { + SwappedT& operator^=(const S& b) { value = swap(swap() ^ b); return *this; } template - swapped_t operator<<(const S& b) const { + SwappedT operator<<(const S& b) const { return swap() << b; } template - swapped_t& operator<<=(const S& b) const { + SwappedT& operator<<=(const S& b) const { value = swap(swap() << b); return *this; } template - swapped_t operator>>(const S& b) const { + SwappedT operator>>(const S& b) const { return swap() >> b; } template - swapped_t& operator>>=(const S& b) const { + SwappedT& operator>>=(const S& b) const { value = swap(swap() >> b); return *this; } @@ -370,167 +373,167 @@ public: // Arithmetic template - friend S operator+(const S& p, const swapped_t v); + friend S operator+(const S& p, const SwappedT v); template - friend S operator-(const S& p, const swapped_t v); + friend S operator-(const S& p, const SwappedT v); template - friend S operator/(const S& p, const swapped_t v); + friend S operator/(const S& p, const SwappedT v); template - friend S operator*(const S& p, const swapped_t v); + friend S operator*(const S& p, const SwappedT v); template - friend S operator%(const S& p, const swapped_t v); + friend S operator%(const S& p, const SwappedT v); // Arithmetic + assignments template - friend S operator+=(const S& p, const swapped_t v); + friend S operator+=(const S& p, const SwappedT v); template - friend S operator-=(const S& p, const swapped_t v); + friend S operator-=(const S& p, const SwappedT v); // Bitmath template - friend S operator&(const S& p, const swapped_t v); + friend S operator&(const S& p, const SwappedT v); // Comparison template - friend bool operator<(const S& p, const swapped_t v); + friend bool operator<(const S& p, const SwappedT v); template - friend bool operator>(const S& p, const swapped_t v); + friend bool operator>(const S& p, const SwappedT v); template - friend bool operator<=(const S& p, const swapped_t v); + friend bool operator<=(const S& p, const SwappedT v); template - friend bool operator>=(const S& p, const swapped_t v); + friend bool operator>=(const S& p, const SwappedT v); template - friend bool operator!=(const S& p, const swapped_t v); + friend bool operator!=(const S& p, const SwappedT v); template - friend bool operator==(const S& p, const swapped_t v); + friend bool operator==(const S& p, const SwappedT v); }; // Arithmetic template -S operator+(const S& i, const swap_struct_t v) { +S operator+(const S& i, const SwapStructT v) { return i + v.swap(); } template -S operator-(const S& i, const swap_struct_t v) { +S operator-(const S& i, const SwapStructT v) { return i - v.swap(); } template -S operator/(const S& i, const swap_struct_t v) { +S operator/(const S& i, const SwapStructT v) { return i / v.swap(); } template -S operator*(const S& i, const swap_struct_t v) { +S operator*(const S& i, const SwapStructT v) { return i * v.swap(); } template -S operator%(const S& i, const swap_struct_t v) { +S operator%(const S& i, const SwapStructT v) { return i % v.swap(); } // Arithmetic + assignments template -S& operator+=(S& i, const swap_struct_t v) { +S& operator+=(S& i, const SwapStructT v) { i += v.swap(); return i; } template -S& operator-=(S& i, const swap_struct_t v) { +S& operator-=(S& i, const SwapStructT v) { i -= v.swap(); return i; } // Logical template -S operator&(const S& i, const swap_struct_t v) { +S operator&(const S& i, const SwapStructT v) { return i & v.swap(); } // Comparison template -bool operator<(const S& p, const swap_struct_t v) { +bool operator<(const S& p, const SwapStructT v) { return p < v.swap(); } template -bool operator>(const S& p, const swap_struct_t v) { +bool operator>(const S& p, const SwapStructT v) { return p > v.swap(); } template -bool operator<=(const S& p, const swap_struct_t v) { +bool operator<=(const S& p, const SwapStructT v) { return p <= v.swap(); } template -bool operator>=(const S& p, const swap_struct_t v) { +bool operator>=(const S& p, const SwapStructT v) { return p >= v.swap(); } template -bool operator!=(const S& p, const swap_struct_t v) { +bool operator!=(const S& p, const SwapStructT v) { return p != v.swap(); } template -bool operator==(const S& p, const swap_struct_t v) { +bool operator==(const S& p, const SwapStructT v) { return p == v.swap(); } template -struct swap_64_t { +struct Swap64T { static T swap(T x) { - return static_cast(Common::swap64(x)); + return T(Common::swap64(x)); } }; template -struct swap_32_t { +struct Swap32T { static T swap(T x) { - return static_cast(Common::swap32(x)); + return T(Common::swap32(x)); } }; template -struct swap_16_t { +struct Swap16T { static T swap(T x) { - return static_cast(Common::swap16(x)); + return T(Common::swap16(x)); } }; template -struct swap_float_t { +struct SwapFloatT { static T swap(T x) { - return static_cast(Common::swapf(x)); + return T(Common::swapf(x)); } }; template -struct swap_double_t { +struct SwapDoubleT { static T swap(T x) { - return static_cast(Common::swapd(x)); + return T(Common::swapd(x)); } }; template -struct swap_enum_t { +struct SwapEnumT { static_assert(std::is_enum_v); using base = std::underlying_type_t; public: - swap_enum_t() = default; - swap_enum_t(const T& v) : value(swap(v)) {} + SwapEnumT() = default; + SwapEnumT(const T& v) : value(swap(v)) {} - swap_enum_t& operator=(const T& v) { + SwapEnumT& operator=(const T& v) { value = swap(v); return *this; } @@ -540,22 +543,20 @@ public: } explicit operator base() const { - return static_cast(swap(value)); + return base(swap(value)); } protected: T value{}; - // clang-format off using swap_t = std::conditional_t< - std::is_same_v, swap_16_t, std::conditional_t< - std::is_same_v, swap_16_t, std::conditional_t< - std::is_same_v, swap_32_t, std::conditional_t< - std::is_same_v, swap_32_t, std::conditional_t< - std::is_same_v, swap_64_t, std::conditional_t< - std::is_same_v, swap_64_t, void>>>>>>; - // clang-format on + std::is_same_v, Swap16T, std::conditional_t< + std::is_same_v, Swap16T, std::conditional_t< + std::is_same_v, Swap32T, std::conditional_t< + std::is_same_v, Swap32T, std::conditional_t< + std::is_same_v, Swap64T, std::conditional_t< + std::is_same_v, Swap64T, void>>>>>>; static T swap(T x) { - return static_cast(swap_t::swap(static_cast(x))); + return T(swap_t::swap(base(x))); } }; @@ -581,17 +582,17 @@ struct AddEndian { template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template <> @@ -601,33 +602,33 @@ struct AddEndian { template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template <> struct AddEndian { - using type = swap_struct_t>; + using type = SwapStructT>; }; template struct AddEndian { static_assert(std::is_enum_v); - using type = swap_enum_t; + using type = SwapEnumT; }; // Alias LETag/BETag as KeepTag/SwapTag depending on the system