From bd0651774861eb7f788cf7a221298b2c5063e2f5 Mon Sep 17 00:00:00 2001
From: cousteaulecommandant <cousteaulecommandant@gmail.com>
Date: Fri, 7 Sep 2018 15:35:58 +0200
Subject: [PATCH] Introduce variadic print

based on https://github.com/arduino/Arduino/pull/5829
---
 api/Print.cpp | 123 +-------------------------------------------------
 api/Print.h   |  73 +++++++++++++++++++++---------
 2 files changed, 53 insertions(+), 143 deletions(-)

diff --git a/api/Print.cpp b/api/Print.cpp
index 4f0016c4..e4825b9d 100644
--- a/api/Print.cpp
+++ b/api/Print.cpp
@@ -58,32 +58,7 @@ 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)
+size_t Print::print(signed long n, int base)
 {
   if (base == 0) {
     return write(n);
@@ -132,107 +107,11 @@ 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);
-}
-
 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(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();
-  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/api/Print.h b/api/Print.h
index 6a06bad6..80aed85a 100644
--- a/api/Print.h
+++ b/api/Print.h
@@ -29,6 +29,8 @@
 #define OCT 8
 #define BIN 2
 
+#define _always_inline __attribute__ ((__always_inline__)) // undefined at end
+
 class Print
 {
   private:
@@ -56,31 +58,60 @@ 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(  signed 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 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(long long, int = DEC);
-    size_t println(unsigned long long, int = DEC);
-    size_t println(double, int = 2);
-    size_t println(const Printable&);
+
+    _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); }
+
+    _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);
+
+#if __cplusplus >= 201103L
+    template<typename ...Ts> _always_inline size_t println(const Ts &...args) { size_t t = print(args...); return t + println(); }
+#else
+    template<typename T> _always_inline size_t println(const T &arg)      { size_t t = print(arg);  return t + println(); }
+    template<typename T> _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<typename T, typename T2, typename ...Ts>
+    _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<typename ...Ts> _always_inline size_t print(  signed char  n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(  signed short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(  signed int   n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(  signed long  n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(unsigned char  n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(unsigned short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(unsigned int   n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(unsigned long  n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(    float      n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(    double     n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(long long      n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+    template<typename ...Ts> _always_inline size_t print(unsigned long long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
+#endif // __cplusplus >= 201103L
 };