Skip to content

Commit 1e9e9b0

Browse files
mikee47slaff
authored andcommitted
Add support for 64-bit number printing (SmingHub#1822)
Adds support to `Print` and `String` classes for `long long` and `unsigned long long` numbers using revised `stringconversion` routines. `Print` class revised to use `stringconversion` routines for consistency with `String`. Note that Print used its own code for this which produced hex in uppercase, rather than lowercase. `stringconversion` updates: * Fix incorrect `width` parameter passing in `ultoa_wp()` * Move alias functions into header as static inline (removes redundant function calls) * Eliminate code duplication by calling `ultoa_wp` from `ltoa_wp` * Avoid un-necessary use of strlen in conversions * Check `base` parameter and default to base 10 if invalid - this was in Print.cpp but moving it here ensures it's applied consistently * Add 64-bit string conversion functions for `long long` and `unsigned long long`.
1 parent b50a4f8 commit 1e9e9b0

File tree

6 files changed

+313
-262
lines changed

6 files changed

+313
-262
lines changed

Sming/System/include/stringconversion.h

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,75 @@
1717
extern "C" {
1818
#endif
1919

20-
int atoi(const char *nptr); // Already implemented
20+
/*
21+
* Since C does not support default func parameters, we define inline versions which
22+
* translate to ltoa_wp, ultoa_wp, lltoa_wp and ulltoa_wp functions.
23+
*/
2124

2225
extern char* ltoa_wp(long val, char* buffer, int base, int width, char pad);
23-
extern char* ltoa_w (long, char*, int, int width);
24-
extern char* ltoa (long, char*, int);
26+
27+
static inline char* ltoa_w(long val, char* buffer, int base, int width)
28+
{
29+
return ltoa_wp(val, buffer, base, width, ' ');
30+
}
31+
32+
static inline char* ltoa (long val, char* buffer, int base)
33+
{
34+
return ltoa_wp(val, buffer, base, 0, ' ');
35+
}
36+
37+
static inline char* itoa (int val, char* buffer, int base)
38+
{
39+
return ltoa_wp(val, buffer, base, 0, ' ');
40+
}
2541

2642
extern char* ultoa_wp(unsigned long val, char* buffer, unsigned int base, int width, char pad);
27-
extern char* ultoa_w(unsigned long val, char* buffer, unsigned int base, int width);
28-
extern char* ultoa(unsigned long val, char* buffer, unsigned int base);
43+
44+
static inline char* ultoa_w(unsigned long val, char* buffer, unsigned int base, int width)
45+
{
46+
return ultoa_wp(val, buffer, base, width, ' ');
47+
}
48+
49+
static inline char* ultoa(unsigned long val, char* buffer, unsigned int base)
50+
{
51+
return ultoa_wp(val, buffer, base, 0, ' ');
52+
}
53+
54+
extern char* lltoa_wp(long long val, char* buffer, int base, int width, char pad);
55+
56+
static inline char* lltoa_w(long long val, char* buffer, int base, int width)
57+
{
58+
return lltoa_wp(val, buffer, base, width, ' ');
59+
}
60+
61+
static inline char* lltoa(long long val, char* buffer, int base)
62+
{
63+
return lltoa_wp(val, buffer, base, 0, ' ');
64+
}
65+
66+
67+
extern char* ulltoa_wp(unsigned long long val, char* buffer, unsigned int base, int width, char pad);
68+
69+
static inline char* ulltoa_w(unsigned long long val, char* buffer, unsigned int base, int width)
70+
{
71+
return ulltoa_wp(val, buffer, base, width, ' ');
72+
}
73+
74+
static inline char* ulltoa(unsigned long long val, char* buffer, unsigned int base)
75+
{
76+
return ulltoa_wp(val, buffer, base, 0, ' ');
77+
}
78+
2979

3080
extern char* itoa(int, char*, int);
3181

3282
extern char *dtostrf_p(double floatVar, int minStringWidthIncDecimalPoint, int numDigitsAfterDecimal, char *outputBuffer, char pad);
33-
extern char *dtostrf(double floatVar, int minStringWidthIncDecimalPoint, int numDigitsAfterDecimal, char *outputBuffer);
83+
84+
static inline char *dtostrf(double floatVar, int minStringWidthIncDecimalPoint, int numDigitsAfterDecimal, char *outputBuffer)
85+
{
86+
return dtostrf_p(floatVar, minStringWidthIncDecimalPoint, numDigitsAfterDecimal, outputBuffer, ' ');
87+
}
88+
3489
long atol(const char *nptr);
3590
extern long os_strtol(const char* str, char** endptr, int base);
3691
extern double os_strtod(const char* str, char** endptr);

Sming/System/stringconversion.cpp

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,86 +14,97 @@
1414
#include "stringconversion.h"
1515
#include "stringutil.h"
1616

17-
//Since C does not support default func parameters, keep this function as used by framework
18-
//and create extended _w funct to handle width
19-
char* ltoa(long val, char* buffer, int base)
20-
{
21-
return ltoa_w(val, buffer, base, 0);
22-
}
23-
24-
char* itoa (int, char*, int) __attribute__((alias("ltoa")));
2517

26-
char* ltoa_w(long val, char* buffer, int base, int width)
18+
char* ltoa_wp(long val, char* buffer, int base, int width, char pad)
2719
{
28-
return ltoa_wp(val, buffer, base, width, ' ');
20+
if(val < 0) {
21+
*buffer++ = '-';
22+
val = -val;
23+
}
24+
return ultoa_wp((unsigned long)val, buffer, base, width, pad);
2925
}
3026

31-
char* ltoa_wp(long val, char* buffer, int base, int width, char pad)
27+
char* ultoa_wp(unsigned long val, char* buffer, unsigned int base, int width, char pad)
3228
{
33-
int i = 38, p = 0;
34-
char buf[40] = {0};
35-
bool ngt = val < 0;
36-
if (ngt) val = -val;
29+
char buf[40];
30+
constexpr int nulpos = sizeof(buf) - 1;
31+
buf[nulpos] = '\0';
3732

38-
for(; val && i ; --i, p++, val /= base)
39-
buf[i] = hexchar(val % base);
40-
if (p == 0) buf[i--] = '0'; // case for zero
33+
// prevent crash if called with base == 1
34+
if(base < 2 || base > 16) {
35+
base = 10;
36+
}
4137

42-
if (ngt)
43-
buf[i--] = '-';
38+
int i = nulpos - 1;
39+
int p = 0;
40+
for(; val != 0 && i != 0; --i, p++, val /= base) {
41+
buf[i] = hexchar(val % base);
42+
}
43+
if (p == 0) {
44+
buf[i--] = '0'; // case for zero
45+
}
4446

4547
if(width != 0)
4648
{
47-
width -= strlen(&buf[i+1]);
49+
width -= (nulpos - i - 1);
4850
if(width > 0)
4951
{
5052
memset(buffer, pad, width);
5153
}
52-
else width = 0;
54+
else {
55+
width = 0;
56+
}
5357
}
58+
memcpy(buffer + width, &buf[i+1], nulpos - i);
5459

55-
strcpy(buffer + width, &buf[i+1]);
5660
return buffer;
5761
}
5862

59-
//Since C does not support default func parameters, keep this function as used by framework
60-
//and create extended _w funct to handle width
61-
char* ultoa(unsigned long val, char* buffer, unsigned int base)
63+
char* lltoa_wp(long long val, char* buffer, int base, int width, char pad)
6264
{
63-
return ultoa_w(val, buffer, base, 0);
65+
if(val < 0) {
66+
*buffer++ = '-';
67+
val = -val;
68+
}
69+
return ulltoa_wp((unsigned long long)val, buffer, base, width, pad);
6470
}
6571

66-
char* ultoa_w(unsigned long val, char* buffer, unsigned int base, int width)
67-
{
68-
return ultoa_wp(val, buffer, base, 0, ' ');
69-
}
70-
char* ultoa_wp(unsigned long val, char* buffer, unsigned int base, int width, char pad)
72+
char* ulltoa_wp(unsigned long long val, char* buffer, unsigned int base, int width, char pad)
7173
{
72-
int i = 38, p = 0;
73-
char buf[40] = {0};
74+
char buf[80];
75+
constexpr int nulpos = sizeof(buf) - 1;
76+
buf[nulpos] = '\0';
77+
78+
// prevent crash if called with base == 1
79+
if(base < 2) {
80+
base = 10;
81+
}
7482

75-
for(; val && i ; --i, p++, val /= base)
83+
int i = nulpos - 1;
84+
int p = 0;
85+
for(; val != 0 && i != 0; --i, p++, val /= base) {
7686
buf[i] = hexchar(val % base);
77-
if (p == 0) buf[i--] = '0'; // case for zero
87+
}
88+
if (p == 0) {
89+
buf[i--] = '0'; // case for zero
90+
}
7891

7992
if(width != 0)
8093
{
81-
width -= strlen(&buf[i+1]);
94+
width -= (nulpos - i - 1);
8295
if(width > 0)
8396
{
8497
memset(buffer, pad, width);
8598
}
86-
else width = 0;
99+
else {
100+
width = 0;
101+
}
87102
}
88-
strcpy(buffer + width, &buf[i+1]);
103+
memcpy(buffer + width, &buf[i+1], nulpos - i);
89104

90105
return buffer;
91106
}
92107

93-
char *dtostrf(double floatVar, int minStringWidthIncDecimalPoint, int numDigitsAfterDecimal, char *outputBuffer)
94-
{
95-
return dtostrf_p(floatVar, minStringWidthIncDecimalPoint, numDigitsAfterDecimal, outputBuffer, ' ');
96-
}
97108
// Author zitron: http://forum.arduino.cc/index.php?topic=37391#msg276209
98109
// modified by ADiea: remove dependencies strcat, floor, round; reorganize+speedup code
99110
char *dtostrf_p(double floatVar, int minStringWidthIncDecimalPoint, int numDigitsAfterDecimal, char *outputBuffer, char pad)

0 commit comments

Comments
 (0)