From 8445327c84dd0bfd23646dc2d92fed105b8fae8c Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Thu, 1 Aug 2024 19:30:30 -0700 Subject: [PATCH] Simplify spec handling --- include/fmt/base.h | 1 - include/fmt/format.h | 36 +++++++++++++----------------------- test/base-test.cc | 2 +- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index 4c9525e9..141ffe08 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -2430,7 +2430,6 @@ FMT_CONSTEXPR auto parse_format_specs(const Char* begin, const Char* end, specs.sign = sign::plus; break; case '-': - specs.sign = sign::minus; break; case ' ': specs.sign = sign::space; diff --git a/include/fmt/format.h b/include/fmt/format.h index 2cab8939..b0976f47 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -3165,11 +3165,10 @@ FMT_CONSTEXPR20 auto format_float(Float value, int precision, buffer& buf) -> int { // float is passed as double to reduce the number of instantiations. static_assert(!std::is_same::value, ""); - FMT_ASSERT(value >= 0, "value is negative"); auto converted_value = convert_float(value); const bool fixed = specs.type == presentation_type::fixed; - if (value <= 0) { // <= instead of == to silence a warning. + if (value == 0) { if (precision <= 0 || !fixed) { buf.push_back('0'); return 0; @@ -3462,13 +3461,8 @@ FMT_CONSTEXPR20 auto format_float(Float value, int precision, template FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, locale_ref loc) -> OutputIt { - sign_t sign = specs.sign; - if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit. - sign = sign::minus; - value = -value; - } else if (sign == sign::minus) { - sign = sign::none; - } + // Use signbit because value < 0 is false for NaN. + sign_t sign = detail::signbit(value) ? sign::minus : specs.sign; if (!detail::isfinite(value)) return write_nonfinite(out, detail::isnan(value), specs, sign); @@ -3479,14 +3473,6 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, if (specs.width != 0) --specs.width; } - memory_buffer buffer; - if (specs.type == presentation_type::hexfloat) { - if (sign) buffer.push_back(detail::sign(sign)); - format_hexfloat(convert_float(value), specs, buffer); - return write_bytes(out, {buffer.data(), buffer.size()}, - specs); - } - int precision = specs.precision; if (precision < 0) { if (specs.type != presentation_type::none) { @@ -3499,6 +3485,14 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, } } + memory_buffer buffer; + if (specs.type == presentation_type::hexfloat) { + if (sign) buffer.push_back(detail::sign(sign)); + format_hexfloat(convert_float(value), specs, buffer); + return write_bytes(out, {buffer.data(), buffer.size()}, + specs); + } + if (specs.type == presentation_type::exp) { if (precision == max_value()) report_error("number is too big"); @@ -3534,14 +3528,10 @@ FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { if (is_constant_evaluated()) return write(out, value, format_specs()); if (const_check(!is_supported_floating_point(value))) return out; - auto sign = sign_t::none; - if (detail::signbit(value)) { - sign = sign::minus; - value = -value; - } + auto sign = detail::signbit(value) ? sign::minus : sign_t::none; constexpr auto specs = format_specs(); - using floaty = conditional_t::value, double, T>; + using floaty = conditional_t= sizeof(double), double, float>; using floaty_uint = typename dragonbox::float_info::carrier_uint; floaty_uint mask = exponent_mask(); if ((bit_cast(value) & mask) == mask) diff --git a/test/base-test.cc b/test/base-test.cc index 4afd99da..0c49494d 100644 --- a/test/base-test.cc +++ b/test/base-test.cc @@ -519,7 +519,7 @@ TEST(base_test, constexpr_parse_format_specs) { static_assert(parse_test_specs("<").align == fmt::align::left, ""); static_assert(parse_test_specs("*^").fill.get() == '*', ""); static_assert(parse_test_specs("+").sign == fmt::sign::plus, ""); - static_assert(parse_test_specs("-").sign == fmt::sign::minus, ""); + static_assert(parse_test_specs("-").sign == fmt::sign::none, ""); static_assert(parse_test_specs(" ").sign == fmt::sign::space, ""); static_assert(parse_test_specs("#").alt, ""); static_assert(parse_test_specs("0").align == fmt::align::numeric, "");