2021-03-29 17:14:01 +02:00
|
|
|
// ArduinoJson - https://arduinojson.org
|
2024-01-03 08:47:06 +01:00
|
|
|
// Copyright © 2014-2024, Benoit BLANCHON
|
2019-03-06 15:31:37 +01:00
|
|
|
// MIT License
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2019-08-26 11:57:57 +02:00
|
|
|
#include <ArduinoJson/Numbers/FloatTraits.hpp>
|
|
|
|
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
|
|
|
#include <ArduinoJson/Polyfills/assert.hpp>
|
|
|
|
#include <ArduinoJson/Polyfills/ctype.hpp>
|
|
|
|
#include <ArduinoJson/Polyfills/math.hpp>
|
|
|
|
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
2021-03-20 14:52:47 +01:00
|
|
|
#include <ArduinoJson/Variant/Converter.hpp>
|
2020-09-04 09:23:40 +02:00
|
|
|
#include <ArduinoJson/Variant/VariantData.hpp>
|
2019-03-06 15:31:37 +01:00
|
|
|
|
2023-02-14 10:04:48 +01:00
|
|
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
2019-03-06 15:31:37 +01:00
|
|
|
|
|
|
|
template <typename A, typename B>
|
2024-05-22 09:59:12 +02:00
|
|
|
using largest_type = conditional_t<(sizeof(A) > sizeof(B)), A, B>;
|
2019-03-06 15:31:37 +01:00
|
|
|
|
2020-09-04 09:23:40 +02:00
|
|
|
inline bool parseNumber(const char* s, VariantData& result) {
|
2022-12-19 11:43:20 +01:00
|
|
|
typedef FloatTraits<JsonFloat> traits;
|
2024-05-22 09:59:12 +02:00
|
|
|
typedef largest_type<traits::mantissa_type, JsonUInt> mantissa_t;
|
2020-09-04 09:23:40 +02:00
|
|
|
typedef traits::exponent_type exponent_t;
|
2019-03-06 15:31:37 +01:00
|
|
|
|
|
|
|
ARDUINOJSON_ASSERT(s != 0);
|
|
|
|
|
|
|
|
bool is_negative = false;
|
|
|
|
switch (*s) {
|
|
|
|
case '-':
|
|
|
|
is_negative = true;
|
|
|
|
s++;
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
s++;
|
|
|
|
break;
|
|
|
|
}
|
2019-05-19 15:48:27 +02:00
|
|
|
|
2019-05-18 12:15:36 +02:00
|
|
|
#if ARDUINOJSON_ENABLE_NAN
|
2020-07-26 12:23:55 +02:00
|
|
|
if (*s == 'n' || *s == 'N') {
|
|
|
|
result.setFloat(traits::nan());
|
2020-09-04 09:23:40 +02:00
|
|
|
return true;
|
2020-07-26 12:23:55 +02:00
|
|
|
}
|
2019-05-18 12:15:36 +02:00
|
|
|
#endif
|
2019-05-19 15:48:27 +02:00
|
|
|
|
|
|
|
#if ARDUINOJSON_ENABLE_INFINITY
|
2020-07-26 12:23:55 +02:00
|
|
|
if (*s == 'i' || *s == 'I') {
|
|
|
|
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
2020-09-04 09:23:40 +02:00
|
|
|
return true;
|
2020-07-26 12:23:55 +02:00
|
|
|
}
|
2019-05-19 15:48:27 +02:00
|
|
|
#endif
|
|
|
|
|
2020-02-16 15:05:23 +01:00
|
|
|
if (!isdigit(*s) && *s != '.')
|
2020-09-04 09:23:40 +02:00
|
|
|
return false;
|
2019-03-06 15:31:37 +01:00
|
|
|
|
|
|
|
mantissa_t mantissa = 0;
|
|
|
|
exponent_t exponent_offset = 0;
|
2022-12-19 12:14:16 +01:00
|
|
|
const mantissa_t maxUint = JsonUInt(-1);
|
2019-03-06 15:31:37 +01:00
|
|
|
|
|
|
|
while (isdigit(*s)) {
|
|
|
|
uint8_t digit = uint8_t(*s - '0');
|
2020-02-16 15:05:23 +01:00
|
|
|
if (mantissa > maxUint / 10)
|
|
|
|
break;
|
2019-03-06 15:31:37 +01:00
|
|
|
mantissa *= 10;
|
2020-02-16 15:05:23 +01:00
|
|
|
if (mantissa > maxUint - digit)
|
|
|
|
break;
|
2019-03-06 15:31:37 +01:00
|
|
|
mantissa += digit;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
2020-07-26 12:23:55 +02:00
|
|
|
if (*s == '\0') {
|
2021-04-14 11:42:53 +02:00
|
|
|
if (is_negative) {
|
|
|
|
const mantissa_t sintMantissaMax = mantissa_t(1)
|
2022-12-19 11:46:44 +01:00
|
|
|
<< (sizeof(JsonInteger) * 8 - 1);
|
2021-04-14 11:42:53 +02:00
|
|
|
if (mantissa <= sintMantissaMax) {
|
2022-12-19 11:46:44 +01:00
|
|
|
result.setInteger(JsonInteger(~mantissa + 1));
|
2021-04-14 11:42:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} else {
|
2022-12-19 12:14:16 +01:00
|
|
|
result.setInteger(JsonUInt(mantissa));
|
2021-04-14 11:42:53 +02:00
|
|
|
return true;
|
|
|
|
}
|
2020-07-26 12:23:55 +02:00
|
|
|
}
|
2019-03-06 15:31:37 +01:00
|
|
|
|
|
|
|
// avoid mantissa overflow
|
|
|
|
while (mantissa > traits::mantissa_max) {
|
|
|
|
mantissa /= 10;
|
|
|
|
exponent_offset++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// remaing digits can't fit in the mantissa
|
|
|
|
while (isdigit(*s)) {
|
|
|
|
exponent_offset++;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*s == '.') {
|
|
|
|
s++;
|
|
|
|
while (isdigit(*s)) {
|
|
|
|
if (mantissa < traits::mantissa_max / 10) {
|
|
|
|
mantissa = mantissa * 10 + uint8_t(*s - '0');
|
|
|
|
exponent_offset--;
|
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int exponent = 0;
|
|
|
|
if (*s == 'e' || *s == 'E') {
|
|
|
|
s++;
|
|
|
|
bool negative_exponent = false;
|
|
|
|
if (*s == '-') {
|
|
|
|
negative_exponent = true;
|
|
|
|
s++;
|
|
|
|
} else if (*s == '+') {
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (isdigit(*s)) {
|
|
|
|
exponent = exponent * 10 + (*s - '0');
|
|
|
|
if (exponent + exponent_offset > traits::exponent_max) {
|
|
|
|
if (negative_exponent)
|
2020-07-26 12:23:55 +02:00
|
|
|
result.setFloat(is_negative ? -0.0f : 0.0f);
|
2019-03-06 15:31:37 +01:00
|
|
|
else
|
2020-07-26 12:23:55 +02:00
|
|
|
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
2020-09-04 09:23:40 +02:00
|
|
|
return true;
|
2019-03-06 15:31:37 +01:00
|
|
|
}
|
|
|
|
s++;
|
|
|
|
}
|
2020-02-16 15:05:23 +01:00
|
|
|
if (negative_exponent)
|
|
|
|
exponent = -exponent;
|
2019-03-06 15:31:37 +01:00
|
|
|
}
|
|
|
|
exponent += exponent_offset;
|
|
|
|
|
2019-04-20 15:12:29 +02:00
|
|
|
// we should be at the end of the string, otherwise it's an error
|
2020-02-16 15:05:23 +01:00
|
|
|
if (*s != '\0')
|
2020-09-04 09:23:40 +02:00
|
|
|
return false;
|
2019-04-20 15:12:29 +02:00
|
|
|
|
2022-12-19 11:43:20 +01:00
|
|
|
JsonFloat final_result =
|
2023-02-22 14:35:05 +01:00
|
|
|
make_float(static_cast<JsonFloat>(mantissa), exponent);
|
2019-03-06 15:31:37 +01:00
|
|
|
|
2020-07-26 12:23:55 +02:00
|
|
|
result.setFloat(is_negative ? -final_result : final_result);
|
2020-09-04 09:23:40 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
inline T parseNumber(const char* s) {
|
|
|
|
VariantData value;
|
|
|
|
parseNumber(s, value);
|
2023-07-03 09:20:54 +02:00
|
|
|
return Converter<T>::fromJson(JsonVariantConst(&value, nullptr));
|
2019-03-06 15:31:37 +01:00
|
|
|
}
|
2023-02-14 10:04:48 +01:00
|
|
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|