Ver Fonte

Reduced stack usage when compiled with -Og (issue #1210)
This saves 96 bytes on ESP8266

Benoit Blanchon há 5 anos atrás
pai
commit
824b7a25ca

+ 5 - 5
extras/tests/Numbers/parseNumber.cpp

@@ -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));
 }

+ 2 - 1
src/ArduinoJson/Json/JsonDeserializer.hpp

@@ -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:

+ 3 - 1
src/ArduinoJson/Numbers/parseFloat.hpp

@@ -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

+ 3 - 1
src/ArduinoJson/Numbers/parseInteger.hpp

@@ -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

+ 38 - 24
src/ArduinoJson/Numbers/parseNumber.hpp

@@ -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