From eeca22357beff15fcec7b7baf431cd6ea947c4c8 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 30 Jul 2014 07:37:16 -0700 Subject: [PATCH] Handle 'h' length specifier in printf. --- format.cc | 27 +++++++++++++++++++++++++-- test/printf-test.cc | 6 ++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/format.cc b/format.cc index a473f30b..07c619d2 100644 --- a/format.cc +++ b/format.cc @@ -207,6 +207,27 @@ class PrecisionHandler : } }; +// Converts an integer argument to type T. +template +class ArgConverter : public fmt::internal::ArgVisitor, void> { + private: + fmt::internal::Arg &arg_; + + public: + explicit ArgConverter(fmt::internal::Arg &arg) : arg_(arg) {} + + template + void visit_any_int(U value) { + if (std::numeric_limits::is_signed) { + arg_.type = fmt::internal::Arg::INT; + arg_.int_value = static_cast(value); + } else { + arg_.type = fmt::internal::Arg::UINT; + arg_.uint_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. @@ -859,7 +880,7 @@ void fmt::internal::PrintfFormatter::format( } } - const Arg &arg = handle_arg_index(arg_index); + Arg arg = handle_arg_index(arg_index); if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg)) spec.flags_ &= ~HASH_FLAG; if (spec.fill_ == '0') { @@ -872,7 +893,9 @@ void fmt::internal::PrintfFormatter::format( // Parse length. switch (*s) { case 'h': - // TODO: convert to short + ++s; + ArgConverter(arg).visit(arg); + break; case 'l': case 'j': case 'z': diff --git a/test/printf-test.cc b/test/printf-test.cc index 06c035d5..b67339bd 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -273,6 +273,12 @@ TEST(PrintfTest, DynamicPrecision) { } TEST(PrintfTest, Length) { + EXPECT_PRINTF("42", "%hd", 42); + char buffer[BUFFER_SIZE]; + safe_sprintf(buffer, "%hd", SHRT_MAX + 1); + EXPECT_PRINTF(buffer, "%hd", SHRT_MAX + 1); + safe_sprintf(buffer, "%hd", fmt::LongLong(SHRT_MAX) + 1); + EXPECT_PRINTF(buffer, "%hd", fmt::LongLong(SHRT_MAX) + 1); // TODO }