Added custom implementation of ftoa (issues #266, #267, #269 and #270)

This commit is contained in:
Benoit Blanchon
2016-04-28 18:54:14 +02:00
parent f9f002c8f7
commit a138791964
15 changed files with 396 additions and 139 deletions

View File

@@ -8,6 +8,9 @@
#pragma once
#include "../Arduino/Print.hpp"
#include "../Polyfills/isNaN.hpp"
#include "../Polyfills/isInfinity.hpp"
#include "../Polyfills/normalize.hpp"
#include "Encoding.hpp"
#include "ForceInline.hpp"
#include "JsonFloat.hpp"
@@ -63,10 +66,70 @@ class JsonWriter {
}
}
void writeInteger(JsonUInt value) { _length += _sink.print(value); }
void writeFloat(JsonFloat value, int digits = 2) {
if (Polyfills::isNaN(value)) return writeRaw("NaN");
void writeFloat(JsonFloat value, uint8_t decimals) {
_length += _sink.print(value, decimals);
if (value < 0.0) {
writeRaw('-');
value = -value;
}
if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
short powersOf10;
if (value > 1000 || value < 0.001) {
powersOf10 = Polyfills::normalize(value);
} else {
powersOf10 = 0;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
JsonFloat rounding = 0.5;
for (uint8_t i = 0; i < digits; ++i) rounding /= 10.0;
value += rounding;
// Extract the integer part of the value and print it
JsonUInt int_part = static_cast<JsonUInt>(value);
JsonFloat remainder = value - static_cast<JsonFloat>(int_part);
writeInteger(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits > 0) {
writeRaw('.');
}
// Extract digits from the remainder one at a time
while (digits-- > 0) {
remainder *= 10.0;
JsonUInt toPrint = JsonUInt(remainder);
writeInteger(JsonUInt(remainder));
remainder -= static_cast<JsonFloat>(toPrint);
}
if (powersOf10 < 0) {
writeRaw("e-");
writeInteger(-powersOf10);
}
if (powersOf10 > 0) {
writeRaw('e');
writeInteger(powersOf10);
}
}
void writeInteger(JsonUInt value) {
char buffer[22];
uint8_t i = 0;
do {
buffer[i++] = static_cast<char>(value % 10 + '0');
value /= 10;
} while (value);
while (i > 0) {
writeRaw(buffer[--i]);
}
}
void writeRaw(const char *s) { _length += _sink.print(s); }