mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	This commit is contained in:
		
							
								
								
									
										37
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -4,9 +4,34 @@ ArduinoJson: change log | |||||||
| HEAD | HEAD | ||||||
| ---- | ---- | ||||||
|  |  | ||||||
|  | * Removed configurable number of decimal places (issues #288, #427 and #506) | ||||||
|  | * Changed exponentation thresholds to `1e7` and `1e-5` (issues #288, #427 and #506) | ||||||
|  | * `JsonVariant::is<double>()` now returns `true` for integers | ||||||
| * Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495) | * Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (issue #495) | ||||||
| * Fixed error `forming reference to reference` (issue #495) | * Fixed error `forming reference to reference` (issue #495) | ||||||
|  |  | ||||||
|  | ### BREAKING CHANGES :warning: | ||||||
|  |  | ||||||
|  | | Old syntax                      | New syntax          | | ||||||
|  | |---------------------------------|---------------------| | ||||||
|  | | `double_with_n_digits(3.14, 2)` | `3.14`              | | ||||||
|  | | `float_with_n_digits(3.14, 2)`  | `3.14f`             | | ||||||
|  | | `obj.set("key", 3.14, 2)`       | `obj["key"] = 3.14` | | ||||||
|  | | `arr.add(3.14, 2)`              | `arr.add(3.14)`     | | ||||||
|  |  | ||||||
|  | | Input     | Old output | New output | | ||||||
|  | |-----------|------------|------------| | ||||||
|  | | `3.14159` | `3.14`     | `3.14159`  | | ||||||
|  | | `42.0`    | `42.00`    | `42`       | | ||||||
|  | | `0.0`     | `0.00`     | `0`        | | ||||||
|  |  | ||||||
|  | | Expression                     | Old result | New result | | ||||||
|  | |--------------------------------|------------|------------| | ||||||
|  | | `JsonVariant(42).is<int>()`    | `true`     | `true`     | | ||||||
|  | | `JsonVariant(42).is<float>()`  | `false`    | `true`     | | ||||||
|  | | `JsonVariant(42).is<double>()` | `false`    | `true`     | | ||||||
|  |  | ||||||
|  |  | ||||||
| v5.9.0 | v5.9.0 | ||||||
| ------ | ------ | ||||||
|  |  | ||||||
| @@ -59,7 +84,8 @@ v5.8.0 | |||||||
| * Added support for `Stream` (issue #300) | * Added support for `Stream` (issue #300) | ||||||
| * Reduced memory consumption by not duplicating spaces and comments | * Reduced memory consumption by not duplicating spaces and comments | ||||||
|  |  | ||||||
| **BREAKING CHANGES**: | ### BREAKING CHANGES :warning: | ||||||
|  |  | ||||||
|  |  | ||||||
| `JsonBuffer::parseObject()` and  `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`. | `JsonBuffer::parseObject()` and  `JsonBuffer::parseArray()` have been pulled down to the derived classes `DynamicJsonBuffer` and `StaticJsonBufferBase`. | ||||||
|  |  | ||||||
| @@ -108,7 +134,8 @@ v5.7.0 | |||||||
| * Added example `StringExample.ino` to show where `String` can be used | * Added example `StringExample.ino` to show where `String` can be used | ||||||
| * Increased default nesting limit to 50 when compiled for a computer (issue #349) | * Increased default nesting limit to 50 when compiled for a computer (issue #349) | ||||||
|  |  | ||||||
| **BREAKING CHANGES**: | ### BREAKING CHANGES :warning: | ||||||
|  |  | ||||||
|  |  | ||||||
| The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return. | The non-template functions `JsonObject::get()` and `JsonArray.get()` have been removed. This means that you need to explicitely tell the type you expect in return. | ||||||
|  |  | ||||||
| @@ -235,7 +262,8 @@ v5.0.7 | |||||||
| * Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)` | * Made library easier to use from a CMake project: simply `add_subdirectory(ArduinoJson/src)` | ||||||
| * Changed `String` to be a `typedef` of `std::string` (issues #142 and #161) | * Changed `String` to be a `typedef` of `std::string` (issues #142 and #161) | ||||||
|  |  | ||||||
| **BREAKING CHANGES**: | ### BREAKING CHANGES :warning: | ||||||
|  |  | ||||||
| - `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"` | - `JsonVariant(true).as<String>()` now returns `"true"` instead of `"1"` | ||||||
| - `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"` | - `JsonVariant(false).as<String>()` now returns `"false"` instead of `"0"` | ||||||
|  |  | ||||||
| @@ -291,7 +319,8 @@ v5.0.0 | |||||||
| * Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) | * Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66) | ||||||
| * Switched to new the library layout (requires Arduino 1.0.6 or above) | * Switched to new the library layout (requires Arduino 1.0.6 or above) | ||||||
|  |  | ||||||
| **BREAKING CHANGES**: | ### BREAKING CHANGES :warning: | ||||||
|  |  | ||||||
| - `JsonObject::add()` was renamed to `set()` | - `JsonObject::add()` was renamed to `set()` | ||||||
| - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` | - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` | ||||||
| - Number of digits of floating point value are now set with `double_with_n_digits()` | - Number of digits of floating point value are now set with `double_with_n_digits()` | ||||||
|   | |||||||
| @@ -68,8 +68,8 @@ root["sensor"] = "gps"; | |||||||
| root["time"] = 1351824120; | root["time"] = 1351824120; | ||||||
|  |  | ||||||
| JsonArray& data = root.createNestedArray("data"); | JsonArray& data = root.createNestedArray("data"); | ||||||
| data.add(48.756080, 6);  // 6 is the number of decimals to print | data.add(48.756080); | ||||||
| data.add(2.302038, 6);   // if not specified, 2 digits are printed | data.add(2.302038); | ||||||
|  |  | ||||||
| root.printTo(Serial); | root.printTo(Serial); | ||||||
| // This prints: | // This prints: | ||||||
|   | |||||||
| @@ -44,8 +44,8 @@ void setup() { | |||||||
|   // It's also possible to create the array separately and add it to the |   // It's also possible to create the array separately and add it to the | ||||||
|   // JsonObject but it's less efficient. |   // JsonObject but it's less efficient. | ||||||
|   JsonArray& data = root.createNestedArray("data"); |   JsonArray& data = root.createNestedArray("data"); | ||||||
|   data.add(double_with_n_digits(48.756080, 6)); |   data.add(48.756080); | ||||||
|   data.add(double_with_n_digits(2.302038, 6)); |   data.add(2.302038); | ||||||
|  |  | ||||||
|   root.printTo(Serial); |   root.printTo(Serial); | ||||||
|   // This prints: |   // This prints: | ||||||
|   | |||||||
| @@ -12,6 +12,17 @@ | |||||||
| #define ARDUINOJSON_ENABLE_DEPRECATED 1 | #define ARDUINOJSON_ENABLE_DEPRECATED 1 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | // control the exponentiation threshold for big numbers | ||||||
|  | // CAUTION: cannot be more that 1e9 !!!! | ||||||
|  | #ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD | ||||||
|  | #define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | // control the exponentiation threshold for small numbers | ||||||
|  | #ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD | ||||||
|  | #define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef ARDUINO  // assume this is an embedded platform | #ifdef ARDUINO  // assume this is an embedded platform | ||||||
|  |  | ||||||
| // store using float instead of double to reduce the memory usage (issue #134) | // store using float instead of double to reduce the memory usage (issue #134) | ||||||
|   | |||||||
| @@ -20,20 +20,11 @@ enum JsonVariantType { | |||||||
|   JSON_UNPARSED,          // JsonVariant contains an unparsed string |   JSON_UNPARSED,          // JsonVariant contains an unparsed string | ||||||
|   JSON_STRING,            // JsonVariant stores a const char* |   JSON_STRING,            // JsonVariant stores a const char* | ||||||
|   JSON_BOOLEAN,           // JsonVariant stores a bool |   JSON_BOOLEAN,           // JsonVariant stores a bool | ||||||
|   JSON_POSITIVE_INTEGER,  // JsonVariant stores an unsigned long |   JSON_POSITIVE_INTEGER,  // JsonVariant stores an JsonUInt | ||||||
|   JSON_NEGATIVE_INTEGER,  // JsonVariant stores an unsigned long that must be |   JSON_NEGATIVE_INTEGER,  // JsonVariant stores an JsonUInt that must be negated | ||||||
|                           // negated |  | ||||||
|   JSON_ARRAY,             // JsonVariant stores a pointer to a JsonArray |   JSON_ARRAY,             // JsonVariant stores a pointer to a JsonArray | ||||||
|   JSON_OBJECT,            // JsonVariant stores a pointer to a JsonObject |   JSON_OBJECT,            // JsonVariant stores a pointer to a JsonObject | ||||||
|  |   JSON_FLOAT              // JsonVariant stores a JsonFloat | ||||||
|   // The following values are reserved for float values |  | ||||||
|   // Multiple values are used for double, depending on the number of decimal |  | ||||||
|   // digits that must be printed in the JSON output. |  | ||||||
|   // This little trick allow to save one extra member in JsonVariant |  | ||||||
|   JSON_FLOAT_0_DECIMALS |  | ||||||
|   // JSON_FLOAT_1_DECIMAL |  | ||||||
|   // JSON_FLOAT_2_DECIMALS |  | ||||||
|   // ... |  | ||||||
| }; | }; | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -76,8 +76,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>, | |||||||
|   // bool add(TValue value, uint8_t decimals); |   // bool add(TValue value, uint8_t decimals); | ||||||
|   // TValue = float, double |   // TValue = float, double | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool add(T value, uint8_t decimals) { |   DEPRECATED("Second argument is not supported anymore") | ||||||
|     return add_impl<const JsonVariant &>(JsonVariant(value, decimals)); |   bool add(T value, uint8_t) { | ||||||
|  |     return add_impl<const JsonVariant &>(JsonVariant(value)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Sets the value at specified index. |   // Sets the value at specified index. | ||||||
|   | |||||||
| @@ -81,8 +81,9 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> { | |||||||
|   // bool set(TValue, uint8_t decimals); |   // bool set(TValue, uint8_t decimals); | ||||||
|   // TValue = float, double |   // TValue = float, double | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { |   DEPRECATED("Second argument is not supported anymore") | ||||||
|     return _array.set(_index, value, decimals); |   FORCE_INLINE bool set(const TValue& value, uint8_t) { | ||||||
|  |     return _array.set(_index, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   | |||||||
| @@ -134,23 +134,25 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>, | |||||||
|   // TKey = const std::string&, const String& |   // TKey = const std::string&, const String& | ||||||
|   // TValue = float, double |   // TValue = float, double | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|  |   DEPRECATED("Second argument is not supported anymore") | ||||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value && |   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value && | ||||||
|                                     !TypeTraits::IsArray<TString>::value, |                                     !TypeTraits::IsArray<TString>::value, | ||||||
|                                 bool>::type |                                 bool>::type | ||||||
|   set(const TString& key, TValue value, uint8_t decimals) { |       set(const TString& key, TValue value, uint8_t) { | ||||||
|     return set_impl<const TString&, const JsonVariant&>( |     return set_impl<const TString&, const JsonVariant&>(key, | ||||||
|         key, JsonVariant(value, decimals)); |                                                         JsonVariant(value)); | ||||||
|   } |   } | ||||||
|   // |   // | ||||||
|   // bool set(TKey, TValue, uint8_t decimals); |   // bool set(TKey, TValue, uint8_t decimals); | ||||||
|   // TKey = const char*, const char[N], const FlashStringHelper* |   // TKey = const char*, const char[N], const FlashStringHelper* | ||||||
|   // TValue = float, double |   // TValue = float, double | ||||||
|   template <typename TValue, typename TString> |   template <typename TValue, typename TString> | ||||||
|  |   DEPRECATED("Second argument is not supported anymore") | ||||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, |   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<TValue>::value, | ||||||
|                                 bool>::type |                                 bool>::type | ||||||
|   set(const TString* key, TValue value, uint8_t decimals) { |       set(const TString* key, TValue value, uint8_t) { | ||||||
|     return set_impl<const TString*, const JsonVariant&>( |     return set_impl<const TString*, const JsonVariant&>(key, | ||||||
|         key, JsonVariant(value, decimals)); |                                                         JsonVariant(value)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Gets the value associated with the specified key. |   // Gets the value associated with the specified key. | ||||||
|   | |||||||
| @@ -93,8 +93,9 @@ class JsonObjectSubscript | |||||||
|   // bool set(TValue, uint8_t decimals); |   // bool set(TValue, uint8_t decimals); | ||||||
|   // TValue = float, double |   // TValue = float, double | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { |   DEPRECATED("Second argument is not supported anymore") | ||||||
|     return _object.set(_key, value, decimals); |   FORCE_INLINE bool set(const TValue& value, uint8_t) { | ||||||
|  |     return _object.set(_key, value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   | |||||||
| @@ -56,16 +56,22 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create a JsonVariant containing a floating point value. |   // Create a JsonVariant containing a floating point value. | ||||||
|   // The second argument specifies the number of decimal digits to write in |   // JsonVariant(double value); | ||||||
|   // the JSON string. |   // JsonVariant(float value); | ||||||
|   // JsonVariant(double value, uint8_t decimals); |  | ||||||
|   // JsonVariant(float value, uint8_t decimals); |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   JsonVariant(T value, uint8_t decimals = 2, |   JsonVariant(T value, typename TypeTraits::EnableIf< | ||||||
|  |                            TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||||
|  |     using namespace Internals; | ||||||
|  |     _type = JSON_FLOAT; | ||||||
|  |     _content.asFloat = static_cast<JsonFloat>(value); | ||||||
|  |   } | ||||||
|  |   template <typename T> | ||||||
|  |   DEPRECATED("Second argument is not supported anymore") | ||||||
|  |   JsonVariant(T value, uint8_t, | ||||||
|               typename TypeTraits::EnableIf< |               typename TypeTraits::EnableIf< | ||||||
|                   TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { |                   TypeTraits::IsFloatingPoint<T>::value>::type * = 0) { | ||||||
|     using namespace Internals; |     using namespace Internals; | ||||||
|     _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals); |     _type = JSON_FLOAT; | ||||||
|     _content.asFloat = static_cast<JsonFloat>(value); |     _content.asFloat = static_cast<JsonFloat>(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -342,11 +348,13 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | |||||||
|   Internals::JsonVariantContent _content; |   Internals::JsonVariantContent _content; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| inline JsonVariant float_with_n_digits(float value, uint8_t digits) { | DEPRECATED("Decimal places are ignored, use the float value instead") | ||||||
|   return JsonVariant(value, digits); | inline JsonVariant float_with_n_digits(float value, uint8_t) { | ||||||
|  |   return JsonVariant(value); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline JsonVariant double_with_n_digits(double value, uint8_t digits) { | DEPRECATED("Decimal places are ignored, use the double value instead") | ||||||
|   return JsonVariant(value, digits); | inline JsonVariant double_with_n_digits(double value, uint8_t) { | ||||||
|  |   return JsonVariant(value); | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -117,7 +117,7 @@ inline bool JsonVariant::variantIsInteger() const { | |||||||
| inline bool JsonVariant::variantIsFloat() const { | inline bool JsonVariant::variantIsFloat() const { | ||||||
|   using namespace Internals; |   using namespace Internals; | ||||||
|  |  | ||||||
|   return _type >= JSON_FLOAT_0_DECIMALS || |   return _type == JSON_FLOAT || _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER ||  | ||||||
|          (_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString)); |          (_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString)); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,24 +19,23 @@ inline bool isFloat(const char* s) { | |||||||
|   if (!strcmp(s, "NaN")) return true; |   if (!strcmp(s, "NaN")) return true; | ||||||
|   if (issign(*s)) s++; |   if (issign(*s)) s++; | ||||||
|   if (!strcmp(s, "Infinity")) return true; |   if (!strcmp(s, "Infinity")) return true; | ||||||
|  |   if (*s == '\0') return false; | ||||||
|  |  | ||||||
|   while (isdigit(*s)) s++; |   while (isdigit(*s)) s++; | ||||||
|  |  | ||||||
|   bool has_dot = *s == '.'; |   if (*s == '.') { | ||||||
|   if (has_dot) { |  | ||||||
|     s++; |     s++; | ||||||
|     while (isdigit(*s)) s++; |     while (isdigit(*s)) s++; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool has_exponent = *s == 'e' || *s == 'E'; |   if (*s == 'e' || *s == 'E') { | ||||||
|   if (has_exponent) { |  | ||||||
|     s++; |     s++; | ||||||
|     if (issign(*s)) s++; |     if (issign(*s)) s++; | ||||||
|     if (!isdigit(*s)) return false; |     if (!isdigit(*s)) return false; | ||||||
|     while (isdigit(*s)) s++; |     while (isdigit(*s)) s++; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return (has_dot || has_exponent) && *s == '\0'; |   return *s == '\0'; | ||||||
| } | } | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,41 +7,97 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "../Configuration.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Polyfills { | namespace Polyfills { | ||||||
|  |  | ||||||
| #ifdef ARDUINO |  | ||||||
|  |  | ||||||
| // on embedded platform, favor code size over speed |  | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| short normalize(T& value) { | int16_t normalize(T& value) { | ||||||
|   short powersOf10 = 0; |   int16_t powersOf10 = 0; | ||||||
|   while (value && value < 1) { |  | ||||||
|     powersOf10--; |   if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) { | ||||||
|     value *= 10; | #if !defined(__SIZEOF_DOUBLE__) || __SIZEOF_DOUBLE__ >= 8 | ||||||
|  |     if (value >= 1e256) { | ||||||
|  |       value /= 1e256; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 256); | ||||||
|     } |     } | ||||||
|   while (value > 10) { |     if (value >= 1e128) { | ||||||
|     powersOf10++; |       value /= 1e128; | ||||||
|     value /= 10; |       powersOf10 = int16_t(powersOf10 + 128); | ||||||
|     } |     } | ||||||
|   return powersOf10; |     if (value >= 1e64) { | ||||||
|  |       value /= 1e64; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 64); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| #else |  | ||||||
|  |  | ||||||
| // on non-embedded platform, favor speed over code size |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| short normalize(T& value) { |  | ||||||
|   if (value == 0.0) return 0; |  | ||||||
|  |  | ||||||
|   short powersOf10 = static_cast<short>(floor(log10(value))); |  | ||||||
|   value /= pow(T(10), powersOf10); |  | ||||||
|  |  | ||||||
|   return powersOf10; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |     if (value >= 1e32) { | ||||||
|  |       value /= 1e32; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 32); | ||||||
|  |     } | ||||||
|  |     if (value >= 1e16) { | ||||||
|  |       value /= 1e16; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 16); | ||||||
|  |     } | ||||||
|  |     if (value >= 1e8) { | ||||||
|  |       value /= 1e8; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 8); | ||||||
|  |     } | ||||||
|  |     if (value >= 1e4) { | ||||||
|  |       value /= 1e4; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 4); | ||||||
|  |     } | ||||||
|  |     if (value >= 1e2) { | ||||||
|  |       value /= 1e2; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 2); | ||||||
|  |     } | ||||||
|  |     if (value >= 1e1) { | ||||||
|  |       value /= 1e1; | ||||||
|  |       powersOf10 = int16_t(powersOf10 + 1); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) { | ||||||
|  | #if !defined(__SIZEOF_DOUBLE__) || __SIZEOF_DOUBLE__ >= 8 | ||||||
|  |     if (value < 1e-255) { | ||||||
|  |       value *= 1e256; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 256); | ||||||
|  |     } | ||||||
|  |     if (value < 1e-127) { | ||||||
|  |       value *= 1e128; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 128); | ||||||
|  |     } | ||||||
|  |     if (value < 1e-63) { | ||||||
|  |       value *= 1e64; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 64); | ||||||
|  |     } | ||||||
|  | #endif | ||||||
|  |     if (value < 1e-31) { | ||||||
|  |       value *= 1e32; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 32); | ||||||
|  |     } | ||||||
|  |     if (value < 1e-15) { | ||||||
|  |       value *= 1e16; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 16); | ||||||
|  |     } | ||||||
|  |     if (value < 1e-7) { | ||||||
|  |       value *= 1e8; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 8); | ||||||
|  |     } | ||||||
|  |     if (value < 1e-3) { | ||||||
|  |       value *= 1e4; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 4); | ||||||
|  |     } | ||||||
|  |     if (value < 1e-1) { | ||||||
|  |       value *= 1e2; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 2); | ||||||
|  |     } | ||||||
|  |     if (value < 1e0) { | ||||||
|  |       value *= 1e1; | ||||||
|  |       powersOf10 = int16_t(powersOf10 - 1); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return powersOf10; | ||||||
|  | } | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -69,7 +69,8 @@ template <typename Writer> | |||||||
| inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize( | inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize( | ||||||
|     const JsonVariant& variant, Writer& writer) { |     const JsonVariant& variant, Writer& writer) { | ||||||
|   switch (variant._type) { |   switch (variant._type) { | ||||||
|     case JSON_UNDEFINED: |     case JSON_FLOAT: | ||||||
|  |       writer.writeFloat(variant._content.asFloat); | ||||||
|       return; |       return; | ||||||
|  |  | ||||||
|     case JSON_ARRAY: |     case JSON_ARRAY: | ||||||
| @@ -98,9 +99,7 @@ inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize( | |||||||
|       writer.writeBoolean(variant._content.asInteger != 0); |       writer.writeBoolean(variant._content.asInteger != 0); | ||||||
|       return; |       return; | ||||||
|  |  | ||||||
|     default: |     default:  // JSON_UNDEFINED | ||||||
|       uint8_t decimals = |       return; | ||||||
|           static_cast<uint8_t>(variant._type - JSON_FLOAT_0_DECIMALS); |  | ||||||
|       writer.writeFloat(variant._content.asFloat, decimals); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ | |||||||
| #include "../Polyfills/attributes.hpp" | #include "../Polyfills/attributes.hpp" | ||||||
| #include "../Polyfills/math.hpp" | #include "../Polyfills/math.hpp" | ||||||
| #include "../Polyfills/normalize.hpp" | #include "../Polyfills/normalize.hpp" | ||||||
|  | #include "../TypeTraits/FloatTraits.hpp" | ||||||
|  |  | ||||||
| namespace ArduinoJson { | namespace ArduinoJson { | ||||||
| namespace Internals { | namespace Internals { | ||||||
| @@ -27,40 +28,28 @@ namespace Internals { | |||||||
| // indentation. | // indentation. | ||||||
| template <typename Print> | template <typename Print> | ||||||
| class JsonWriter { | class JsonWriter { | ||||||
|  |   static const uint8_t maxDecimalPlaces = sizeof(JsonFloat) >= 8 ? 9 : 6; | ||||||
|  |   static const uint32_t maxDecimalPart = | ||||||
|  |       sizeof(JsonFloat) >= 8 ? 1000000000 : 1000000; | ||||||
|  |  | ||||||
|  public: |  public: | ||||||
|   explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} |   explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} | ||||||
|  |  | ||||||
|   // Returns the number of bytes sent to the Print implementation. |   // Returns the number of bytes sent to the Print implementation. | ||||||
|   // This is very handy for implementations of printTo() that must return the |   // This is very handy for implementations of printTo() that must return the | ||||||
|   // number of bytes written. |   // number of bytes written. | ||||||
|   size_t bytesWritten() const { |   size_t bytesWritten() const { return _length; } | ||||||
|     return _length; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void beginArray() { |   void beginArray() { writeRaw('['); } | ||||||
|     writeRaw('['); |   void endArray() { writeRaw(']'); } | ||||||
|   } |  | ||||||
|   void endArray() { |  | ||||||
|     writeRaw(']'); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void beginObject() { |   void beginObject() { writeRaw('{'); } | ||||||
|     writeRaw('{'); |   void endObject() { writeRaw('}'); } | ||||||
|   } |  | ||||||
|   void endObject() { |  | ||||||
|     writeRaw('}'); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void writeColon() { |   void writeColon() { writeRaw(':'); } | ||||||
|     writeRaw(':'); |   void writeComma() { writeRaw(','); } | ||||||
|   } |  | ||||||
|   void writeComma() { |  | ||||||
|     writeRaw(','); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void writeBoolean(bool value) { |   void writeBoolean(bool value) { writeRaw(value ? "true" : "false"); } | ||||||
|     writeRaw(value ? "true" : "false"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void writeString(const char *value) { |   void writeString(const char *value) { | ||||||
|     if (!value) { |     if (!value) { | ||||||
| @@ -82,7 +71,7 @@ class JsonWriter { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeFloat(JsonFloat value, uint8_t digits = 2) { |   void writeFloat(JsonFloat value) { | ||||||
|     if (Polyfills::isNaN(value)) return writeRaw("NaN"); |     if (Polyfills::isNaN(value)) return writeRaw("NaN"); | ||||||
|  |  | ||||||
|     if (value < 0.0) { |     if (value < 0.0) { | ||||||
| @@ -92,36 +81,12 @@ class JsonWriter { | |||||||
|  |  | ||||||
|     if (Polyfills::isInfinity(value)) return writeRaw("Infinity"); |     if (Polyfills::isInfinity(value)) return writeRaw("Infinity"); | ||||||
|  |  | ||||||
|     short powersOf10; |     uint32_t integralPart, decimalPart; | ||||||
|     if (value > 1000 || value < 0.001) { |     int16_t powersOf10; | ||||||
|       powersOf10 = Polyfills::normalize(value); |     splitFloat(value, integralPart, decimalPart, powersOf10); | ||||||
|     } else { |  | ||||||
|       powersOf10 = 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Round up last digit (so that print(1.999, 2) prints as "2.00") |     writeInteger(integralPart); | ||||||
|     value += getRoundingBias(digits); |     if (decimalPart) writeDecimals(decimalPart, maxDecimalPlaces); | ||||||
|  |  | ||||||
|     // Extract the integer part of the value and print it |  | ||||||
|     JsonUInt int_part = static_cast<JsonUInt>(value); |  | ||||||
|     JsonFloat remainder = value - static_cast<JsonFloat>(int_part); |  | ||||||
|     writeInteger(int_part); |  | ||||||
|  |  | ||||||
|     // Print the decimal point, but only if there are digits beyond |  | ||||||
|     if (digits > 0) { |  | ||||||
|       writeRaw('.'); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Extract digits from the remainder one at a time |  | ||||||
|     while (digits-- > 0) { |  | ||||||
|       // Extract digit |  | ||||||
|       remainder *= 10.0; |  | ||||||
|       char currentDigit = char(remainder); |  | ||||||
|       remainder -= static_cast<JsonFloat>(currentDigit); |  | ||||||
|  |  | ||||||
|       // Print |  | ||||||
|       writeRaw(char('0' + currentDigit)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (powersOf10 < 0) { |     if (powersOf10 < 0) { | ||||||
|       writeRaw("e-"); |       writeRaw("e-"); | ||||||
| @@ -134,25 +99,46 @@ class JsonWriter { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeInteger(JsonUInt value) { |   template <typename UInt> | ||||||
|  |   void writeInteger(UInt value) { | ||||||
|     char buffer[22]; |     char buffer[22]; | ||||||
|     char *ptr = buffer + sizeof(buffer) - 1; |     char *ptr = buffer + sizeof(buffer) - 1; | ||||||
|  |  | ||||||
|     *ptr = 0; |     *ptr = 0; | ||||||
|     do { |     do { | ||||||
|       *--ptr = static_cast<char>(value % 10 + '0'); |       *--ptr = static_cast<char>(value % 10 + '0'); | ||||||
|       value /= 10; |       value = UInt(value / 10); | ||||||
|     } while (value); |     } while (value); | ||||||
|  |  | ||||||
|     writeRaw(ptr); |     writeRaw(ptr); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void writeRaw(const char *s) { |   void writeDecimals(uint32_t value, int8_t width) { | ||||||
|     _length += _sink.print(s); |     // remove trailing zeros | ||||||
|  |     while (value % 10 == 0 && width > 0) { | ||||||
|  |       value /= 10; | ||||||
|  |       width--; | ||||||
|     } |     } | ||||||
|   void writeRaw(char c) { |  | ||||||
|     _length += _sink.print(c); |     // buffer should be big enough for all digits, the dot and the null | ||||||
|  |     // terminator | ||||||
|  |     char buffer[maxDecimalPlaces + 2]; | ||||||
|  |     char *ptr = buffer + sizeof(buffer) - 1; | ||||||
|  |  | ||||||
|  |     // write the string in reverse order | ||||||
|  |     *ptr = 0; | ||||||
|  |     while (width--) { | ||||||
|  |       *--ptr = char(value % 10 + '0'); | ||||||
|  |       value /= 10; | ||||||
|     } |     } | ||||||
|  |     *--ptr = '.'; | ||||||
|  |  | ||||||
|  |     // and dump it in the right order | ||||||
|  |     writeRaw(ptr); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void writeRaw(const char *s) { _length += _sink.print(s); } | ||||||
|  |   void writeRaw(char c) { _length += _sink.print(c); } | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
|   Print &_sink; |   Print &_sink; | ||||||
| @@ -161,24 +147,28 @@ class JsonWriter { | |||||||
|  private: |  private: | ||||||
|   JsonWriter &operator=(const JsonWriter &);  // cannot be assigned |   JsonWriter &operator=(const JsonWriter &);  // cannot be assigned | ||||||
|  |  | ||||||
|   static JsonFloat getLastDigit(uint8_t digits) { |   void splitFloat(JsonFloat value, uint32_t &integralPart, | ||||||
|     // Designed as a compromise between code size and speed |                   uint32_t &decimalPart, int16_t &powersOf10) { | ||||||
|     switch (digits) { |     powersOf10 = Polyfills::normalize(value); | ||||||
|       case 0: |  | ||||||
|         return 1e-0; |  | ||||||
|       case 1: |  | ||||||
|         return 1e-1; |  | ||||||
|       case 2: |  | ||||||
|         return 1e-2; |  | ||||||
|       case 3: |  | ||||||
|         return 1e-3; |  | ||||||
|       default: |  | ||||||
|         return getLastDigit(uint8_t(digits - 4)) * 1e-4; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE static JsonFloat getRoundingBias(uint8_t digits) { |     integralPart = uint32_t(value); | ||||||
|     return 0.5 * getLastDigit(digits); |     JsonFloat remainder = value - JsonFloat(integralPart); | ||||||
|  |  | ||||||
|  |     decimalPart = uint32_t(remainder * maxDecimalPart); | ||||||
|  |     remainder = remainder * maxDecimalPart - JsonFloat(decimalPart); | ||||||
|  |  | ||||||
|  |     // rounding | ||||||
|  |     if (remainder > 0.5) { | ||||||
|  |       decimalPart++; | ||||||
|  |       if (decimalPart >= maxDecimalPart) { | ||||||
|  |         decimalPart -= maxDecimalPart; | ||||||
|  |         integralPart++; | ||||||
|  |         if (powersOf10 && integralPart >= 10) { | ||||||
|  |           powersOf10++; | ||||||
|  |           integralPart /= 10; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
| #include "../Configuration.hpp" | #include "../Configuration.hpp" | ||||||
| #include "../TypeTraits/EnableIf.hpp" | #include "../TypeTraits/EnableIf.hpp" | ||||||
| #include "../TypeTraits/IsBaseOf.hpp" | #include "../TypeTraits/IsBaseOf.hpp" | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ struct FloatTraits<T, 8 /*64bits*/> { | |||||||
|              (e & 8 ? 1e8 : 1) * (e & 16 ? 1e16 : 1) * (e & 32 ? 1e32 : 1) * |              (e & 8 ? 1e8 : 1) * (e & 16 ? 1e16 : 1) * (e & 32 ? 1e32 : 1) * | ||||||
|              (e & 64 ? 1e64 : 1) * (e & 128 ? 1e128 : 1) * |              (e & 64 ? 1e64 : 1) * (e & 128 ? 1e128 : 1) * | ||||||
|              (e & 256 ? 1e256 : 1); |              (e & 256 ? 1e256 : 1); | ||||||
|     e = -e; |     e = TExponent(-e); | ||||||
|     return m * (e & 1 ? 1e-1 : 1) * (e & 2 ? 1e-2 : 1) * (e & 4 ? 1e-4 : 1) * |     return m * (e & 1 ? 1e-1 : 1) * (e & 2 ? 1e-2 : 1) * (e & 4 ? 1e-4 : 1) * | ||||||
|            (e & 8 ? 1e-8 : 1) * (e & 16 ? 1e-16 : 1) * (e & 32 ? 1e-32 : 1) * |            (e & 8 ? 1e-8 : 1) * (e & 16 ? 1e-16 : 1) * (e & 32 ? 1e-32 : 1) * | ||||||
|            (e & 64 ? 1e-64 : 1) * (e & 128 ? 1e-128 : 1) * |            (e & 64 ? 1e-64 : 1) * (e & 128 ? 1e-128 : 1) * | ||||||
|   | |||||||
| @@ -17,28 +17,28 @@ TEST_CASE("JsonArray::add()") { | |||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == _array.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreInteger") { |   SECTION("int") { | ||||||
|     _array.add(123); |     _array.add(123); | ||||||
|     REQUIRE(123 == _array[0].as<int>()); |     REQUIRE(123 == _array[0].as<int>()); | ||||||
|     REQUIRE(_array[0].is<int>()); |     REQUIRE(_array[0].is<int>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<double>()); |     REQUIRE(_array[0].is<double>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreDouble") { |   SECTION("double") { | ||||||
|     _array.add(123.45); |     _array.add(123.45); | ||||||
|     REQUIRE(123.45 == _array[0].as<double>()); |     REQUIRE(123.45 == _array[0].as<double>()); | ||||||
|     REQUIRE(_array[0].is<double>()); |     REQUIRE(_array[0].is<double>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreBoolean") { |   SECTION("bool") { | ||||||
|     _array.add(true); |     _array.add(true); | ||||||
|     REQUIRE(true == _array[0].as<bool>()); |     REQUIRE(true == _array[0].as<bool>()); | ||||||
|     REQUIRE(_array[0].is<bool>()); |     REQUIRE(_array[0].is<bool>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreString") { |   SECTION("const char*") { | ||||||
|     const char* str = "hello"; |     const char* str = "hello"; | ||||||
|     _array.add(str); |     _array.add(str); | ||||||
|     REQUIRE(str == _array[0].as<const char*>()); |     REQUIRE(str == _array[0].as<const char*>()); | ||||||
| @@ -46,7 +46,7 @@ TEST_CASE("JsonArray::add()") { | |||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreNestedArray") { |   SECTION("nested array") { | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|  |  | ||||||
|     _array.add(arr); |     _array.add(arr); | ||||||
| @@ -56,7 +56,7 @@ TEST_CASE("JsonArray::add()") { | |||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreNestedObject") { |   SECTION("nested object") { | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|     _array.add(obj); |     _array.add(obj); | ||||||
| @@ -66,7 +66,7 @@ TEST_CASE("JsonArray::add()") { | |||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreArraySubscript") { |   SECTION("array subscript") { | ||||||
|     const char* str = "hello"; |     const char* str = "hello"; | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|     arr.add(str); |     arr.add(str); | ||||||
| @@ -76,7 +76,7 @@ TEST_CASE("JsonArray::add()") { | |||||||
|     REQUIRE(str == _array[0]); |     REQUIRE(str == _array[0]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreObjectSubscript") { |   SECTION("object subscript") { | ||||||
|     const char* str = "hello"; |     const char* str = "hello"; | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|     obj["x"] = str; |     obj["x"] = str; | ||||||
|   | |||||||
| @@ -52,29 +52,9 @@ TEST_CASE("JsonArray::printTo()") { | |||||||
|     check(array, "[\"hello\",\"world\"]"); |     check(array, "[\"hello\",\"world\"]"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("OneDoubleDefaultDigits") { |   SECTION("One double") { | ||||||
|     array.add(3.14159265358979323846); |     array.add(3.1415927); | ||||||
|     check(array, "[3.14]"); |     check(array, "[3.1415927]"); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneDoubleFourDigits") { |  | ||||||
|     array.add(3.14159265358979323846, 4); |  | ||||||
|     check(array, "[3.1416]"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneDoubleFourDigits_AlternativeSyntax") { |  | ||||||
|     array.add(double_with_n_digits(3.14159265358979323846, 4)); |  | ||||||
|     check(array, "[3.1416]"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneFloatDefaultDigits") { |  | ||||||
|     array.add(3.14159f); |  | ||||||
|     check(array, "[3.14]"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("OneFloatFourDigits") { |  | ||||||
|     array.add(3.14159f, 4); |  | ||||||
|     check(array, "[3.1416]"); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("OneInteger") { |   SECTION("OneInteger") { | ||||||
|   | |||||||
| @@ -20,35 +20,35 @@ TEST_CASE("JsonArray::set()") { | |||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == _array.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreInteger") { |   SECTION("int") { | ||||||
|     _array.set(0, 123); |     _array.set(0, 123); | ||||||
|     REQUIRE(123 == _array[0].as<int>()); |     REQUIRE(123 == _array[0].as<int>()); | ||||||
|     REQUIRE(_array[0].is<int>()); |     REQUIRE(_array[0].is<int>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<double>()); |     REQUIRE_FALSE(_array[0].is<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreDouble") { |   SECTION("double") { | ||||||
|     _array.set(0, 123.45); |     _array.set(0, 123.45); | ||||||
|     REQUIRE(123.45 == _array[0].as<double>()); |     REQUIRE(123.45 == _array[0].as<double>()); | ||||||
|     REQUIRE(_array[0].is<double>()); |     REQUIRE(_array[0].is<double>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreBoolean") { |   SECTION("bool") { | ||||||
|     _array.set(0, true); |     _array.set(0, true); | ||||||
|     REQUIRE(true == _array[0].as<bool>()); |     REQUIRE(true == _array[0].as<bool>()); | ||||||
|     REQUIRE(_array[0].is<bool>()); |     REQUIRE(_array[0].is<bool>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreString") { |   SECTION("const char*") { | ||||||
|     _array.set(0, "hello"); |     _array.set(0, "hello"); | ||||||
|     REQUIRE_THAT(_array[0].as<const char*>(), Equals("hello")); |     REQUIRE_THAT(_array[0].as<const char*>(), Equals("hello")); | ||||||
|     REQUIRE(_array[0].is<const char*>()); |     REQUIRE(_array[0].is<const char*>()); | ||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreNestedArray") { |   SECTION("nested array") { | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|  |  | ||||||
|     _array.set(0, arr); |     _array.set(0, arr); | ||||||
| @@ -58,7 +58,7 @@ TEST_CASE("JsonArray::set()") { | |||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreNestedObject") { |   SECTION("nested object") { | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|     _array.set(0, obj); |     _array.set(0, obj); | ||||||
| @@ -68,7 +68,7 @@ TEST_CASE("JsonArray::set()") { | |||||||
|     REQUIRE_FALSE(_array[0].is<int>()); |     REQUIRE_FALSE(_array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreArraySubscript") { |   SECTION("array subscript") { | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|     arr.add("hello"); |     arr.add("hello"); | ||||||
|  |  | ||||||
| @@ -77,7 +77,7 @@ TEST_CASE("JsonArray::set()") { | |||||||
|     REQUIRE_THAT(_array[0].as<char*>(), Equals("hello")); |     REQUIRE_THAT(_array[0].as<char*>(), Equals("hello")); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreObjectSubscript") { |   SECTION("object subscript") { | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|     obj["x"] = "hello"; |     obj["x"] = "hello"; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,44 +19,37 @@ TEST_CASE("JsonArray::operator[]") { | |||||||
|     REQUIRE(1U == _array.size()); |     REQUIRE(1U == _array.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreInteger") { |   SECTION("int") { | ||||||
|     _array[0] = 123; |     _array[0] = 123; | ||||||
|     REQUIRE(123 == _array[0].as<int>()); |     REQUIRE(123 == _array[0].as<int>()); | ||||||
|     REQUIRE(true == _array[0].is<int>()); |     REQUIRE(true == _array[0].is<int>()); | ||||||
|     REQUIRE(false == _array[0].is<double>()); |     REQUIRE(false == _array[0].is<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 | ||||||
|   SECTION("StoreLongLong") { |   SECTION("long long") { | ||||||
|     _array[0] = 9223372036854775807; |     _array[0] = 9223372036854775807; | ||||||
|     REQUIRE(9223372036854775807 == _array[0].as<long long>()); |     REQUIRE(9223372036854775807 == _array[0].as<long long>()); | ||||||
|     REQUIRE(true == _array[0].is<int>()); |     REQUIRE(true == _array[0].is<int>()); | ||||||
|     REQUIRE(false == _array[0].is<double>()); |     REQUIRE(false == _array[0].is<bool>()); | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   SECTION("StoreDouble") { |   SECTION("double") { | ||||||
|     _array[0] = 123.45; |     _array[0] = 123.45; | ||||||
|     REQUIRE(123.45 == _array[0].as<double>()); |     REQUIRE(123.45 == _array[0].as<double>()); | ||||||
|     REQUIRE(true == _array[0].is<double>()); |     REQUIRE(true == _array[0].is<double>()); | ||||||
|     REQUIRE(false == _array[0].is<int>()); |     REQUIRE(false == _array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreDoubleWithDecimals") { |   SECTION("bool") { | ||||||
|     _array[0].set(123.45, 2); |  | ||||||
|     REQUIRE(123.45 == _array[0].as<double>()); |  | ||||||
|     REQUIRE(true == _array[0].is<double>()); |  | ||||||
|     REQUIRE(false == _array[0].is<int>()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("StoreBoolean") { |  | ||||||
|     _array[0] = true; |     _array[0] = true; | ||||||
|     REQUIRE(true == _array[0].as<bool>()); |     REQUIRE(true == _array[0].as<bool>()); | ||||||
|     REQUIRE(true == _array[0].is<bool>()); |     REQUIRE(true == _array[0].is<bool>()); | ||||||
|     REQUIRE(false == _array[0].is<int>()); |     REQUIRE(false == _array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreString") { |   SECTION("const char*") { | ||||||
|     const char* str = "hello"; |     const char* str = "hello"; | ||||||
|  |  | ||||||
|     _array[0] = str; |     _array[0] = str; | ||||||
| @@ -66,7 +59,7 @@ TEST_CASE("JsonArray::operator[]") { | |||||||
|     REQUIRE(false == _array[0].is<int>()); |     REQUIRE(false == _array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreNestedArray") { |   SECTION("nested array") { | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|  |  | ||||||
|     _array[0] = arr; |     _array[0] = arr; | ||||||
| @@ -79,7 +72,7 @@ TEST_CASE("JsonArray::operator[]") { | |||||||
|     REQUIRE(false == _array[0].is<int>()); |     REQUIRE(false == _array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreNestedObject") { |   SECTION("nested object") { | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|     _array[0] = obj; |     _array[0] = obj; | ||||||
| @@ -92,7 +85,7 @@ TEST_CASE("JsonArray::operator[]") { | |||||||
|     REQUIRE(false == _array[0].is<int>()); |     REQUIRE(false == _array[0].is<int>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreArraySubscript") { |   SECTION("array subscript") { | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|     const char* str = "hello"; |     const char* str = "hello"; | ||||||
|  |  | ||||||
| @@ -103,7 +96,7 @@ TEST_CASE("JsonArray::operator[]") { | |||||||
|     REQUIRE(str == _array[0]); |     REQUIRE(str == _array[0]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreObjectSubscript") { |   SECTION("object subscript") { | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|     const char* str = "hello"; |     const char* str = "hello"; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ TEST_CASE("JsonBuffer::parse()") { | |||||||
|     JsonVariant variant = jb.parse("-42"); |     JsonVariant variant = jb.parse("-42"); | ||||||
|     REQUIRE(variant.success()); |     REQUIRE(variant.success()); | ||||||
|     REQUIRE(variant.is<int>()); |     REQUIRE(variant.is<int>()); | ||||||
|     REQUIRE_FALSE(variant.is<double>()); |     REQUIRE_FALSE(variant.is<bool>()); | ||||||
|     REQUIRE(variant == -42); |     REQUIRE(variant == -42); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -76,17 +76,10 @@ TEST_CASE("JsonObject::printTo()") { | |||||||
|     check(obj, "{\"a\":[1,2],\"b\":[4,5]}"); |     check(obj, "{\"a\":[1,2],\"b\":[4,5]}"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("TwoDoublesFourDigits") { |   SECTION("Two doubles") { | ||||||
|     obj["a"] = double_with_n_digits(3.14159265358979323846, 4); |     obj["a"] = 12.34; | ||||||
|     obj.set("b", 2.71828182845904523536, 4); |     obj.set("b", 56.78); | ||||||
|     obj.set("c", double_with_n_digits(3.14159265358979323846, 3)); |     check(obj, "{\"a\":12.34,\"b\":56.78}"); | ||||||
|     check(obj, "{\"a\":3.1416,\"b\":2.7183,\"c\":3.142}"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("TwoDoubleDefaultDigits") { |  | ||||||
|     obj["a"] = 3.14159265358979323846; |  | ||||||
|     obj.set("b", 2.71828182845904523536); |  | ||||||
|     check(obj, "{\"a\":3.14,\"b\":2.72}"); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("TwoNull") { |   SECTION("TwoNull") { | ||||||
|   | |||||||
| @@ -24,31 +24,23 @@ TEST_CASE("JsonObject::set()") { | |||||||
|     REQUIRE(1 == _object.size()); |     REQUIRE(1 == _object.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreInteger") { |   SECTION("int") { | ||||||
|     _object.set("hello", 123); |     _object.set("hello", 123); | ||||||
|  |  | ||||||
|     REQUIRE(123 == _object["hello"].as<int>()); |     REQUIRE(123 == _object["hello"].as<int>()); | ||||||
|     REQUIRE(_object["hello"].is<int>()); |     REQUIRE(_object["hello"].is<int>()); | ||||||
|     REQUIRE_FALSE(_object["hello"].is<double>()); |     REQUIRE_FALSE(_object["hello"].is<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreDouble") { |   SECTION("double") { | ||||||
|     _object.set("hello", 123.45); |     _object.set("hello", 123.45); | ||||||
|  |  | ||||||
|     REQUIRE(123.45 == _object["hello"].as<double>()); |     REQUIRE(123.45 == _object["hello"].as<double>()); | ||||||
|     REQUIRE(_object["hello"].is<double>()); |     REQUIRE(_object["hello"].is<double>()); | ||||||
|     REQUIRE_FALSE(_object["hello"].is<long>()); |     REQUIRE_FALSE(_object["hello"].is<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreDoubleWithDigits") { |   SECTION("bool") { | ||||||
|     _object.set("hello", 123.45, 2); |  | ||||||
|  |  | ||||||
|     REQUIRE(123.45 == _object["hello"].as<double>()); |  | ||||||
|     REQUIRE(_object["hello"].is<double>()); |  | ||||||
|     REQUIRE_FALSE(_object["hello"].is<long>()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("StoreBoolean") { |  | ||||||
|     _object.set("hello", true); |     _object.set("hello", true); | ||||||
|  |  | ||||||
|     REQUIRE(_object["hello"].as<bool>()); |     REQUIRE(_object["hello"].as<bool>()); | ||||||
| @@ -56,7 +48,7 @@ TEST_CASE("JsonObject::set()") { | |||||||
|     REQUIRE_FALSE(_object["hello"].is<long>()); |     REQUIRE_FALSE(_object["hello"].is<long>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreString") { |   SECTION("const char*") { | ||||||
|     _object.set("hello", "h3110"); |     _object.set("hello", "h3110"); | ||||||
|  |  | ||||||
|     REQUIRE(std::string("h3110") == _object["hello"].as<const char*>()); |     REQUIRE(std::string("h3110") == _object["hello"].as<const char*>()); | ||||||
| @@ -64,7 +56,7 @@ TEST_CASE("JsonObject::set()") { | |||||||
|     REQUIRE_FALSE(_object["hello"].is<long>()); |     REQUIRE_FALSE(_object["hello"].is<long>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreArray") { |   SECTION("nested array") { | ||||||
|     JsonArray& arr = jb.createArray(); |     JsonArray& arr = jb.createArray(); | ||||||
|  |  | ||||||
|     _object.set("hello", arr); |     _object.set("hello", arr); | ||||||
| @@ -74,7 +66,7 @@ TEST_CASE("JsonObject::set()") { | |||||||
|     REQUIRE_FALSE(_object["hello"].is<JsonObject&>()); |     REQUIRE_FALSE(_object["hello"].is<JsonObject&>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreObject") { |   SECTION("nested object") { | ||||||
|     JsonObject& obj = jb.createObject(); |     JsonObject& obj = jb.createObject(); | ||||||
|  |  | ||||||
|     _object.set("hello", obj); |     _object.set("hello", obj); | ||||||
| @@ -84,7 +76,7 @@ TEST_CASE("JsonObject::set()") { | |||||||
|     REQUIRE_FALSE(_object["hello"].is<JsonArray&>()); |     REQUIRE_FALSE(_object["hello"].is<JsonArray&>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreArraySubscript") { |   SECTION("array subscript") { | ||||||
|     JsonArray& arr = jb.createArray(); |     JsonArray& arr = jb.createArray(); | ||||||
|     arr.add(42); |     arr.add(42); | ||||||
|  |  | ||||||
| @@ -93,7 +85,7 @@ TEST_CASE("JsonObject::set()") { | |||||||
|     REQUIRE(42 == _object["a"]); |     REQUIRE(42 == _object["a"]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreObjectSubscript") { |   SECTION("object subscript") { | ||||||
|     JsonObject& obj = jb.createObject(); |     JsonObject& obj = jb.createObject(); | ||||||
|     obj.set("x", 42); |     obj.set("x", 42); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,24 +23,24 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(1 == _object.size()); |     REQUIRE(1 == _object.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreInteger") { |   SECTION("int") { | ||||||
|     _object["hello"] = 123; |     _object["hello"] = 123; | ||||||
|  |  | ||||||
|     REQUIRE(123 == _object["hello"].as<int>()); |     REQUIRE(123 == _object["hello"].as<int>()); | ||||||
|     REQUIRE(true == _object["hello"].is<int>()); |     REQUIRE(true == _object["hello"].is<int>()); | ||||||
|     REQUIRE(false == _object["hello"].is<double>()); |     REQUIRE(false == _object["hello"].is<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreVolatileInteger") {  // issue #415 |   SECTION("volatile int") {  // issue #415 | ||||||
|     volatile int i = 123; |     volatile int i = 123; | ||||||
|     _object["hello"] = i; |     _object["hello"] = i; | ||||||
|  |  | ||||||
|     REQUIRE(123 == _object["hello"].as<int>()); |     REQUIRE(123 == _object["hello"].as<int>()); | ||||||
|     REQUIRE(true == _object["hello"].is<int>()); |     REQUIRE(true == _object["hello"].is<int>()); | ||||||
|     REQUIRE(false == _object["hello"].is<double>()); |     REQUIRE(false == _object["hello"].is<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreDouble") { |   SECTION("double") { | ||||||
|     _object["hello"] = 123.45; |     _object["hello"] = 123.45; | ||||||
|  |  | ||||||
|     REQUIRE(true == _object["hello"].is<double>()); |     REQUIRE(true == _object["hello"].is<double>()); | ||||||
| @@ -48,15 +48,7 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(123.45 == _object["hello"].as<double>()); |     REQUIRE(123.45 == _object["hello"].as<double>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreDoubleWithDigits") { |   SECTION("bool") { | ||||||
|     _object["hello"].set(123.45, 2); |  | ||||||
|  |  | ||||||
|     REQUIRE(true == _object["hello"].is<double>()); |  | ||||||
|     REQUIRE(false == _object["hello"].is<long>()); |  | ||||||
|     REQUIRE(123.45 == _object["hello"].as<double>()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("StoreBoolean") { |  | ||||||
|     _object["hello"] = true; |     _object["hello"] = true; | ||||||
|  |  | ||||||
|     REQUIRE(true == _object["hello"].is<bool>()); |     REQUIRE(true == _object["hello"].is<bool>()); | ||||||
| @@ -64,7 +56,7 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(true == _object["hello"].as<bool>()); |     REQUIRE(true == _object["hello"].as<bool>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreString") { |   SECTION("const char*") { | ||||||
|     _object["hello"] = "h3110"; |     _object["hello"] = "h3110"; | ||||||
|  |  | ||||||
|     REQUIRE(true == _object["hello"].is<const char*>()); |     REQUIRE(true == _object["hello"].is<const char*>()); | ||||||
| @@ -74,7 +66,7 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|             _object["hello"].as<char*>());  // <- short hand |             _object["hello"].as<char*>());  // <- short hand | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreArray") { |   SECTION("array") { | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|  |  | ||||||
|     _object["hello"] = arr; |     _object["hello"] = arr; | ||||||
| @@ -90,7 +82,7 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(false == _object["hello"].is<JsonObject&>()); |     REQUIRE(false == _object["hello"].is<JsonObject&>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreObject") { |   SECTION("object") { | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|  |  | ||||||
|     _object["hello"] = obj; |     _object["hello"] = obj; | ||||||
| @@ -106,7 +98,7 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(false == _object["hello"].is<JsonArray&>()); |     REQUIRE(false == _object["hello"].is<JsonArray&>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreArraySubscript") { |   SECTION("array subscript") { | ||||||
|     JsonArray& arr = _jsonBuffer.createArray(); |     JsonArray& arr = _jsonBuffer.createArray(); | ||||||
|     arr.add(42); |     arr.add(42); | ||||||
|  |  | ||||||
| @@ -115,7 +107,7 @@ TEST_CASE("JsonObject::operator[]") { | |||||||
|     REQUIRE(42 == _object["a"]); |     REQUIRE(42 == _object["a"]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("StoreObjectSubscript") { |   SECTION("object subscript") { | ||||||
|     JsonObject& obj = _jsonBuffer.createObject(); |     JsonObject& obj = _jsonBuffer.createObject(); | ||||||
|     obj.set("x", 42); |     obj.set("x", 42); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ TEST_CASE("JsonVariant::as()") { | |||||||
|  |  | ||||||
|   SECTION("DoubleAsString") { |   SECTION("DoubleAsString") { | ||||||
|     JsonVariant variant = 4.2; |     JsonVariant variant = 4.2; | ||||||
|     REQUIRE(std::string("4.20") == variant.as<std::string>()); |     REQUIRE(std::string("4.2") == variant.as<std::string>()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("DoubleAsLong") { |   SECTION("DoubleAsLong") { | ||||||
|   | |||||||
| @@ -50,10 +50,10 @@ void checkIsFloat(JsonVariant var) { | |||||||
| void checkIsInteger(JsonVariant var) { | void checkIsInteger(JsonVariant var) { | ||||||
|   REQUIRE(var.is<long>()); |   REQUIRE(var.is<long>()); | ||||||
|   REQUIRE(var.is<int>()); |   REQUIRE(var.is<int>()); | ||||||
|  |   REQUIRE(var.is<float>()); | ||||||
|  |   REQUIRE(var.is<double>()); | ||||||
|  |  | ||||||
|   REQUIRE_FALSE(var.is<bool>()); |   REQUIRE_FALSE(var.is<bool>()); | ||||||
|   REQUIRE_FALSE(var.is<double>()); |  | ||||||
|   REQUIRE_FALSE(var.is<float>()); |  | ||||||
|   REQUIRE_FALSE(var.is<const char*>()); |   REQUIRE_FALSE(var.is<const char*>()); | ||||||
|   REQUIRE_FALSE(var.is<JsonArray>()); |   REQUIRE_FALSE(var.is<JsonArray>()); | ||||||
|   REQUIRE_FALSE(var.is<JsonObject>()); |   REQUIRE_FALSE(var.is<JsonObject>()); | ||||||
|   | |||||||
| @@ -29,48 +29,8 @@ TEST_CASE("JsonVariant::printTo()") { | |||||||
|     check("hello", "\"hello\""); |     check("hello", "\"hello\""); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("DoubleZero") { |   SECTION("Double") { | ||||||
|     check(0.0, "0.00"); |     check(3.1415927, "3.1415927"); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("DoubleDefaultDigits") { |  | ||||||
|     check(3.14159265358979323846, "3.14"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("DoubleFourDigits") { |  | ||||||
|     check(JsonVariant(3.14159265358979323846, 4), "3.1416"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("Infinity") { |  | ||||||
|     check(std::numeric_limits<double>::infinity(), "Infinity"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("MinusInfinity") { |  | ||||||
|     check(-std::numeric_limits<double>::infinity(), "-Infinity"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("SignalingNaN") { |  | ||||||
|     check(std::numeric_limits<double>::signaling_NaN(), "NaN"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("QuietNaN") { |  | ||||||
|     check(std::numeric_limits<double>::quiet_NaN(), "NaN"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("VeryBigPositiveDouble") { |  | ||||||
|     check(JsonVariant(3.14159265358979323846e42, 4), "3.1416e42"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("VeryBigNegativeDouble") { |  | ||||||
|     check(JsonVariant(-3.14159265358979323846e42, 4), "-3.1416e42"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("VerySmallPositiveDouble") { |  | ||||||
|     check(JsonVariant(3.14159265358979323846e-42, 4), "3.1416e-42"); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("VerySmallNegativeDouble") { |  | ||||||
|     check(JsonVariant(-3.14159265358979323846e-42, 4), "-3.1416e-42"); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Integer") { |   SECTION("Integer") { | ||||||
|   | |||||||
| @@ -9,82 +9,96 @@ | |||||||
| #include <limits> | #include <limits> | ||||||
| #include <string> | #include <string> | ||||||
|  |  | ||||||
|  | #include <ArduinoJson/Serialization/DynamicStringBuilder.hpp> | ||||||
| #include <ArduinoJson/Serialization/JsonWriter.hpp> | #include <ArduinoJson/Serialization/JsonWriter.hpp> | ||||||
| #include <ArduinoJson/Serialization/StaticStringBuilder.hpp> |  | ||||||
|  |  | ||||||
| using namespace ArduinoJson::Internals; | using namespace ArduinoJson::Internals; | ||||||
|  |  | ||||||
| void check(const std::string& expected, double input, uint8_t digits = 2) { | void check(double input, const std::string& expected) { | ||||||
|   char output[1024]; |   std::string output; | ||||||
|   StaticStringBuilder sb(output, sizeof(output)); |   DynamicStringBuilder<std::string> sb(output); | ||||||
|   JsonWriter<StaticStringBuilder> writer(sb); |   JsonWriter<DynamicStringBuilder<std::string> > writer(sb); | ||||||
|   writer.writeFloat(input, digits); |   writer.writeFloat(input); | ||||||
|   REQUIRE(output == expected); |   REQUIRE(writer.bytesWritten() == output.size()); | ||||||
|   REQUIRE(writer.bytesWritten() == expected.size()); |   CHECK(expected == output); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("JsonWriter::writeFloat()") { | TEST_CASE("JsonWriter::writeFloat()") { | ||||||
|   SECTION("NaN") { |   SECTION("Pi") { | ||||||
|     check("NaN", std::numeric_limits<double>::signaling_NaN()); |     check(3.14159265359, "3.141592654"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("PositiveInfinity") { |   SECTION("Signaling NaN") { | ||||||
|     check("Infinity", std::numeric_limits<double>::infinity()); |     double nan = std::numeric_limits<double>::signaling_NaN(); | ||||||
|  |     check(nan, "NaN"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("NegativeInfinity") { |   SECTION("Quiet NaN") { | ||||||
|     check("-Infinity", -std::numeric_limits<double>::infinity()); |     double nan = std::numeric_limits<double>::quiet_NaN(); | ||||||
|  |     check(nan, "NaN"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("Infinity") { | ||||||
|  |     double inf = std::numeric_limits<double>::infinity(); | ||||||
|  |     check(inf, "Infinity"); | ||||||
|  |     check(-inf, "-Infinity"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Zero") { |   SECTION("Zero") { | ||||||
|     check("0.00", 0); |     check(0.0, "0"); | ||||||
|  |     check(-0.0, "0"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("ZeroDigits_Rounding") { |   SECTION("Espilon") { | ||||||
|     check("10", 9.5, 0); |     check(2.2250738585072014E-308, "2.225073859e-308"); | ||||||
|  |     check(-2.2250738585072014E-308, "-2.225073859e-308"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("ZeroDigits_NoRounding") { |   SECTION("Max double") { | ||||||
|     check("9", 9.4, 0); |     check(1.7976931348623157E+308, "1.797693135e308"); | ||||||
|  |     check(-1.7976931348623157E+308, "-1.797693135e308"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("OneDigit_Rounding") { |   SECTION("Big exponent") { | ||||||
|     check("10.0", 9.95, 1); |     // this test increases coverage of normalize() | ||||||
|  |     check(1e255, "1e255"); | ||||||
|  |     check(1e-255, "1e-255"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("OneDigit_NoRounding") { |   SECTION("Exponentation when <= 1e-5") { | ||||||
|     check("9.9", 9.94, 1); |     check(1e-4, "0.0001"); | ||||||
|  |     check(1e-5, "1e-5"); | ||||||
|  |  | ||||||
|  |     check(-1e-4, "-0.0001"); | ||||||
|  |     check(-1e-5, "-1e-5"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("TwoDigits_Rounding") { |   SECTION("Exponentation when >= 1e7") { | ||||||
|     check("10.00", 9.995, 2); |     check(9999999.999, "9999999.999"); | ||||||
|  |     check(10000000, "1e7"); | ||||||
|  |  | ||||||
|  |     check(-9999999.999, "-9999999.999"); | ||||||
|  |     check(-10000000, "-1e7"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("TwoDigits_NoRounding") { |   SECTION("Rounding when too many decimals") { | ||||||
|     check("9.99", 9.994, 2); |     check(0.000099999999999, "0.0001"); | ||||||
|  |     check(0.0000099999999999, "1e-5"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("ThreeDigits_Rounding") { |   SECTION("9 decimal places") { | ||||||
|     check("10.000", 9.9995, 3); |     check(0.100000001, "0.100000001"); | ||||||
|  |     check(0.999999999, "0.999999999"); | ||||||
|  |  | ||||||
|  |     check(9.000000001, "9.000000001"); | ||||||
|  |     check(9.999999999, "9.999999999"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("ThreeDigits_NoRounding") { |   SECTION("10 decimal places") { | ||||||
|     check("9.999", 9.9994, 3); |     check(0.1000000001, "0.1"); | ||||||
|   } |     check(0.9999999999, "1"); | ||||||
|  |  | ||||||
|   SECTION("FourDigits_Rounding") { |     check(9.0000000001, "9"); | ||||||
|     check("10.0000", 9.99995, 4); |     check(9.9999999999, "10"); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("FourDigits_NoRounding") { |  | ||||||
|     check("9.9999", 9.99994, 4); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("FiveDigits_Rounding") { |  | ||||||
|     check("10.00000", 9.999995, 5); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("FiveDigits_NoRounding") { |  | ||||||
|     check("9.99999", 9.999994, 5); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,14 +19,14 @@ | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| TEST_CASE("Deprecated functions") { | TEST_CASE("Deprecated functions") { | ||||||
|   SECTION("JsonVariant::asArray()") { |  | ||||||
|   DynamicJsonBuffer jsonBuffer; |   DynamicJsonBuffer jsonBuffer; | ||||||
|  |  | ||||||
|  |   SECTION("JsonVariant::asArray()") { | ||||||
|     JsonVariant variant = jsonBuffer.createArray(); |     JsonVariant variant = jsonBuffer.createArray(); | ||||||
|     REQUIRE(variant.asArray().success()); |     REQUIRE(variant.asArray().success()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonVariant::asObject()") { |   SECTION("JsonVariant::asObject()") { | ||||||
|     DynamicJsonBuffer jsonBuffer; |  | ||||||
|     JsonVariant variant = jsonBuffer.createObject(); |     JsonVariant variant = jsonBuffer.createObject(); | ||||||
|     REQUIRE(variant.asObject().success()); |     REQUIRE(variant.asObject().success()); | ||||||
|   } |   } | ||||||
| @@ -37,8 +37,73 @@ TEST_CASE("Deprecated functions") { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonArray::removeAt()") { |   SECTION("JsonArray::removeAt()") { | ||||||
|     DynamicJsonBuffer jsonBuffer; |  | ||||||
|     JsonArray& arr = jsonBuffer.createArray(); |     JsonArray& arr = jsonBuffer.createArray(); | ||||||
|     arr.removeAt(0); |     arr.removeAt(0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonVariant::JsonVariant(float, uint8_t)") { | ||||||
|  |     JsonVariant variant(3.14f, 2); | ||||||
|  |     REQUIRE(variant == 3.14f); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonVariant::JsonVariant(double, uint8_t)") { | ||||||
|  |     JsonVariant variant(3.14, 2); | ||||||
|  |     REQUIRE(variant == 3.14); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("float_with_n_digits()") { | ||||||
|  |     JsonVariant variant = float_with_n_digits(3.14f, 4); | ||||||
|  |     REQUIRE(variant == 3.14f); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("double_with_n_digits()") { | ||||||
|  |     JsonVariant variant = double_with_n_digits(3.14f, 4); | ||||||
|  |     REQUIRE(variant == 3.14f); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonArraySubscript::set(double, uint8_t)") { | ||||||
|  |     JsonArray& arr = jsonBuffer.createArray(); | ||||||
|  |     arr.add(666); | ||||||
|  |     arr[0].set(123.45, 2); | ||||||
|  |     REQUIRE(123.45 == arr[0].as<double>()); | ||||||
|  |     REQUIRE(true == arr[0].is<double>()); | ||||||
|  |     REQUIRE(false == arr[0].is<int>()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonArray::add(double, uint8_t)") { | ||||||
|  |     JsonArray& arr = jsonBuffer.createArray(); | ||||||
|  |     arr.add(3.14159265358979323846, 4); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonArray::add(float, uint8_t)") { | ||||||
|  |     JsonArray& arr = jsonBuffer.createArray(); | ||||||
|  |     arr.add(3.14159265358979323846f, 4); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonObject::set(unsigned char[], double, uint8_t)") { | ||||||
|  |     unsigned char key[] = "hello"; | ||||||
|  |  | ||||||
|  |     JsonObject& obj = jsonBuffer.createObject(); | ||||||
|  |     obj.set(key, 3.14, 2); | ||||||
|  |  | ||||||
|  |     REQUIRE(3.14 == obj["hello"]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonObject::set(const char*, double, uint8_t)") { | ||||||
|  |     JsonObject& obj = jsonBuffer.createObject(); | ||||||
|  |     obj.set("hello", 123.45, 2); | ||||||
|  |  | ||||||
|  |     REQUIRE(123.45 == obj["hello"].as<double>()); | ||||||
|  |     REQUIRE(obj["hello"].is<double>()); | ||||||
|  |     REQUIRE_FALSE(obj["hello"].is<long>()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonObjectSubscript::set(double, uint8_t)") { | ||||||
|  |     JsonObject& obj = jsonBuffer.createObject(); | ||||||
|  |     obj["hello"].set(123.45, 2); | ||||||
|  |  | ||||||
|  |     REQUIRE(true == obj["hello"].is<double>()); | ||||||
|  |     REQUIRE(false == obj["hello"].is<long>()); | ||||||
|  |     REQUIRE(123.45 == obj["hello"].as<double>()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -166,16 +166,6 @@ TEST_CASE("unsigned char string") { | |||||||
|     REQUIRE(std::string("world") == obj["hello"]); |     REQUIRE(std::string("world") == obj["hello"]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonObject::set() key with decimals") { |  | ||||||
|     unsigned char key[] = "hello"; |  | ||||||
|  |  | ||||||
|     DynamicJsonBuffer jsonBuffer; |  | ||||||
|     JsonObject& obj = jsonBuffer.createObject(); |  | ||||||
|     obj.set(key, 3.14, 2); |  | ||||||
|  |  | ||||||
|     REQUIRE(3.14 == obj["hello"]); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("JsonObject::set key&value") { |   SECTION("JsonObject::set key&value") { | ||||||
|     unsigned char key[] = "world"; |     unsigned char key[] = "world"; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -214,18 +214,6 @@ TEST_CASE("Variable Length Array") { | |||||||
|     REQUIRE(std::string("world") == obj["hello"]); |     REQUIRE(std::string("world") == obj["hello"]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("JsonObject_Set_Key_WithDecimals") { |  | ||||||
|     int i = 16; |  | ||||||
|     char vla[i]; |  | ||||||
|     strcpy(vla, "hello"); |  | ||||||
|  |  | ||||||
|     DynamicJsonBuffer jsonBuffer; |  | ||||||
|     JsonObject& obj = jsonBuffer.createObject(); |  | ||||||
|     obj.set(vla, 3.14, 2); |  | ||||||
|  |  | ||||||
|     REQUIRE(3.14 == obj["hello"]); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   SECTION("JsonObject_Set_KeyAndValue") { |   SECTION("JsonObject_Set_KeyAndValue") { | ||||||
|     int i = 16; |     int i = 16; | ||||||
|     char vla[i]; |     char vla[i]; | ||||||
|   | |||||||
| @@ -40,9 +40,9 @@ TEST_CASE("isFloat()") { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("Integer") { |   SECTION("Integer") { | ||||||
|     REQUIRE_FALSE(isFloat("14")); |     REQUIRE(isFloat("14")); | ||||||
|     REQUIRE_FALSE(isFloat("-14")); |     REQUIRE(isFloat("-14")); | ||||||
|     REQUIRE_FALSE(isFloat("+14")); |     REQUIRE(isFloat("+14")); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("ExponentMissing") { |   SECTION("ExponentMissing") { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user