From 77e5dd1c6d345a21ac4841f74347d29d69783ccc Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 2 Jan 2025 22:51:25 +0500 Subject: [PATCH 1/2] Improve xchar support for std::bitset formatter Signed-off-by: Vladislav Shchapov --- include/fmt/std.h | 5 +++-- test/xchar-test.cc | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/fmt/std.h b/include/fmt/std.h index b00e402255f5..cae14fb6b033 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -184,7 +184,8 @@ FMT_END_NAMESPACE FMT_BEGIN_NAMESPACE FMT_EXPORT template -struct formatter, Char> : nested_formatter { +struct formatter, Char> + : nested_formatter, Char> { private: // Functor because C++11 doesn't support generic lambdas. struct writer { @@ -204,7 +205,7 @@ struct formatter, Char> : nested_formatter { template auto format(const std::bitset& bs, FormatContext& ctx) const -> decltype(ctx.out()) { - return write_padded(ctx, writer{bs}); + return this->write_padded(ctx, writer{bs}); } }; diff --git a/test/xchar-test.cc b/test/xchar-test.cc index 0f91aa319e84..9b02cd221b4b 100644 --- a/test/xchar-test.cc +++ b/test/xchar-test.cc @@ -491,6 +491,13 @@ TEST(locale_test, sign) { EXPECT_EQ(fmt::format(std::locale(), L"{:L}", -50), L"-50"); } +TEST(std_test_xchar, format_bitset) { + auto bs = std::bitset<6>(42); + EXPECT_EQ(fmt::format(L"{}", bs), L"101010"); + EXPECT_EQ(fmt::format(L"{:0>8}", bs), L"00101010"); + EXPECT_EQ(fmt::format(L"{:-^12}", bs), L"---101010---"); +} + TEST(std_test_xchar, complex) { auto s = fmt::format(L"{}", std::complex(1, 2)); EXPECT_EQ(s, L"(1+2i)"); From 73f57298ce4b6819effddd51bbc313f5bcbb9a95 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 2 Jan 2025 22:54:19 +0500 Subject: [PATCH 2/2] Fix a bug when copying the fill from basic_specs Signed-off-by: Vladislav Shchapov --- include/fmt/format.h | 14 ++++++++++++-- include/fmt/std.h | 4 +--- test/std-test.cc | 3 +++ test/xchar-test.cc | 3 ++- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index d1b83d18673e..2fb85fef0350 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -3654,6 +3654,17 @@ void vformat_to(buffer& buf, basic_string_view fmt, parse_format_string( fmt, format_handler{parse_context(fmt), {out, args, loc}}); } + +template +void basic_specs_copy_fill(basic_specs& dst, const basic_specs& src) { + if (src.fill_size() == 1 && const_check(!std::is_same::value)) { + Char fill = src.fill_unit(); + dst.set_fill(basic_string_view(&fill, 1)); + return; + } + dst.set_fill(basic_string_view(src.fill(), src.fill_size())); +} + } // namespace detail FMT_BEGIN_EXPORT @@ -3960,8 +3971,7 @@ template struct nested_formatter { write(basic_appender(buf)); auto specs = format_specs(); specs.width = width_; - specs.set_fill( - basic_string_view(specs_.fill(), specs_.fill_size())); + detail::basic_specs_copy_fill(specs, specs_); specs.set_align(specs_.align()); return detail::write( ctx.out(), basic_string_view(buf.data(), buf.size()), specs); diff --git a/include/fmt/std.h b/include/fmt/std.h index cae14fb6b033..bc277d646267 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -696,9 +696,7 @@ template struct formatter, Char> { auto outer_specs = format_specs(); outer_specs.width = specs.width; - auto fill = specs.template fill(); - if (fill) - outer_specs.set_fill(basic_string_view(fill, specs.fill_size())); + detail::basic_specs_copy_fill(outer_specs, specs); outer_specs.set_align(specs.align()); specs.width = 0; diff --git a/test/std-test.cc b/test/std-test.cc index ab458ae885db..2c57b3f6e394 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -91,6 +91,9 @@ TEST(std_test, complex) { EXPECT_EQ(fmt::format("{: }", std::complex(1, 2.2)), "( 1+2.2i)"); EXPECT_EQ(fmt::format("{: }", std::complex(1, -2.2)), "( 1-2.2i)"); + EXPECT_EQ(fmt::format("{:8}", std::complex(1, 2)), "(1+2i) "); + EXPECT_EQ(fmt::format("{:-<8}", std::complex(1, 2)), "(1+2i)--"); + EXPECT_EQ(fmt::format("{:>20.2f}", std::complex(1, 2.2)), " (1.00+2.20i)"); EXPECT_EQ(fmt::format("{:<20.2f}", std::complex(1, 2.2)), diff --git a/test/xchar-test.cc b/test/xchar-test.cc index 9b02cd221b4b..fd613e820ad8 100644 --- a/test/xchar-test.cc +++ b/test/xchar-test.cc @@ -79,7 +79,7 @@ TEST(xchar_test, format) { EXPECT_THROW(fmt::format(fmt::runtime(L"{:*\x343E}"), 42), fmt::format_error); EXPECT_EQ(fmt::format(L"{}", true), L"true"); EXPECT_EQ(fmt::format(L"{0}", L'a'), L"a"); - EXPECT_EQ(fmt::format(L"Letter {}", L'\x40e'), L"Letter \x40e"); // Ў + EXPECT_EQ(fmt::format(L"Letter {}", L'\x40e'), L"Letter \x40e"); // Ў if (sizeof(wchar_t) == 4) EXPECT_EQ(fmt::format(fmt::runtime(L"{:𓀨>3}"), 42), L"𓀨42"); EXPECT_EQ(fmt::format(L"{}c{}", L"ab", 1), L"abc1"); @@ -504,6 +504,7 @@ TEST(std_test_xchar, complex) { EXPECT_EQ(fmt::format(L"{:.2f}", std::complex(1, 2)), L"(1.00+2.00i)"); EXPECT_EQ(fmt::format(L"{:8}", std::complex(1, 2)), L"(1+2i) "); + EXPECT_EQ(fmt::format(L"{:-<8}", std::complex(1, 2)), L"(1+2i)--"); } TEST(std_test_xchar, optional) {