Skip to content

Commit

Permalink
Add support for variadic Serial.print(...)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cousteaulecommandant committed Jan 10, 2017
1 parent d2f7f1b commit 587eec5
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
30 changes: 30 additions & 0 deletions hardware/arduino/avr/cores/arduino/Print.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,38 @@ class Print

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...); }
#endif // __cplusplus >= 201103L
};

#undef _always_inline
Expand Down
30 changes: 30 additions & 0 deletions hardware/arduino/sam/cores/arduino/Print.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,38 @@ class Print

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...); }
#endif // __cplusplus >= 201103L
};

#undef _always_inline
Expand Down

0 comments on commit 587eec5

Please sign in to comment.