Added ARDUINOJSON_ENABLE_INFINITY to enable Infinity in JSON

This commit is contained in:
Benoit Blanchon
2019-05-19 15:48:27 +02:00
parent 7427888e05
commit 80a02cd90d
8 changed files with 107 additions and 10 deletions

View File

@ -8,6 +8,7 @@ HEAD
* Fixed invalid result from `operator|` (issue #981)
* Made `deserializeJson()` more picky about trailing characters (issue #980)
* Added `ARDUINOJSON_ENABLE_NAN` to enable NaN in JSON (issue #973)
* Added `ARDUINOJSON_ENABLE_INFINITY` to enable Infinity in JSON
> ### BREAKING CHANGE
>

View File

@ -140,6 +140,11 @@
#define ARDUINOJSON_ENABLE_NAN 1
#endif
// Support Infinity in JSON
#ifndef ARDUINOJSON_ENABLE_INFINITY
#define ARDUINOJSON_ENABLE_INFINITY 1
#endif
// Control the exponentiation threshold for big numbers
// CAUTION: cannot be more that 1e9 !!!!
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD

View File

@ -54,12 +54,21 @@ class TextFormatter {
void writeFloat(T value) {
if (isnan(value)) return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
#if ARDUINOJSON_ENABLE_INFINITY
if (value < 0.0) {
writeRaw('-');
value = -value;
}
if (isinf(value)) return writeRaw("Infinity");
#else
if (isinf(value)) return writeRaw("null");
if (value < 0.0) {
writeRaw('-');
value = -value;
}
#endif
FloatParts<T> parts(value);

View File

@ -10,17 +10,19 @@
#define ARDUINOJSON_DO_CONCAT(A, B) A##B
#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_DO_CONCAT(A, B)
#define ARDUINOJSON_CONCAT3(A, B, C) \
ARDUINOJSON_CONCAT2(A, ARDUINOJSON_CONCAT2(B, C))
#define ARDUINOJSON_CONCAT4(A, B, C, D) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
#define ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, H) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), \
ARDUINOJSON_CONCAT4(E, F, G, H))
#define ARDUINOJSON_CONCAT9(A, B, C, D, E, F, G, H, I) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), \
ARDUINOJSON_CONCAT4(E, F, G, ARDUINOJSON_CONCAT2(H, I)))
#define ARDUINOJSON_CONCAT10(A, B, C, D, E, F, G, H, I, J) \
ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, ARDUINOJSON_CONCAT3(H, I, J))
#define ARDUINOJSON_NAMESPACE \
ARDUINOJSON_CONCAT9(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
ARDUINOJSON_VERSION_MINOR, ARDUINOJSON_VERSION_REVISION, \
_, ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \
ARDUINOJSON_DECODE_UNICODE, ARDUINOJSON_ENABLE_NAN)
#define ARDUINOJSON_NAMESPACE \
ARDUINOJSON_CONCAT10( \
ArduinoJson, ARDUINOJSON_VERSION_MAJOR, ARDUINOJSON_VERSION_MINOR, \
ARDUINOJSON_VERSION_REVISION, _, ARDUINOJSON_USE_LONG_LONG, \
ARDUINOJSON_USE_DOUBLE, ARDUINOJSON_DECODE_UNICODE, \
ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY)

View File

@ -71,11 +71,16 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
s++;
break;
}
#if ARDUINOJSON_ENABLE_NAN
if (*s == 'n' || *s == 'N') return traits::nan();
#endif
#if ARDUINOJSON_ENABLE_INFINITY
if (*s == 'i' || *s == 'I')
return is_negative ? -traits::inf() : traits::inf();
#endif
if (!isdigit(*s) && *s != '.') return return_type();
mantissa_t mantissa = 0;

View File

@ -8,12 +8,14 @@ set(CMAKE_CXX_STANDARD 11)
add_executable(MixedConfigurationTests
decode_unicode_0.cpp
decode_unicode_1.cpp
enable_nan_0.cpp
enable_nan_1.cpp
enable_infinity_0.cpp
enable_infinity_1.cpp
use_double_0.cpp
use_double_1.cpp
use_long_long_0.cpp
use_long_long_1.cpp
enable_nan_0.cpp
enable_nan_1.cpp
)
target_link_libraries(MixedConfigurationTests catch)

View File

@ -0,0 +1,35 @@
#define ARDUINOJSON_ENABLE_INFINITY 0
#include <ArduinoJson.h>
#include <catch.hpp>
#include <limits>
static void assertParseFails(const char* json) {
DynamicJsonDocument doc(4096);
auto err = deserializeJson(doc, json);
REQUIRE(err == DeserializationError::InvalidInput);
}
static void assertJsonEquals(const JsonDocument& doc,
std::string expectedJson) {
std::string actualJson;
serializeJson(doc, actualJson);
REQUIRE(actualJson == expectedJson);
}
TEST_CASE("ARDUINOJSON_ENABLE_INFINITY == 0") {
SECTION("serializeJson()") {
DynamicJsonDocument doc(4096);
doc.add(std::numeric_limits<double>::infinity());
doc.add(-std::numeric_limits<double>::infinity());
assertJsonEquals(doc, "[null,null]");
}
SECTION("deserializeJson()") {
assertParseFails("{\"X\":Infinity}");
assertParseFails("{\"X\":-Infinity}");
assertParseFails("{\"X\":+Infinity}");
}
}

View File

@ -0,0 +1,38 @@
#define ARDUINOJSON_ENABLE_INFINITY 1
#include <ArduinoJson.h>
#include <catch.hpp>
#include <limits>
namespace my {
using ARDUINOJSON_NAMESPACE::isinf;
} // namespace my
TEST_CASE("ARDUINOJSON_ENABLE_INFINITY == 1") {
DynamicJsonDocument doc(4096);
SECTION("serializeJson()") {
doc.add(std::numeric_limits<double>::infinity());
doc.add(-std::numeric_limits<double>::infinity());
std::string json;
serializeJson(doc, json);
REQUIRE(json == "[Infinity,-Infinity]");
}
SECTION("deserializeJson()") {
auto err = deserializeJson(doc, "[Infinity,-Infinity,+Infinity]");
float a = doc[0];
float b = doc[1];
float c = doc[2];
REQUIRE(err == DeserializationError::Ok);
REQUIRE(my::isinf(a));
REQUIRE(a > 0);
REQUIRE(my::isinf(b));
REQUIRE(b < 0);
REQUIRE(my::isinf(c));
REQUIRE(c > 0);
}
}