diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp index 97e3f93870..7eb6dff491 100644 --- a/cores/arduino/Print.cpp +++ b/cores/arduino/Print.cpp @@ -1,6 +1,5 @@ /* - Print.cpp - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. + Copyright (c) 2014 Arduino. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -9,16 +8,13 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 23 November 2006 by David A. Mellis - Modified 03 August 2015 by Chuck Todd - */ +*/ #include #include @@ -108,6 +104,31 @@ size_t Print::print(unsigned long n, int base) } } +size_t Print::print(long long n, int base) +{ + if (base == 0) { + return write(n); + } else if (base == 10) { + if (n < 0) { + int t = print('-'); + n = -n; + return printULLNumber(n, 10) + t; + } + return printULLNumber(n, 10); + } else { + return printULLNumber(n, base); + } +} + +size_t Print::print(unsigned long long n, int base) +{ + if (base == 0) { + return write(n); + } else { + return printULLNumber(n, base); + } +} + size_t Print::print(double n, int digits) { return printFloat(n, digits); @@ -186,6 +207,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); @@ -262,6 +297,100 @@ size_t Print::printNumber(unsigned long n, uint8_t base) return write(str); } +/* +void Print::printULLNumber(uint64_t n, uint8_t base) +{ + unsigned char buf[16 * sizeof(long)]; + unsigned int i = 0; + + if (n == 0) { + print((char)'0'); + return; + } + + while (n > 0) { + buf[i++] = n % base; + n /= base; + } + + for (; i > 0; i--) { + print((char)(buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10)); + } +} +*/ +// REFERENCE IMPLEMENTATION FOR ULL +// size_t Print::printULLNumber(unsigned long long n, uint8_t base) +// { +// // if limited to base 10 and 16 the bufsize can be smaller +// char buf[65]; +// char *str = &buf[64]; + +// *str = '\0'; + +// // prevent crash if called with base == 1 +// if (base < 2) base = 10; + +// do { +// unsigned long long t = n / base; +// char c = n - t * base; // faster than c = n%base; +// n = t; +// *--str = c < 10 ? c + '0' : c + 'A' - 10; +// } while(n); + +// return write(str); +// } + +// FAST IMPLEMENTATION FOR ULL +size_t Print::printULLNumber(unsigned long long n64, uint8_t base) +{ + // if limited to base 10 and 16 the bufsize can be 20 + char buf[64]; + uint8_t i = 0; + uint8_t innerLoops = 0; + + // prevent crash if called with base == 1 + if (base < 2) { + base = 10; + } + + // process chunks that fit in "16 bit math". + uint16_t top = 0xFFFF / base; + uint16_t th16 = 1; + while (th16 < top) { + th16 *= base; + innerLoops++; + } + + while (n64 > th16) { + // 64 bit math part + uint64_t q = n64 / th16; + uint16_t r = n64 - q * th16; + n64 = q; + + // 16 bit math loop to do remainder. (note buffer is filled reverse) + for (uint8_t j = 0; j < innerLoops; j++) { + uint16_t qq = r / base; + buf[i++] = r - qq * base; + r = qq; + } + } + + uint16_t n16 = n64; + while (n16 > 0) { + uint16_t qq = n16 / base; + buf[i++] = n16 - qq * base; + n16 = qq; + } + + size_t bytes = i; + for (; i > 0; i--) { + write((char)(buf[i - 1] < 10 ? + '0' + buf[i - 1] : + 'A' + buf[i - 1] - 10)); + } + return bytes; +} + size_t Print::printFloat(double number, uint8_t digits) { size_t n = 0; @@ -300,71 +429,16 @@ size_t Print::printFloat(double number, uint8_t digits) // Print the decimal point, but only if there are digits beyond if (digits > 0) { - n += print("."); + n += print('.'); } // Extract digits from the remainder one at a time while (digits-- > 0) { remainder *= 10.0; - int toPrint = int(remainder); + unsigned int toPrint = (unsigned int)remainder; n += print(toPrint); remainder -= toPrint; } return n; -} - -#ifdef SUPPORT_LONGLONG - -void Print::println(int64_t n, uint8_t base) -{ - print(n, base); - println(); -} - -void Print::print(int64_t n, uint8_t base) -{ - if (n < 0) { - print((char)'-'); - n = -n; - } - if (base < 2) { - base = 2; - } - print((uint64_t)n, base); -} - -void Print::println(uint64_t n, uint8_t base) -{ - print(n, base); - println(); -} - -void Print::print(uint64_t n, uint8_t base) -{ - if (base < 2) { - base = 2; - } - printLLNumber(n, base); -} - -void Print::printLLNumber(uint64_t n, uint8_t base) -{ - unsigned char buf[16 * sizeof(long)]; - unsigned int i = 0; - - if (n == 0) { - print((char)'0'); - return; - } - - while (n > 0) { - buf[i++] = n % base; - n /= base; - } - - for (; i > 0; i--) { - print((char)(buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10)); - } -} -#endif +} \ No newline at end of file diff --git a/cores/arduino/Print.h b/cores/arduino/Print.h index 0e37080abc..ad835cd5f3 100644 --- a/cores/arduino/Print.h +++ b/cores/arduino/Print.h @@ -1,6 +1,5 @@ /* - Print.h - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. All right reserved. + Copyright (c) 2016 Arduino LLC. All right reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -9,8 +8,8 @@ This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software @@ -32,16 +31,11 @@ #define OCT 8 #define BIN 2 -// uncomment next line to support printing of 64 bit ints. -#define SUPPORT_LONGLONG - class Print { private: int write_error; size_t printNumber(unsigned long, uint8_t); -#ifdef SUPPORT_LONGLONG - void printLLNumber(uint64_t, uint8_t); -#endif + size_t printULLNumber(unsigned long long, uint8_t); size_t printFloat(double, uint8_t); protected: void setWriteError(int err = 1) @@ -74,6 +68,13 @@ class Print { return write((const uint8_t *)buffer, size); } + // default to zero, meaning "a single write may block" + // should be overriden by subclasses with buffering + virtual int availableForWrite() + { + return 0; + } + size_t print(const __FlashStringHelper *); size_t print(const String &); size_t print(const char[]); @@ -83,6 +84,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 &); @@ -95,18 +98,16 @@ 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); -#ifdef SUPPORT_LONGLONG - void println(int64_t, uint8_t = DEC); - void print(int64_t, uint8_t = DEC); - void println(uint64_t, uint8_t = DEC); - void print(uint64_t, uint8_t = DEC); -#endif int printf(const char *format, ...); int printf(const __FlashStringHelper *format, ...); + + virtual void flush() { /* Empty implementation for backward compatibility */ } }; #endif diff --git a/cores/arduino/Stream.h b/cores/arduino/Stream.h index ad0f9f7c01..38b82be719 100644 --- a/cores/arduino/Stream.h +++ b/cores/arduino/Stream.h @@ -58,7 +58,6 @@ class Stream : public Print { virtual int available() = 0; virtual int read() = 0; virtual int peek() = 0; - virtual void flush() = 0; Stream() {