mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01: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; | ||||
|  | ||||
| TEST_CASE("Test uint32_t overflow") { | ||||
|   ParsedNumber<float, uint32_t> first = | ||||
|       parseNumber<float, uint32_t>("4294967295"); | ||||
|   ParsedNumber<float, uint32_t> second = | ||||
|       parseNumber<float, uint32_t>("4294967296"); | ||||
|   ParsedNumber<float, uint32_t> first, second; | ||||
|   parseNumber("4294967295", first); | ||||
|   parseNumber("4294967296", second); | ||||
|  | ||||
|   REQUIRE(first.type() == uint8_t(VALUE_IS_POSITIVE_INTEGER)); | ||||
|   REQUIRE(second.type() == uint8_t(VALUE_IS_FLOAT)); | ||||
| } | ||||
|  | ||||
| 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)); | ||||
| } | ||||
|   | ||||
| @@ -466,7 +466,8 @@ class JsonDeserializer { | ||||
|                     : DeserializationError::IncompleteInput; | ||||
|     } | ||||
|  | ||||
|     ParsedNumber<Float, UInt> num = parseNumber<Float, UInt>(_buffer); | ||||
|     ParsedNumber<Float, UInt> num; | ||||
|     parseNumber<Float, UInt>(_buffer, num); | ||||
|  | ||||
|     switch (num.type()) { | ||||
|       case VALUE_IS_NEGATIVE_INTEGER: | ||||
|   | ||||
| @@ -13,6 +13,8 @@ template <typename T> | ||||
| inline T parseFloat(const char* s) { | ||||
|   // try to reuse the same parameters as JsonDeserializer | ||||
|   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 | ||||
|   | ||||
| @@ -14,6 +14,8 @@ T parseInteger(const char *s) { | ||||
|   // try to reuse the same parameters as JsonDeserializer | ||||
|   typedef typename choose_largest<UInt, typename make_unsigned<T>::type>::type | ||||
|       TUInt; | ||||
|   return parseNumber<Float, TUInt>(s).template as<T>(); | ||||
|   ParsedNumber<Float, TUInt> value; | ||||
|   parseNumber(s, value); | ||||
|   return value.template as<T>(); | ||||
| } | ||||
| }  // namespace ARDUINOJSON_NAMESPACE | ||||
|   | ||||
| @@ -16,14 +16,18 @@ namespace ARDUINOJSON_NAMESPACE { | ||||
|  | ||||
| template <typename TFloat, typename TUInt> | ||||
| struct ParsedNumber { | ||||
|   ParsedNumber() : uintValue(0), floatValue(0), _type(VALUE_IS_NULL) {} | ||||
|   ParsedNumber() : _type(VALUE_IS_NULL) {} | ||||
|  | ||||
|   ParsedNumber(TUInt value, bool is_negative) | ||||
|       : uintValue(value), | ||||
|         floatValue(TFloat(value)), | ||||
|         _type(uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER | ||||
|                                   : VALUE_IS_POSITIVE_INTEGER)) {} | ||||
|   ParsedNumber(TFloat value) : floatValue(value), _type(VALUE_IS_FLOAT) {} | ||||
|   void setInteger(TUInt value, bool is_negative) { | ||||
|     uintValue = value; | ||||
|     _type = uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER | ||||
|                                 : VALUE_IS_POSITIVE_INTEGER); | ||||
|   } | ||||
|  | ||||
|   void setFloat(TFloat value) { | ||||
|     floatValue = value; | ||||
|     _type = VALUE_IS_FLOAT; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   T as() const { | ||||
| @@ -43,21 +47,22 @@ struct ParsedNumber { | ||||
|     return _type; | ||||
|   } | ||||
|  | ||||
|   TUInt uintValue; | ||||
|   TFloat floatValue; | ||||
|   union { | ||||
|     TUInt uintValue; | ||||
|     TFloat floatValue; | ||||
|   }; | ||||
|   uint8_t _type; | ||||
| }; | ||||
| };  // namespace ARDUINOJSON_NAMESPACE | ||||
|  | ||||
| template <typename A, typename B> | ||||
| struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {}; | ||||
|  | ||||
| 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 typename choose_largest<typename traits::mantissa_type, TUInt>::type | ||||
|       mantissa_t; | ||||
|   typedef typename traits::exponent_type exponent_t; | ||||
|   typedef ParsedNumber<TFloat, TUInt> return_type; | ||||
|  | ||||
|   ARDUINOJSON_ASSERT(s != 0); | ||||
|  | ||||
| @@ -73,17 +78,22 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) { | ||||
|   } | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_NAN | ||||
|   if (*s == 'n' || *s == 'N') | ||||
|     return traits::nan(); | ||||
|   if (*s == 'n' || *s == 'N') { | ||||
|     result.setFloat(traits::nan()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_INFINITY | ||||
|   if (*s == 'i' || *s == 'I') | ||||
|     return is_negative ? -traits::inf() : traits::inf(); | ||||
|   if (*s == 'i' || *s == 'I') { | ||||
|     result.setFloat(is_negative ? -traits::inf() : traits::inf()); | ||||
|     return; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   if (!isdigit(*s) && *s != '.') | ||||
|     return return_type(); | ||||
|     return; | ||||
|  | ||||
|   mantissa_t mantissa = 0; | ||||
|   exponent_t exponent_offset = 0; | ||||
| @@ -100,8 +110,10 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) { | ||||
|     s++; | ||||
|   } | ||||
|  | ||||
|   if (*s == '\0') | ||||
|     return return_type(TUInt(mantissa), is_negative); | ||||
|   if (*s == '\0') { | ||||
|     result.setInteger(TUInt(mantissa), is_negative); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   // avoid mantissa overflow | ||||
|   while (mantissa > traits::mantissa_max) { | ||||
| @@ -141,9 +153,10 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) { | ||||
|       exponent = exponent * 10 + (*s - '0'); | ||||
|       if (exponent + exponent_offset > traits::exponent_max) { | ||||
|         if (negative_exponent) | ||||
|           return is_negative ? -0.0f : 0.0f; | ||||
|           result.setFloat(is_negative ? -0.0f : 0.0f); | ||||
|         else | ||||
|           return is_negative ? -traits::inf() : traits::inf(); | ||||
|           result.setFloat(is_negative ? -traits::inf() : traits::inf()); | ||||
|         return; | ||||
|       } | ||||
|       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 | ||||
|   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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user