Skip to content

Commit 870432e

Browse files
committed
improved on base 2 and base 16 print number implementations
added compile flag to disable those additional optimized implementations
1 parent e2f54b1 commit 870432e

File tree

1 file changed

+87
-27
lines changed

1 file changed

+87
-27
lines changed

cores/arduino/Print.cpp

+87-27
Original file line numberDiff line numberDiff line change
@@ -210,34 +210,94 @@ size_t Print::printNumber(unsigned long n, uint8_t base)
210210
// prevent crash if called with base == 1
211211
if (base < 2) base = 10;
212212

213-
unsigned long reverse = 0;
214-
uint8_t digits = 0;
215-
char avoid_overflow = n % base;
216-
217-
// this step and 'avoid_overflow' will make sure it stays in unsigned long range beeing able to print all 10 digits no matter what
218-
n /= base;
219-
220-
// reverse the number and count digits
221-
while (n != 0) {
222-
uint8_t remainder = n % base;
223-
reverse = reverse * base + remainder;
224-
n /= base;
225-
digits++;
226-
}
227-
228-
// from here onwards reuse of variable 'n' to count written chars
229-
while (digits--) {
230-
char c = reverse % base;
231-
reverse /= base;
232-
233-
c = (c < 10 ? c + '0' : c + 'A' - 10);
234-
n += write(c);
213+
// use -D ARDUINO_PRINT_NUMBER_GENERIC_ONLY when compiling to get only the generic version
214+
#ifndef ARDUINO_PRINT_NUMBER_GENERIC_ONLY
215+
switch (base) {
216+
case 16:
217+
// optimized version for hex prints
218+
{
219+
uint8_t *access = (uint8_t*) &n;
220+
uint8_t written = 0;
221+
for (int8_t i=3; i>=0; i--) {
222+
char c;
223+
c = (access[i] & 0xf0) >> 4;
224+
if (c != 0 || written != 0) {
225+
c = (c < 10 ? c + '0' : c + 'A' - 10);
226+
written += write(c);
227+
} // else: skip leading zeros
228+
c = access[i] & 0x0f;
229+
if (c != 0 || written != 0) {
230+
// skip leading zeros
231+
c = (c < 10 ? c + '0' : c + 'A' - 10);
232+
written += write(c);
233+
} // else: skip leading zeros
234+
}
235+
return written;
236+
}
237+
case 2:
238+
// optimized version for binary prints
239+
{
240+
uint8_t *access = (uint8_t*) &n;
241+
uint8_t written = 0;
242+
for (int8_t i=3; i>=0; i--) {
243+
if (access[i] == 0 && written == 0) {
244+
// skip leading zeros
245+
continue;
246+
}
247+
for (int8_t j=7; j>=0; j--) {
248+
char c;
249+
if (j == 0) {
250+
// avoid shift by 0 - undefined
251+
c = (access[i] & 0x01);
252+
} else {
253+
c = (access[i] & 1<<j) >> j;
254+
}
255+
if (c == 0 && written == 0) {
256+
// skip leading zeros
257+
continue;
258+
}
259+
c = (c < 10 ? c + '0' : c + 'A' - 10);
260+
written += write(c);
261+
}
262+
}
263+
return written;
264+
}
265+
default:
266+
// the generic implementation
267+
#endif
268+
{
269+
unsigned long reverse = 0;
270+
uint8_t digits = 0;
271+
char avoid_overflow = n % base;
272+
273+
// this step and 'avoid_overflow' will make sure it stays in unsigned long range beeing able to print all 10 digits no matter what
274+
n /= base;
275+
276+
// reverse the number and count digits
277+
while (n != 0) {
278+
uint8_t remainder = n % base;
279+
reverse = reverse * base + remainder;
280+
n /= base;
281+
digits++;
282+
}
283+
284+
// from here onwards reuse of variable 'n' to count written chars
285+
while (digits--) {
286+
char c = reverse % base;
287+
reverse /= base;
288+
289+
c = (c < 10 ? c + '0' : c + 'A' - 10);
290+
n += write(c);
291+
}
292+
293+
avoid_overflow = (avoid_overflow < 10 ? avoid_overflow + '0' : avoid_overflow + 'A' - 10);
294+
n += write(avoid_overflow);
295+
296+
return n;
297+
}
298+
#ifndef ARDUINO_PRINT_NUMBER_GENERIC_ONLY
235299
}
236-
237-
avoid_overflow = (avoid_overflow < 10 ? avoid_overflow + '0' : avoid_overflow + 'A' - 10);
238-
n += write(avoid_overflow);
239-
240-
return n;
300+
#endif
241301
}
242302

243303
size_t Print::printFloat(double number, uint8_t digits)

0 commit comments

Comments
 (0)