From e178f4ec7ca92a46f1c1812b5306b13d7d0a8672 Mon Sep 17 00:00:00 2001 From: Eyal Rozenberg Date: Sat, 31 Jul 2021 22:33:18 +0300 Subject: [PATCH] Fixes #114; regards #109, #99, #110. * Added a couple of test cases for exposing the behavior of the `#` modifier (alternative mode) together with `ll` (long long modifier), and specifically exposing the example format string mentioned in bug #114. * Our fix for #109 was too eager to keep `FLAG_HASH` - it dropped it only when a precision wasn't specified. We're now going part of the way back - dropping `FLAG_HASH` even when precision wasn't specific - except for octal. * The `long long` version of ntoa now behaves just like the `long` version. --- printf.c | 33 +++++++++++++++++++++++---------- test/test_suite.cpp | 30 +++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/printf.c b/printf.c index c69851cf..143ee2ca 100644 --- a/printf.c +++ b/printf.c @@ -305,11 +305,16 @@ static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxl if (!value) { if ( !(flags & FLAGS_PRECISION) ) { buf[len++] = '0'; - flags &= ~FLAGS_HASH; - // We drop this flag this since either the alternative and regular modes of the specifier - // don't differ on 0 values, or (in the case of octal) we've already provided the special - // handling for this mode. - } + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values, or (in the case of octal) we've already provided the special + // handling for this mode. + } + else if (base != 8U) { + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values + } } else { do { @@ -330,13 +335,21 @@ static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t char buf[PRINTF_NTOA_BUFFER_SIZE]; size_t len = 0U; - // no hash for 0 values if (!value) { - flags &= ~FLAGS_HASH; + if ( !(flags & FLAGS_PRECISION) ) { + buf[len++] = '0'; + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values, or (in the case of octal) we've already provided the special + // handling for this mode. + } + else if (base == 16U) { + flags &= ~FLAGS_HASH; + // We drop this flag this since either the alternative and regular modes of the specifier + // don't differ on 0 values + } } - - // write if precision != 0 and value is != 0 - if (!(flags & FLAGS_PRECISION) || value) { + else { do { const char digit = (char)(value % base); buf[len++] = (char)(digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10); diff --git a/test/test_suite.cpp b/test/test_suite.cpp index 07bd10b3..85848775 100644 --- a/test/test_suite.cpp +++ b/test/test_suite.cpp @@ -379,7 +379,7 @@ TEST_CASE("# flag", "[]" ) { PRINTING_CHECK("0001", ==, test::sprintf_, buffer, "%#.4o", 1 ); PRINTING_CHECK("0x1001", ==, test::sprintf_, buffer, "%#04x", 0x1001 ); PRINTING_CHECK("01001", ==, test::sprintf_, buffer, "%#04o", 01001 ); - PRINTING_CHECK("", ==, test::sprintf_, buffer, "%#.0llx", (long long) 0); + PRINTING_CHECK("", ==, test::sprintf_, buffer, "%#.0x", 0 ); PRINTING_CHECK("0x0000614e", ==, test::sprintf_, buffer, "%#.8x", 0x614e ); } @@ -390,6 +390,34 @@ TEST_CASE("# flag - non-standard format", "[]" ) { } #endif +TEST_CASE("# flag with long-long", "[]" ) { + char buffer[100]; + PRINTING_CHECK("0", ==, test::sprintf_, buffer, "%#llo", (long long) 0 ); + PRINTING_CHECK("0", ==, test::sprintf_, buffer, "%#0llo", (long long) 0 ); + PRINTING_CHECK("0", ==, test::sprintf_, buffer, "%#.0llo", (long long) 0 ); + PRINTING_CHECK("0", ==, test::sprintf_, buffer, "%#.1llo", (long long) 0 ); + PRINTING_CHECK(" 0", ==, test::sprintf_, buffer, "%#4llo", (long long) 0 ); + PRINTING_CHECK("0000", ==, test::sprintf_, buffer, "%#.4llo", (long long) 0 ); + PRINTING_CHECK("01", ==, test::sprintf_, buffer, "%#llo", (long long) 1 ); + PRINTING_CHECK("01", ==, test::sprintf_, buffer, "%#0llo", (long long) 1 ); + PRINTING_CHECK("01", ==, test::sprintf_, buffer, "%#.0llo", (long long) 1 ); + PRINTING_CHECK("01", ==, test::sprintf_, buffer, "%#.1llo", (long long) 1 ); + PRINTING_CHECK(" 01", ==, test::sprintf_, buffer, "%#4llo", (long long) 1 ); + PRINTING_CHECK("0001", ==, test::sprintf_, buffer, "%#.4llo", (long long) 1 ); + PRINTING_CHECK("0x1001", ==, test::sprintf_, buffer, "%#04llx", (long long) 0x1001 ); + PRINTING_CHECK("01001", ==, test::sprintf_, buffer, "%#04llo", (long long) 01001 ); + PRINTING_CHECK("", ==, test::sprintf_, buffer, "%#.0llx", (long long) 0 ); + PRINTING_CHECK("0x0000614e", ==, test::sprintf_, buffer, "%#.8llx", (long long) 0x614e ); +} + +#ifdef TEST_WITH_NON_STANDARD_FORMAT_STRINGS +TEST_CASE("# flag with long-long - non-standard format", "[]" ) { + char buffer[100]; + PRINTING_CHECK("0b110", ==, test::sprintf_, buffer, "%#llb", (long long) 6); +} +#endif + + TEST_CASE("specifier", "[]" ) { char buffer[100]; PRINTING_CHECK("Hello testing", ==, test::sprintf_, buffer, "Hello testing");