mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-23 15:27:30 +02:00
Reduced stack usage when compiled with -Og (issue #1210)
This saves 96 bytes on ESP8266
This commit is contained in:
@ -8,17 +8,17 @@
|
|||||||
using namespace ARDUINOJSON_NAMESPACE;
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
TEST_CASE("Test uint32_t overflow") {
|
TEST_CASE("Test uint32_t overflow") {
|
||||||
ParsedNumber<float, uint32_t> first =
|
ParsedNumber<float, uint32_t> first, second;
|
||||||
parseNumber<float, uint32_t>("4294967295");
|
parseNumber("4294967295", first);
|
||||||
ParsedNumber<float, uint32_t> second =
|
parseNumber("4294967296", second);
|
||||||
parseNumber<float, uint32_t>("4294967296");
|
|
||||||
|
|
||||||
REQUIRE(first.type() == uint8_t(VALUE_IS_POSITIVE_INTEGER));
|
REQUIRE(first.type() == uint8_t(VALUE_IS_POSITIVE_INTEGER));
|
||||||
REQUIRE(second.type() == uint8_t(VALUE_IS_FLOAT));
|
REQUIRE(second.type() == uint8_t(VALUE_IS_FLOAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Invalid value") {
|
TEST_CASE("Invalid value") {
|
||||||
ParsedNumber<float, uint32_t> result = parseNumber<float, uint32_t>("6a3");
|
ParsedNumber<float, uint32_t> result;
|
||||||
|
parseNumber("6a3", result);
|
||||||
|
|
||||||
REQUIRE(result.type() == uint8_t(VALUE_IS_NULL));
|
REQUIRE(result.type() == uint8_t(VALUE_IS_NULL));
|
||||||
}
|
}
|
||||||
|
@ -466,7 +466,8 @@ class JsonDeserializer {
|
|||||||
: DeserializationError::IncompleteInput;
|
: DeserializationError::IncompleteInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParsedNumber<Float, UInt> num = parseNumber<Float, UInt>(_buffer);
|
ParsedNumber<Float, UInt> num;
|
||||||
|
parseNumber<Float, UInt>(_buffer, num);
|
||||||
|
|
||||||
switch (num.type()) {
|
switch (num.type()) {
|
||||||
case VALUE_IS_NEGATIVE_INTEGER:
|
case VALUE_IS_NEGATIVE_INTEGER:
|
||||||
|
@ -13,6 +13,8 @@ template <typename T>
|
|||||||
inline T parseFloat(const char* s) {
|
inline T parseFloat(const char* s) {
|
||||||
// try to reuse the same parameters as JsonDeserializer
|
// try to reuse the same parameters as JsonDeserializer
|
||||||
typedef typename choose_largest<Float, T>::type TFloat;
|
typedef typename choose_largest<Float, T>::type TFloat;
|
||||||
return parseNumber<TFloat, UInt>(s).template as<T>();
|
ParsedNumber<TFloat, UInt> value;
|
||||||
|
parseNumber(s, value);
|
||||||
|
return value.template as<T>();
|
||||||
}
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -14,6 +14,8 @@ T parseInteger(const char *s) {
|
|||||||
// try to reuse the same parameters as JsonDeserializer
|
// try to reuse the same parameters as JsonDeserializer
|
||||||
typedef typename choose_largest<UInt, typename make_unsigned<T>::type>::type
|
typedef typename choose_largest<UInt, typename make_unsigned<T>::type>::type
|
||||||
TUInt;
|
TUInt;
|
||||||
return parseNumber<Float, TUInt>(s).template as<T>();
|
ParsedNumber<Float, TUInt> value;
|
||||||
|
parseNumber(s, value);
|
||||||
|
return value.template as<T>();
|
||||||
}
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -16,14 +16,18 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
|
|
||||||
template <typename TFloat, typename TUInt>
|
template <typename TFloat, typename TUInt>
|
||||||
struct ParsedNumber {
|
struct ParsedNumber {
|
||||||
ParsedNumber() : uintValue(0), floatValue(0), _type(VALUE_IS_NULL) {}
|
ParsedNumber() : _type(VALUE_IS_NULL) {}
|
||||||
|
|
||||||
ParsedNumber(TUInt value, bool is_negative)
|
void setInteger(TUInt value, bool is_negative) {
|
||||||
: uintValue(value),
|
uintValue = value;
|
||||||
floatValue(TFloat(value)),
|
_type = uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER
|
||||||
_type(uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER
|
: VALUE_IS_POSITIVE_INTEGER);
|
||||||
: VALUE_IS_POSITIVE_INTEGER)) {}
|
}
|
||||||
ParsedNumber(TFloat value) : floatValue(value), _type(VALUE_IS_FLOAT) {}
|
|
||||||
|
void setFloat(TFloat value) {
|
||||||
|
floatValue = value;
|
||||||
|
_type = VALUE_IS_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T as() const {
|
T as() const {
|
||||||
@ -43,21 +47,22 @@ struct ParsedNumber {
|
|||||||
return _type;
|
return _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
TUInt uintValue;
|
union {
|
||||||
TFloat floatValue;
|
TUInt uintValue;
|
||||||
|
TFloat floatValue;
|
||||||
|
};
|
||||||
uint8_t _type;
|
uint8_t _type;
|
||||||
};
|
}; // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
|
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
|
||||||
|
|
||||||
template <typename TFloat, typename TUInt>
|
template <typename TFloat, typename TUInt>
|
||||||
inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
|
inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||||
typedef FloatTraits<TFloat> traits;
|
typedef FloatTraits<TFloat> traits;
|
||||||
typedef typename choose_largest<typename traits::mantissa_type, TUInt>::type
|
typedef typename choose_largest<typename traits::mantissa_type, TUInt>::type
|
||||||
mantissa_t;
|
mantissa_t;
|
||||||
typedef typename traits::exponent_type exponent_t;
|
typedef typename traits::exponent_type exponent_t;
|
||||||
typedef ParsedNumber<TFloat, TUInt> return_type;
|
|
||||||
|
|
||||||
ARDUINOJSON_ASSERT(s != 0);
|
ARDUINOJSON_ASSERT(s != 0);
|
||||||
|
|
||||||
@ -73,17 +78,22 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_NAN
|
#if ARDUINOJSON_ENABLE_NAN
|
||||||
if (*s == 'n' || *s == 'N')
|
if (*s == 'n' || *s == 'N') {
|
||||||
return traits::nan();
|
result.setFloat(traits::nan());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_INFINITY
|
#if ARDUINOJSON_ENABLE_INFINITY
|
||||||
if (*s == 'i' || *s == 'I')
|
if (*s == 'i' || *s == 'I') {
|
||||||
return is_negative ? -traits::inf() : traits::inf();
|
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!isdigit(*s) && *s != '.')
|
if (!isdigit(*s) && *s != '.')
|
||||||
return return_type();
|
return;
|
||||||
|
|
||||||
mantissa_t mantissa = 0;
|
mantissa_t mantissa = 0;
|
||||||
exponent_t exponent_offset = 0;
|
exponent_t exponent_offset = 0;
|
||||||
@ -100,8 +110,10 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
|
|||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*s == '\0')
|
if (*s == '\0') {
|
||||||
return return_type(TUInt(mantissa), is_negative);
|
result.setInteger(TUInt(mantissa), is_negative);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// avoid mantissa overflow
|
// avoid mantissa overflow
|
||||||
while (mantissa > traits::mantissa_max) {
|
while (mantissa > traits::mantissa_max) {
|
||||||
@ -141,9 +153,10 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
|
|||||||
exponent = exponent * 10 + (*s - '0');
|
exponent = exponent * 10 + (*s - '0');
|
||||||
if (exponent + exponent_offset > traits::exponent_max) {
|
if (exponent + exponent_offset > traits::exponent_max) {
|
||||||
if (negative_exponent)
|
if (negative_exponent)
|
||||||
return is_negative ? -0.0f : 0.0f;
|
result.setFloat(is_negative ? -0.0f : 0.0f);
|
||||||
else
|
else
|
||||||
return is_negative ? -traits::inf() : traits::inf();
|
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
@ -154,10 +167,11 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
|
|||||||
|
|
||||||
// we should be at the end of the string, otherwise it's an error
|
// we should be at the end of the string, otherwise it's an error
|
||||||
if (*s != '\0')
|
if (*s != '\0')
|
||||||
return return_type();
|
return;
|
||||||
|
|
||||||
TFloat result = traits::make_float(static_cast<TFloat>(mantissa), exponent);
|
TFloat final_result =
|
||||||
|
traits::make_float(static_cast<TFloat>(mantissa), exponent);
|
||||||
|
|
||||||
return is_negative ? -result : result;
|
result.setFloat(is_negative ? -final_result : final_result);
|
||||||
}
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
Reference in New Issue
Block a user