Improve handling of char in printf.

This commit is contained in:
Victor Zverovich 2014-08-19 08:14:21 -07:00
parent f2be7851cc
commit c4a4a05d12
2 changed files with 35 additions and 4 deletions

View File

@ -270,6 +270,21 @@ class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
} }
}; };
// Converts an integer argument to char.
class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
private:
fmt::internal::Arg &arg_;
public:
explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
template <typename T>
void visit_any_int(T value) {
arg_.type = Arg::CHAR;
arg_.int_value = static_cast<char>(value);
}
};
// This function template is used to prevent compile errors when handling // This function template is used to prevent compile errors when handling
// incompatible string arguments, e.g. handling a wide string in a narrow // incompatible string arguments, e.g. handling a wide string in a narrow
// string formatter. // string formatter.
@ -954,7 +969,8 @@ void fmt::internal::PrintfFormatter<Char>::format(
ArgConverter<ptrdiff_t>(arg, *s).visit(arg); ArgConverter<ptrdiff_t>(arg, *s).visit(arg);
break; break;
case 'L': case 'L':
// TODO: handle length // printf produces garbage when 'L' is omitted for long double, no
// need to do the same.
break; break;
default: default:
--s; --s;
@ -966,9 +982,17 @@ void fmt::internal::PrintfFormatter<Char>::format(
if (error_) if (error_)
throw FormatError(error_); throw FormatError(error_);
spec.type_ = static_cast<char>(*s++); spec.type_ = static_cast<char>(*s++);
if (arg.type <= Arg::LAST_INTEGER_TYPE && if (arg.type <= Arg::LAST_INTEGER_TYPE) {
(spec.type_ == 'i' || spec.type_ == 'u')) { // Normalize type.
switch (spec.type_) {
case 'i': case 'u':
spec.type_ = 'd'; spec.type_ = 'd';
break;
case 'c':
// TODO: handle wchar_t
CharConverter(arg).visit(arg);
break;
}
} }
start = s; start = s;

View File

@ -368,7 +368,14 @@ TEST(PrintfTest, Length) {
long double max = std::numeric_limits<long double>::max(); long double max = std::numeric_limits<long double>::max();
EXPECT_PRINTF(fmt::format("{}", max), "%g", max); EXPECT_PRINTF(fmt::format("{}", max), "%g", max);
EXPECT_PRINTF(fmt::format("{}", max), "%Lg", max); EXPECT_PRINTF(fmt::format("{}", max), "%Lg", max);
// TODO: test char, string }
TEST(PrintfTest, Char) {
EXPECT_PRINTF("x", "%c", 'x');
int max = std::numeric_limits<int>::max();
EXPECT_PRINTF(fmt::format("{}", static_cast<char>(max)), "%c", max);
// TODO: test wchar_t
} }
// TODO: test type specifier // TODO: test type specifier
// TODO: test char, string