From 8bf28e6bb11bcf6d4a2a2944b9f0fabdaaa96ae2 Mon Sep 17 00:00:00 2001 From: Ivan Polyakov Date: Sat, 23 Jan 2021 18:32:41 +0300 Subject: [PATCH] Add support for s format specifier to bool (#2094) (#2109) --- include/fmt/format.h | 31 +++++++++++++++++++++++++++++-- test/format-test.cc | 4 +++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 654540819ee6..822a03eb7cef 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1423,6 +1423,14 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) { } } +template +FMT_CONSTEXPR void handle_bool_type_spec(const basic_format_specs* specs, + Handler&& handler) { + if (!specs) return handler.on_str(); + if (specs->type && specs->type != 's') return handler.on_int(); + handler.on_str(); +} + template FMT_CONSTEXPR float_specs parse_float_type_spec( const basic_format_specs& specs, ErrorHandler&& eh = {}) { @@ -1542,6 +1550,21 @@ class cstring_type_checker : public ErrorHandler { FMT_CONSTEXPR void on_pointer() {} }; +template +class bool_type_checker : private ErrorHandler { + private: + char type_; + + public: + FMT_CONSTEXPR explicit bool_type_checker(char type, ErrorHandler eh) + : ErrorHandler(eh), type_(type) {} + + FMT_CONSTEXPR void on_int() { + handle_int_type_spec(type_, int_type_checker(*this)); + } + FMT_CONSTEXPR void on_str() {} +}; + template FMT_NOINLINE FMT_CONSTEXPR OutputIt fill(OutputIt it, size_t n, const fill_t& fill) { @@ -2344,7 +2367,8 @@ class arg_formatter_base { } FMT_CONSTEXPR iterator operator()(bool value) { - if (specs_ && specs_->type) return (*this)(value ? 1 : 0); + if (specs_ && specs_->type && specs_->type != 's') + return (*this)(value ? 1 : 0); write(value != 0); return out_; } @@ -3515,10 +3539,13 @@ struct formatter(eh)); break; + case detail::type::bool_type: + handle_bool_type_spec( + &specs_, detail::bool_type_checker(specs_.type, eh)); + break; case detail::type::char_type: handle_char_specs( &specs_, detail::char_specs_checker(specs_.type, eh)); diff --git a/test/format-test.cc b/test/format-test.cc index 804ce1b6df15..899a8b4b171a 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1129,6 +1129,9 @@ TEST(BoolTest, FormatBool) { EXPECT_EQ("1", format("{:d}", true)); EXPECT_EQ("true ", format("{:5}", true)); EXPECT_EQ(L"true", format(L"{}", true)); + EXPECT_EQ("true", format("{:s}", true)); + EXPECT_EQ("false", format("{:s}", false)); + EXPECT_EQ("false ", format("{:6s}", false)); } TEST(FormatterTest, FormatShort) { @@ -2435,7 +2438,6 @@ TEST(FormatTest, FormatStringErrors) { EXPECT_ERROR("{:.{}}", "argument not found", double); EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int); EXPECT_ERROR("{:s}", "invalid type specifier", int); - EXPECT_ERROR("{:s}", "invalid type specifier", bool); EXPECT_ERROR("{:s}", "invalid type specifier", char); EXPECT_ERROR("{:+}", "invalid format specifier for char", char); EXPECT_ERROR("{:s}", "invalid type specifier", double);