From c68703c9f4e40cc391ed997566ba60b457f00a48 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Tue, 26 Nov 2019 15:52:56 -0800 Subject: [PATCH] float_spec -> float_specs --- include/fmt/format-inl.h | 30 ++++++------ include/fmt/format.h | 100 ++++++++++++++++++++------------------- src/format.cc | 11 +++-- test/format-impl-test.cc | 2 +- 4 files changed, 74 insertions(+), 69 deletions(-) diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index 1bdbff78..6bee711a 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -1039,11 +1039,11 @@ void fallback_format(Double d, buffer& buf, int& exp10) { // (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf) // if T is a IEEE754 binary32 or binary64 and snprintf otherwise. template -int format_float(T value, int precision, float_spec spec, buffer& buf) { +int format_float(T value, int precision, float_specs specs, buffer& buf) { static_assert(!std::is_same(), ""); FMT_ASSERT(value >= 0, "value is negative"); - const bool fixed = spec.format == float_format::fixed; + const bool fixed = specs.format == float_format::fixed; if (value <= 0) { // <= instead of == to silence a warning. if (precision <= 0 || !fixed) { buf.push_back('0'); @@ -1054,20 +1054,20 @@ int format_float(T value, int precision, float_spec spec, buffer& buf) { return -precision; } - if (!spec.use_grisu) return snprintf_float(value, precision, spec, buf); + if (!specs.use_grisu) return snprintf_float(value, precision, specs, buf); int exp = 0; const int min_exp = -60; // alpha in Grisu. int cached_exp10 = 0; // K in Grisu. if (precision != -1) { - if (precision > 17) return snprintf_float(value, precision, spec, buf); + if (precision > 17) return snprintf_float(value, precision, specs, buf); fp normalized = normalize(fp(value)); const auto cached_pow = get_cached_power( min_exp - (normalized.e + fp::significand_size), cached_exp10); normalized = normalized * cached_pow; fixed_handler handler{buf.data(), 0, precision, -cached_exp10, fixed}; if (grisu_gen_digits(normalized, 1, exp, handler) == digits::error) - return snprintf_float(value, precision, spec, buf); + return snprintf_float(value, precision, specs, buf); int num_digits = handler.size; if (!fixed) { // Remove trailing zeros. @@ -1079,7 +1079,7 @@ int format_float(T value, int precision, float_spec spec, buffer& buf) { buf.resize(to_unsigned(num_digits)); } else { fp fp_value; - auto boundaries = spec.binary32 + auto boundaries = specs.binary32 ? fp_value.assign_float_with_boundaries(value) : fp_value.assign_with_boundaries(value); fp_value = normalize(fp_value); @@ -1111,14 +1111,16 @@ int format_float(T value, int precision, float_spec spec, buffer& buf) { } template -int snprintf_float(T value, int precision, float_spec spec, buffer& buf) { +int snprintf_float(T value, int precision, float_specs specs, + buffer& buf) { // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail. FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer"); static_assert(!std::is_same(), ""); // Subtract 1 to account for the difference in precision since we use %e for // both general and exponent format. - if (spec.format == float_format::general || spec.format == float_format::exp) + if (specs.format == float_format::general || + specs.format == float_format::exp) precision = (precision >= 0 ? precision : 6) - 1; // Build the format string. @@ -1126,15 +1128,15 @@ int snprintf_float(T value, int precision, float_spec spec, buffer& buf) { char format[max_format_size]; char* format_ptr = format; *format_ptr++ = '%'; - if (spec.alt) *format_ptr++ = '#'; + if (specs.alt) *format_ptr++ = '#'; if (precision >= 0) { *format_ptr++ = '.'; *format_ptr++ = '*'; } if (std::is_same()) *format_ptr++ = 'L'; - *format_ptr++ = spec.format != float_format::hex - ? (spec.format == float_format::fixed ? 'f' : 'e') - : (spec.upper ? 'A' : 'a'); + *format_ptr++ = specs.format != float_format::hex + ? (specs.format == float_format::fixed ? 'f' : 'e') + : (specs.upper ? 'A' : 'a'); *format_ptr = '\0'; // Format using snprintf. @@ -1163,7 +1165,7 @@ int snprintf_float(T value, int precision, float_spec spec, buffer& buf) { continue; } auto is_digit = [](char c) { return c >= '0' && c <= '9'; }; - if (spec.format == float_format::fixed) { + if (specs.format == float_format::fixed) { if (precision == 0) { buf.resize(size); return 0; @@ -1178,7 +1180,7 @@ int snprintf_float(T value, int precision, float_spec spec, buffer& buf) { buf.resize(size - 1); return -fraction_size; } - if (spec.format == float_format::hex) { + if (specs.format == float_format::hex) { buf.resize(size + offset); return 0; } diff --git a/include/fmt/format.h b/include/fmt/format.h index ae134bde..041de3f9 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1062,24 +1062,24 @@ using format_specs = basic_format_specs; namespace internal { // A floating-point presentation format. -enum class float_format { +enum class float_format : unsigned char { general, // General: exponent notation or fixed point based on magnitude. exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3. fixed, // Fixed point with the default precision of 6, e.g. 0.0012. hex }; -struct float_spec { +struct float_specs { int precision; - float_format format; - sign_t sign : 3; - bool upper; - bool locale; - bool percent; - bool alt; - bool binary32; - bool use_grisu; - bool trailing_zeros; + float_format format : 8; + sign_t sign : 8; + bool upper : 1; + bool locale : 1; + bool percent : 1; + bool alt : 1; + bool binary32 : 1; + bool use_grisu : 1; + bool trailing_zeros : 1; }; // Writes the exponent exp in the form "[+-]d{2,3}" to buffer. @@ -1110,7 +1110,7 @@ template class float_writer { int num_digits_; int exp_; size_t size_; - float_spec params_; + float_specs params_; Char decimal_point_; template It prettify(It it) const { @@ -1182,21 +1182,21 @@ template class float_writer { } public: - float_writer(const char* digits, int num_digits, int exp, float_spec spec, + float_writer(const char* digits, int num_digits, int exp, float_specs specs, Char decimal_point) : digits_(digits), num_digits_(num_digits), exp_(exp), - params_(spec), + params_(specs), decimal_point_(decimal_point) { int full_exp = num_digits + exp - 1; - int precision = spec.precision > 0 ? spec.precision : 16; + int precision = specs.precision > 0 ? specs.precision : 16; if (params_.format == float_format::general && !(full_exp >= -4 && full_exp < precision)) { params_.format = float_format::exp; } size_ = prettify(counting_iterator()).count(); - size_ += spec.sign ? 1 : 0; + size_ += specs.sign ? 1 : 0; } size_t size() const { return size_; } @@ -1209,11 +1209,12 @@ template class float_writer { }; template -int format_float(T value, int precision, float_spec spec, buffer& buf); +int format_float(T value, int precision, float_specs specs, buffer& buf); // Formats a floating-point number with snprintf. template -int snprintf_float(T value, int precision, float_spec spec, buffer& buf); +int snprintf_float(T value, int precision, float_specs specs, + buffer& buf); template T promote_float(T value) { return value; } inline double promote_float(float value) { return value; } @@ -1245,9 +1246,9 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) { } template -FMT_CONSTEXPR float_spec parse_float_type_spec(char spec, - ErrorHandler&& eh = {}) { - auto result = float_spec(); +FMT_CONSTEXPR float_specs parse_float_type_spec(char spec, + ErrorHandler&& eh = {}) { + auto result = float_specs(); switch (spec) { case 'G': result.upper = true; @@ -1690,62 +1691,63 @@ template class basic_writer { template ::value)> void write(T value, format_specs specs = {}) { - float_spec fspec = parse_float_type_spec(specs.type); - fspec.sign = specs.sign; + float_specs fspecs = parse_float_type_spec(specs.type); + fspecs.sign = specs.sign; if (std::signbit(value)) { // value < 0 is false for NaN so use signbit. - fspec.sign = sign::minus; + fspecs.sign = sign::minus; value = -value; - } else if (fspec.sign == sign::minus) { - fspec.sign = sign::none; + } else if (fspecs.sign == sign::minus) { + fspecs.sign = sign::none; } if (!std::isfinite(value)) { - auto str = std::isinf(value) ? (fspec.upper ? "INF" : "inf") - : (fspec.upper ? "NAN" : "nan"); - return write_padded(specs, inf_or_nan_writer{fspec.sign, str}); + auto str = std::isinf(value) ? (fspecs.upper ? "INF" : "inf") + : (fspecs.upper ? "NAN" : "nan"); + return write_padded(specs, + inf_or_nan_writer{fspecs.sign, str}); } if (specs.align == align::none) { specs.align = align::right; } else if (specs.align == align::numeric) { - if (fspec.sign) { + if (fspecs.sign) { auto&& it = reserve(1); - *it++ = static_cast(data::signs[fspec.sign]); - fspec.sign = sign::none; + *it++ = static_cast(data::signs[fspecs.sign]); + fspecs.sign = sign::none; if (specs.width != 0) --specs.width; } specs.align = align::right; } memory_buffer buffer; - if (fspec.format == float_format::hex) { - if (fspec.sign) buffer.push_back(data::signs[fspec.sign]); - fspec.alt = specs.alt; - snprintf_float(promote_float(value), specs.precision, fspec, buffer); + if (fspecs.format == float_format::hex) { + if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]); + fspecs.alt = specs.alt; + snprintf_float(promote_float(value), specs.precision, fspecs, buffer); write_padded(specs, str_writer{buffer.data(), buffer.size()}); return; } int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6; - if (fspec.format == float_format::exp) ++precision; - fspec.trailing_zeros = + if (fspecs.format == float_format::exp) ++precision; + fspecs.trailing_zeros = (precision != 0 && - (!specs.type || fspec.format == float_format::fixed || - fspec.format == float_format::exp)) || + (!specs.type || fspecs.format == float_format::fixed || + fspecs.format == float_format::exp)) || specs.alt; - if (const_check(std::is_same())) fspec.binary32 = true; - fspec.use_grisu = use_grisu(); - if (const_check(FMT_DEPRECATED_PERCENT) && fspec.percent) value *= 100; - int exp = format_float(promote_float(value), precision, fspec, buffer); - if (const_check(FMT_DEPRECATED_PERCENT) && fspec.percent) { + if (const_check(std::is_same())) fspecs.binary32 = true; + fspecs.use_grisu = use_grisu(); + if (const_check(FMT_DEPRECATED_PERCENT) && fspecs.percent) value *= 100; + int exp = format_float(promote_float(value), precision, fspecs, buffer); + if (const_check(FMT_DEPRECATED_PERCENT) && fspecs.percent) { buffer.push_back('%'); --exp; // Adjust decimal place position. } - fspec.precision = precision; - char_type point = fspec.locale ? decimal_point(locale_) - : static_cast('.'); + fspecs.precision = precision; + char_type point = fspecs.locale ? decimal_point(locale_) + : static_cast('.'); write_padded(specs, float_writer(buffer.data(), static_cast(buffer.size()), - exp, fspec, point)); + exp, fspecs, point)); } void write(char value) { diff --git a/src/format.cc b/src/format.cc index 267f74ee..bf569af4 100644 --- a/src/format.cc +++ b/src/format.cc @@ -11,7 +11,7 @@ FMT_BEGIN_NAMESPACE template struct FMT_API internal::basic_data; // Workaround a bug in MSVC2013 that prevents instantiation of format_float. -int (*instantiate_format_float)(double, int, internal::float_spec, +int (*instantiate_format_float)(double, int, internal::float_specs, internal::buffer&) = internal::format_float; @@ -37,15 +37,16 @@ template FMT_API std::string internal::vformat( template FMT_API format_context::iterator internal::vformat_to( internal::buffer&, string_view, basic_format_args); -template FMT_API int internal::snprintf_float(double, int, internal::float_spec, +template FMT_API int internal::snprintf_float(double, int, + internal::float_specs, internal::buffer&); template FMT_API int internal::snprintf_float(long double, int, - internal::float_spec, + internal::float_specs, internal::buffer&); -template FMT_API int internal::format_float(double, int, internal::float_spec, +template FMT_API int internal::format_float(double, int, internal::float_specs, internal::buffer&); template FMT_API int internal::format_float(long double, int, - internal::float_spec, + internal::float_specs, internal::buffer&); // Explicit instantiations for wchar_t. diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index d42afe67..cdba7699 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -318,7 +318,7 @@ TEST(FPTest, FixedHandler) { TEST(FPTest, GrisuFormatCompilesWithNonIEEEDouble) { fmt::memory_buffer buf; - format_float(0.42, -1, fmt::internal::float_spec(), buf); + format_float(0.42, -1, fmt::internal::float_specs(), buf); } template struct value_extractor {