diff --git a/include/fmt/core.h b/include/fmt/core.h index bf144a35..ec7a946c 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -311,6 +311,10 @@ struct int128_t {}; struct uint128_t {}; #endif +#if !defined(FMT_USE_SMALLEST_INT) +#define FMT_USE_SMALLEST_INT 1 +#endif + // Casts a nonnegative integer to unsigned. template FMT_CONSTEXPR typename std::make_unsigned::type to_unsigned(Int value) { diff --git a/include/fmt/format.h b/include/fmt/format.h index 989819f3..81ce7b96 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -726,18 +726,19 @@ FMT_CONSTEXPR bool is_supported_floating_point(T) { (std::is_same::value && FMT_USE_LONG_DOUBLE); } +#if FMT_USE_SMALLEST_INT // Smallest of uint32_t, uint64_t, uint128_t that is large enough to // represent all values of T. template using uint32_or_64_or_128_t = conditional_t< std::numeric_limits::digits <= 32, uint32_t, conditional_t::digits <= 64, uint64_t, uint128_t>>; - -// Selects the between uint64_t or uint128_t based on the how uint128_t is -// defined. If macro FMT_USE_INT128 defined as 0, then its size will be 1 byte, -// meaning the largest sized int that can be used is uint64_t. -using uint_largest_t = +#else +// Pick the largest integer container to represent represent all values of T. +template +using uint32_or_64_or_128_t = conditional_t; +#endif // Static data is placed in this class template for the header-only config. template struct FMT_EXTERN_TEMPLATE_API basic_data { @@ -1464,21 +1465,11 @@ OutputIt write(OutputIt out, basic_string_view s, } // The handle_int_type_spec handler that writes an integer. -template struct int_writer { - enum class int_bytes { - byte1 = sizeof(uint8_t), - byte2 = sizeof(uint16_t), - byte4 = sizeof(uint32_t), - byte8 = sizeof(uint64_t), - byte16 = 16, // Must be directly set because uint128_t can be 16 bytes if - // FMT_USE_INT128 == 1 and 1 byte if FMT_USE_INT128 == 0. - }; - +template struct int_writer { OutputIt out; locale_ref locale; const basic_format_specs& specs; - uint_largest_t abs_value; - int_bytes value_bytes; + UInt abs_value; char prefix[4]; unsigned prefix_size; @@ -1493,11 +1484,9 @@ template struct int_writer { : out(output), locale(loc), specs(s), - abs_value(static_cast(value)), - value_bytes(int_bytes::byte8), + abs_value(static_cast(value)), prefix_size(0) { - value_bytes = static_cast(sizeof(value)); - + static_assert(std::is_same, UInt>::value, ""); if (is_negative(value)) { prefix[0] = '-'; ++prefix_size; @@ -1509,28 +1498,7 @@ template struct int_writer { } void on_dec() { - int num_digits = 0; - - switch (value_bytes) { - case int_bytes::byte1: - case int_bytes::byte2: - case int_bytes::byte4: - num_digits = count_digits(static_cast(abs_value)); - break; - case int_bytes::byte8: - num_digits = count_digits(static_cast(abs_value)); - break; -#if !FMT_USE_INT128 - case int_bytes::byte16: - num_digits = count_digits(static_cast(abs_value)); - break; -#else - case int_bytes::byte16: - num_digits = count_digits(abs_value); - break; -#endif - } - + auto num_digits = count_digits(abs_value); out = write_int( out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) { return format_decimal(it, abs_value, num_digits).end; @@ -1870,7 +1838,8 @@ class arg_formatter_base { detail::reserve(std::declval(), 0))>; template void write_int(T value, const format_specs& spec) { - int_writer w(out_, locale_, value, spec); + using uint_type = uint32_or_64_or_128_t; + int_writer w(out_, locale_, value, spec); handle_int_type_spec(spec.type, w); out_ = w.out; }