mirror of
https://github.com/fmtlib/fmt.git
synced 2026-11-09 14:50:24 +08:00
Reject sign-aware zero padding in std::exception and error_code formatters
Treat a leading '0' as the zero flag rather than the start of the width so it is rejected (as in the core formatter) instead of being silently consumed. Also trim the exception_align test to the cases this actually introduces.
This commit is contained in:
parent
cde18a38bb
commit
21d4cc15c8
@ -562,7 +562,7 @@ template <> struct formatter<std::error_code> {
|
||||
it = detail::parse_align(it, end, specs_);
|
||||
|
||||
char c = *it;
|
||||
if (it != end && ((c >= '0' && c <= '9') || c == '{'))
|
||||
if (it != end && ((c >= '1' && c <= '9') || c == '{'))
|
||||
it = detail::parse_width(it, end, specs_, width_ref_, ctx);
|
||||
|
||||
if (it != end && *it == '?') {
|
||||
@ -634,7 +634,7 @@ struct formatter<
|
||||
if (it == end) return it;
|
||||
|
||||
char c = *it;
|
||||
if ((c >= '0' && c <= '9') || c == '{')
|
||||
if ((c >= '1' && c <= '9') || c == '{')
|
||||
it = detail::parse_width(it, end, specs_, width_ref_, ctx);
|
||||
if (it != end && *it == 't') {
|
||||
++it;
|
||||
|
||||
@ -466,34 +466,25 @@ TEST(std_test, exception_ptr) {
|
||||
}
|
||||
|
||||
TEST(std_test, exception_align) {
|
||||
// The exception formatter supports standard width, fill and alignment.
|
||||
auto ex = std::runtime_error("boom");
|
||||
EXPECT_EQ(fmt::format("{:>8}", ex), " boom");
|
||||
EXPECT_EQ(fmt::format("{:<8}", ex), "boom ");
|
||||
EXPECT_EQ(fmt::format("{:^8}", ex), " boom ");
|
||||
EXPECT_EQ(fmt::format("{:*>8}", ex), "****boom");
|
||||
|
||||
// Static width, fill and alignment.
|
||||
EXPECT_EQ(fmt::format("{:*^8}", ex), "**boom**");
|
||||
|
||||
// Dynamic width.
|
||||
EXPECT_EQ(fmt::format("{:{}}", ex, 8), "boom ");
|
||||
// A width smaller than the message leaves the message untouched.
|
||||
EXPECT_EQ(fmt::format("{:>2}", ex), "boom");
|
||||
|
||||
// Sign-aware zero padding is not applicable to exceptions.
|
||||
EXPECT_THROW((void)fmt::format(fmt::runtime("{:08}"), ex), fmt::format_error);
|
||||
|
||||
#if FMT_USE_RTTI
|
||||
// Alignment combines with the 't' (type name) presentation type.
|
||||
try {
|
||||
using namespace my_ns1::my_ns2;
|
||||
throw my_exception("oops");
|
||||
} catch (const std::exception& e) {
|
||||
auto base = fmt::format("{:t}", e);
|
||||
auto padded = fmt::format("{:*<40t}", e);
|
||||
EXPECT_EQ(padded.size(), 40u);
|
||||
EXPECT_EQ(padded.substr(0, base.size()), base);
|
||||
EXPECT_EQ(padded.substr(base.size()), std::string(40 - base.size(), '*'));
|
||||
}
|
||||
// Formatting specs followed by the exception-specific 't'.
|
||||
EXPECT_EQ(fmt::format("{:*<40t}", ex),
|
||||
"std::runtime_error: boom****************");
|
||||
#endif // FMT_USE_RTTI
|
||||
|
||||
// exception_ptr honors the same specifiers, for both the empty ("none")
|
||||
// and the non-empty case.
|
||||
std::exception_ptr enull = nullptr;
|
||||
EXPECT_EQ(fmt::format("{:>8}", enull), " none");
|
||||
// exception_ptr takes a distinct path: null formats directly as "none", while
|
||||
// a non-null pointer is rethrown and delegated to the exception formatter.
|
||||
std::exception_ptr ep;
|
||||
try {
|
||||
throw std::runtime_error("bang");
|
||||
@ -501,6 +492,9 @@ TEST(std_test, exception_align) {
|
||||
ep = std::current_exception();
|
||||
}
|
||||
EXPECT_EQ(fmt::format("{:>8}", ep), " bang");
|
||||
|
||||
std::exception_ptr enull;
|
||||
EXPECT_EQ(fmt::format("{:>8}", enull), " none");
|
||||
}
|
||||
#if FMT_USE_RTTI
|
||||
TEST(std_test, type_info) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user