Skip to content

Commit a3f0e33

Browse files
WIP: Custom formatters
This allows passing formatters to print. E.g. instead of print(10, HEX), you can pass any object that has a suitable printTo(Print*, ValueT) method. This is a WIP on top of the variadic print PR and it makes some changes that should probably go into there. As an example of usage: struct EvenOddFormatter { int printTo(Print *p, int x) { return p->print(x % 2 ? "odd" : "even"); } }; Serial.println(1, EvenOddFormatter());
1 parent 587eec5 commit a3f0e33

File tree

2 files changed

+51
-29
lines changed

2 files changed

+51
-29
lines changed

Diff for: hardware/arduino/avr/cores/arduino/Print.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size)
4141
return n;
4242
}
4343

44-
size_t Print::print(const __FlashStringHelper *ifsh)
44+
size_t Print::doPrint(const __FlashStringHelper *ifsh)
4545
{
4646
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
4747
size_t n = 0;
@@ -54,12 +54,12 @@ size_t Print::print(const __FlashStringHelper *ifsh)
5454
return n;
5555
}
5656

57-
size_t Print::print(const String &s)
57+
size_t Print::doPrint(const String &s)
5858
{
5959
return write(s.c_str(), s.length());
6060
}
6161

62-
size_t Print::print(signed long n, int base)
62+
size_t Print::doPrint(signed long n, int base)
6363
{
6464
if (base == 0) {
6565
return write(n);
@@ -75,13 +75,13 @@ size_t Print::print(signed long n, int base)
7575
}
7676
}
7777

78-
size_t Print::print(unsigned long n, int base)
78+
size_t Print::doPrint(unsigned long n, int base)
7979
{
8080
if (base == 0) return write(n);
8181
else return printNumber(n, base);
8282
}
8383

84-
size_t Print::print(double n, int digits)
84+
size_t Print::doPrint(double n, int digits)
8585
{
8686
return printFloat(n, digits);
8787
}

Diff for: hardware/arduino/avr/cores/arduino/Print.h

+46-24
Original file line numberDiff line numberDiff line change
@@ -57,45 +57,63 @@ class Print
5757
return write((const uint8_t *)buffer, size);
5858
}
5959

60-
size_t print(const __FlashStringHelper *);
61-
size_t print(const String &);
62-
size_t print( signed long, int = DEC);
63-
size_t print(unsigned long, int = DEC);
64-
size_t print(double, int = 2);
60+
size_t doPrint(const __FlashStringHelper *);
61+
size_t doPrint(const String &);
62+
size_t doPrint( signed long, int = DEC);
63+
size_t doPrint(unsigned long, int = DEC);
64+
size_t doPrint(double, int = 2);
6565

66-
_always_inline size_t print(const char str[]) { return write(str); }
67-
_always_inline size_t print(const char c) { return write(c); }
68-
_always_inline size_t print(const Printable &x) { return x.printTo(*this); }
69-
70-
_always_inline size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); }
71-
_always_inline size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); }
72-
_always_inline size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); }
73-
_always_inline size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); }
74-
_always_inline size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); }
75-
_always_inline size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); }
76-
_always_inline size_t print( float n, int f = 2 ) { return print(( double ) n, f); }
66+
_always_inline size_t doPrint(const char str[]) { return write(str); }
67+
_always_inline size_t doPrint(const char c) { return write(c); }
68+
_always_inline size_t doPrint(const Printable &x) { return x.printTo(*this); }
7769

70+
_always_inline size_t doPrint( signed char n, int f = DEC) { return doPrint(( signed long) n, f); }
71+
_always_inline size_t doPrint( signed short n, int f = DEC) { return doPrint(( signed long) n, f); }
72+
_always_inline size_t doPrint( signed int n, int f = DEC) { return doPrint(( signed long) n, f); }
73+
_always_inline size_t doPrint(unsigned char n, int f = DEC) { return doPrint((unsigned long) n, f); }
74+
_always_inline size_t doPrint(unsigned short n, int f = DEC) { return doPrint((unsigned long) n, f); }
75+
_always_inline size_t doPrint(unsigned int n, int f = DEC) { return doPrint((unsigned long) n, f); }
76+
_always_inline size_t doPrint( float n, int f = 2 ) { return doPrint(( double ) n, f); }
77+
78+
template <typename Check, typename T>
79+
struct check_type {
80+
using type = T;
81+
};
82+
template <typename Check, typename T> using check_type_t = typename check_type<Check, T>::type;
83+
84+
template<typename T, typename F>
85+
_always_inline auto doPrint(T v, F f )
86+
-> check_type_t<decltype(f.printTo(this, v)), size_t> {
87+
return f.printTo(this, v);
88+
}
89+
7890
size_t println(void);
7991

8092
#if __cplusplus >= 201103L
8193
template<typename ...Ts> _always_inline size_t println(const Ts &...args) { size_t t = print(args...); return t + println(); }
8294
#else
8395
template<typename T> _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); }
84-
template<typename T> _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); }
96+
template<typename T, typename T2> _always_inline size_t println(const T &arg1, const T2& arg2) { size_t t = print(arg1, arg2); return t + println(); }
8597
#endif // __cplusplus >= 201103L
8698

8799

100+
_always_inline size_t print() { return 0; }
101+
88102
/** Variadic methods **/
89103
#if __cplusplus >= 201103L // requires C++11
90-
// Ensure there are at least two parameters to avoid infinite recursion.
91-
// e.g. `StringSumHelper s; print(s)` may be treated as `print(s, ...)`
92-
// with `...` being the empty list, thus calling `print(s)` again.
93-
// (This is because print(StringSumHelper) isn't explicitly defined.)
104+
template<typename T, typename ...Ts>
105+
_always_inline size_t print(const T &arg, const Ts &...args) {
106+
size_t t = doPrint(arg);
107+
return t + print(args...);
108+
}
109+
94110
template<typename T, typename T2, typename ...Ts>
95-
_always_inline size_t print(const T &arg, const T2 &arg2, const Ts &...args) {
96-
size_t t = print(arg);
97-
return t + print(arg2, args...);
111+
_always_inline auto print(const T &arg, const T2 &arg2, const Ts &...args)
112+
-> check_type_t<decltype(doPrint(arg, arg2)), size_t> {
113+
size_t t = doPrint(arg, arg2);
114+
return t + print(args...);
98115
}
116+
/*
99117
// Some methods take an extra int parameter. If so, use these templates.
100118
// In a future, it would be nice to make the base/precision a special type.
101119
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...); }
@@ -108,6 +126,10 @@ class Print
108126
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...); }
109127
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...); }
110128
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...); }
129+
*/
130+
#else
131+
template<typename T> _always_inline size_t print(const T &arg) { return doPrint(arg); }
132+
template<typename T, typename T2> _always_inline size_t print(const T &arg1, const T2& arg2) { return doPrint(arg1, arg2); }
111133
#endif // __cplusplus >= 201103L
112134
};
113135

0 commit comments

Comments
 (0)