diff --git a/format.cc b/format.cc index 07c619d2..f4c678d6 100644 --- a/format.cc +++ b/format.cc @@ -218,7 +218,7 @@ class ArgConverter : public fmt::internal::ArgVisitor, void> { template void visit_any_int(U value) { - if (std::numeric_limits::is_signed) { + if (std::numeric_limits::is_signed) { arg_.type = fmt::internal::Arg::INT; arg_.int_value = static_cast(value); } else { @@ -892,10 +892,16 @@ void fmt::internal::PrintfFormatter::format( // Parse length. switch (*s) { - case 'h': + case 'h': { ++s; - ArgConverter(arg).visit(arg); + // TODO: handle 'hh' + char type = *s; + if (type == 'd' || type == 'i') + ArgConverter(arg).visit(arg); + else + ArgConverter(arg).visit(arg); break; + } case 'l': case 'j': case 'z': @@ -912,6 +918,8 @@ void fmt::internal::PrintfFormatter::format( if (error_) throw FormatError(error_); spec.type_ = static_cast(*s++); + if (arg.type <= Arg::LAST_INTEGER_TYPE && spec.type_ == 'u') + spec.type_ = 'd'; start = s; diff --git a/test/printf-test.cc b/test/printf-test.cc index b67339bd..a53788e2 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -272,14 +272,38 @@ 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 +#define EXPECT_STD_PRINTF(format, arg) { \ + char buffer[BUFFER_SIZE]; \ + safe_sprintf(buffer, "%hd", arg); \ + EXPECT_PRINTF(buffer, "%hd", arg); \ +} + +template +void TestLength(const char *length_spec) { + EXPECT_STD_PRINTF(format, 42); + T min = std::numeric_limits::min(), max = std::numeric_limits::max(); + const char types[] = {'d', 'i', 'u', 'o', 'x', 'X'}; + for (int i = 0; i < sizeof(types); ++i) { + std::string format = fmt::format("%{}{}", length_spec, types[i]); + EXPECT_STD_PRINTF(format, min); + EXPECT_STD_PRINTF(format, max); + EXPECT_STD_PRINTF(format, fmt::LongLong(min) - 1); + EXPECT_STD_PRINTF(format, fmt::LongLong(max) + 1); + EXPECT_STD_PRINTF(format, std::numeric_limits::min()); + EXPECT_STD_PRINTF(format, std::numeric_limits::max()); + EXPECT_STD_PRINTF(format, std::numeric_limits::min()); + EXPECT_STD_PRINTF(format, std::numeric_limits::max()); + EXPECT_STD_PRINTF(format, std::numeric_limits::min()); + EXPECT_STD_PRINTF(format, std::numeric_limits::max()); + EXPECT_STD_PRINTF(format, std::numeric_limits::min()); + EXPECT_STD_PRINTF(format, std::numeric_limits::max()); + } +} + +TEST(PrintfTest, ShortLength) { + TestLength("h"); + TestLength("h"); + // TODO: more tests } // TODO: test type specifier