From af53772e7b5f96bc3e791582a04971bb9e61c361 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Tue, 28 Jan 2020 16:34:54 +0100 Subject: [PATCH 1/5] Extend Print class for 64bit integers. --- cores/esp8266/Print.cpp | 74 ++++++++++++++++++++++++++++++++--------- cores/esp8266/Print.h | 7 ++++ 2 files changed, 65 insertions(+), 16 deletions(-) diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index b0e2e31a1..37259109e 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -146,25 +146,35 @@ size_t Print::print(unsigned int n, int base) { } size_t Print::print(long n, int base) { - if(base == 0) { - return write(n); - } else if(base == 10) { - if(n < 0) { - int t = print('-'); - n = -n; - return printNumber(n, 10) + t; - } - return printNumber(n, 10); - } else { - return printNumber(n, base); + int t = 0; + if (base == 10 && n < 0) { + t = print('-'); + n = -n; } + return printNumber(static_cast(n), base) + t; } size_t Print::print(unsigned long n, int base) { - if(base == 0) + if (base == 0) { return write(n); - else - return printNumber(n, base); + } + return printNumber(n, base); +} + +size_t Print::print(long long n, int base) { + int t = 0; + if (base == 10 && n < 0) { + t = print('-'); + n = -n; + } + return printNumber(static_cast(n), base) + t; +} + +size_t Print::print(unsigned long long n, int base) { + if (base == 0) { + return write(n); + } + return printNumber(n, base); } size_t Print::print(double n, int digits) { @@ -233,6 +243,18 @@ size_t Print::println(unsigned long num, int base) { return n; } +size_t Print::println(long long num, int base) { + size_t n = print(num, base); + n += println(); + return n; +} + +size_t Print::println(unsigned long long num, int base) { + size_t n = print(num, base); + n += println(); + return n; +} + size_t Print::println(double num, int digits) { size_t n = print(num, digits); n += println(); @@ -258,9 +280,29 @@ size_t Print::printNumber(unsigned long n, uint8_t base) { base = 10; do { - unsigned long m = n; + char c = n % base; n /= base; - char c = m - base * n; + + *--str = c < 10 ? c + '0' : c + 'A' - 10; + } while(n); + + return write(str); +} + +size_t Print::printNumber(unsigned long long n, uint8_t base) { + char buf[8 * sizeof(long long) + 1]; // Assumes 8-bit chars plus zero byte. + char* str = &buf[sizeof(buf) - 1]; + + *str = '\0'; + + // prevent crash if called with base == 1 + if (base < 2) + base = 10; + + do { + char c = n % base; + n /= base; + *--str = c < 10 ? c + '0' : c + 'A' - 10; } while(n); diff --git a/cores/esp8266/Print.h b/cores/esp8266/Print.h index e43883b39..218f58d26 100644 --- a/cores/esp8266/Print.h +++ b/cores/esp8266/Print.h @@ -37,6 +37,7 @@ class Print { private: int write_error; size_t printNumber(unsigned long, uint8_t); + size_t printNumber(unsigned long long, uint8_t); size_t printFloat(double, uint8_t); protected: void setWriteError(int err = 1) { @@ -71,6 +72,8 @@ class Print { inline size_t write(unsigned int t) { return write((uint8_t)t); } inline size_t write(long t) { return write((uint8_t)t); } inline size_t write(unsigned long t) { return write((uint8_t)t); } + inline size_t write(long long t) { return write((uint8_t)t); } + inline size_t write(unsigned long long t) { return write((uint8_t)t); } // Enable write(char) to fall through to write(uint8_t) inline size_t write(char c) { return write((uint8_t) c); } inline size_t write(int8_t c) { return write((uint8_t) c); } @@ -86,6 +89,8 @@ class Print { size_t print(unsigned int, int = DEC); size_t print(long, int = DEC); size_t print(unsigned long, int = DEC); + size_t print(long long, int = DEC); + size_t print(unsigned long long, int = DEC); size_t print(double, int = 2); size_t print(const Printable&); @@ -98,6 +103,8 @@ class Print { size_t println(unsigned int, int = DEC); size_t println(long, int = DEC); size_t println(unsigned long, int = DEC); + size_t println(long long, int = DEC); + size_t println(unsigned long long, int = DEC); size_t println(double, int = 2); size_t println(const Printable&); size_t println(void); From 7e1d891e84f58eacdb770cf9e7469e2b3d419ade Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Tue, 28 Jan 2020 22:42:47 +0100 Subject: [PATCH 2/5] Revert to explicit calculation of modulo, saving 16 bytes in IROM. --- cores/esp8266/Print.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index 37259109e..c9ead745f 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -280,8 +280,9 @@ size_t Print::printNumber(unsigned long n, uint8_t base) { base = 10; do { - char c = n % base; + unsigned long m = n; n /= base; + char c = m - base * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while(n); @@ -300,8 +301,9 @@ size_t Print::printNumber(unsigned long long n, uint8_t base) { base = 10; do { - char c = n % base; + unsigned long m = n; n /= base; + char c = m - base * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while(n); From 8c725d5736e4813cd924562fb9997ac8d2ec41fd Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sun, 2 Feb 2020 09:48:58 +0100 Subject: [PATCH 3/5] Fix for 32bit long used in long long printNumber. --- cores/esp8266/Print.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index c9ead745f..bbe2861ba 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -270,43 +270,45 @@ size_t Print::println(const Printable& x) { // Private Methods ///////////////////////////////////////////////////////////// size_t Print::printNumber(unsigned long n, uint8_t base) { - char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. + char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; *str = '\0'; // prevent crash if called with base == 1 - if(base < 2) + if(base < 2) { base = 10; + } do { - unsigned long m = n; + auto m = n; n /= base; char c = m - base * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); + } while (n); return write(str); } size_t Print::printNumber(unsigned long long n, uint8_t base) { - char buf[8 * sizeof(long long) + 1]; // Assumes 8-bit chars plus zero byte. + char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte. char* str = &buf[sizeof(buf) - 1]; *str = '\0'; // prevent crash if called with base == 1 - if (base < 2) + if (base < 2) { base = 10; + } do { - unsigned long m = n; + auto m = n; n /= base; char c = m - base * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); + } while (n); return write(str); } From 0b502b3f7b656d12ab576fa29a0820e5c4c79296 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sat, 18 Apr 2020 08:33:48 +0200 Subject: [PATCH 4/5] Eliminate code duplication by template for println(...). --- cores/esp8266/Print.cpp | 58 ++++++++++++----------------------------- cores/esp8266/Print.h | 8 ++++++ 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index bbe2861ba..f6fd2ec74 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -181,12 +181,6 @@ size_t Print::print(double n, int digits) { return printFloat(n, digits); } -size_t Print::println(const __FlashStringHelper *ifsh) { - size_t n = print(ifsh); - n += println(); - return n; -} - size_t Print::print(const Printable& x) { return x.printTo(*this); } @@ -195,76 +189,56 @@ size_t Print::println(void) { return print("\r\n"); } +size_t Print::println(const __FlashStringHelper* ifsh) { + return _println(ifsh); +} + size_t Print::println(const String &s) { - size_t n = print(s); - n += println(); - return n; + return _println(s); } size_t Print::println(const char c[]) { - size_t n = print(c); - n += println(); - return n; + return _println(c); } size_t Print::println(char c) { - size_t n = print(c); - n += println(); - return n; + return _println(c); } size_t Print::println(unsigned char b, int base) { - size_t n = print(b, base); - n += println(); - return n; + return _println(b, base); } size_t Print::println(int num, int base) { - size_t n = print(num, base); - n += println(); - return n; + return _println(num, base); } size_t Print::println(unsigned int num, int base) { - size_t n = print(num, base); - n += println(); - return n; + return _println(num, base); } size_t Print::println(long num, int base) { - size_t n = print(num, base); - n += println(); - return n; + return _println(num, base); } size_t Print::println(unsigned long num, int base) { - size_t n = print(num, base); - n += println(); - return n; + return _println(num, base); } size_t Print::println(long long num, int base) { - size_t n = print(num, base); - n += println(); - return n; + return _println(num, base); } size_t Print::println(unsigned long long num, int base) { - size_t n = print(num, base); - n += println(); - return n; + return _println(num, base); } size_t Print::println(double num, int digits) { - size_t n = print(num, digits); - n += println(); - return n; + return _println(num, digits); } size_t Print::println(const Printable& x) { - size_t n = print(x); - n += println(); - return n; + return _println(x); } // Private Methods ///////////////////////////////////////////////////////////// diff --git a/cores/esp8266/Print.h b/cores/esp8266/Print.h index 218f58d26..edfd7f7d6 100644 --- a/cores/esp8266/Print.h +++ b/cores/esp8266/Print.h @@ -39,6 +39,14 @@ class Print { size_t printNumber(unsigned long, uint8_t); size_t printNumber(unsigned long long, uint8_t); size_t printFloat(double, uint8_t); + + template inline size_t _println(T v, P... args) + { + size_t n = print(v, args...); + n += println(); + return n; + }; + protected: void setWriteError(int err = 1) { write_error = err; From 6f57c222c17bfa488d78193554dc5237c3305594 Mon Sep 17 00:00:00 2001 From: "Dirk O. Kaar" Date: Sat, 18 Apr 2020 10:07:08 +0200 Subject: [PATCH 5/5] Eliminate code duplication by template for printNumber(...)/printFloat(...). Move template defintion into cpp file - valid for private member function templates. --- cores/esp8266/Print.cpp | 33 +++++++++------------------------ cores/esp8266/Print.h | 17 +++++------------ 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/cores/esp8266/Print.cpp b/cores/esp8266/Print.cpp index f6fd2ec74..186d6e1cb 100644 --- a/cores/esp8266/Print.cpp +++ b/cores/esp8266/Print.cpp @@ -178,7 +178,7 @@ size_t Print::print(unsigned long long n, int base) { } size_t Print::print(double n, int digits) { - return printFloat(n, digits); + return printNumber(n, digits); } size_t Print::print(const Printable& x) { @@ -243,29 +243,14 @@ size_t Print::println(const Printable& x) { // Private Methods ///////////////////////////////////////////////////////////// -size_t Print::printNumber(unsigned long n, uint8_t base) { - char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte. - char *str = &buf[sizeof(buf) - 1]; +template inline size_t Print::_println(T v, P... args) +{ + size_t n = print(v, args...); + n += println(); + return n; +}; - *str = '\0'; - - // prevent crash if called with base == 1 - if(base < 2) { - base = 10; - } - - do { - auto m = n; - n /= base; - char c = m - base * n; - - *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while (n); - - return write(str); -} - -size_t Print::printNumber(unsigned long long n, uint8_t base) { +template size_t Print::printNumber(T n, uint8_t base) { char buf[8 * sizeof(n) + 1]; // Assumes 8-bit chars plus zero byte. char* str = &buf[sizeof(buf) - 1]; @@ -287,7 +272,7 @@ size_t Print::printNumber(unsigned long long n, uint8_t base) { return write(str); } -size_t Print::printFloat(double number, uint8_t digits) { +template<> size_t Print::printNumber(double number, uint8_t digits) { char buf[40]; return write(dtostrf(number, 0, digits, buf)); } diff --git a/cores/esp8266/Print.h b/cores/esp8266/Print.h index edfd7f7d6..e49332b31 100644 --- a/cores/esp8266/Print.h +++ b/cores/esp8266/Print.h @@ -36,18 +36,9 @@ class Print { private: int write_error; - size_t printNumber(unsigned long, uint8_t); - size_t printNumber(unsigned long long, uint8_t); - size_t printFloat(double, uint8_t); - - template inline size_t _println(T v, P... args) - { - size_t n = print(v, args...); - n += println(); - return n; - }; - - protected: + template size_t printNumber(T n, uint8_t base); + template inline size_t _println(T v, P... args); +protected: void setWriteError(int err = 1) { write_error = err; } @@ -120,4 +111,6 @@ class Print { virtual void flush() { /* Empty implementation for backward compatibility */ } }; +template<> size_t Print::printNumber(double number, uint8_t digits); + #endif