Fix handling of char

This commit is contained in:
Victor Zverovich 2022-12-30 08:59:12 -08:00
parent 8fe4d97d5e
commit 32190859ec
4 changed files with 11 additions and 14 deletions

View File

@ -109,8 +109,8 @@ Note that unless a minimum field width is defined, the field width will always
be the same size as the data to fill it, so that the alignment option has no
meaning in this case.
The *sign* option is only valid for number types, and can be one of the
following:
The *sign* option is only valid for floating point and signed integer types,
and can be one of the following:
+---------+------------------------------------------------------------+
| Option | Meaning |

View File

@ -2485,8 +2485,7 @@ FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(
if (specs.sign != sign::none) {
require_numeric_argument(arg_type);
if (is_integral_type(arg_type) && arg_type != type::int_type &&
arg_type != type::long_long_type && arg_type != type::int128_type &&
arg_type != type::char_type) {
arg_type != type::long_long_type && arg_type != type::int128_type) {
throw_format_error("format specifier requires signed argument");
}
}

View File

@ -1898,9 +1898,12 @@ template <typename Char, typename OutputIt>
FMT_CONSTEXPR auto write(OutputIt out, Char value,
const format_specs<Char>& specs, locale_ref loc = {})
-> OutputIt {
// char is formatted as unsigned char for consistency across platforms.
using unsigned_type =
conditional_t<std::is_same<Char, char>::value, unsigned char, unsigned>;
return check_char_specs(specs)
? write_char(out, value, specs)
: write(out, static_cast<int>(value), specs, loc);
: write(out, static_cast<unsigned_type>(value), specs, loc);
}
// Data for write_int that doesn't depend on output iterator type. It is used to

View File

@ -666,10 +666,8 @@ TEST(format_test, plus_sign) {
"format specifier requires signed argument");
EXPECT_EQ("+42", fmt::format("{0:+}", 42.0));
EXPECT_EQ("+42", fmt::format("{0:+}", 42.0l));
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+"), 'c'), format_error,
"missing '}' in format string");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), 'c'), format_error,
"invalid format specifier for char");
"format specifier requires signed argument");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:+}"), "abc"), format_error,
"format specifier requires numeric argument");
EXPECT_THROW_MSG(
@ -691,10 +689,8 @@ TEST(format_test, minus_sign) {
"format specifier requires signed argument");
EXPECT_EQ("42", fmt::format("{0:-}", 42.0));
EXPECT_EQ("42", fmt::format("{0:-}", 42.0l));
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-"), 'c'), format_error,
"missing '}' in format string");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), 'c'), format_error,
"invalid format specifier for char");
"format specifier requires signed argument");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0:-}"), "abc"), format_error,
"format specifier requires numeric argument");
EXPECT_THROW_MSG(
@ -716,10 +712,8 @@ TEST(format_test, space_sign) {
"format specifier requires signed argument");
EXPECT_EQ(" 42", fmt::format("{0: }", 42.0));
EXPECT_EQ(" 42", fmt::format("{0: }", 42.0l));
EXPECT_THROW_MSG((void)fmt::format(runtime("{0: "), 'c'), format_error,
"missing '}' in format string");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), 'c'), format_error,
"invalid format specifier for char");
"format specifier requires signed argument");
EXPECT_THROW_MSG((void)fmt::format(runtime("{0: }"), "abc"), format_error,
"format specifier requires numeric argument");
EXPECT_THROW_MSG(
@ -1526,6 +1520,7 @@ TEST(format_test, format_char) {
EXPECT_EQ("\n", fmt::format("{}", '\n'));
EXPECT_EQ("'\\n'", fmt::format("{:?}", '\n'));
EXPECT_EQ("ff", fmt::format("{:x}", '\xff'));
}
TEST(format_test, format_volatile_char) {