mirror of
https://github.com/fmtlib/fmt.git
synced 2026-11-09 14:50:24 +08:00
Rename rep to abs_rep in duration_formatter and simplify the tests
The old name differed from Rep only in case, which made the narrowing fixed in #5003 easy to miss.
This commit is contained in:
parent
3a52eb4f1d
commit
a9e41a6df2
@ -1665,30 +1665,33 @@ template <typename Char, typename Rep, typename Period>
|
|||||||
struct duration_formatter {
|
struct duration_formatter {
|
||||||
using iterator = basic_appender<Char>;
|
using iterator = basic_appender<Char>;
|
||||||
iterator out;
|
iterator out;
|
||||||
// rep is unsigned to avoid overflow.
|
// Integral reps are made unsigned so that negating the minimum value can't
|
||||||
using rep =
|
// overflow, and at least as wide as int to leave headroom for the conversion
|
||||||
|
// to seconds.
|
||||||
|
using abs_rep =
|
||||||
conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
|
conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
|
||||||
unsigned, typename make_unsigned_or_unchanged<Rep>::type>;
|
unsigned, typename make_unsigned_or_unchanged<Rep>::type>;
|
||||||
rep val;
|
abs_rep val;
|
||||||
int precision;
|
int precision;
|
||||||
locale_ref locale;
|
locale_ref locale;
|
||||||
bool localized = false;
|
bool localized = false;
|
||||||
using seconds = std::chrono::duration<rep>;
|
using seconds = std::chrono::duration<abs_rep>;
|
||||||
seconds s;
|
seconds s;
|
||||||
using milliseconds = std::chrono::duration<rep, std::milli>;
|
using milliseconds = std::chrono::duration<abs_rep, std::milli>;
|
||||||
bool negative;
|
bool negative = false;
|
||||||
|
|
||||||
using tm_writer_type = tm_writer<iterator, Char>;
|
using tm_writer_type = tm_writer<iterator, Char>;
|
||||||
|
|
||||||
duration_formatter(iterator o, std::chrono::duration<Rep, Period> d,
|
duration_formatter(iterator o, std::chrono::duration<Rep, Period> d,
|
||||||
locale_ref loc)
|
locale_ref loc)
|
||||||
: out(o), val(static_cast<rep>(d.count())), locale(loc), negative(false) {
|
: out(o), val(static_cast<abs_rep>(d.count())), locale(loc) {
|
||||||
if (d.count() < 0) {
|
if (d.count() < 0) {
|
||||||
val = 0 - val;
|
val = 0 - val;
|
||||||
negative = true;
|
negative = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = detail::duration_cast<seconds>(std::chrono::duration<rep, Period>(val));
|
s = detail::duration_cast<seconds>(
|
||||||
|
std::chrono::duration<abs_rep, Period>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If val is NaN or infinite, writes it to out and returns true.
|
// If val is NaN or infinite, writes it to out and returns true.
|
||||||
@ -1703,16 +1706,16 @@ struct duration_formatter {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto days() const -> rep { return s.count() / 86400; }
|
auto days() const -> abs_rep { return s.count() / 86400; }
|
||||||
auto hour() const -> rep { return mod((s.count() / 3600), 24); }
|
auto hour() const -> abs_rep { return mod(s.count() / 3600, 24); }
|
||||||
|
|
||||||
auto hour12() const -> rep {
|
auto hour12() const -> abs_rep {
|
||||||
auto hour = mod((s.count() / 3600), 12);
|
auto hour = mod(s.count() / 3600, 12);
|
||||||
return hour < 1 ? 12 : hour;
|
return hour < 1 ? 12 : hour;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto minute() const -> rep { return mod((s.count() / 60), 60); }
|
auto minute() const -> abs_rep { return mod(s.count() / 60, 60); }
|
||||||
auto second() const -> rep { return mod(s.count(), 60); }
|
auto second() const -> abs_rep { return mod(s.count(), 60); }
|
||||||
|
|
||||||
auto time() const -> std::tm {
|
auto time() const -> std::tm {
|
||||||
auto time = std::tm();
|
auto time = std::tm();
|
||||||
@ -1728,7 +1731,7 @@ struct duration_formatter {
|
|||||||
negative = false;
|
negative = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(rep value, int width, pad_type pad = pad_type::zero) {
|
void write(abs_rep value, int width, pad_type pad = pad_type::zero) {
|
||||||
write_sign();
|
write_sign();
|
||||||
if (isnan(value)) return write_nan();
|
if (isnan(value)) return write_nan();
|
||||||
uint32_or_64_or_128_t<int> n =
|
uint32_or_64_or_128_t<int> n =
|
||||||
@ -1816,9 +1819,9 @@ struct duration_formatter {
|
|||||||
if (write_if_nonfinite()) return;
|
if (write_if_nonfinite()) return;
|
||||||
|
|
||||||
if (ns == numeric_system::standard) {
|
if (ns == numeric_system::standard) {
|
||||||
if (std::is_floating_point<rep>::value) {
|
if (std::is_floating_point<abs_rep>::value) {
|
||||||
auto buf = memory_buffer();
|
auto buf = memory_buffer();
|
||||||
write_floating_seconds(buf, std::chrono::duration<rep, Period>(val),
|
write_floating_seconds(buf, std::chrono::duration<abs_rep, Period>(val),
|
||||||
precision);
|
precision);
|
||||||
write_sign();
|
write_sign();
|
||||||
if (buf.size() < 2 || buf[1] == '.')
|
if (buf.size() < 2 || buf[1] == '.')
|
||||||
@ -1827,7 +1830,7 @@ struct duration_formatter {
|
|||||||
} else {
|
} else {
|
||||||
write(second(), 2, pad);
|
write(second(), 2, pad);
|
||||||
write_fractional_seconds<Char>(
|
write_fractional_seconds<Char>(
|
||||||
out, std::chrono::duration<rep, Period>(val), precision);
|
out, std::chrono::duration<abs_rep, Period>(val), precision);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -538,6 +538,10 @@ TEST(chrono_test, format_specs) {
|
|||||||
EXPECT_EQ(fmt::format("{:%j}", days(12)), "12");
|
EXPECT_EQ(fmt::format("{:%j}", days(12)), "12");
|
||||||
EXPECT_EQ(fmt::format("{:%j}", days(12345)), "12345");
|
EXPECT_EQ(fmt::format("{:%j}", days(12345)), "12345");
|
||||||
EXPECT_EQ(fmt::format("{:%j}", std::chrono::hours(12345 * 24 + 12)), "12345");
|
EXPECT_EQ(fmt::format("{:%j}", std::chrono::hours(12345 * 24 + 12)), "12345");
|
||||||
|
using signed_days = std::chrono::duration<signed char, std::ratio<86400>>;
|
||||||
|
EXPECT_EQ(fmt::format("{:%j}", signed_days(-128)), "-128");
|
||||||
|
using two_days = std::chrono::duration<unsigned char, std::ratio<172800>>;
|
||||||
|
EXPECT_EQ(fmt::format("{:%j}", two_days(200)), "400");
|
||||||
EXPECT_EQ(fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)),
|
EXPECT_EQ(fmt::format("{:%H:%M:%S}", std::chrono::seconds(12345)),
|
||||||
"03:25:45");
|
"03:25:45");
|
||||||
EXPECT_EQ(fmt::format("{:%R}", std::chrono::seconds(12345)), "03:25");
|
EXPECT_EQ(fmt::format("{:%R}", std::chrono::seconds(12345)), "03:25");
|
||||||
@ -546,16 +550,6 @@ TEST(chrono_test, format_specs) {
|
|||||||
EXPECT_EQ(fmt::format("{:%q}", std::chrono::seconds(12345)), "s");
|
EXPECT_EQ(fmt::format("{:%q}", std::chrono::seconds(12345)), "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(chrono_test, format_days_with_signed_char_rep) {
|
|
||||||
using signed_days = std::chrono::duration<signed char, std::ratio<86400>>;
|
|
||||||
EXPECT_EQ(fmt::format("{:%j}", signed_days(-128)), "-128");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(chrono_test, format_days_with_unsigned_char_rep) {
|
|
||||||
using two_days = std::chrono::duration<unsigned char, std::ratio<172800>>;
|
|
||||||
EXPECT_EQ(fmt::format("{:%j}", two_days(200)), "400");
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(chrono_test, invalid_specs) {
|
TEST(chrono_test, invalid_specs) {
|
||||||
auto sec = std::chrono::seconds(0);
|
auto sec = std::chrono::seconds(0);
|
||||||
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%a}"), sec), fmt::format_error,
|
EXPECT_THROW_MSG((void)fmt::format(runtime("{:%a}"), sec), fmt::format_error,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user