From 4204869ec9fde1e5a9ba3080f82b4e358269dca2 Mon Sep 17 00:00:00 2001
From: "Dirk O. Kaar" <19971886+dok-net@users.noreply.github.com>
Date: Wed, 30 Sep 2020 13:31:36 +0200
Subject: [PATCH] Extend Print class for 64bit integers. (#3688)

* Extend Print class for 64bit integers.

modulo 32bit and 64bit tuned for code size.

* Fix 32bit long used in long long printNumber.
---
 cores/esp32/Print.cpp | 74 ++++++++++++++++++++++++++++++++++++-------
 cores/esp32/Print.h   |  5 +++
 2 files changed, 67 insertions(+), 12 deletions(-)

diff --git a/cores/esp32/Print.cpp b/cores/esp32/Print.cpp
index 60964703306..3636d99e658 100644
--- a/cores/esp32/Print.cpp
+++ b/cores/esp32/Print.cpp
@@ -110,24 +110,37 @@ size_t Print::print(unsigned int n, int base)
 }
 
 size_t Print::print(long n, int base)
+{
+    int t = 0;
+    if (base == 10 && n < 0) {
+        t = print('-');
+        n = -n;
+    }
+    return printNumber(static_cast<unsigned long>(n), base) + t;
+}
+
+size_t Print::print(unsigned 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);
     }
 }
 
-size_t Print::print(unsigned long n, int base)
+size_t Print::print(long long n, int base)
 {
-    if(base == 0) {
+    int t = 0;
+    if (base == 10 && n < 0) {
+        t = print('-');
+        n = -n;
+    }
+    return printNumber(static_cast<unsigned long long>(n), base) + t;
+}
+
+size_t Print::print(unsigned long long n, int base)
+{
+    if (base == 0) {
         return write(n);
     } else {
         return printNumber(n, base);
@@ -226,6 +239,20 @@ 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);
@@ -251,7 +278,7 @@ size_t Print::println(struct tm * timeinfo, const char * format)
 
 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';
@@ -262,11 +289,34 @@ size_t Print::printNumber(unsigned long n, uint8_t base)
     }
 
     do {
-        unsigned long m = n;
+        char c = n % base;
+        n /= base;
+
+        *--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(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) {
+        base = 10;
+    }
+
+    do {
+        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);
 }
diff --git a/cores/esp32/Print.h b/cores/esp32/Print.h
index eb2958584d9..15d07357ae9 100644
--- a/cores/esp32/Print.h
+++ b/cores/esp32/Print.h
@@ -36,6 +36,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)
@@ -81,6 +82,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&);
     size_t print(struct tm * timeinfo, const char * format = NULL);
@@ -94,6 +97,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(struct tm * timeinfo, const char * format = NULL);