diff --git a/include/fmt/format-inl.h b/include/fmt/format-inl.h index f02c257e..11c9e525 100644 --- a/include/fmt/format-inl.h +++ b/include/fmt/format-inl.h @@ -232,30 +232,19 @@ FMT_FUNC void system_error::init( namespace internal { template int char_traits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, T value) { - if (width == 0) { - return precision < 0 ? - FMT_SNPRINTF(buffer, size, format, value) : - FMT_SNPRINTF(buffer, size, format, precision, value); - } + char *buffer, std::size_t size, const char *format, int precision, T value) { return precision < 0 ? - FMT_SNPRINTF(buffer, size, format, width, value) : - FMT_SNPRINTF(buffer, size, format, width, precision, value); + FMT_SNPRINTF(buffer, size, format, value) : + FMT_SNPRINTF(buffer, size, format, precision, value); } template int char_traits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, T value) { - if (width == 0) { - return precision < 0 ? - FMT_SWPRINTF(buffer, size, format, value) : - FMT_SWPRINTF(buffer, size, format, precision, value); - } + wchar_t *buffer, std::size_t size, const wchar_t *format, int precision, + T value) { return precision < 0 ? - FMT_SWPRINTF(buffer, size, format, width, value) : - FMT_SWPRINTF(buffer, size, format, width, precision, value); + FMT_SWPRINTF(buffer, size, format, value) : + FMT_SWPRINTF(buffer, size, format, precision, value); } template diff --git a/include/fmt/format.h b/include/fmt/format.h index 3fc2c6f4..369e8869 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -660,30 +660,30 @@ struct char_traits { // Formats a floating-point number. template FMT_API static int format_float(char *buffer, std::size_t size, - const char *format, unsigned width, int precision, T value); + const char *format, int precision, T value); }; template <> struct char_traits { template FMT_API static int format_float(wchar_t *buffer, std::size_t size, - const wchar_t *format, unsigned width, int precision, T value); + const wchar_t *format, int precision, T value); }; #if FMT_USE_EXTERN_TEMPLATES extern template int char_traits::format_float( - char *buffer, std::size_t size, const char* format, unsigned width, - int precision, double value); + char *buffer, std::size_t size, const char* format, int precision, + double value); extern template int char_traits::format_float( - char *buffer, std::size_t size, const char* format, unsigned width, - int precision, long double value); + char *buffer, std::size_t size, const char* format, int precision, + long double value); extern template int char_traits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t* format, unsigned width, - int precision, double value); + wchar_t *buffer, std::size_t size, const wchar_t* format, int precision, + double value); extern template int char_traits::format_float( - wchar_t *buffer, std::size_t size, const wchar_t* format, unsigned width, - int precision, long double value); + wchar_t *buffer, std::size_t size, const wchar_t* format, int precision, + long double value); #endif template @@ -2657,8 +2657,7 @@ class basic_writer { void write_double(T value, const format_specs &spec); template void write_double_sprintf(T value, const format_specs &spec, - internal::basic_buffer& buffer, - char sign); + internal::basic_buffer& buffer); template struct str_writer { @@ -2887,7 +2886,7 @@ void basic_writer::write_double(T value, const format_specs &spec) { fp_value.normalize(); // Find a cached power of 10 close to 1 / fp_value. int dec_exp = 0; - int min_exp = -60; + const int min_exp = -60; auto dec_pow = internal::get_cached_power( min_exp - (fp_value.e + internal::fp::significand_size), dec_exp); internal::fp product = fp_value * dec_pow; @@ -2898,8 +2897,10 @@ void basic_writer::write_double(T value, const format_specs &spec) { typedef back_insert_range> range; basic_writer w{range(buffer)}; w.write(hi); + unsigned digits = buffer.size(); w.write('.'); - for (int i = 0; i < 18; ++i) { + const unsigned max_digits = 18; + while (digits++ < max_digits) { f *= 10; w.write(static_cast('0' + (f >> -one.e))); f &= one.f - 1; @@ -2909,7 +2910,7 @@ void basic_writer::write_double(T value, const format_specs &spec) { } else { format_specs normalized_spec(spec); normalized_spec.type_ = handler.type; - write_double_sprintf(value, normalized_spec, buffer, sign); + write_double_sprintf(value, normalized_spec, buffer); } unsigned n = buffer.size(); align_spec as = spec; @@ -2934,23 +2935,17 @@ template template void basic_writer::write_double_sprintf( T value, const format_specs &spec, - internal::basic_buffer& buffer, char sign) { - unsigned width = spec.width(); - if (sign) { - buffer.reserve(width > 1u ? width : 1u); - if (width > 0) - --width; - } + internal::basic_buffer& buffer) { + // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail. + FMT_ASSERT(buffer.capacity() != 0, "empty buffer"); // Build format string. enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg char_type format[MAX_FORMAT_SIZE]; char_type *format_ptr = format; *format_ptr++ = '%'; - unsigned width_for_sprintf = width; if (spec.flag(HASH_FLAG)) *format_ptr++ = '#'; - width_for_sprintf = 0; if (spec.precision() >= 0) { *format_ptr++ = '.'; *format_ptr++ = '*'; @@ -2964,18 +2959,9 @@ void basic_writer::write_double_sprintf( char_type *start = FMT_NULL; for (;;) { std::size_t buffer_size = buffer.capacity(); -#if FMT_MSC_VER - // MSVC's vsnprintf_s doesn't work with zero size, so reserve - // space for at least one extra character to make the size non-zero. - // Note that the buffer's capacity may increase by more than 1. - if (buffer_size == 0) { - buffer.reserve(1); - buffer_size = buffer.capacity(); - } -#endif start = &buffer[0]; int result = internal::char_traits::format_float( - start, buffer_size, format, width_for_sprintf, spec.precision(), value); + start, buffer_size, format, spec.precision(), value); if (result >= 0) { unsigned n = internal::to_unsigned(result); if (n < buffer.capacity()) { diff --git a/src/format.cc b/src/format.cc index 9ebce0ca..111c671e 100644 --- a/src/format.cc +++ b/src/format.cc @@ -21,12 +21,12 @@ template void internal::arg_map::init( const basic_format_args &args); template FMT_API int internal::char_traits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, double value); + char *buffer, std::size_t size, const char *format, int precision, + double value); template FMT_API int internal::char_traits::format_float( - char *buffer, std::size_t size, const char *format, - unsigned width, int precision, long double value); + char *buffer, std::size_t size, const char *format, int precision, + long double value); // Explicit instantiations for wchar_t. @@ -39,9 +39,9 @@ template void internal::arg_map::init( template FMT_API int internal::char_traits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, double value); + int precision, double value); template FMT_API int internal::char_traits::format_float( wchar_t *buffer, std::size_t size, const wchar_t *format, - unsigned width, int precision, long double value); + int precision, long double value); FMT_END_NAMESPACE diff --git a/support/compute-powers.py b/support/compute-powers.py index 76edef66..967ce8dd 100755 --- a/support/compute-powers.py +++ b/support/compute-powers.py @@ -48,3 +48,6 @@ for i, fp in enumerate(powers): if i % 11 == 0: print(end='\n ') print(' {:5}'.format(fp.e), end=',') + +print('\n\nMax exponent difference:', + max([x.e - powers[i - 1].e for i, x in enumerate(powers)][1:]))