Просмотр исходного кода

Added `ARDUINOJSON_ENABLE_INFINITY` to enable Infinity in JSON

Benoit Blanchon 6 лет назад
Родитель
Сommit
80a02cd90d

+ 1 - 0
CHANGELOG.md

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

+ 5 - 0
src/ArduinoJson/Configuration.hpp

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

+ 9 - 0
src/ArduinoJson/Json/TextFormatter.hpp

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

+ 10 - 8
src/ArduinoJson/Namespace.hpp

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

+ 5 - 0
src/ArduinoJson/Numbers/parseNumber.hpp

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

+ 4 - 2
test/MixedConfiguration/CMakeLists.txt

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

+ 35 - 0
test/MixedConfiguration/enable_infinity_0.cpp

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

+ 38 - 0
test/MixedConfiguration/enable_infinity_1.cpp

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