Minor tweaks to chrono subsecond formatting

This commit is contained in:
Victor Zverovich 2021-12-09 06:55:31 -08:00
parent 0bbc9708f9
commit 91533d3c33

View File

@ -1459,11 +1459,13 @@ inline std::chrono::duration<Rep, std::milli> get_milliseconds(
#endif #endif
} }
// Returns the number of digits according to the c++ 20 spec // Returns the number of fractional digits in the range [0, 18] according to the
// In the range [0, 18], if more than 18 fractional digits are required, // C++20 spec. If more than 18 fractional digits are required then returns 6 for
// then we return 6 for microseconds precision. // microseconds precision.
constexpr int num_digits(long long num, long long den, int n = 0) { constexpr int count_fractional_digits(long long num, long long den, int n = 0) {
return num % den == 0 ? n : (n > 18 ? 6 : num_digits(num * 10, den, n + 1)); return num % den == 0
? n
: (n > 18 ? 6 : count_fractional_digits(num * 10, den, n + 1));
} }
constexpr long long pow10(std::uint32_t n) { constexpr long long pow10(std::uint32_t n) {
@ -1479,13 +1481,13 @@ constexpr std::chrono::duration<Rep, Period> abs(
// when -Wzero-as-null-pointer-constant is enabled. // when -Wzero-as-null-pointer-constant is enabled.
// In clang-12 the bug has been fixed. See // In clang-12 the bug has been fixed. See
// https://bugs.llvm.org/show_bug.cgi?id=46235 and the reproducible example: // https://bugs.llvm.org/show_bug.cgi?id=46235 and the reproducible example:
// https://www.godbolt.org/z/Knbb5joYx // https://www.godbolt.org/z/Knbb5joYx.
return d.count() >= d.zero().count() ? d : -d; return d.count() >= d.zero().count() ? d : -d;
} }
template <class Rep, class Period, template <class Rep, class Period,
FMT_ENABLE_IF(!std::numeric_limits<Rep>::is_signed)> FMT_ENABLE_IF(!std::numeric_limits<Rep>::is_signed)>
static constexpr std::chrono::duration<Rep, Period> abs( constexpr std::chrono::duration<Rep, Period> abs(
std::chrono::duration<Rep, Period> d) { std::chrono::duration<Rep, Period> d) {
return d; return d;
} }
@ -1651,14 +1653,13 @@ struct chrono_formatter {
} }
template <class Duration> void write_fractional_seconds(Duration d) { template <class Duration> void write_fractional_seconds(Duration d) {
constexpr auto fractional_width = constexpr auto num_fractional_digits =
detail::num_digits(Duration::period::num, Duration::period::den); count_fractional_digits(Duration::period::num, Duration::period::den);
using subsecond_precision = std::chrono::duration< using subsecond_precision = std::chrono::duration<
typename std::common_type<typename Duration::rep, typename std::common_type<typename Duration::rep,
std::chrono::seconds::rep>::type, std::chrono::seconds::rep>::type,
std::ratio<1, detail::pow10(fractional_width)>>; std::ratio<1, detail::pow10(num_fractional_digits)>>;
// We could use c++ 17 if constexpr here.
if (std::ratio_less<typename subsecond_precision::period, if (std::ratio_less<typename subsecond_precision::period,
std::chrono::seconds::period>::value) { std::chrono::seconds::period>::value) {
*out++ = '.'; *out++ = '.';
@ -1675,9 +1676,8 @@ struct chrono_formatter {
uint32_or_64_or_128_t<long long> n = uint32_or_64_or_128_t<long long> n =
to_unsigned(to_nonnegative_int(subseconds, max_value<long long>())); to_unsigned(to_nonnegative_int(subseconds, max_value<long long>()));
int num_digits = detail::count_digits(n); int num_digits = detail::count_digits(n);
if (fractional_width > num_digits) { if (num_fractional_digits > num_digits)
out = std::fill_n(out, fractional_width - num_digits, '0'); out = std::fill_n(out, num_fractional_digits - num_digits, '0');
}
out = format_decimal<char_type>(out, n, num_digits).end; out = format_decimal<char_type>(out, n, num_digits).end;
} }
} }