Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5084817

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 a79b445 commit 5084817

File tree

2 files changed

+51
-29
lines changed

2 files changed

+51
-29
lines changed

cores/arduino/Print.cpp

Lines changed: 5 additions & 5 deletions
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
}

cores/arduino/Print.h

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,41 @@ class Print
6060
return write((const uint8_t *)buffer, size);
6161
}
6262

63+
6364
// default to zero, meaning "a single write may block"
6465
// should be overriden by subclasses with buffering
6566
virtual int availableForWrite() { return 0; }
6667

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

77-
_always_inline size_t print( signed char n, int f = DEC) { return print(( signed long) n, f); }
78-
_always_inline size_t print( signed short n, int f = DEC) { return print(( signed long) n, f); }
79-
_always_inline size_t print( signed int n, int f = DEC) { return print(( signed long) n, f); }
80-
_always_inline size_t print(unsigned char n, int f = DEC) { return print((unsigned long) n, f); }
81-
_always_inline size_t print(unsigned short n, int f = DEC) { return print((unsigned long) n, f); }
82-
_always_inline size_t print(unsigned int n, int f = DEC) { return print((unsigned long) n, f); }
83-
_always_inline size_t print( float n, int f = 2 ) { return print(( double ) n, f); }
74+
_always_inline size_t doPrint(const char str[]) { return write(str); }
75+
_always_inline size_t doPrint(const char c) { return write(c); }
76+
_always_inline size_t doPrint(const Printable &x) { return x.printTo(*this); }
8477

78+
_always_inline size_t doPrint( signed char n, int f = DEC) { return doPrint(( signed long) n, f); }
79+
_always_inline size_t doPrint( signed short n, int f = DEC) { return doPrint(( signed long) n, f); }
80+
_always_inline size_t doPrint( signed int n, int f = DEC) { return doPrint(( signed long) n, f); }
81+
_always_inline size_t doPrint(unsigned char n, int f = DEC) { return doPrint((unsigned long) n, f); }
82+
_always_inline size_t doPrint(unsigned short n, int f = DEC) { return doPrint((unsigned long) n, f); }
83+
_always_inline size_t doPrint(unsigned int n, int f = DEC) { return doPrint((unsigned long) n, f); }
84+
_always_inline size_t doPrint( float n, int f = 2 ) { return doPrint(( double ) n, f); }
85+
86+
template <typename Check, typename T>
87+
struct check_type {
88+
using type = T;
89+
};
90+
template <typename Check, typename T> using check_type_t = typename check_type<Check, T>::type;
91+
92+
template<typename T, typename F>
93+
_always_inline auto doPrint(T v, F f )
94+
-> check_type_t<decltype(f.printTo(this, v)), size_t> {
95+
return f.printTo(this, v);
96+
}
97+
8598
size_t println(void);
8699

87100
virtual void flush() { /* Empty implementation for backward compatibility */ }
@@ -90,21 +103,26 @@ class Print
90103
template<typename ...Ts> _always_inline size_t println(const Ts &...args) { size_t t = print(args...); return t + println(); }
91104
#else
92105
template<typename T> _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); }
93-
template<typename T> _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); }
106+
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(); }
94107
#endif // __cplusplus >= 201103L
95108

109+
_always_inline size_t print() { return 0; }
96110

97111
/** Variadic methods **/
98112
#if __cplusplus >= 201103L // requires C++11
99-
// Ensure there are at least two parameters to avoid infinite recursion.
100-
// e.g. `StringSumHelper s; print(s)` may be treated as `print(s, ...)`
101-
// with `...` being the empty list, thus calling `print(s)` again.
102-
// (This is because print(StringSumHelper) isn't explicitly defined.)
113+
template<typename T, typename ...Ts>
114+
_always_inline size_t print(const T &arg, const Ts &...args) {
115+
size_t t = doPrint(arg);
116+
return t + print(args...);
117+
}
118+
103119
template<typename T, typename T2, typename ...Ts>
104-
_always_inline size_t print(const T &arg, const T2 &arg2, const Ts &...args) {
105-
size_t t = print(arg);
106-
return t + print(arg2, args...);
120+
_always_inline auto print(const T &arg, const T2 &arg2, const Ts &...args)
121+
-> check_type_t<decltype(doPrint(arg, arg2)), size_t> {
122+
size_t t = doPrint(arg, arg2);
123+
return t + print(args...);
107124
}
125+
/*
108126
// Some methods take an extra int parameter. If so, use these templates.
109127
// In a future, it would be nice to make the base/precision a special type.
110128
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...); }
@@ -117,6 +135,10 @@ class Print
117135
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...); }
118136
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...); }
119137
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...); }
138+
*/
139+
#else
140+
template<typename T> _always_inline size_t print(const T &arg) { return doPrint(arg); }
141+
template<typename T, typename T2> _always_inline size_t print(const T &arg1, const T2& arg2) { return doPrint(arg1, arg2); }
120142
#endif // __cplusplus >= 201103L
121143
};
122144

0 commit comments

Comments
 (0)