Skip to content

Commit

Permalink
Add support for s format specifier to bool (#2094) (#2109)
Browse files Browse the repository at this point in the history
  • Loading branch information
powercoderlol authored Jan 23, 2021
1 parent 9c418bc commit 8bf28e6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
31 changes: 29 additions & 2 deletions include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -1423,6 +1423,14 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
}
}

template <typename Char, typename Handler>
FMT_CONSTEXPR void handle_bool_type_spec(const basic_format_specs<Char>* specs,
Handler&& handler) {
if (!specs) return handler.on_str();
if (specs->type && specs->type != 's') return handler.on_int();
handler.on_str();
}

template <typename ErrorHandler = error_handler, typename Char>
FMT_CONSTEXPR float_specs parse_float_type_spec(
const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
Expand Down Expand Up @@ -1542,6 +1550,21 @@ class cstring_type_checker : public ErrorHandler {
FMT_CONSTEXPR void on_pointer() {}
};

template <typename ErrorHandler>
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<ErrorHandler>(*this));
}
FMT_CONSTEXPR void on_str() {}
};

template <typename OutputIt, typename Char>
FMT_NOINLINE FMT_CONSTEXPR OutputIt fill(OutputIt it, size_t n,
const fill_t<Char>& fill) {
Expand Down Expand Up @@ -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_;
}
Expand Down Expand Up @@ -3515,10 +3539,13 @@ struct formatter<T, Char,
case detail::type::ulong_long_type:
case detail::type::int128_type:
case detail::type::uint128_type:
case detail::type::bool_type:
handle_int_type_spec(specs_.type,
detail::int_type_checker<decltype(eh)>(eh));
break;
case detail::type::bool_type:
handle_bool_type_spec(
&specs_, detail::bool_type_checker<decltype(eh)>(specs_.type, eh));
break;
case detail::type::char_type:
handle_char_specs(
&specs_, detail::char_specs_checker<decltype(eh)>(specs_.type, eh));
Expand Down
4 changes: 3 additions & 1 deletion test/format-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 8bf28e6

Please sign in to comment.