Skip to content

Commit cd56dc0

Browse files
authored
restore dtostrf when floats are disabled in printf/scanf + round fix (#7093)
* restore dtostrf+fix when float printing is disabled at link time * fix include file * fix with proposal per review * always use dtostrf
1 parent 0a58172 commit cd56dc0

File tree

1 file changed

+74
-4
lines changed

1 file changed

+74
-4
lines changed

cores/esp8266/core_esp8266_noniso.cpp

+74-4
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@
2222
2323
*/
2424

25-
#include <stdio.h>
2625
#include <stdlib.h>
2726
#include <string.h>
2827
#include <stdbool.h>
2928
#include <stdint.h>
3029
#include <math.h>
30+
#include <limits>
3131
#include "stdlib_noniso.h"
3232

3333
extern "C" {
@@ -41,9 +41,79 @@ char* ultoa(unsigned long value, char* result, int base) {
4141
}
4242

4343
char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
44-
char fmt[32];
45-
sprintf(fmt, "%%%d.%df", width, prec);
46-
sprintf(s, fmt, number);
44+
bool negative = false;
45+
46+
if (isnan(number)) {
47+
strcpy(s, "nan");
48+
return s;
49+
}
50+
if (isinf(number)) {
51+
strcpy(s, "inf");
52+
return s;
53+
}
54+
55+
char* out = s;
56+
57+
int fillme = width; // how many cells to fill for the integer part
58+
if (prec > 0) {
59+
fillme -= (prec+1);
60+
}
61+
62+
// Handle negative numbers
63+
if (number < 0.0) {
64+
negative = true;
65+
fillme--;
66+
number = -number;
67+
}
68+
69+
// Round correctly so that print(1.999, 2) prints as "2.00"
70+
// I optimized out most of the divisions
71+
double rounding = 2.0;
72+
for (uint8_t i = 0; i < prec; ++i)
73+
rounding *= 10.0;
74+
rounding = 1.0 / rounding;
75+
76+
number += rounding;
77+
78+
// Figure out how big our number really is
79+
double tenpow = 1.0;
80+
int digitcount = 1;
81+
double nextpow;
82+
while (number >= (nextpow = (10.0 * tenpow))) {
83+
tenpow = nextpow;
84+
digitcount++;
85+
}
86+
87+
// minimal compensation for possible lack of precision (#7087 addition)
88+
number *= 1 + std::numeric_limits<decltype(number)>::epsilon();
89+
90+
number /= tenpow;
91+
fillme -= digitcount;
92+
93+
// Pad unused cells with spaces
94+
while (fillme-- > 0) {
95+
*out++ = ' ';
96+
}
97+
98+
// Handle negative sign
99+
if (negative) *out++ = '-';
100+
101+
// Print the digits, and if necessary, the decimal point
102+
digitcount += prec;
103+
int8_t digit = 0;
104+
while (digitcount-- > 0) {
105+
digit = (int8_t)number;
106+
if (digit > 9) digit = 9; // insurance
107+
*out++ = (char)('0' | digit);
108+
if ((digitcount == prec) && (prec > 0)) {
109+
*out++ = '.';
110+
}
111+
number -= digit;
112+
number *= 10.0;
113+
}
114+
115+
// make sure the string is terminated
116+
*out = 0;
47117
return s;
48118
}
49119

0 commit comments

Comments
 (0)