diff --git a/CHANGELOG.md b/CHANGELOG.md index ba1ede28..10e7720c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,34 @@ ArduinoJson: change log 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()` now returns `true` for integers * Fixed error `IsBaseOf is not a member of ArduinoJson::TypeTraits` (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()` | `true` | `true` | +| `JsonVariant(42).is()` | `false` | `true` | +| `JsonVariant(42).is()` | `false` | `true` | + + v5.9.0 ------ @@ -59,7 +84,8 @@ v5.8.0 * Added support for `Stream` (issue #300) * 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`. @@ -108,7 +134,8 @@ v5.7.0 * Added example `StringExample.ino` to show where `String` can be used * 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. @@ -235,7 +262,8 @@ v5.0.7 * 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) -**BREAKING CHANGES**: +### BREAKING CHANGES :warning: + - `JsonVariant(true).as()` now returns `"true"` instead of `"1"` - `JsonVariant(false).as()` 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) * Switched to new the library layout (requires Arduino 1.0.6 or above) -**BREAKING CHANGES**: +### BREAKING CHANGES :warning: + - `JsonObject::add()` was renamed to `set()` - `JsonArray::at()` and `JsonObject::at()` were renamed to `get()` - Number of digits of floating point value are now set with `double_with_n_digits()` diff --git a/README.md b/README.md index 5e1f56f5..1ccb8051 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,8 @@ root["sensor"] = "gps"; root["time"] = 1351824120; JsonArray& data = root.createNestedArray("data"); -data.add(48.756080, 6); // 6 is the number of decimals to print -data.add(2.302038, 6); // if not specified, 2 digits are printed +data.add(48.756080); +data.add(2.302038); root.printTo(Serial); // This prints: diff --git a/examples/JsonGeneratorExample/JsonGeneratorExample.ino b/examples/JsonGeneratorExample/JsonGeneratorExample.ino index 1d0b826d..25bafac3 100644 --- a/examples/JsonGeneratorExample/JsonGeneratorExample.ino +++ b/examples/JsonGeneratorExample/JsonGeneratorExample.ino @@ -44,8 +44,8 @@ void setup() { // It's also possible to create the array separately and add it to the // JsonObject but it's less efficient. JsonArray& data = root.createNestedArray("data"); - data.add(double_with_n_digits(48.756080, 6)); - data.add(double_with_n_digits(2.302038, 6)); + data.add(48.756080); + data.add(2.302038); root.printTo(Serial); // This prints: diff --git a/src/ArduinoJson/Configuration.hpp b/src/ArduinoJson/Configuration.hpp index 0af4f3df..ce1e420e 100644 --- a/src/ArduinoJson/Configuration.hpp +++ b/src/ArduinoJson/Configuration.hpp @@ -12,6 +12,17 @@ #define ARDUINOJSON_ENABLE_DEPRECATED 1 #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 // store using float instead of double to reduce the memory usage (issue #134) diff --git a/src/ArduinoJson/Data/JsonVariantType.hpp b/src/ArduinoJson/Data/JsonVariantType.hpp index 3506e3e5..ba6a2499 100644 --- a/src/ArduinoJson/Data/JsonVariantType.hpp +++ b/src/ArduinoJson/Data/JsonVariantType.hpp @@ -20,20 +20,11 @@ enum JsonVariantType { JSON_UNPARSED, // JsonVariant contains an unparsed string JSON_STRING, // JsonVariant stores a const char* JSON_BOOLEAN, // JsonVariant stores a bool - JSON_POSITIVE_INTEGER, // JsonVariant stores an unsigned long - JSON_NEGATIVE_INTEGER, // JsonVariant stores an unsigned long that must be - // negated + JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt + JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject - - // 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 - // ... + JSON_FLOAT // JsonVariant stores a JsonFloat }; } } diff --git a/src/ArduinoJson/JsonArray.hpp b/src/ArduinoJson/JsonArray.hpp index ec3b6497..a87d2548 100644 --- a/src/ArduinoJson/JsonArray.hpp +++ b/src/ArduinoJson/JsonArray.hpp @@ -76,8 +76,9 @@ class JsonArray : public Internals::JsonPrintable, // bool add(TValue value, uint8_t decimals); // TValue = float, double template - bool add(T value, uint8_t decimals) { - return add_impl(JsonVariant(value, decimals)); + DEPRECATED("Second argument is not supported anymore") + bool add(T value, uint8_t) { + return add_impl(JsonVariant(value)); } // Sets the value at specified index. diff --git a/src/ArduinoJson/JsonArraySubscript.hpp b/src/ArduinoJson/JsonArraySubscript.hpp index 131906fc..dddfbd1d 100644 --- a/src/ArduinoJson/JsonArraySubscript.hpp +++ b/src/ArduinoJson/JsonArraySubscript.hpp @@ -81,8 +81,9 @@ class JsonArraySubscript : public JsonVariantBase { // bool set(TValue, uint8_t decimals); // TValue = float, double template - FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { - return _array.set(_index, value, decimals); + DEPRECATED("Second argument is not supported anymore") + FORCE_INLINE bool set(const TValue& value, uint8_t) { + return _array.set(_index, value); } private: diff --git a/src/ArduinoJson/JsonObject.hpp b/src/ArduinoJson/JsonObject.hpp index c057b71e..da61c893 100644 --- a/src/ArduinoJson/JsonObject.hpp +++ b/src/ArduinoJson/JsonObject.hpp @@ -134,23 +134,25 @@ class JsonObject : public Internals::JsonPrintable, // TKey = const std::string&, const String& // TValue = float, double template + DEPRECATED("Second argument is not supported anymore") typename TypeTraits::EnableIf::value && !TypeTraits::IsArray::value, bool>::type - set(const TString& key, TValue value, uint8_t decimals) { - return set_impl( - key, JsonVariant(value, decimals)); + set(const TString& key, TValue value, uint8_t) { + return set_impl(key, + JsonVariant(value)); } // // bool set(TKey, TValue, uint8_t decimals); // TKey = const char*, const char[N], const FlashStringHelper* // TValue = float, double template + DEPRECATED("Second argument is not supported anymore") typename TypeTraits::EnableIf::value, bool>::type - set(const TString* key, TValue value, uint8_t decimals) { - return set_impl( - key, JsonVariant(value, decimals)); + set(const TString* key, TValue value, uint8_t) { + return set_impl(key, + JsonVariant(value)); } // Gets the value associated with the specified key. diff --git a/src/ArduinoJson/JsonObjectSubscript.hpp b/src/ArduinoJson/JsonObjectSubscript.hpp index 998750ee..99dfe7cd 100644 --- a/src/ArduinoJson/JsonObjectSubscript.hpp +++ b/src/ArduinoJson/JsonObjectSubscript.hpp @@ -93,8 +93,9 @@ class JsonObjectSubscript // bool set(TValue, uint8_t decimals); // TValue = float, double template - FORCE_INLINE bool set(const TValue& value, uint8_t decimals) { - return _object.set(_key, value, decimals); + DEPRECATED("Second argument is not supported anymore") + FORCE_INLINE bool set(const TValue& value, uint8_t) { + return _object.set(_key, value); } private: diff --git a/src/ArduinoJson/JsonVariant.hpp b/src/ArduinoJson/JsonVariant.hpp index 93abcd76..2899c8d6 100644 --- a/src/ArduinoJson/JsonVariant.hpp +++ b/src/ArduinoJson/JsonVariant.hpp @@ -56,16 +56,22 @@ class JsonVariant : public JsonVariantBase { } // Create a JsonVariant containing a floating point value. - // The second argument specifies the number of decimal digits to write in - // the JSON string. - // JsonVariant(double value, uint8_t decimals); - // JsonVariant(float value, uint8_t decimals); + // JsonVariant(double value); + // JsonVariant(float value); template - JsonVariant(T value, uint8_t decimals = 2, + JsonVariant(T value, typename TypeTraits::EnableIf< + TypeTraits::IsFloatingPoint::value>::type * = 0) { + using namespace Internals; + _type = JSON_FLOAT; + _content.asFloat = static_cast(value); + } + template + DEPRECATED("Second argument is not supported anymore") + JsonVariant(T value, uint8_t, typename TypeTraits::EnableIf< TypeTraits::IsFloatingPoint::value>::type * = 0) { using namespace Internals; - _type = static_cast(JSON_FLOAT_0_DECIMALS + decimals); + _type = JSON_FLOAT; _content.asFloat = static_cast(value); } @@ -342,11 +348,13 @@ class JsonVariant : public JsonVariantBase { Internals::JsonVariantContent _content; }; -inline JsonVariant float_with_n_digits(float value, uint8_t digits) { - return JsonVariant(value, digits); +DEPRECATED("Decimal places are ignored, use the float value instead") +inline JsonVariant float_with_n_digits(float value, uint8_t) { + return JsonVariant(value); } -inline JsonVariant double_with_n_digits(double value, uint8_t digits) { - return JsonVariant(value, digits); +DEPRECATED("Decimal places are ignored, use the double value instead") +inline JsonVariant double_with_n_digits(double value, uint8_t) { + return JsonVariant(value); } } diff --git a/src/ArduinoJson/JsonVariantImpl.hpp b/src/ArduinoJson/JsonVariantImpl.hpp index ddb1498b..0bd6535d 100644 --- a/src/ArduinoJson/JsonVariantImpl.hpp +++ b/src/ArduinoJson/JsonVariantImpl.hpp @@ -117,7 +117,7 @@ inline bool JsonVariant::variantIsInteger() const { inline bool JsonVariant::variantIsFloat() const { 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)); } diff --git a/src/ArduinoJson/Polyfills/isFloat.hpp b/src/ArduinoJson/Polyfills/isFloat.hpp index 1b93653f..f6b9c97d 100644 --- a/src/ArduinoJson/Polyfills/isFloat.hpp +++ b/src/ArduinoJson/Polyfills/isFloat.hpp @@ -19,24 +19,23 @@ inline bool isFloat(const char* s) { if (!strcmp(s, "NaN")) return true; if (issign(*s)) s++; if (!strcmp(s, "Infinity")) return true; + if (*s == '\0') return false; while (isdigit(*s)) s++; - bool has_dot = *s == '.'; - if (has_dot) { + if (*s == '.') { s++; while (isdigit(*s)) s++; } - bool has_exponent = *s == 'e' || *s == 'E'; - if (has_exponent) { + if (*s == 'e' || *s == 'E') { s++; if (issign(*s)) s++; if (!isdigit(*s)) return false; while (isdigit(*s)) s++; } - return (has_dot || has_exponent) && *s == '\0'; + return *s == '\0'; } } } diff --git a/src/ArduinoJson/Polyfills/normalize.hpp b/src/ArduinoJson/Polyfills/normalize.hpp index 2b020a32..fb2848f3 100644 --- a/src/ArduinoJson/Polyfills/normalize.hpp +++ b/src/ArduinoJson/Polyfills/normalize.hpp @@ -7,41 +7,97 @@ #pragma once +#include "../Configuration.hpp" + namespace ArduinoJson { namespace Polyfills { - -#ifdef ARDUINO - -// on embedded platform, favor code size over speed - template -short normalize(T& value) { - short 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 -short normalize(T& value) { - if (value == 0.0) return 0; - - short powersOf10 = static_cast(floor(log10(value))); - value /= pow(T(10), powersOf10); - - return powersOf10; -} +int16_t normalize(T& value) { + int16_t powersOf10 = 0; + 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 + 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; +} } } diff --git a/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp b/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp index 63b2c3f3..fde11fb1 100644 --- a/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp +++ b/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp @@ -69,7 +69,8 @@ template inline void ArduinoJson::Internals::JsonSerializer::serialize( const JsonVariant& variant, Writer& writer) { switch (variant._type) { - case JSON_UNDEFINED: + case JSON_FLOAT: + writer.writeFloat(variant._content.asFloat); return; case JSON_ARRAY: @@ -98,9 +99,7 @@ inline void ArduinoJson::Internals::JsonSerializer::serialize( writer.writeBoolean(variant._content.asInteger != 0); return; - default: - uint8_t decimals = - static_cast(variant._type - JSON_FLOAT_0_DECIMALS); - writer.writeFloat(variant._content.asFloat, decimals); + default: // JSON_UNDEFINED + return; } } diff --git a/src/ArduinoJson/Serialization/JsonWriter.hpp b/src/ArduinoJson/Serialization/JsonWriter.hpp index 68822a1b..b6b27763 100644 --- a/src/ArduinoJson/Serialization/JsonWriter.hpp +++ b/src/ArduinoJson/Serialization/JsonWriter.hpp @@ -14,6 +14,7 @@ #include "../Polyfills/attributes.hpp" #include "../Polyfills/math.hpp" #include "../Polyfills/normalize.hpp" +#include "../TypeTraits/FloatTraits.hpp" namespace ArduinoJson { namespace Internals { @@ -27,40 +28,28 @@ namespace Internals { // indentation. template class JsonWriter { + static const uint8_t maxDecimalPlaces = sizeof(JsonFloat) >= 8 ? 9 : 6; + static const uint32_t maxDecimalPart = + sizeof(JsonFloat) >= 8 ? 1000000000 : 1000000; + public: explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {} // Returns the number of bytes sent to the Print implementation. // This is very handy for implementations of printTo() that must return the // number of bytes written. - size_t bytesWritten() const { - return _length; - } + size_t bytesWritten() const { return _length; } - void beginArray() { - writeRaw('['); - } - void endArray() { - writeRaw(']'); - } + void beginArray() { writeRaw('['); } + void endArray() { writeRaw(']'); } - void beginObject() { - writeRaw('{'); - } - void endObject() { - writeRaw('}'); - } + void beginObject() { writeRaw('{'); } + void endObject() { writeRaw('}'); } - void writeColon() { - writeRaw(':'); - } - void writeComma() { - writeRaw(','); - } + void writeColon() { writeRaw(':'); } + void writeComma() { writeRaw(','); } - void writeBoolean(bool value) { - writeRaw(value ? "true" : "false"); - } + void writeBoolean(bool value) { writeRaw(value ? "true" : "false"); } void writeString(const char *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 (value < 0.0) { @@ -92,36 +81,12 @@ class JsonWriter { if (Polyfills::isInfinity(value)) return writeRaw("Infinity"); - short powersOf10; - if (value > 1000 || value < 0.001) { - powersOf10 = Polyfills::normalize(value); - } else { - powersOf10 = 0; - } + uint32_t integralPart, decimalPart; + int16_t powersOf10; + splitFloat(value, integralPart, decimalPart, powersOf10); - // Round up last digit (so that print(1.999, 2) prints as "2.00") - value += getRoundingBias(digits); - - // Extract the integer part of the value and print it - JsonUInt int_part = static_cast(value); - JsonFloat remainder = value - static_cast(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(currentDigit); - - // Print - writeRaw(char('0' + currentDigit)); - } + writeInteger(integralPart); + if (decimalPart) writeDecimals(decimalPart, maxDecimalPlaces); if (powersOf10 < 0) { writeRaw("e-"); @@ -134,26 +99,47 @@ class JsonWriter { } } - void writeInteger(JsonUInt value) { + template + void writeInteger(UInt value) { char buffer[22]; char *ptr = buffer + sizeof(buffer) - 1; *ptr = 0; do { *--ptr = static_cast(value % 10 + '0'); - value /= 10; + value = UInt(value / 10); } while (value); writeRaw(ptr); } - void writeRaw(const char *s) { - _length += _sink.print(s); - } - void writeRaw(char c) { - _length += _sink.print(c); + void writeDecimals(uint32_t value, int8_t width) { + // remove trailing zeros + while (value % 10 == 0 && width > 0) { + value /= 10; + 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: Print &_sink; size_t _length; @@ -161,24 +147,28 @@ class JsonWriter { private: JsonWriter &operator=(const JsonWriter &); // cannot be assigned - static JsonFloat getLastDigit(uint8_t digits) { - // Designed as a compromise between code size and speed - switch (digits) { - 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; - } - } + void splitFloat(JsonFloat value, uint32_t &integralPart, + uint32_t &decimalPart, int16_t &powersOf10) { + powersOf10 = Polyfills::normalize(value); - FORCE_INLINE static JsonFloat getRoundingBias(uint8_t digits) { - return 0.5 * getLastDigit(digits); + integralPart = uint32_t(value); + 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; + } + } + } } }; } diff --git a/src/ArduinoJson/StringTraits/StringTraits.hpp b/src/ArduinoJson/StringTraits/StringTraits.hpp index 51f49c0a..55bacca2 100644 --- a/src/ArduinoJson/StringTraits/StringTraits.hpp +++ b/src/ArduinoJson/StringTraits/StringTraits.hpp @@ -7,6 +7,7 @@ #pragma once +#include #include "../Configuration.hpp" #include "../TypeTraits/EnableIf.hpp" #include "../TypeTraits/IsBaseOf.hpp" diff --git a/src/ArduinoJson/TypeTraits/FloatTraits.hpp b/src/ArduinoJson/TypeTraits/FloatTraits.hpp index 2e0b0d9d..3c737323 100644 --- a/src/ArduinoJson/TypeTraits/FloatTraits.hpp +++ b/src/ArduinoJson/TypeTraits/FloatTraits.hpp @@ -35,7 +35,7 @@ struct FloatTraits { (e & 8 ? 1e8 : 1) * (e & 16 ? 1e16 : 1) * (e & 32 ? 1e32 : 1) * (e & 64 ? 1e64 : 1) * (e & 128 ? 1e128 : 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) * (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) * diff --git a/test/JsonArray/add.cpp b/test/JsonArray/add.cpp index bda73291..e844bc2b 100644 --- a/test/JsonArray/add.cpp +++ b/test/JsonArray/add.cpp @@ -17,28 +17,28 @@ TEST_CASE("JsonArray::add()") { REQUIRE(1U == _array.size()); } - SECTION("StoreInteger") { + SECTION("int") { _array.add(123); REQUIRE(123 == _array[0].as()); REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); + REQUIRE(_array[0].is()); } - SECTION("StoreDouble") { + SECTION("double") { _array.add(123.45); REQUIRE(123.45 == _array[0].as()); REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); + REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreBoolean") { + SECTION("bool") { _array.add(true); REQUIRE(true == _array[0].as()); REQUIRE(_array[0].is()); REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreString") { + SECTION("const char*") { const char* str = "hello"; _array.add(str); REQUIRE(str == _array[0].as()); @@ -46,7 +46,7 @@ TEST_CASE("JsonArray::add()") { REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreNestedArray") { + SECTION("nested array") { JsonArray& arr = _jsonBuffer.createArray(); _array.add(arr); @@ -56,7 +56,7 @@ TEST_CASE("JsonArray::add()") { REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreNestedObject") { + SECTION("nested object") { JsonObject& obj = _jsonBuffer.createObject(); _array.add(obj); @@ -66,7 +66,7 @@ TEST_CASE("JsonArray::add()") { REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreArraySubscript") { + SECTION("array subscript") { const char* str = "hello"; JsonArray& arr = _jsonBuffer.createArray(); arr.add(str); @@ -76,7 +76,7 @@ TEST_CASE("JsonArray::add()") { REQUIRE(str == _array[0]); } - SECTION("StoreObjectSubscript") { + SECTION("object subscript") { const char* str = "hello"; JsonObject& obj = _jsonBuffer.createObject(); obj["x"] = str; diff --git a/test/JsonArray/printTo.cpp b/test/JsonArray/printTo.cpp index beec7f4c..429332f0 100644 --- a/test/JsonArray/printTo.cpp +++ b/test/JsonArray/printTo.cpp @@ -52,29 +52,9 @@ TEST_CASE("JsonArray::printTo()") { check(array, "[\"hello\",\"world\"]"); } - SECTION("OneDoubleDefaultDigits") { - array.add(3.14159265358979323846); - check(array, "[3.14]"); - } - - 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("One double") { + array.add(3.1415927); + check(array, "[3.1415927]"); } SECTION("OneInteger") { diff --git a/test/JsonArray/set.cpp b/test/JsonArray/set.cpp index d7023bc4..8d58570a 100644 --- a/test/JsonArray/set.cpp +++ b/test/JsonArray/set.cpp @@ -20,35 +20,35 @@ TEST_CASE("JsonArray::set()") { REQUIRE(1U == _array.size()); } - SECTION("StoreInteger") { + SECTION("int") { _array.set(0, 123); REQUIRE(123 == _array[0].as()); REQUIRE(_array[0].is()); - REQUIRE_FALSE(_array[0].is()); + REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreDouble") { + SECTION("double") { _array.set(0, 123.45); REQUIRE(123.45 == _array[0].as()); REQUIRE(_array[0].is()); REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreBoolean") { + SECTION("bool") { _array.set(0, true); REQUIRE(true == _array[0].as()); REQUIRE(_array[0].is()); REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreString") { + SECTION("const char*") { _array.set(0, "hello"); REQUIRE_THAT(_array[0].as(), Equals("hello")); REQUIRE(_array[0].is()); REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreNestedArray") { + SECTION("nested array") { JsonArray& arr = _jsonBuffer.createArray(); _array.set(0, arr); @@ -58,7 +58,7 @@ TEST_CASE("JsonArray::set()") { REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreNestedObject") { + SECTION("nested object") { JsonObject& obj = _jsonBuffer.createObject(); _array.set(0, obj); @@ -68,7 +68,7 @@ TEST_CASE("JsonArray::set()") { REQUIRE_FALSE(_array[0].is()); } - SECTION("StoreArraySubscript") { + SECTION("array subscript") { JsonArray& arr = _jsonBuffer.createArray(); arr.add("hello"); @@ -77,7 +77,7 @@ TEST_CASE("JsonArray::set()") { REQUIRE_THAT(_array[0].as(), Equals("hello")); } - SECTION("StoreObjectSubscript") { + SECTION("object subscript") { JsonObject& obj = _jsonBuffer.createObject(); obj["x"] = "hello"; diff --git a/test/JsonArray/subscript.cpp b/test/JsonArray/subscript.cpp index 07adc607..fd985568 100644 --- a/test/JsonArray/subscript.cpp +++ b/test/JsonArray/subscript.cpp @@ -19,44 +19,37 @@ TEST_CASE("JsonArray::operator[]") { REQUIRE(1U == _array.size()); } - SECTION("StoreInteger") { + SECTION("int") { _array[0] = 123; REQUIRE(123 == _array[0].as()); REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); + REQUIRE(false == _array[0].is()); } #if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 - SECTION("StoreLongLong") { + SECTION("long long") { _array[0] = 9223372036854775807; REQUIRE(9223372036854775807 == _array[0].as()); REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); + REQUIRE(false == _array[0].is()); } #endif - SECTION("StoreDouble") { + SECTION("double") { _array[0] = 123.45; REQUIRE(123.45 == _array[0].as()); REQUIRE(true == _array[0].is()); REQUIRE(false == _array[0].is()); } - SECTION("StoreDoubleWithDecimals") { - _array[0].set(123.45, 2); - REQUIRE(123.45 == _array[0].as()); - REQUIRE(true == _array[0].is()); - REQUIRE(false == _array[0].is()); - } - - SECTION("StoreBoolean") { + SECTION("bool") { _array[0] = true; REQUIRE(true == _array[0].as()); REQUIRE(true == _array[0].is()); REQUIRE(false == _array[0].is()); } - SECTION("StoreString") { + SECTION("const char*") { const char* str = "hello"; _array[0] = str; @@ -66,7 +59,7 @@ TEST_CASE("JsonArray::operator[]") { REQUIRE(false == _array[0].is()); } - SECTION("StoreNestedArray") { + SECTION("nested array") { JsonArray& arr = _jsonBuffer.createArray(); _array[0] = arr; @@ -79,7 +72,7 @@ TEST_CASE("JsonArray::operator[]") { REQUIRE(false == _array[0].is()); } - SECTION("StoreNestedObject") { + SECTION("nested object") { JsonObject& obj = _jsonBuffer.createObject(); _array[0] = obj; @@ -92,7 +85,7 @@ TEST_CASE("JsonArray::operator[]") { REQUIRE(false == _array[0].is()); } - SECTION("StoreArraySubscript") { + SECTION("array subscript") { JsonArray& arr = _jsonBuffer.createArray(); const char* str = "hello"; @@ -103,7 +96,7 @@ TEST_CASE("JsonArray::operator[]") { REQUIRE(str == _array[0]); } - SECTION("StoreObjectSubscript") { + SECTION("object subscript") { JsonObject& obj = _jsonBuffer.createObject(); const char* str = "hello"; diff --git a/test/JsonBuffer/parse.cpp b/test/JsonBuffer/parse.cpp index 76f113fb..df15edc0 100644 --- a/test/JsonBuffer/parse.cpp +++ b/test/JsonBuffer/parse.cpp @@ -29,7 +29,7 @@ TEST_CASE("JsonBuffer::parse()") { JsonVariant variant = jb.parse("-42"); REQUIRE(variant.success()); REQUIRE(variant.is()); - REQUIRE_FALSE(variant.is()); + REQUIRE_FALSE(variant.is()); REQUIRE(variant == -42); } diff --git a/test/JsonObject/printTo.cpp b/test/JsonObject/printTo.cpp index dfacf30e..89b9f7a0 100644 --- a/test/JsonObject/printTo.cpp +++ b/test/JsonObject/printTo.cpp @@ -76,17 +76,10 @@ TEST_CASE("JsonObject::printTo()") { check(obj, "{\"a\":[1,2],\"b\":[4,5]}"); } - SECTION("TwoDoublesFourDigits") { - obj["a"] = double_with_n_digits(3.14159265358979323846, 4); - obj.set("b", 2.71828182845904523536, 4); - obj.set("c", double_with_n_digits(3.14159265358979323846, 3)); - 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("Two doubles") { + obj["a"] = 12.34; + obj.set("b", 56.78); + check(obj, "{\"a\":12.34,\"b\":56.78}"); } SECTION("TwoNull") { diff --git a/test/JsonObject/set.cpp b/test/JsonObject/set.cpp index 34eba6fa..75a11aa8 100644 --- a/test/JsonObject/set.cpp +++ b/test/JsonObject/set.cpp @@ -24,31 +24,23 @@ TEST_CASE("JsonObject::set()") { REQUIRE(1 == _object.size()); } - SECTION("StoreInteger") { + SECTION("int") { _object.set("hello", 123); REQUIRE(123 == _object["hello"].as()); REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); + REQUIRE_FALSE(_object["hello"].is()); } - SECTION("StoreDouble") { + SECTION("double") { _object.set("hello", 123.45); REQUIRE(123.45 == _object["hello"].as()); REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); + REQUIRE_FALSE(_object["hello"].is()); } - SECTION("StoreDoubleWithDigits") { - _object.set("hello", 123.45, 2); - - REQUIRE(123.45 == _object["hello"].as()); - REQUIRE(_object["hello"].is()); - REQUIRE_FALSE(_object["hello"].is()); - } - - SECTION("StoreBoolean") { + SECTION("bool") { _object.set("hello", true); REQUIRE(_object["hello"].as()); @@ -56,7 +48,7 @@ TEST_CASE("JsonObject::set()") { REQUIRE_FALSE(_object["hello"].is()); } - SECTION("StoreString") { + SECTION("const char*") { _object.set("hello", "h3110"); REQUIRE(std::string("h3110") == _object["hello"].as()); @@ -64,7 +56,7 @@ TEST_CASE("JsonObject::set()") { REQUIRE_FALSE(_object["hello"].is()); } - SECTION("StoreArray") { + SECTION("nested array") { JsonArray& arr = jb.createArray(); _object.set("hello", arr); @@ -74,7 +66,7 @@ TEST_CASE("JsonObject::set()") { REQUIRE_FALSE(_object["hello"].is()); } - SECTION("StoreObject") { + SECTION("nested object") { JsonObject& obj = jb.createObject(); _object.set("hello", obj); @@ -84,7 +76,7 @@ TEST_CASE("JsonObject::set()") { REQUIRE_FALSE(_object["hello"].is()); } - SECTION("StoreArraySubscript") { + SECTION("array subscript") { JsonArray& arr = jb.createArray(); arr.add(42); @@ -93,7 +85,7 @@ TEST_CASE("JsonObject::set()") { REQUIRE(42 == _object["a"]); } - SECTION("StoreObjectSubscript") { + SECTION("object subscript") { JsonObject& obj = jb.createObject(); obj.set("x", 42); diff --git a/test/JsonObject/subscript.cpp b/test/JsonObject/subscript.cpp index 61d0de98..30c14039 100644 --- a/test/JsonObject/subscript.cpp +++ b/test/JsonObject/subscript.cpp @@ -23,24 +23,24 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(1 == _object.size()); } - SECTION("StoreInteger") { + SECTION("int") { _object["hello"] = 123; REQUIRE(123 == _object["hello"].as()); REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); + REQUIRE(false == _object["hello"].is()); } - SECTION("StoreVolatileInteger") { // issue #415 + SECTION("volatile int") { // issue #415 volatile int i = 123; _object["hello"] = i; REQUIRE(123 == _object["hello"].as()); REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); + REQUIRE(false == _object["hello"].is()); } - SECTION("StoreDouble") { + SECTION("double") { _object["hello"] = 123.45; REQUIRE(true == _object["hello"].is()); @@ -48,15 +48,7 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(123.45 == _object["hello"].as()); } - SECTION("StoreDoubleWithDigits") { - _object["hello"].set(123.45, 2); - - REQUIRE(true == _object["hello"].is()); - REQUIRE(false == _object["hello"].is()); - REQUIRE(123.45 == _object["hello"].as()); - } - - SECTION("StoreBoolean") { + SECTION("bool") { _object["hello"] = true; REQUIRE(true == _object["hello"].is()); @@ -64,7 +56,7 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(true == _object["hello"].as()); } - SECTION("StoreString") { + SECTION("const char*") { _object["hello"] = "h3110"; REQUIRE(true == _object["hello"].is()); @@ -74,7 +66,7 @@ TEST_CASE("JsonObject::operator[]") { _object["hello"].as()); // <- short hand } - SECTION("StoreArray") { + SECTION("array") { JsonArray& arr = _jsonBuffer.createArray(); _object["hello"] = arr; @@ -90,7 +82,7 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(false == _object["hello"].is()); } - SECTION("StoreObject") { + SECTION("object") { JsonObject& obj = _jsonBuffer.createObject(); _object["hello"] = obj; @@ -106,7 +98,7 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(false == _object["hello"].is()); } - SECTION("StoreArraySubscript") { + SECTION("array subscript") { JsonArray& arr = _jsonBuffer.createArray(); arr.add(42); @@ -115,7 +107,7 @@ TEST_CASE("JsonObject::operator[]") { REQUIRE(42 == _object["a"]); } - SECTION("StoreObjectSubscript") { + SECTION("object subscript") { JsonObject& obj = _jsonBuffer.createObject(); obj.set("x", 42); diff --git a/test/JsonVariant/as.cpp b/test/JsonVariant/as.cpp index cc9ad6c3..e8089808 100644 --- a/test/JsonVariant/as.cpp +++ b/test/JsonVariant/as.cpp @@ -24,7 +24,7 @@ TEST_CASE("JsonVariant::as()") { SECTION("DoubleAsString") { JsonVariant variant = 4.2; - REQUIRE(std::string("4.20") == variant.as()); + REQUIRE(std::string("4.2") == variant.as()); } SECTION("DoubleAsLong") { diff --git a/test/JsonVariant/is.cpp b/test/JsonVariant/is.cpp index 0b552828..747df359 100644 --- a/test/JsonVariant/is.cpp +++ b/test/JsonVariant/is.cpp @@ -50,10 +50,10 @@ void checkIsFloat(JsonVariant var) { void checkIsInteger(JsonVariant var) { REQUIRE(var.is()); REQUIRE(var.is()); + REQUIRE(var.is()); + REQUIRE(var.is()); REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); - REQUIRE_FALSE(var.is()); REQUIRE_FALSE(var.is()); REQUIRE_FALSE(var.is()); REQUIRE_FALSE(var.is()); diff --git a/test/JsonVariant/printTo.cpp b/test/JsonVariant/printTo.cpp index 30aacd46..bbb96e19 100644 --- a/test/JsonVariant/printTo.cpp +++ b/test/JsonVariant/printTo.cpp @@ -29,48 +29,8 @@ TEST_CASE("JsonVariant::printTo()") { check("hello", "\"hello\""); } - SECTION("DoubleZero") { - check(0.0, "0.00"); - } - - SECTION("DoubleDefaultDigits") { - check(3.14159265358979323846, "3.14"); - } - - SECTION("DoubleFourDigits") { - check(JsonVariant(3.14159265358979323846, 4), "3.1416"); - } - - SECTION("Infinity") { - check(std::numeric_limits::infinity(), "Infinity"); - } - - SECTION("MinusInfinity") { - check(-std::numeric_limits::infinity(), "-Infinity"); - } - - SECTION("SignalingNaN") { - check(std::numeric_limits::signaling_NaN(), "NaN"); - } - - SECTION("QuietNaN") { - check(std::numeric_limits::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("Double") { + check(3.1415927, "3.1415927"); } SECTION("Integer") { diff --git a/test/JsonWriter/writeFloat.cpp b/test/JsonWriter/writeFloat.cpp index 1560fd2f..2f01b6f1 100644 --- a/test/JsonWriter/writeFloat.cpp +++ b/test/JsonWriter/writeFloat.cpp @@ -9,82 +9,96 @@ #include #include +#include #include -#include using namespace ArduinoJson::Internals; -void check(const std::string& expected, double input, uint8_t digits = 2) { - char output[1024]; - StaticStringBuilder sb(output, sizeof(output)); - JsonWriter writer(sb); - writer.writeFloat(input, digits); - REQUIRE(output == expected); - REQUIRE(writer.bytesWritten() == expected.size()); +void check(double input, const std::string& expected) { + std::string output; + DynamicStringBuilder sb(output); + JsonWriter > writer(sb); + writer.writeFloat(input); + REQUIRE(writer.bytesWritten() == output.size()); + CHECK(expected == output); } TEST_CASE("JsonWriter::writeFloat()") { - SECTION("NaN") { - check("NaN", std::numeric_limits::signaling_NaN()); + SECTION("Pi") { + check(3.14159265359, "3.141592654"); } - SECTION("PositiveInfinity") { - check("Infinity", std::numeric_limits::infinity()); + SECTION("Signaling NaN") { + double nan = std::numeric_limits::signaling_NaN(); + check(nan, "NaN"); } - SECTION("NegativeInfinity") { - check("-Infinity", -std::numeric_limits::infinity()); + SECTION("Quiet NaN") { + double nan = std::numeric_limits::quiet_NaN(); + check(nan, "NaN"); + } + + SECTION("Infinity") { + double inf = std::numeric_limits::infinity(); + check(inf, "Infinity"); + check(-inf, "-Infinity"); } SECTION("Zero") { - check("0.00", 0); + check(0.0, "0"); + check(-0.0, "0"); } - SECTION("ZeroDigits_Rounding") { - check("10", 9.5, 0); + SECTION("Espilon") { + check(2.2250738585072014E-308, "2.225073859e-308"); + check(-2.2250738585072014E-308, "-2.225073859e-308"); } - SECTION("ZeroDigits_NoRounding") { - check("9", 9.4, 0); + SECTION("Max double") { + check(1.7976931348623157E+308, "1.797693135e308"); + check(-1.7976931348623157E+308, "-1.797693135e308"); } - SECTION("OneDigit_Rounding") { - check("10.0", 9.95, 1); + SECTION("Big exponent") { + // this test increases coverage of normalize() + check(1e255, "1e255"); + check(1e-255, "1e-255"); } - SECTION("OneDigit_NoRounding") { - check("9.9", 9.94, 1); + SECTION("Exponentation when <= 1e-5") { + check(1e-4, "0.0001"); + check(1e-5, "1e-5"); + + check(-1e-4, "-0.0001"); + check(-1e-5, "-1e-5"); } - SECTION("TwoDigits_Rounding") { - check("10.00", 9.995, 2); + SECTION("Exponentation when >= 1e7") { + check(9999999.999, "9999999.999"); + check(10000000, "1e7"); + + check(-9999999.999, "-9999999.999"); + check(-10000000, "-1e7"); } - SECTION("TwoDigits_NoRounding") { - check("9.99", 9.994, 2); + SECTION("Rounding when too many decimals") { + check(0.000099999999999, "0.0001"); + check(0.0000099999999999, "1e-5"); } - SECTION("ThreeDigits_Rounding") { - check("10.000", 9.9995, 3); + SECTION("9 decimal places") { + check(0.100000001, "0.100000001"); + check(0.999999999, "0.999999999"); + + check(9.000000001, "9.000000001"); + check(9.999999999, "9.999999999"); } - SECTION("ThreeDigits_NoRounding") { - check("9.999", 9.9994, 3); - } + SECTION("10 decimal places") { + check(0.1000000001, "0.1"); + check(0.9999999999, "1"); - SECTION("FourDigits_Rounding") { - check("10.0000", 9.99995, 4); - } - - 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); + check(9.0000000001, "9"); + check(9.9999999999, "10"); } } diff --git a/test/Misc/deprecated.cpp b/test/Misc/deprecated.cpp index ef9f5751..a04c791f 100644 --- a/test/Misc/deprecated.cpp +++ b/test/Misc/deprecated.cpp @@ -19,14 +19,14 @@ #endif TEST_CASE("Deprecated functions") { + DynamicJsonBuffer jsonBuffer; + SECTION("JsonVariant::asArray()") { - DynamicJsonBuffer jsonBuffer; JsonVariant variant = jsonBuffer.createArray(); REQUIRE(variant.asArray().success()); } SECTION("JsonVariant::asObject()") { - DynamicJsonBuffer jsonBuffer; JsonVariant variant = jsonBuffer.createObject(); REQUIRE(variant.asObject().success()); } @@ -37,8 +37,73 @@ TEST_CASE("Deprecated functions") { } SECTION("JsonArray::removeAt()") { - DynamicJsonBuffer jsonBuffer; JsonArray& arr = jsonBuffer.createArray(); 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()); + REQUIRE(true == arr[0].is()); + REQUIRE(false == arr[0].is()); + } + + 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()); + REQUIRE(obj["hello"].is()); + REQUIRE_FALSE(obj["hello"].is()); + } + + SECTION("JsonObjectSubscript::set(double, uint8_t)") { + JsonObject& obj = jsonBuffer.createObject(); + obj["hello"].set(123.45, 2); + + REQUIRE(true == obj["hello"].is()); + REQUIRE(false == obj["hello"].is()); + REQUIRE(123.45 == obj["hello"].as()); + } } diff --git a/test/Misc/unsigned_char.cpp b/test/Misc/unsigned_char.cpp index e551c107..7239a412 100644 --- a/test/Misc/unsigned_char.cpp +++ b/test/Misc/unsigned_char.cpp @@ -166,16 +166,6 @@ TEST_CASE("unsigned char string") { 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") { unsigned char key[] = "world"; diff --git a/test/Misc/vla.cpp b/test/Misc/vla.cpp index de4dc2a1..85959914 100644 --- a/test/Misc/vla.cpp +++ b/test/Misc/vla.cpp @@ -214,18 +214,6 @@ TEST_CASE("Variable Length Array") { 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") { int i = 16; char vla[i]; diff --git a/test/Polyfills/isFloat.cpp b/test/Polyfills/isFloat.cpp index 3ba8947a..1e18c972 100644 --- a/test/Polyfills/isFloat.cpp +++ b/test/Polyfills/isFloat.cpp @@ -40,9 +40,9 @@ TEST_CASE("isFloat()") { } SECTION("Integer") { - REQUIRE_FALSE(isFloat("14")); - REQUIRE_FALSE(isFloat("-14")); - REQUIRE_FALSE(isFloat("+14")); + REQUIRE(isFloat("14")); + REQUIRE(isFloat("-14")); + REQUIRE(isFloat("+14")); } SECTION("ExponentMissing") {