forked from bblanchon/ArduinoJson
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--;
|
|
||||||
value *= 10;
|
|
||||||
}
|
|
||||||
while (value > 10) {
|
|
||||||
powersOf10++;
|
|
||||||
value /= 10;
|
|
||||||
}
|
|
||||||
return powersOf10;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
|
||||||
|
#if !defined(__SIZEOF_DOUBLE__) || __SIZEOF_DOUBLE__ >= 8
|
||||||
|
if (value >= 1e256) {
|
||||||
|
value /= 1e256;
|
||||||
|
powersOf10 = int16_t(powersOf10 + 256);
|
||||||
|
}
|
||||||
|
if (value >= 1e128) {
|
||||||
|
value /= 1e128;
|
||||||
|
powersOf10 = int16_t(powersOf10 + 128);
|
||||||
|
}
|
||||||
|
if (value >= 1e64) {
|
||||||
|
value /= 1e64;
|
||||||
|
powersOf10 = int16_t(powersOf10 + 64);
|
||||||
|
}
|
||||||
#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,26 +99,47 @@ 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) {
|
||||||
void writeRaw(char c) {
|
value /= 10;
|
||||||
_length += _sink.print(c);
|
width--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
size_t _length;
|
size_t _length;
|
||||||
@ -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") {
|
||||||
|
DynamicJsonBuffer jsonBuffer;
|
||||||
|
|
||||||
SECTION("JsonVariant::asArray()") {
|
SECTION("JsonVariant::asArray()") {
|
||||||
DynamicJsonBuffer jsonBuffer;
|
|
||||||
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