Kaynağa Gözat

Break build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0

Benoit Blanchon 5 yıl önce
ebeveyn
işleme
f7de027617

+ 1 - 0
CHANGELOG.md

@@ -11,6 +11,7 @@ HEAD
 * Added support for `enum`s in `as<T>()` and `is<T>()`  (issue #1256)
 * Added `JsonVariant` as an input type for `deserializeXxx()`  
   For example, you can do: `deserializeJson(doc2, doc1["payload"])`
+* Break the build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0
 
 v6.15.1 (2020-04-08)
 -------

+ 8 - 0
extras/tests/FailingBuilds/CMakeLists.txt

@@ -28,3 +28,11 @@ build_should_fail(Issue978)
 
 add_executable(Issue1189 Issue1189.cpp)
 build_should_fail(Issue1189)
+
+add_executable(read_long_long read_long_long.cpp)
+set_property(TARGET read_long_long PROPERTY CXX_STANDARD 11)
+build_should_fail(read_long_long)
+
+add_executable(write_long_long write_long_long.cpp)
+set_property(TARGET write_long_long PROPERTY CXX_STANDARD 11)
+build_should_fail(write_long_long)

+ 20 - 0
extras/tests/FailingBuilds/read_long_long.cpp

@@ -0,0 +1,20 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2020
+// MIT License
+
+#define ARDUINOJSON_USE_LONG_LONG 0
+#include <ArduinoJson.h>
+
+#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
+#error This test requires sizeof(long) < 8
+#endif
+
+#if !ARDUINOJSON_HAS_LONG_LONG
+#error This test requires C++11
+#endif
+
+ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(long long)
+int main() {
+  DynamicJsonDocument doc(1024);
+  doc["dummy"].as<long long>();
+}

+ 19 - 0
extras/tests/FailingBuilds/write_long_long.cpp

@@ -0,0 +1,19 @@
+// ArduinoJson - arduinojson.org
+// Copyright Benoit Blanchon 2014-2020
+// MIT License
+
+#define ARDUINOJSON_USE_LONG_LONG 0
+#include <ArduinoJson.h>
+
+#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
+#error This test requires sizeof(long) < 8
+#endif
+
+#if !ARDUINOJSON_HAS_LONG_LONG
+#error This test requires C++11
+#endif
+
+int main() {
+  DynamicJsonDocument doc(1024);
+  doc["dummy"] = static_cast<long long>(42);
+}

+ 3 - 17
extras/tests/MixedConfiguration/use_long_long_0.cpp

@@ -3,28 +3,14 @@
 
 #include <catch.hpp>
 
-template <size_t size_of_long>
-std::string get_expected_json();
-
-template <>
-std::string get_expected_json<4>() {
-  return "{\"A\":2899336981,\"B\":2129924785}";
-}
-
-template <>
-std::string get_expected_json<8>() {
-  return "{\"A\":123456789123456789,\"B\":987654321987654321}";
-}
-
 TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
   DynamicJsonDocument doc(4096);
-  JsonObject root = doc.to<JsonObject>();
 
-  root["A"] = 123456789123456789;
-  root["B"] = 987654321987654321;
+  doc["A"] = 42;
+  doc["B"] = 84;
 
   std::string json;
   serializeJson(doc, json);
 
-  REQUIRE(json == get_expected_json<sizeof(long)>());
+  REQUIRE(json == "{\"A\":42,\"B\":84}");
 }

+ 11 - 0
src/ArduinoJson/Numbers/Integer.hpp

@@ -18,4 +18,15 @@ typedef uint64_t UInt;
 typedef long Integer;
 typedef unsigned long UInt;
 #endif
+
 }  // namespace ARDUINOJSON_NAMESPACE
+
+#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG
+#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)                  \
+  static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer),     \
+                "To use 64-bit integers with ArduinoJson, you must set " \
+                "ARDUINOJSON_USE_LONG_LONG to 1. See "                   \
+                "https://arduinojson.org/v6/api/config/use_long_long/");
+#else
+#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)
+#endif

+ 1 - 0
src/ArduinoJson/Variant/VariantAs.hpp

@@ -55,6 +55,7 @@ struct VariantConstAs<ArrayRef> {
 template <typename T>
 inline typename enable_if<is_integral<T>::value, T>::type variantAs(
     const VariantData* data) {
+  ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
   return data != 0 ? data->asIntegral<T>() : T(0);
 }
 

+ 5 - 5
src/ArduinoJson/Variant/VariantData.hpp

@@ -258,6 +258,11 @@ class VariantData {
     }
   }
 
+  void setUnsignedInteger(UInt value) {
+    setType(VALUE_IS_POSITIVE_INTEGER);
+    _content.asInteger = static_cast<UInt>(value);
+  }
+
   void setPositiveInteger(UInt value) {
     setType(VALUE_IS_POSITIVE_INTEGER);
     _content.asInteger = value;
@@ -301,11 +306,6 @@ class VariantData {
     return setOwnedString(value.save(pool));
   }
 
-  void setUnsignedInteger(UInt value) {
-    setType(VALUE_IS_POSITIVE_INTEGER);
-    _content.asInteger = static_cast<UInt>(value);
-  }
-
   CollectionData &toArray() {
     setType(VALUE_IS_ARRAY);
     _content.asCollection.clear();

+ 4 - 10
src/ArduinoJson/Variant/VariantFunctions.hpp

@@ -105,14 +105,6 @@ inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value,
   return var != 0 && var->setOwnedRaw(value, pool);
 }
 
-template <typename T>
-inline bool variantSetSignedInteger(VariantData *var, T value) {
-  if (!var)
-    return false;
-  var->setSignedInteger(value);
-  return true;
-}
-
 inline bool variantSetLinkedString(VariantData *var, const char *value) {
   if (!var)
     return false;
@@ -138,10 +130,12 @@ inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) {
   return var != 0 && var->setOwnedString(value, pool);
 }
 
-inline bool variantSetUnsignedInteger(VariantData *var, UInt value) {
+template <typename T>
+inline bool variantSetInteger(VariantData *var, T value) {
+  ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
   if (!var)
     return false;
-  var->setUnsignedInteger(value);
+  var->setInteger(value);
   return true;
 }
 

+ 3 - 12
src/ArduinoJson/Variant/VariantRef.hpp

@@ -178,22 +178,13 @@ class VariantRef : public VariantRefBase<VariantData>,
   // set(signed int)
   // set(signed long)
   // set(signed char)
-  template <typename T>
-  FORCE_INLINE bool set(
-      T value,
-      typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * =
-          0) const {
-    return variantSetSignedInteger(_data, value);
-  }
-
   // set(unsigned short)
   // set(unsigned int)
   // set(unsigned long)
   template <typename T>
   FORCE_INLINE bool set(
-      T value, typename enable_if<is_integral<T>::value &&
-                                  is_unsigned<T>::value>::type * = 0) const {
-    return variantSetUnsignedInteger(_data, static_cast<UInt>(value));
+      T value, typename enable_if<is_integral<T>::value>::type * = 0) const {
+    return variantSetInteger<T>(_data, value);
   }
 
   // set(SerializedValue<const char *>)
@@ -248,7 +239,7 @@ class VariantRef : public VariantRefBase<VariantData>,
   template <typename T>
   FORCE_INLINE bool set(
       T value, typename enable_if<is_enum<T>::value>::type * = 0) const {
-    return variantSetSignedInteger(_data, static_cast<Integer>(value));
+    return variantSetInteger(_data, static_cast<Integer>(value));
   }
 
   template <typename T>