From c4a4a05d120a951f7a2b4b4ed4aae98d69375b78 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Tue, 19 Aug 2014 08:14:21 -0700 Subject: [PATCH] Improve handling of char in printf. --- format.cc | 30 +++++++++++++++++++++++++++--- test/printf-test.cc | 9 ++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/format.cc b/format.cc index 6a78b941..2eda7cfe 100644 --- a/format.cc +++ b/format.cc @@ -270,6 +270,21 @@ class ArgConverter : public fmt::internal::ArgVisitor, void> { } }; +// Converts an integer argument to char. +class CharConverter : public fmt::internal::ArgVisitor { + private: + fmt::internal::Arg &arg_; + + public: + explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {} + + template + void visit_any_int(T value) { + arg_.type = Arg::CHAR; + arg_.int_value = static_cast(value); + } +}; + // This function template is used to prevent compile errors when handling // incompatible string arguments, e.g. handling a wide string in a narrow // string formatter. @@ -954,7 +969,8 @@ void fmt::internal::PrintfFormatter::format( ArgConverter(arg, *s).visit(arg); break; case 'L': - // TODO: handle length + // printf produces garbage when 'L' is omitted for long double, no + // need to do the same. break; default: --s; @@ -966,9 +982,17 @@ void fmt::internal::PrintfFormatter::format( if (error_) throw FormatError(error_); spec.type_ = static_cast(*s++); - if (arg.type <= Arg::LAST_INTEGER_TYPE && - (spec.type_ == 'i' || spec.type_ == 'u')) { + if (arg.type <= Arg::LAST_INTEGER_TYPE) { + // Normalize type. + switch (spec.type_) { + case 'i': case 'u': spec.type_ = 'd'; + break; + case 'c': + // TODO: handle wchar_t + CharConverter(arg).visit(arg); + break; + } } start = s; diff --git a/test/printf-test.cc b/test/printf-test.cc index 8e840857..a6fc16d3 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -368,7 +368,14 @@ TEST(PrintfTest, Length) { long double max = std::numeric_limits::max(); EXPECT_PRINTF(fmt::format("{}", max), "%g", 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::max(); + EXPECT_PRINTF(fmt::format("{}", static_cast(max)), "%c", max); + // TODO: test wchar_t } // TODO: test type specifier +// TODO: test char, string