JsonDeserializer: use float when the value has few digits

This commit is contained in:
Benoit Blanchon committed 2024-09-04 14:33:14 +02:00
1 parent fd6314e132
commit 1f7a3f3174
8 files changed
+163 -28

No files matched your search

+20 -6
View File
@@ -520,16 +520,30 @@ class JsonDeserializer {
auto number = parseNumber(buffer_);
switch (number.type()) {
case NumberType::UnsignedInteger:
result.setInteger(number.asUnsignedInteger(), resources_);
return DeserializationError::Ok;
if (result.setInteger(number.asUnsignedInteger(), resources_))
return DeserializationError::Ok;
else
return DeserializationError::NoMemory;
case NumberType::SignedInteger:
result.setInteger(number.asSignedInteger(), resources_);
return DeserializationError::Ok;
if (result.setInteger(number.asSignedInteger(), resources_))
return DeserializationError::Ok;
else
return DeserializationError::NoMemory;
case NumberType::Float:
result.setFloat(number.asFloat(), resources_);
return DeserializationError::Ok;
if (result.setFloat(number.asFloat(), resources_))
return DeserializationError::Ok;
else
return DeserializationError::NoMemory;
#if ARDUINOJSON_USE_DOUBLE
case NumberType::Double:
if (result.setFloat(number.asDouble(), resources_))
return DeserializationError::Ok;
else
return DeserializationError::NoMemory;
#endif
default:
return DeserializationError::InvalidInput;
+41 -9
View File
@@ -21,18 +21,27 @@ enum class NumberType : uint8_t {
Invalid,
Float,
SignedInteger,
UnsignedInteger
UnsignedInteger,
#if ARDUINOJSON_USE_DOUBLE
Double,
#endif
};
union NumberValue {
NumberValue() {}
NumberValue(JsonFloat x) : asFloat(x) {}
NumberValue(float x) : asFloat(x) {}
NumberValue(JsonInteger x) : asSignedInteger(x) {}
NumberValue(JsonUInt x) : asUnsignedInteger(x) {}
#if ARDUINOJSON_USE_DOUBLE
NumberValue(double x) : asDouble(x) {}
#endif
JsonInteger asSignedInteger;
JsonUInt asUnsignedInteger;
JsonFloat asFloat;
float asFloat;
#if ARDUINOJSON_USE_DOUBLE
double asDouble;
#endif
};
class Number {
@@ -41,9 +50,12 @@ class Number {
public:
Number() : type_(NumberType::Invalid) {}
Number(JsonFloat value) : type_(NumberType::Float), value_(value) {}
Number(float value) : type_(NumberType::Float), value_(value) {}
Number(JsonInteger value) : type_(NumberType::SignedInteger), value_(value) {}
Number(JsonUInt value) : type_(NumberType::UnsignedInteger), value_(value) {}
#if ARDUINOJSON_USE_DOUBLE
Number(double value) : type_(NumberType::Double), value_(value) {}
#endif
template <typename T>
T convertTo() const {
@@ -54,6 +66,10 @@ class Number {
return convertNumber<T>(value_.asSignedInteger);
case NumberType::UnsignedInteger:
return convertNumber<T>(value_.asUnsignedInteger);
#if ARDUINOJSON_USE_DOUBLE
case NumberType::Double:
return convertNumber<T>(value_.asDouble);
#endif
default:
return T();
}
@@ -73,10 +89,17 @@ class Number {
return value_.asUnsignedInteger;
}
JsonFloat asFloat() const {
float asFloat() const {
ARDUINOJSON_ASSERT(type_ == NumberType::Float);
return value_.asFloat;
}
#if ARDUINOJSON_USE_DOUBLE
double asDouble() const {
ARDUINOJSON_ASSERT(type_ == NumberType::Double);
return value_.asDouble;
}
#endif
};
inline Number parseNumber(const char* s) {
@@ -192,10 +215,19 @@ inline Number parseNumber(const char* s) {
if (*s != '\0')
return Number();
JsonFloat final_result =
make_float(static_cast<JsonFloat>(mantissa), exponent);
return Number(is_negative ? -final_result : final_result);
#if ARDUINOJSON_USE_DOUBLE
bool isDouble = exponent < -FloatTraits<float>::exponent_max ||
exponent > FloatTraits<float>::exponent_max ||
mantissa > FloatTraits<float>::mantissa_max;
if (isDouble) {
auto final_result = make_float(double(mantissa), exponent);
return Number(is_negative ? -final_result : final_result);
} else
#endif
{
auto final_result = make_float(float(mantissa), exponent);
return Number(is_negative ? -final_result : final_result);
}
}
template <typename T>