mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 02:37:36 +02:00
Refactor fallback ints
This commit is contained in:
@ -141,7 +141,7 @@ FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str,
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template <> FMT_FUNC int count_digits<4>(detail::fallback_uintptr n) {
|
template <> FMT_FUNC int count_digits<4>(detail::uintptr_fallback n) {
|
||||||
// fallback_uintptr is always stored in little endian.
|
// fallback_uintptr is always stored in little endian.
|
||||||
int i = static_cast<int>(sizeof(void*)) - 1;
|
int i = static_cast<int>(sizeof(void*)) - 1;
|
||||||
while (i > 0 && n.value[i] == 0) --i;
|
while (i > 0 && n.value[i] == 0) --i;
|
||||||
|
@ -315,12 +315,12 @@ inline auto is_big_endian() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A fallback implementation of uintptr_t for systems that lack it.
|
// A fallback implementation of uintptr_t for systems that lack it.
|
||||||
struct fallback_uintptr {
|
struct uintptr_fallback {
|
||||||
unsigned char value[sizeof(void*)];
|
unsigned char value[sizeof(void*)];
|
||||||
|
|
||||||
fallback_uintptr() = default;
|
uintptr_fallback() = default;
|
||||||
explicit fallback_uintptr(const void* p) {
|
explicit uintptr_fallback(const void* p) {
|
||||||
*this = bit_cast<fallback_uintptr>(p);
|
*this = bit_cast<uintptr_fallback>(p);
|
||||||
if (const_check(is_big_endian())) {
|
if (const_check(is_big_endian())) {
|
||||||
for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
|
for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
|
||||||
std::swap(value[i], value[j]);
|
std::swap(value[i], value[j]);
|
||||||
@ -333,42 +333,46 @@ inline auto to_uintptr(const void* p) -> uintptr_t {
|
|||||||
return bit_cast<uintptr_t>(p);
|
return bit_cast<uintptr_t>(p);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
using uintptr_t = fallback_uintptr;
|
using uintptr_t = uintptr_fallback;
|
||||||
inline auto to_uintptr(const void* p) -> fallback_uintptr {
|
inline auto to_uintptr(const void* p) -> uintptr_fallback {
|
||||||
return fallback_uintptr(p);
|
return uintptr_fallback(p);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class uint128_t {
|
class uint128_fallback {
|
||||||
private:
|
private:
|
||||||
uint64_t lo_, hi_;
|
uint64_t lo_, hi_;
|
||||||
constexpr uint128_t(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
|
constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr uint128_t(uint64_t value = 0) : lo_(value), hi_(0) {}
|
constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {}
|
||||||
explicit operator int() const { return static_cast<int>(lo_); }
|
explicit operator int() const { return static_cast<int>(lo_); }
|
||||||
explicit operator uint64_t() const { return lo_; }
|
explicit operator uint64_t() const { return lo_; }
|
||||||
friend auto operator==(const uint128_t& lhs, const uint128_t& rhs) -> bool {
|
friend auto operator==(const uint128_fallback& lhs,
|
||||||
|
const uint128_fallback& rhs) -> bool {
|
||||||
return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
|
return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
|
||||||
}
|
}
|
||||||
friend auto operator&(const uint128_t& lhs, const uint128_t& rhs)
|
friend auto operator&(const uint128_fallback& lhs,
|
||||||
-> uint128_t {
|
const uint128_fallback& rhs) -> uint128_fallback {
|
||||||
return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
|
return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
|
||||||
}
|
}
|
||||||
friend auto operator-(const uint128_t& lhs, uint64_t rhs) -> uint128_t {
|
friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
|
||||||
|
-> uint128_fallback {
|
||||||
FMT_ASSERT(lhs.lo_ >= rhs, "");
|
FMT_ASSERT(lhs.lo_ >= rhs, "");
|
||||||
return {lhs.hi_, lhs.lo_ - rhs};
|
return {lhs.hi_, lhs.lo_ - rhs};
|
||||||
}
|
}
|
||||||
auto operator>>(int shift) const -> uint128_t {
|
auto operator>>(int shift) const -> uint128_fallback {
|
||||||
if (shift == 64) return {0, hi_};
|
if (shift == 64) return {0, hi_};
|
||||||
return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
|
return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
|
||||||
}
|
}
|
||||||
auto operator<<(int shift) const -> uint128_t {
|
auto operator<<(int shift) const -> uint128_fallback {
|
||||||
if (shift == 64) return {lo_, 0};
|
if (shift == 64) return {lo_, 0};
|
||||||
return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
|
return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using uint128_t = conditional_t<FMT_USE_INT128, uint128_opt, uint128_fallback>;
|
||||||
|
|
||||||
// Returns the largest possible value for type T. Same as
|
// Returns the largest possible value for type T. Same as
|
||||||
// std::numeric_limits<T>::max() but shorter and not affected by the max macro.
|
// std::numeric_limits<T>::max() but shorter and not affected by the max macro.
|
||||||
template <typename T> constexpr auto max_value() -> T {
|
template <typename T> constexpr auto max_value() -> T {
|
||||||
@ -380,7 +384,7 @@ template <typename T> constexpr auto num_bits() -> int {
|
|||||||
// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
|
// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
|
||||||
template <> constexpr auto num_bits<int128_opt>() -> int { return 128; }
|
template <> constexpr auto num_bits<int128_opt>() -> int { return 128; }
|
||||||
template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
|
template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
|
||||||
template <> constexpr auto num_bits<fallback_uintptr>() -> int {
|
template <> constexpr auto num_bits<uintptr_fallback>() -> int {
|
||||||
return static_cast<int>(sizeof(void*) *
|
return static_cast<int>(sizeof(void*) *
|
||||||
std::numeric_limits<unsigned char>::digits);
|
std::numeric_limits<unsigned char>::digits);
|
||||||
}
|
}
|
||||||
@ -1035,7 +1039,7 @@ FMT_CONSTEXPR auto count_digits(UInt n) -> int {
|
|||||||
}(n);
|
}(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> auto count_digits<4>(detail::fallback_uintptr n) -> int;
|
template <> auto count_digits<4>(detail::uintptr_fallback n) -> int;
|
||||||
|
|
||||||
#ifdef FMT_BUILTIN_CLZ
|
#ifdef FMT_BUILTIN_CLZ
|
||||||
// It is a separate function rather than a part of count_digits to workaround
|
// It is a separate function rather than a part of count_digits to workaround
|
||||||
@ -1179,7 +1183,7 @@ FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <unsigned BASE_BITS, typename Char>
|
template <unsigned BASE_BITS, typename Char>
|
||||||
auto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,
|
auto format_uint(Char* buffer, detail::uintptr_fallback n, int num_digits,
|
||||||
bool = false) -> Char* {
|
bool = false) -> Char* {
|
||||||
auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
|
auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
|
||||||
int start = (num_digits + char_digits - 1) / char_digits - 1;
|
int start = (num_digits + char_digits - 1) / char_digits - 1;
|
||||||
|
@ -361,7 +361,7 @@ TEST(format_impl_test, write_fallback_uintptr) {
|
|||||||
std::string s;
|
std::string s;
|
||||||
fmt::detail::write_ptr<char>(
|
fmt::detail::write_ptr<char>(
|
||||||
std::back_inserter(s),
|
std::back_inserter(s),
|
||||||
fmt::detail::fallback_uintptr(reinterpret_cast<void*>(0xface)), nullptr);
|
fmt::detail::uintptr_fallback(reinterpret_cast<void*>(0xface)), nullptr);
|
||||||
EXPECT_EQ(s, "0xface");
|
EXPECT_EQ(s, "0xface");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,16 +40,16 @@ using testing::StrictMock;
|
|||||||
enum { buffer_size = 256 };
|
enum { buffer_size = 256 };
|
||||||
|
|
||||||
TEST(uint128_test, ctor) {
|
TEST(uint128_test, ctor) {
|
||||||
using fmt::detail::uint128_t;
|
using fmt::detail::uint128_fallback;
|
||||||
auto n = uint128_t();
|
auto n = uint128_fallback();
|
||||||
EXPECT_EQ(n, 0);
|
EXPECT_EQ(n, 0);
|
||||||
n = uint128_t(42);
|
n = uint128_fallback(42);
|
||||||
EXPECT_EQ(n, 42);
|
EXPECT_EQ(n, 42);
|
||||||
EXPECT_EQ(static_cast<uint64_t>(n), 42);
|
EXPECT_EQ(static_cast<uint64_t>(n), 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(uint128_test, shift) {
|
TEST(uint128_test, shift) {
|
||||||
auto n = fmt::detail::uint128_t(42);
|
auto n = fmt::detail::uint128_fallback(42);
|
||||||
n = n << 64;
|
n = n << 64;
|
||||||
EXPECT_EQ(static_cast<uint64_t>(n), 0);
|
EXPECT_EQ(static_cast<uint64_t>(n), 0);
|
||||||
n = n >> 64;
|
n = n >> 64;
|
||||||
@ -62,7 +62,7 @@ TEST(uint128_test, shift) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(uint128_test, minus) {
|
TEST(uint128_test, minus) {
|
||||||
auto n = fmt::detail::uint128_t(42);
|
auto n = fmt::detail::uint128_fallback(42);
|
||||||
EXPECT_EQ(n - 2, 40);
|
EXPECT_EQ(n - 2, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user