Skip to content

Commit 70a6928

Browse files
authored
Merge pull request stm32duino#1173 from fpistm/api-fixes
Update Print/Stream API
2 parents 0f155d0 + 7dfd03b commit 70a6928

File tree

3 files changed

+157
-83
lines changed

3 files changed

+157
-83
lines changed

cores/arduino/Print.cpp

+140-66
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/*
2-
Print.cpp - Base class that provides print() and println()
3-
Copyright (c) 2008 David A. Mellis. All right reserved.
2+
Copyright (c) 2014 Arduino. All right reserved.
43
54
This library is free software; you can redistribute it and/or
65
modify it under the terms of the GNU Lesser General Public
@@ -9,16 +8,13 @@
98
109
This library is distributed in the hope that it will be useful,
1110
but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13-
Lesser General Public License for more details.
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
1413
1514
You should have received a copy of the GNU Lesser General Public
1615
License along with this library; if not, write to the Free Software
1716
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18-
19-
Modified 23 November 2006 by David A. Mellis
20-
Modified 03 August 2015 by Chuck Todd
21-
*/
17+
*/
2218

2319
#include <stdlib.h>
2420
#include <string.h>
@@ -108,6 +104,31 @@ size_t Print::print(unsigned long n, int base)
108104
}
109105
}
110106

107+
size_t Print::print(long long n, int base)
108+
{
109+
if (base == 0) {
110+
return write(n);
111+
} else if (base == 10) {
112+
if (n < 0) {
113+
int t = print('-');
114+
n = -n;
115+
return printULLNumber(n, 10) + t;
116+
}
117+
return printULLNumber(n, 10);
118+
} else {
119+
return printULLNumber(n, base);
120+
}
121+
}
122+
123+
size_t Print::print(unsigned long long n, int base)
124+
{
125+
if (base == 0) {
126+
return write(n);
127+
} else {
128+
return printULLNumber(n, base);
129+
}
130+
}
131+
111132
size_t Print::print(double n, int digits)
112133
{
113134
return printFloat(n, digits);
@@ -186,6 +207,20 @@ size_t Print::println(unsigned long num, int base)
186207
return n;
187208
}
188209

210+
size_t Print::println(long long num, int base)
211+
{
212+
size_t n = print(num, base);
213+
n += println();
214+
return n;
215+
}
216+
217+
size_t Print::println(unsigned long long num, int base)
218+
{
219+
size_t n = print(num, base);
220+
n += println();
221+
return n;
222+
}
223+
189224
size_t Print::println(double num, int digits)
190225
{
191226
size_t n = print(num, digits);
@@ -262,6 +297,100 @@ size_t Print::printNumber(unsigned long n, uint8_t base)
262297
return write(str);
263298
}
264299

300+
/*
301+
void Print::printULLNumber(uint64_t n, uint8_t base)
302+
{
303+
unsigned char buf[16 * sizeof(long)];
304+
unsigned int i = 0;
305+
306+
if (n == 0) {
307+
print((char)'0');
308+
return;
309+
}
310+
311+
while (n > 0) {
312+
buf[i++] = n % base;
313+
n /= base;
314+
}
315+
316+
for (; i > 0; i--) {
317+
print((char)(buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10));
318+
}
319+
}
320+
*/
321+
// REFERENCE IMPLEMENTATION FOR ULL
322+
// size_t Print::printULLNumber(unsigned long long n, uint8_t base)
323+
// {
324+
// // if limited to base 10 and 16 the bufsize can be smaller
325+
// char buf[65];
326+
// char *str = &buf[64];
327+
328+
// *str = '\0';
329+
330+
// // prevent crash if called with base == 1
331+
// if (base < 2) base = 10;
332+
333+
// do {
334+
// unsigned long long t = n / base;
335+
// char c = n - t * base; // faster than c = n%base;
336+
// n = t;
337+
// *--str = c < 10 ? c + '0' : c + 'A' - 10;
338+
// } while(n);
339+
340+
// return write(str);
341+
// }
342+
343+
// FAST IMPLEMENTATION FOR ULL
344+
size_t Print::printULLNumber(unsigned long long n64, uint8_t base)
345+
{
346+
// if limited to base 10 and 16 the bufsize can be 20
347+
char buf[64];
348+
uint8_t i = 0;
349+
uint8_t innerLoops = 0;
350+
351+
// prevent crash if called with base == 1
352+
if (base < 2) {
353+
base = 10;
354+
}
355+
356+
// process chunks that fit in "16 bit math".
357+
uint16_t top = 0xFFFF / base;
358+
uint16_t th16 = 1;
359+
while (th16 < top) {
360+
th16 *= base;
361+
innerLoops++;
362+
}
363+
364+
while (n64 > th16) {
365+
// 64 bit math part
366+
uint64_t q = n64 / th16;
367+
uint16_t r = n64 - q * th16;
368+
n64 = q;
369+
370+
// 16 bit math loop to do remainder. (note buffer is filled reverse)
371+
for (uint8_t j = 0; j < innerLoops; j++) {
372+
uint16_t qq = r / base;
373+
buf[i++] = r - qq * base;
374+
r = qq;
375+
}
376+
}
377+
378+
uint16_t n16 = n64;
379+
while (n16 > 0) {
380+
uint16_t qq = n16 / base;
381+
buf[i++] = n16 - qq * base;
382+
n16 = qq;
383+
}
384+
385+
size_t bytes = i;
386+
for (; i > 0; i--) {
387+
write((char)(buf[i - 1] < 10 ?
388+
'0' + buf[i - 1] :
389+
'A' + buf[i - 1] - 10));
390+
}
391+
return bytes;
392+
}
393+
265394
size_t Print::printFloat(double number, uint8_t digits)
266395
{
267396
size_t n = 0;
@@ -300,71 +429,16 @@ size_t Print::printFloat(double number, uint8_t digits)
300429

301430
// Print the decimal point, but only if there are digits beyond
302431
if (digits > 0) {
303-
n += print(".");
432+
n += print('.');
304433
}
305434

306435
// Extract digits from the remainder one at a time
307436
while (digits-- > 0) {
308437
remainder *= 10.0;
309-
int toPrint = int(remainder);
438+
unsigned int toPrint = (unsigned int)remainder;
310439
n += print(toPrint);
311440
remainder -= toPrint;
312441
}
313442

314443
return n;
315-
}
316-
317-
#ifdef SUPPORT_LONGLONG
318-
319-
void Print::println(int64_t n, uint8_t base)
320-
{
321-
print(n, base);
322-
println();
323-
}
324-
325-
void Print::print(int64_t n, uint8_t base)
326-
{
327-
if (n < 0) {
328-
print((char)'-');
329-
n = -n;
330-
}
331-
if (base < 2) {
332-
base = 2;
333-
}
334-
print((uint64_t)n, base);
335-
}
336-
337-
void Print::println(uint64_t n, uint8_t base)
338-
{
339-
print(n, base);
340-
println();
341-
}
342-
343-
void Print::print(uint64_t n, uint8_t base)
344-
{
345-
if (base < 2) {
346-
base = 2;
347-
}
348-
printLLNumber(n, base);
349-
}
350-
351-
void Print::printLLNumber(uint64_t n, uint8_t base)
352-
{
353-
unsigned char buf[16 * sizeof(long)];
354-
unsigned int i = 0;
355-
356-
if (n == 0) {
357-
print((char)'0');
358-
return;
359-
}
360-
361-
while (n > 0) {
362-
buf[i++] = n % base;
363-
n /= base;
364-
}
365-
366-
for (; i > 0; i--) {
367-
print((char)(buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10));
368-
}
369-
}
370-
#endif
444+
}

cores/arduino/Print.h

+17-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/*
2-
Print.h - Base class that provides print() and println()
3-
Copyright (c) 2008 David A. Mellis. All right reserved.
2+
Copyright (c) 2016 Arduino LLC. All right reserved.
43
54
This library is free software; you can redistribute it and/or
65
modify it under the terms of the GNU Lesser General Public
@@ -9,8 +8,8 @@
98
109
This library is distributed in the hope that it will be useful,
1110
but WITHOUT ANY WARRANTY; without even the implied warranty of
12-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13-
Lesser General Public License for more details.
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
1413
1514
You should have received a copy of the GNU Lesser General Public
1615
License along with this library; if not, write to the Free Software
@@ -32,16 +31,11 @@
3231
#define OCT 8
3332
#define BIN 2
3433

35-
// uncomment next line to support printing of 64 bit ints.
36-
#define SUPPORT_LONGLONG
37-
3834
class Print {
3935
private:
4036
int write_error;
4137
size_t printNumber(unsigned long, uint8_t);
42-
#ifdef SUPPORT_LONGLONG
43-
void printLLNumber(uint64_t, uint8_t);
44-
#endif
38+
size_t printULLNumber(unsigned long long, uint8_t);
4539
size_t printFloat(double, uint8_t);
4640
protected:
4741
void setWriteError(int err = 1)
@@ -74,6 +68,13 @@ class Print {
7468
return write((const uint8_t *)buffer, size);
7569
}
7670

71+
// default to zero, meaning "a single write may block"
72+
// should be overriden by subclasses with buffering
73+
virtual int availableForWrite()
74+
{
75+
return 0;
76+
}
77+
7778
size_t print(const __FlashStringHelper *);
7879
size_t print(const String &);
7980
size_t print(const char[]);
@@ -83,6 +84,8 @@ class Print {
8384
size_t print(unsigned int, int = DEC);
8485
size_t print(long, int = DEC);
8586
size_t print(unsigned long, int = DEC);
87+
size_t print(long long, int = DEC);
88+
size_t print(unsigned long long, int = DEC);
8689
size_t print(double, int = 2);
8790
size_t print(const Printable &);
8891

@@ -95,18 +98,16 @@ class Print {
9598
size_t println(unsigned int, int = DEC);
9699
size_t println(long, int = DEC);
97100
size_t println(unsigned long, int = DEC);
101+
size_t println(long long, int = DEC);
102+
size_t println(unsigned long long, int = DEC);
98103
size_t println(double, int = 2);
99104
size_t println(const Printable &);
100105
size_t println(void);
101-
#ifdef SUPPORT_LONGLONG
102-
void println(int64_t, uint8_t = DEC);
103-
void print(int64_t, uint8_t = DEC);
104-
void println(uint64_t, uint8_t = DEC);
105-
void print(uint64_t, uint8_t = DEC);
106-
#endif
107106

108107
int printf(const char *format, ...);
109108
int printf(const __FlashStringHelper *format, ...);
109+
110+
virtual void flush() { /* Empty implementation for backward compatibility */ }
110111
};
111112

112113
#endif

cores/arduino/Stream.h

-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ class Stream : public Print {
5858
virtual int available() = 0;
5959
virtual int read() = 0;
6060
virtual int peek() = 0;
61-
virtual void flush() = 0;
6261

6362
Stream()
6463
{

0 commit comments

Comments
 (0)