From b9281c96e5b3d6478fcb77c22c6a9abcb5b43e89 Mon Sep 17 00:00:00 2001 From: cousteaulecommandant Date: Tue, 10 Jan 2017 18:44:02 +0100 Subject: [PATCH 1/5] Inline println(...) functions Remove all definitions of println(...) from Print.cpp except println(void), and replace them with inline methods in Print.h. This simplifies the code in Print.cpp improving maintainability. --- hardware/arduino/avr/cores/arduino/Print.cpp | 77 -------------------- hardware/arduino/avr/cores/arduino/Print.h | 14 +--- hardware/arduino/sam/cores/arduino/Print.cpp | 77 -------------------- hardware/arduino/sam/cores/arduino/Print.h | 14 +--- 4 files changed, 6 insertions(+), 176 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/Print.cpp b/hardware/arduino/avr/cores/arduino/Print.cpp index 1e4c99a6552..bfdcfb99d15 100644 --- a/hardware/arduino/avr/cores/arduino/Print.cpp +++ b/hardware/arduino/avr/cores/arduino/Print.cpp @@ -111,13 +111,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); @@ -128,76 +121,6 @@ size_t Print::println(void) return write("\r\n"); } -size_t Print::println(const String &s) -{ - size_t n = print(s); - n += println(); - return n; -} - -size_t Print::println(const char c[]) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(char c) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(unsigned char b, int base) -{ - size_t n = print(b, base); - n += println(); - return n; -} - -size_t Print::println(int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned 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(); - return n; -} - -size_t Print::println(const Printable& x) -{ - size_t n = print(x); - n += println(); - return n; -} - // Private Methods ///////////////////////////////////////////////////////////// size_t Print::printNumber(unsigned long n, uint8_t base) diff --git a/hardware/arduino/avr/cores/arduino/Print.h b/hardware/arduino/avr/cores/arduino/Print.h index 7b53aa4d17e..c9d3066efb0 100644 --- a/hardware/arduino/avr/cores/arduino/Print.h +++ b/hardware/arduino/avr/cores/arduino/Print.h @@ -67,18 +67,10 @@ class Print size_t print(double, int = 2); size_t print(const Printable&); - size_t println(const __FlashStringHelper *); - size_t println(const String &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(double, int = 2); - size_t println(const Printable&); size_t println(void); + + template size_t println(const T &arg) { size_t t = print(arg); return t + println(); } + template size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } }; #endif diff --git a/hardware/arduino/sam/cores/arduino/Print.cpp b/hardware/arduino/sam/cores/arduino/Print.cpp index 881722e8962..294bfce2c29 100644 --- a/hardware/arduino/sam/cores/arduino/Print.cpp +++ b/hardware/arduino/sam/cores/arduino/Print.cpp @@ -103,13 +103,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); @@ -120,76 +113,6 @@ size_t Print::println(void) return write("\r\n"); } -size_t Print::println(const String &s) -{ - size_t n = print(s); - n += println(); - return n; -} - -size_t Print::println(const char c[]) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(char c) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(unsigned char b, int base) -{ - size_t n = print(b, base); - n += println(); - return n; -} - -size_t Print::println(int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned 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(); - return n; -} - -size_t Print::println(const Printable& x) -{ - size_t n = print(x); - n += println(); - return n; -} - // Private Methods ///////////////////////////////////////////////////////////// size_t Print::printNumber(unsigned long n, uint8_t base) diff --git a/hardware/arduino/sam/cores/arduino/Print.h b/hardware/arduino/sam/cores/arduino/Print.h index 7b53aa4d17e..c9d3066efb0 100644 --- a/hardware/arduino/sam/cores/arduino/Print.h +++ b/hardware/arduino/sam/cores/arduino/Print.h @@ -67,18 +67,10 @@ class Print size_t print(double, int = 2); size_t print(const Printable&); - size_t println(const __FlashStringHelper *); - size_t println(const String &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(double, int = 2); - size_t println(const Printable&); size_t println(void); + + template size_t println(const T &arg) { size_t t = print(arg); return t + println(); } + template size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } }; #endif From d6058b9ed0b1bf74036bdfbf24c5ca0445fafded Mon Sep 17 00:00:00 2001 From: cousteaulecommandant Date: Tue, 10 Jan 2017 19:03:49 +0100 Subject: [PATCH 2/5] Inline some print() functions Remove print(char | char[] | Printable | unsigned char | int | unsigned int) from Print.cpp and replace them with inline versions in Print.h. --- hardware/arduino/avr/cores/arduino/Print.cpp | 30 -------------------- hardware/arduino/avr/cores/arduino/Print.h | 16 ++++++----- hardware/arduino/sam/cores/arduino/Print.cpp | 30 -------------------- hardware/arduino/sam/cores/arduino/Print.h | 16 ++++++----- 4 files changed, 18 insertions(+), 74 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/Print.cpp b/hardware/arduino/avr/cores/arduino/Print.cpp index bfdcfb99d15..723db4a9be1 100644 --- a/hardware/arduino/avr/cores/arduino/Print.cpp +++ b/hardware/arduino/avr/cores/arduino/Print.cpp @@ -59,31 +59,6 @@ size_t Print::print(const String &s) return write(s.c_str(), s.length()); } -size_t Print::print(const char str[]) -{ - return write(str); -} - -size_t Print::print(char c) -{ - return write(c); -} - -size_t Print::print(unsigned char b, int base) -{ - return print((unsigned long) b, base); -} - -size_t Print::print(int n, int base) -{ - return print((long) n, base); -} - -size_t Print::print(unsigned int n, int base) -{ - return print((unsigned long) n, base); -} - size_t Print::print(long n, int base) { if (base == 0) { @@ -111,11 +86,6 @@ size_t Print::print(double n, int digits) return printFloat(n, digits); } -size_t Print::print(const Printable& x) -{ - return x.printTo(*this); -} - size_t Print::println(void) { return write("\r\n"); diff --git a/hardware/arduino/avr/cores/arduino/Print.h b/hardware/arduino/avr/cores/arduino/Print.h index c9d3066efb0..10815d35998 100644 --- a/hardware/arduino/avr/cores/arduino/Print.h +++ b/hardware/arduino/avr/cores/arduino/Print.h @@ -57,16 +57,18 @@ class Print size_t print(const __FlashStringHelper *); size_t print(const String &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); size_t print(long, int = DEC); size_t print(unsigned long, int = DEC); size_t print(double, int = 2); - size_t print(const Printable&); - + + size_t print(const char str[]) { return write(str); } + size_t print(const char c) { return write(c); } + size_t print(const Printable &x) { return x.printTo(*this); } + + size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } + size_t print( int n, int f = DEC) { return print(( long) n, f); } + size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } + size_t println(void); template size_t println(const T &arg) { size_t t = print(arg); return t + println(); } diff --git a/hardware/arduino/sam/cores/arduino/Print.cpp b/hardware/arduino/sam/cores/arduino/Print.cpp index 294bfce2c29..ad6f8011183 100644 --- a/hardware/arduino/sam/cores/arduino/Print.cpp +++ b/hardware/arduino/sam/cores/arduino/Print.cpp @@ -51,31 +51,6 @@ size_t Print::print(const String &s) return write(s.c_str(), s.length()); } -size_t Print::print(const char str[]) -{ - return write(str); -} - -size_t Print::print(char c) -{ - return write(c); -} - -size_t Print::print(unsigned char b, int base) -{ - return print((unsigned long) b, base); -} - -size_t Print::print(int n, int base) -{ - return print((long) n, base); -} - -size_t Print::print(unsigned int n, int base) -{ - return print((unsigned long) n, base); -} - size_t Print::print(long n, int base) { if (base == 0) { @@ -103,11 +78,6 @@ size_t Print::print(double n, int digits) return printFloat(n, digits); } -size_t Print::print(const Printable& x) -{ - return x.printTo(*this); -} - size_t Print::println(void) { return write("\r\n"); diff --git a/hardware/arduino/sam/cores/arduino/Print.h b/hardware/arduino/sam/cores/arduino/Print.h index c9d3066efb0..10815d35998 100644 --- a/hardware/arduino/sam/cores/arduino/Print.h +++ b/hardware/arduino/sam/cores/arduino/Print.h @@ -57,16 +57,18 @@ class Print size_t print(const __FlashStringHelper *); size_t print(const String &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); size_t print(long, int = DEC); size_t print(unsigned long, int = DEC); size_t print(double, int = 2); - size_t print(const Printable&); - + + size_t print(const char str[]) { return write(str); } + size_t print(const char c) { return write(c); } + size_t print(const Printable &x) { return x.printTo(*this); } + + size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } + size_t print( int n, int f = DEC) { return print(( long) n, f); } + size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } + size_t println(void); template size_t println(const T &arg) { size_t t = print(arg); return t + println(); } From ceee9e9fdac99e4121a017ff896ddcbc0806519a Mon Sep 17 00:00:00 2001 From: cousteaulecommandant Date: Tue, 10 Jan 2017 19:14:37 +0100 Subject: [PATCH 3/5] Add print(signed char | short | float) explicitly Add explicit print() support for signed char, unsigned/signed short, and float. Also, add `signed` keyword explicitly to int and long (even if unnecessary). Notice that `char` and `signed char` are considered different types, even if their ranges are the same (ditto for `unsigned char` in SAM). Both AVR and SAM seem to define [u]int8_t explicitly as [un]signed char and not as char, so printing them will print them as numbers as expected. (This does not apply to `int` and `signed int`; those are the same type.) --- hardware/arduino/avr/cores/arduino/Print.cpp | 2 +- hardware/arduino/avr/cores/arduino/Print.h | 8 ++++++-- hardware/arduino/sam/cores/arduino/Print.cpp | 2 +- hardware/arduino/sam/cores/arduino/Print.h | 8 ++++++-- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/Print.cpp b/hardware/arduino/avr/cores/arduino/Print.cpp index 723db4a9be1..3f9534c0ea6 100644 --- a/hardware/arduino/avr/cores/arduino/Print.cpp +++ b/hardware/arduino/avr/cores/arduino/Print.cpp @@ -59,7 +59,7 @@ size_t Print::print(const String &s) return write(s.c_str(), s.length()); } -size_t Print::print(long n, int base) +size_t Print::print(signed long n, int base) { if (base == 0) { return write(n); diff --git a/hardware/arduino/avr/cores/arduino/Print.h b/hardware/arduino/avr/cores/arduino/Print.h index 10815d35998..88564008851 100644 --- a/hardware/arduino/avr/cores/arduino/Print.h +++ b/hardware/arduino/avr/cores/arduino/Print.h @@ -57,7 +57,7 @@ class Print size_t print(const __FlashStringHelper *); size_t print(const String &); - size_t print(long, int = DEC); + size_t print( signed long, int = DEC); size_t print(unsigned long, int = DEC); size_t print(double, int = 2); @@ -65,9 +65,13 @@ class Print size_t print(const char c) { return write(c); } size_t print(const Printable &x) { return x.printTo(*this); } + size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); } + size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); } + size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); } size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } - size_t print( int n, int f = DEC) { return print(( long) n, f); } + size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); } size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } + size_t print( float n, int f = 2 ) { return print(( double ) n, f); } size_t println(void); diff --git a/hardware/arduino/sam/cores/arduino/Print.cpp b/hardware/arduino/sam/cores/arduino/Print.cpp index ad6f8011183..3df7ed049cd 100644 --- a/hardware/arduino/sam/cores/arduino/Print.cpp +++ b/hardware/arduino/sam/cores/arduino/Print.cpp @@ -51,7 +51,7 @@ size_t Print::print(const String &s) return write(s.c_str(), s.length()); } -size_t Print::print(long n, int base) +size_t Print::print(signed long n, int base) { if (base == 0) { return write(n); diff --git a/hardware/arduino/sam/cores/arduino/Print.h b/hardware/arduino/sam/cores/arduino/Print.h index 10815d35998..88564008851 100644 --- a/hardware/arduino/sam/cores/arduino/Print.h +++ b/hardware/arduino/sam/cores/arduino/Print.h @@ -57,7 +57,7 @@ class Print size_t print(const __FlashStringHelper *); size_t print(const String &); - size_t print(long, int = DEC); + size_t print( signed long, int = DEC); size_t print(unsigned long, int = DEC); size_t print(double, int = 2); @@ -65,9 +65,13 @@ class Print size_t print(const char c) { return write(c); } size_t print(const Printable &x) { return x.printTo(*this); } + size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); } + size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); } + size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); } size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } - size_t print( int n, int f = DEC) { return print(( long) n, f); } + size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); } size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } + size_t print( float n, int f = 2 ) { return print(( double ) n, f); } size_t println(void); From d2f7f1be996bf43aa803dcfe3e0f4b12707e605e Mon Sep 17 00:00:00 2001 From: cousteaulecommandant Date: Tue, 10 Jan 2017 20:00:31 +0100 Subject: [PATCH 4/5] Force inlining of inline print[ln] methods Add GCC __attribute__ ((__always_inline__)) to inlined methods in Print.h. This seems necessary since not doing so increases the executable size (probably because that would create several function definitions), even with LTO optimizations. This change combined with the inlining of print/printf methods seems to reduce the executable size for most applications by a fair amount. (Note that the `inline` keyword does not imply actual inlining.) --- hardware/arduino/avr/cores/arduino/Print.h | 28 ++++++++++++---------- hardware/arduino/sam/cores/arduino/Print.h | 28 ++++++++++++---------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/hardware/arduino/avr/cores/arduino/Print.h b/hardware/arduino/avr/cores/arduino/Print.h index 88564008851..3fb1ff16c13 100644 --- a/hardware/arduino/avr/cores/arduino/Print.h +++ b/hardware/arduino/avr/cores/arduino/Print.h @@ -31,6 +31,8 @@ #define OCT 8 #define BIN 2 +#define _always_inline __attribute__ ((__always_inline__)) // undefined at end + class Print { private: @@ -61,22 +63,24 @@ class Print size_t print(unsigned long, int = DEC); size_t print(double, int = 2); - size_t print(const char str[]) { return write(str); } - size_t print(const char c) { return write(c); } - size_t print(const Printable &x) { return x.printTo(*this); } + _always_inline size_t print(const char str[]) { return write(str); } + _always_inline size_t print(const char c) { return write(c); } + _always_inline size_t print(const Printable &x) { return x.printTo(*this); } - size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); } - size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); } - size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); } - size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } - size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); } - size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } - size_t print( float n, int f = 2 ) { return print(( double ) n, f); } + _always_inline size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); } + _always_inline size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); } + _always_inline size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); } + _always_inline size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } + _always_inline size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); } + _always_inline size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } + _always_inline size_t print( float n, int f = 2 ) { return print(( double ) n, f); } size_t println(void); - template size_t println(const T &arg) { size_t t = print(arg); return t + println(); } - template size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } + template _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); } + template _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } }; +#undef _always_inline + #endif diff --git a/hardware/arduino/sam/cores/arduino/Print.h b/hardware/arduino/sam/cores/arduino/Print.h index 88564008851..3fb1ff16c13 100644 --- a/hardware/arduino/sam/cores/arduino/Print.h +++ b/hardware/arduino/sam/cores/arduino/Print.h @@ -31,6 +31,8 @@ #define OCT 8 #define BIN 2 +#define _always_inline __attribute__ ((__always_inline__)) // undefined at end + class Print { private: @@ -61,22 +63,24 @@ class Print size_t print(unsigned long, int = DEC); size_t print(double, int = 2); - size_t print(const char str[]) { return write(str); } - size_t print(const char c) { return write(c); } - size_t print(const Printable &x) { return x.printTo(*this); } + _always_inline size_t print(const char str[]) { return write(str); } + _always_inline size_t print(const char c) { return write(c); } + _always_inline size_t print(const Printable &x) { return x.printTo(*this); } - size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); } - size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); } - size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); } - size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } - size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); } - size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } - size_t print( float n, int f = 2 ) { return print(( double ) n, f); } + _always_inline size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); } + _always_inline size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); } + _always_inline size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); } + _always_inline size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); } + _always_inline size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); } + _always_inline size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); } + _always_inline size_t print( float n, int f = 2 ) { return print(( double ) n, f); } size_t println(void); - template size_t println(const T &arg) { size_t t = print(arg); return t + println(); } - template size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } + template _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); } + template _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } }; +#undef _always_inline + #endif From 587eec51422f661f16696b9f0c73635b13838346 Mon Sep 17 00:00:00 2001 From: cousteaulecommandant Date: Tue, 10 Jan 2017 20:31:07 +0100 Subject: [PATCH 5/5] Add support for variadic Serial.print(...) Allows combining multiple arguments into a single call to Print::print[ln], like Serial.print("Answer=", 66, HEX). This feature requires C++11 or newer to work, but if it is not available the old calls can still be used (the change has been wrapped in `#if __cplusplus >= 201103L ... #endif`). This change is backwards compatible: print(42, 16) prints "2A" as always, not "4216" (the latter can still be achieved with print(42, "", 16) ). This also works with multiple arguments: any numeric argument followed by an int will be treated as a (number, format) pair. The variadic function calls are inlined using an __attribute__ ((__always_inline__)), so they're equivalent to writing multiple sequential calls to print with one argument. --- hardware/arduino/avr/cores/arduino/Print.h | 30 ++++++++++++++++++++++ hardware/arduino/sam/cores/arduino/Print.h | 30 ++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/hardware/arduino/avr/cores/arduino/Print.h b/hardware/arduino/avr/cores/arduino/Print.h index 3fb1ff16c13..172f599a3b3 100644 --- a/hardware/arduino/avr/cores/arduino/Print.h +++ b/hardware/arduino/avr/cores/arduino/Print.h @@ -77,8 +77,38 @@ class Print size_t println(void); +#if __cplusplus >= 201103L + template _always_inline size_t println(const Ts &...args) { size_t t = print(args...); return t + println(); } +#else template _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); } template _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } +#endif // __cplusplus >= 201103L + + + /** Variadic methods **/ +#if __cplusplus >= 201103L // requires C++11 + // Ensure there are at least two parameters to avoid infinite recursion. + // e.g. `StringSumHelper s; print(s)` may be treated as `print(s, ...)` + // with `...` being the empty list, thus calling `print(s)` again. + // (This is because print(StringSumHelper) isn't explicitly defined.) + template + _always_inline size_t print(const T &arg, const T2 &arg2, const Ts &...args) { + size_t t = print(arg); + return t + print(arg2, args...); + } + // Some methods take an extra int parameter. If so, use these templates. + // In a future, it would be nice to make the base/precision a special type. + template _always_inline size_t print( signed char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( signed short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( signed int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( signed long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( float n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( double n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } +#endif // __cplusplus >= 201103L }; #undef _always_inline diff --git a/hardware/arduino/sam/cores/arduino/Print.h b/hardware/arduino/sam/cores/arduino/Print.h index 3fb1ff16c13..172f599a3b3 100644 --- a/hardware/arduino/sam/cores/arduino/Print.h +++ b/hardware/arduino/sam/cores/arduino/Print.h @@ -77,8 +77,38 @@ class Print size_t println(void); +#if __cplusplus >= 201103L + template _always_inline size_t println(const Ts &...args) { size_t t = print(args...); return t + println(); } +#else template _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); } template _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); } +#endif // __cplusplus >= 201103L + + + /** Variadic methods **/ +#if __cplusplus >= 201103L // requires C++11 + // Ensure there are at least two parameters to avoid infinite recursion. + // e.g. `StringSumHelper s; print(s)` may be treated as `print(s, ...)` + // with `...` being the empty list, thus calling `print(s)` again. + // (This is because print(StringSumHelper) isn't explicitly defined.) + template + _always_inline size_t print(const T &arg, const T2 &arg2, const Ts &...args) { + size_t t = print(arg); + return t + print(arg2, args...); + } + // Some methods take an extra int parameter. If so, use these templates. + // In a future, it would be nice to make the base/precision a special type. + template _always_inline size_t print( signed char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( signed short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( signed int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( signed long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print(unsigned long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( float n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } + template _always_inline size_t print( double n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); } +#endif // __cplusplus >= 201103L }; #undef _always_inline