diff --git a/doc/syntax.rst b/doc/syntax.rst index b6db4c0b..6ec33d93 100644 --- a/doc/syntax.rst +++ b/doc/syntax.rst @@ -220,6 +220,9 @@ The available integer presentation types are: +---------+----------------------------------------------------------+ Integer presentation types can also be used with character and Boolean values. +Boolean values are formatted using textual representation, either ``true`` or +``false``, if the presentation type is not specified. + The available presentation types for floating-point values are: +---------+----------------------------------------------------------+ diff --git a/format.cc b/format.cc index a6a85651..d46ea4cc 100644 --- a/format.cc +++ b/format.cc @@ -653,6 +653,16 @@ class fmt::internal::ArgFormatter : template void visit_any_double(T value) { writer_.write_double(value, spec_); } + void visit_bool(bool value) { + if (spec_.type_) { + writer_.write_int(value, spec_); + return; + } + const char *str_value = value ? "true" : "false"; + Arg::StringValue str = { str_value, strlen(str_value) }; + writer_.write_str(str, spec_); + } + void visit_char(int value) { if (spec_.type_ && spec_.type_ != 'c') { spec_.flags_ |= CHAR_FLAG; diff --git a/format.h b/format.h index 0515b516..411768ae 100644 --- a/format.h +++ b/format.h @@ -760,7 +760,7 @@ struct Value { enum Type { NONE, NAMED_ARG, // Integer types should go first, - INT, UINT, LONG_LONG, ULONG_LONG, CHAR, LAST_INTEGER_TYPE = CHAR, + INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR, // followed by floating-point types. DOUBLE, LONG_DOUBLE, LAST_NUMERIC_TYPE = LONG_DOUBLE, CSTRING, STRING, WSTRING, POINTER, CUSTOM @@ -886,7 +886,7 @@ class MakeValue : public Arg { MakeValue(Type value) { field = value; } \ static uint64_t type(Type) { return Arg::TYPE; } - FMT_MAKE_VALUE(bool, int_value, INT) + FMT_MAKE_VALUE(bool, int_value, BOOL) FMT_MAKE_VALUE(short, int_value, INT) FMT_MAKE_VALUE(unsigned short, uint_value, UINT) FMT_MAKE_VALUE(int, int_value, INT) @@ -1036,6 +1036,9 @@ class ArgVisitor { Result visit_ulong_long(ULongLong value) { return FMT_DISPATCH(visit_any_int(value)); } + Result visit_bool(bool value) { + return FMT_DISPATCH(visit_any_int(value)); + } Result visit_char(int value) { return FMT_DISPATCH(visit_any_int(value)); } @@ -1081,12 +1084,14 @@ class ArgVisitor { return FMT_DISPATCH(visit_long_long(arg.long_long_value)); case Arg::ULONG_LONG: return FMT_DISPATCH(visit_ulong_long(arg.ulong_long_value)); + case Arg::BOOL: + return FMT_DISPATCH(visit_bool(arg.int_value)); + case Arg::CHAR: + return FMT_DISPATCH(visit_char(arg.int_value)); case Arg::DOUBLE: return FMT_DISPATCH(visit_double(arg.double_value)); case Arg::LONG_DOUBLE: return FMT_DISPATCH(visit_long_double(arg.long_double_value)); - case Arg::CHAR: - return FMT_DISPATCH(visit_char(arg.int_value)); case Arg::CSTRING: { Arg::StringValue str = arg.string; str.size = 0; diff --git a/test/format-test.cc b/test/format-test.cc index c7c1f596..9bee0200 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1147,8 +1147,12 @@ void check_unknown_types( } } -TEST(FormatterTest, FormatBool) { - EXPECT_EQ(L"1", format(L"{}", true)); +TEST(BoolTest, FormatBool) { + EXPECT_EQ("true", format("{}", true)); + EXPECT_EQ("false", format("{}", false)); + EXPECT_EQ("1", format("{:d}", true)); + EXPECT_EQ("true ", format("{:5}", true)); + EXPECT_EQ(L"true", format(L"{}", true)); } TEST(FormatterTest, FormatShort) { diff --git a/test/util-test.cc b/test/util-test.cc index 895e1641..3723a0b1 100644 --- a/test/util-test.cc +++ b/test/util-test.cc @@ -413,9 +413,10 @@ ARG_INFO(INT, int, int_value); ARG_INFO(UINT, unsigned, uint_value); ARG_INFO(LONG_LONG, fmt::LongLong, long_long_value); ARG_INFO(ULONG_LONG, fmt::ULongLong, ulong_long_value); +ARG_INFO(BOOL, int, int_value); +ARG_INFO(CHAR, int, int_value); ARG_INFO(DOUBLE, double, double_value); ARG_INFO(LONG_DOUBLE, long double, long_double_value); -ARG_INFO(CHAR, int, int_value); ARG_INFO(CSTRING, const char *, string.value); ARG_INFO(STRING, const char *, string.value); ARG_INFO(WSTRING, const wchar_t *, wstring.value); @@ -463,8 +464,8 @@ TEST(ArgTest, ArgInfo) { TEST(ArgTest, MakeArg) { // Test bool. - EXPECT_ARG_(char, INT, bool, int, true); - EXPECT_ARG_(wchar_t, INT, bool, int, true); + EXPECT_ARG_(char, BOOL, bool, int, true); + EXPECT_ARG_(wchar_t, BOOL, bool, int, true); // Test char. EXPECT_ARG(CHAR, signed char, 'a');