From 09fab30bcbf3d8aa074096839061d614037dc921 Mon Sep 17 00:00:00 2001 From: aSumo <1xtelescope@gmail.com> Date: Thu, 3 Sep 2026 21:01:13 +0900 Subject: [PATCH] Make Serial.print(foo, HEX) ALWAYS print 2 chars per byte --- api/Print.cpp | 22 +++++++++++++++++++--- test/src/Print/test_print.cpp | 12 ++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/api/Print.cpp b/api/Print.cpp index 4a6e942a..5c6cc845 100644 --- a/api/Print.cpp +++ b/api/Print.cpp @@ -242,11 +242,16 @@ size_t Print::printNumber(unsigned long n, uint8_t base) { char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; - *str = '\0'; + size_t leadingZero = 0; // prevent crash if called with base == 1 if (base < 2) base = 10; + // insert leading zero for hex values less than 0x10 + else if (base == 16 && n < 16) { + write('0'); + leadingZero = 1; + } do { char c = n % base; @@ -255,7 +260,7 @@ size_t Print::printNumber(unsigned long n, uint8_t base) *--str = c < 10 ? c + '0' : c + 'A' - 10; } while(n); - return write(str); + return write(str) + leadingZero; } // REFERENCE IMPLEMENTATION FOR ULL @@ -287,15 +292,26 @@ size_t Print::printULLNumber(unsigned long long n64, uint8_t base) char buf[64]; uint8_t i = 0; uint8_t innerLoops = 0; + size_t leadingZero = 0; // Special case workaround https://github.com/arduino/ArduinoCore-API/issues/178 if (n64 == 0) { + if (base == 16) { + write('0'); + write('0'); + return 2; + } write('0'); return 1; } // prevent crash if called with base == 1 if (base < 2) base = 10; + // insert leading zero for hex values less than 0x10 + else if (base == 16 && n64 < 16) { + write('0'); + leadingZero = 1; + } // process chunks that fit in "16 bit math". uint16_t top = 0xFFFF / base; @@ -336,7 +352,7 @@ size_t Print::printULLNumber(unsigned long long n64, uint8_t base) '0' + buf[i - 1] : 'A' + buf[i - 1] - 10)); - return bytes; + return bytes + leadingZero; } size_t Print::printFloat(double number, int digits) diff --git a/test/src/Print/test_print.cpp b/test/src/Print/test_print.cpp index 1a41c462..b92f530e 100644 --- a/test/src/Print/test_print.cpp +++ b/test/src/Print/test_print.cpp @@ -118,18 +118,18 @@ TEST_CASE ("Print::print(unsigned long long, int = DEC|HEX|OCT|BIN)", "[Print-pr unsigned long long const val = 0; WHEN("DEC") { mock.print(val, DEC); REQUIRE(mock._str == "0"); } - WHEN("HEX") { mock.print(val, HEX); REQUIRE(mock._str == "0"); } + WHEN("HEX") { mock.print(val, HEX); REQUIRE(mock._str == "00"); } WHEN("OCT") { mock.print(val, OCT); REQUIRE(mock._str == "0"); } WHEN("BIN") { mock.print(val, BIN); REQUIRE(mock._str == "0"); } } GIVEN("a non-zero value ...") { - unsigned long long const val = 17; + unsigned long long const val = 15; - WHEN("DEC") { mock.print(val, DEC); REQUIRE(mock._str == "17"); } - WHEN("HEX") { mock.print(val, HEX); REQUIRE(mock._str == "11"); } - WHEN("OCT") { mock.print(val, OCT); REQUIRE(mock._str == "21"); } - WHEN("BIN") { mock.print(val, BIN); REQUIRE(mock._str == "10001"); } + WHEN("DEC") { mock.print(val, DEC); REQUIRE(mock._str == "15"); } + WHEN("HEX") { mock.print(val, HEX); REQUIRE(mock._str == "0F"); } + WHEN("OCT") { mock.print(val, OCT); REQUIRE(mock._str == "17"); } + WHEN("BIN") { mock.print(val, BIN); REQUIRE(mock._str == "1111"); } } }