Add support for s format specifier to bool (#2094) (#2109)

This commit is contained in:
Ivan Polyakov 2021-01-23 18:32:41 +03:00 committed by GitHub
parent 9c418bc468
commit 8bf28e6bb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 3 deletions

View File

@ -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 = {}) {
@ -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) {
@ -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<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));

View File

@ -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);