Skip to content

Commit 4c59dca

Browse files
committed
Add support for s format specifier to bool (#2094)
1 parent 456efa4 commit 4c59dca

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

include/fmt/format.h

+29-2
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,14 @@ FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
14231423
}
14241424
}
14251425

1426+
template <typename Char, typename Handler>
1427+
FMT_CONSTEXPR void handle_bool_type_spec(const basic_format_specs<Char>* specs,
1428+
Handler&& handler) {
1429+
if (!specs) return handler.on_str();
1430+
if (specs->type && specs->type != 's') return handler.on_int();
1431+
handler.on_str();
1432+
}
1433+
14261434
template <typename ErrorHandler = error_handler, typename Char>
14271435
FMT_CONSTEXPR float_specs parse_float_type_spec(
14281436
const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
@@ -1542,6 +1550,21 @@ class cstring_type_checker : public ErrorHandler {
15421550
FMT_CONSTEXPR void on_pointer() {}
15431551
};
15441552

1553+
template <typename ErrorHandler>
1554+
class bool_type_checker : private ErrorHandler {
1555+
private:
1556+
char type_;
1557+
1558+
public:
1559+
FMT_CONSTEXPR explicit bool_type_checker(char type, ErrorHandler eh)
1560+
: ErrorHandler(eh), type_(type) {}
1561+
1562+
FMT_CONSTEXPR void on_int() {
1563+
handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));
1564+
}
1565+
FMT_CONSTEXPR void on_str() {}
1566+
};
1567+
15451568
template <typename OutputIt, typename Char>
15461569
FMT_NOINLINE FMT_CONSTEXPR OutputIt fill(OutputIt it, size_t n,
15471570
const fill_t<Char>& fill) {
@@ -2344,7 +2367,8 @@ class arg_formatter_base {
23442367
}
23452368

23462369
FMT_CONSTEXPR iterator operator()(bool value) {
2347-
if (specs_ && specs_->type) return (*this)(value ? 1 : 0);
2370+
if (specs_ && specs_->type && specs_->type != 's')
2371+
return (*this)(value ? 1 : 0);
23482372
write(value != 0);
23492373
return out_;
23502374
}
@@ -3515,10 +3539,13 @@ struct formatter<T, Char,
35153539
case detail::type::ulong_long_type:
35163540
case detail::type::int128_type:
35173541
case detail::type::uint128_type:
3518-
case detail::type::bool_type:
35193542
handle_int_type_spec(specs_.type,
35203543
detail::int_type_checker<decltype(eh)>(eh));
35213544
break;
3545+
case detail::type::bool_type:
3546+
handle_bool_type_spec(
3547+
&specs_, detail::bool_type_checker<decltype(eh)>(specs_.type, eh));
3548+
break;
35223549
case detail::type::char_type:
35233550
handle_char_specs(
35243551
&specs_, detail::char_specs_checker<decltype(eh)>(specs_.type, eh));

test/format-test.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -1129,6 +1129,9 @@ TEST(BoolTest, FormatBool) {
11291129
EXPECT_EQ("1", format("{:d}", true));
11301130
EXPECT_EQ("true ", format("{:5}", true));
11311131
EXPECT_EQ(L"true", format(L"{}", true));
1132+
EXPECT_EQ("true", format("{:s}", true));
1133+
EXPECT_EQ("false", format("{:s}", false));
1134+
EXPECT_EQ("false ", format("{:6s}", false));
11321135
}
11331136

11341137
TEST(FormatterTest, FormatShort) {
@@ -2435,7 +2438,6 @@ TEST(FormatTest, FormatStringErrors) {
24352438
EXPECT_ERROR("{:.{}}", "argument not found", double);
24362439
EXPECT_ERROR("{:.2}", "precision not allowed for this argument type", int);
24372440
EXPECT_ERROR("{:s}", "invalid type specifier", int);
2438-
EXPECT_ERROR("{:s}", "invalid type specifier", bool);
24392441
EXPECT_ERROR("{:s}", "invalid type specifier", char);
24402442
EXPECT_ERROR("{:+}", "invalid format specifier for char", char);
24412443
EXPECT_ERROR("{:s}", "invalid type specifier", double);

0 commit comments

Comments
 (0)