Ver Fonte

Fixed support for volatile float and double (fixes #1557)

Benoit Blanchon há 4 anos atrás
pai
commit
622e7dd287

+ 5 - 0
CHANGELOG.md

@@ -1,6 +1,11 @@
 ArduinoJson: change log
 =======================
 
+HEAD
+----
+
+* Fixed support for `volatile float` and `volatile double` (issue #1557)
+
 v6.18.0 (2021-05-05)
 -------
 

+ 26 - 0
extras/tests/JsonVariant/types.cpp

@@ -135,3 +135,29 @@ TEST_CASE("JsonVariant set()/get()") {
     checkValue<JsonObject>(object);
   }
 }
+
+TEST_CASE("volatile") {
+  DynamicJsonDocument doc(4096);
+  JsonVariant variant = doc.to<JsonVariant>();
+
+  SECTION("volatile int") {
+    volatile int f = 42;
+    variant.set(f);
+    CHECK(variant.is<int>() == true);
+    CHECK(variant.as<int>() == 42);
+  }
+
+  SECTION("volatile float") {  // issue #1557
+    volatile float f = 3.14f;
+    variant.set(f);
+    CHECK(variant.is<float>() == true);
+    CHECK(variant.as<float>() == 3.14f);
+  }
+
+  SECTION("volatile double") {
+    volatile double f = 3.14;
+    variant.set(f);
+    CHECK(variant.is<double>() == true);
+    CHECK(variant.as<double>() == 3.14);
+  }
+}

+ 102 - 0
extras/tests/Misc/TypeTraits.cpp

@@ -32,6 +32,12 @@ TEST_CASE("Polyfills/type_traits") {
   SECTION("is_integral") {
     CHECK(is_integral<double>::value == false);
     CHECK(is_integral<float>::value == false);
+    CHECK(is_integral<const double>::value == false);
+    CHECK(is_integral<const float>::value == false);
+    CHECK(is_integral<volatile double>::value == false);
+    CHECK(is_integral<volatile float>::value == false);
+    CHECK(is_integral<const volatile double>::value == false);
+    CHECK(is_integral<const volatile float>::value == false);
 
     CHECK(is_integral<bool>::value == true);
     CHECK(is_integral<char>::value == true);
@@ -43,6 +49,36 @@ TEST_CASE("Polyfills/type_traits") {
     CHECK(is_integral<unsigned int>::value == true);
     CHECK(is_integral<unsigned long>::value == true);
     CHECK(is_integral<unsigned short>::value == true);
+    CHECK(is_integral<const bool>::value == true);
+    CHECK(is_integral<const char>::value == true);
+    CHECK(is_integral<const signed char>::value == true);
+    CHECK(is_integral<const signed int>::value == true);
+    CHECK(is_integral<const signed long>::value == true);
+    CHECK(is_integral<const signed short>::value == true);
+    CHECK(is_integral<const unsigned char>::value == true);
+    CHECK(is_integral<const unsigned int>::value == true);
+    CHECK(is_integral<const unsigned long>::value == true);
+    CHECK(is_integral<const unsigned short>::value == true);
+    CHECK(is_integral<volatile bool>::value == true);
+    CHECK(is_integral<volatile char>::value == true);
+    CHECK(is_integral<volatile signed char>::value == true);
+    CHECK(is_integral<volatile signed int>::value == true);
+    CHECK(is_integral<volatile signed long>::value == true);
+    CHECK(is_integral<volatile signed short>::value == true);
+    CHECK(is_integral<volatile unsigned char>::value == true);
+    CHECK(is_integral<volatile unsigned int>::value == true);
+    CHECK(is_integral<volatile unsigned long>::value == true);
+    CHECK(is_integral<volatile unsigned short>::value == true);
+    CHECK(is_integral<const volatile bool>::value == true);
+    CHECK(is_integral<const volatile char>::value == true);
+    CHECK(is_integral<const volatile signed char>::value == true);
+    CHECK(is_integral<const volatile signed int>::value == true);
+    CHECK(is_integral<const volatile signed long>::value == true);
+    CHECK(is_integral<const volatile signed short>::value == true);
+    CHECK(is_integral<const volatile unsigned char>::value == true);
+    CHECK(is_integral<const volatile unsigned int>::value == true);
+    CHECK(is_integral<const volatile unsigned long>::value == true);
+    CHECK(is_integral<const volatile unsigned short>::value == true);
 
     CHECK(is_integral<UInt>::value == true);
   }
@@ -56,6 +92,33 @@ TEST_CASE("Polyfills/type_traits") {
     CHECK(is_signed<float>::value == true);
     CHECK(is_signed<double>::value == true);
     CHECK(is_signed<bool>::value == false);
+
+    CHECK(is_signed<const char>::value == true);
+    CHECK(is_signed<const signed char>::value == true);
+    CHECK(is_signed<const signed int>::value == true);
+    CHECK(is_signed<const signed short>::value == true);
+    CHECK(is_signed<const signed long>::value == true);
+    CHECK(is_signed<const float>::value == true);
+    CHECK(is_signed<const double>::value == true);
+    CHECK(is_signed<const bool>::value == false);
+
+    CHECK(is_signed<volatile char>::value == true);
+    CHECK(is_signed<volatile signed char>::value == true);
+    CHECK(is_signed<volatile signed int>::value == true);
+    CHECK(is_signed<volatile signed short>::value == true);
+    CHECK(is_signed<volatile signed long>::value == true);
+    CHECK(is_signed<volatile float>::value == true);
+    CHECK(is_signed<volatile double>::value == true);
+    CHECK(is_signed<volatile bool>::value == false);
+
+    CHECK(is_signed<const volatile char>::value == true);
+    CHECK(is_signed<const volatile signed char>::value == true);
+    CHECK(is_signed<const volatile signed int>::value == true);
+    CHECK(is_signed<const volatile signed short>::value == true);
+    CHECK(is_signed<const volatile signed long>::value == true);
+    CHECK(is_signed<const volatile float>::value == true);
+    CHECK(is_signed<const volatile double>::value == true);
+    CHECK(is_signed<const volatile bool>::value == false);
   }
 
   SECTION("is_unsigned") {
@@ -67,6 +130,45 @@ TEST_CASE("Polyfills/type_traits") {
     CHECK(is_unsigned<char>::value == false);
     CHECK(is_unsigned<float>::value == false);
     CHECK(is_unsigned<double>::value == false);
+
+    CHECK(is_unsigned<const unsigned char>::value == true);
+    CHECK(is_unsigned<const unsigned int>::value == true);
+    CHECK(is_unsigned<const unsigned short>::value == true);
+    CHECK(is_unsigned<const unsigned long>::value == true);
+    CHECK(is_unsigned<const bool>::value == true);
+    CHECK(is_unsigned<const char>::value == false);
+    CHECK(is_unsigned<const float>::value == false);
+    CHECK(is_unsigned<const double>::value == false);
+
+    CHECK(is_unsigned<volatile unsigned char>::value == true);
+    CHECK(is_unsigned<volatile unsigned int>::value == true);
+    CHECK(is_unsigned<volatile unsigned short>::value == true);
+    CHECK(is_unsigned<volatile unsigned long>::value == true);
+    CHECK(is_unsigned<volatile bool>::value == true);
+    CHECK(is_unsigned<volatile char>::value == false);
+    CHECK(is_unsigned<volatile float>::value == false);
+    CHECK(is_unsigned<volatile double>::value == false);
+
+    CHECK(is_unsigned<const volatile unsigned char>::value == true);
+    CHECK(is_unsigned<const volatile unsigned int>::value == true);
+    CHECK(is_unsigned<const volatile unsigned short>::value == true);
+    CHECK(is_unsigned<const volatile unsigned long>::value == true);
+    CHECK(is_unsigned<const volatile bool>::value == true);
+    CHECK(is_unsigned<const volatile char>::value == false);
+    CHECK(is_unsigned<const volatile float>::value == false);
+    CHECK(is_unsigned<const volatile double>::value == false);
+  }
+
+  SECTION("is_floating_point") {
+    CHECK(is_floating_point<int>::value == false);
+    CHECK(is_floating_point<float>::value == true);
+    CHECK(is_floating_point<double>::value == true);
+    CHECK(is_floating_point<const float>::value == true);
+    CHECK(is_floating_point<const double>::value == true);
+    CHECK(is_floating_point<volatile float>::value == true);
+    CHECK(is_floating_point<volatile double>::value == true);
+    CHECK(is_floating_point<const volatile float>::value == true);
+    CHECK(is_floating_point<const volatile double>::value == true);
   }
 
   SECTION("is_convertible") {

+ 8 - 7
src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp

@@ -5,15 +5,16 @@
 #pragma once
 
 #include "integral_constant.hpp"
+#include "is_same.hpp"
+#include "remove_cv.hpp"
 
 namespace ARDUINOJSON_NAMESPACE {
 
-template <typename>
-struct is_floating_point : false_type {};
+template <class T>
+struct is_floating_point
+    : integral_constant<
+          bool,  //
+          is_same<float, typename remove_cv<T>::type>::value ||
+              is_same<double, typename remove_cv<T>::type>::value> {};
 
-template <>
-struct is_floating_point<float> : true_type {};
-
-template <>
-struct is_floating_point<double> : true_type {};
 }  // namespace ARDUINOJSON_NAMESPACE

+ 20 - 16
src/ArduinoJson/Polyfills/type_traits/is_integral.hpp

@@ -5,29 +5,33 @@
 #pragma once
 
 #include <ArduinoJson/Configuration.hpp>
+
+#include "integral_constant.hpp"
 #include "is_same.hpp"
+#include "remove_cv.hpp"
 
 namespace ARDUINOJSON_NAMESPACE {
 
-// A meta-function that returns true if T is an integral type.
+// clang-format off
 template <typename T>
-struct is_integral {
-  static const bool value =
-      is_same<T, signed char>::value || is_same<T, unsigned char>::value ||
-      is_same<T, signed short>::value || is_same<T, unsigned short>::value ||
-      is_same<T, signed int>::value || is_same<T, unsigned int>::value ||
-      is_same<T, signed long>::value || is_same<T, unsigned long>::value ||
+struct is_integral : integral_constant<bool,
+    is_same<typename remove_cv<T>::type, signed char>::value ||
+    is_same<typename remove_cv<T>::type, unsigned char>::value ||
+    is_same<typename remove_cv<T>::type, signed short>::value ||
+    is_same<typename remove_cv<T>::type, unsigned short>::value ||
+    is_same<typename remove_cv<T>::type, signed int>::value ||
+    is_same<typename remove_cv<T>::type, unsigned int>::value ||
+    is_same<typename remove_cv<T>::type, signed long>::value ||
+    is_same<typename remove_cv<T>::type, unsigned long>::value ||
 #if ARDUINOJSON_HAS_LONG_LONG
-      is_same<T, signed long long>::value ||
-      is_same<T, unsigned long long>::value ||
+    is_same<typename remove_cv<T>::type, signed long long>::value ||
+    is_same<typename remove_cv<T>::type, unsigned long long>::value ||
 #endif
 #if ARDUINOJSON_HAS_INT64
-      is_same<T, signed __int64>::value ||
-      is_same<T, unsigned __int64>::value ||
+    is_same<typename remove_cv<T>::type, signed __int64>::value ||
+    is_same<typename remove_cv<T>::type, unsigned __int64>::value ||
 #endif
-      is_same<T, char>::value || is_same<T, bool>::value;
-};
-
-template <typename T>
-struct is_integral<const T> : is_integral<T> {};
+    is_same<typename remove_cv<T>::type, char>::value ||
+    is_same<typename remove_cv<T>::type, bool>::value> {};
+// clang-format on
 }  // namespace ARDUINOJSON_NAMESPACE

+ 16 - 29
src/ArduinoJson/Polyfills/type_traits/is_signed.hpp

@@ -5,39 +5,26 @@
 #pragma once
 
 #include "integral_constant.hpp"
-namespace ARDUINOJSON_NAMESPACE {
-
-template <typename>
-struct is_signed : false_type {};
-
-template <>
-struct is_signed<char> : true_type {};
-
-template <>
-struct is_signed<signed char> : true_type {};
-
-template <>
-struct is_signed<signed short> : true_type {};
+#include "is_same.hpp"
+#include "remove_cv.hpp"
 
-template <>
-struct is_signed<signed int> : true_type {};
-
-template <>
-struct is_signed<signed long> : true_type {};
-
-template <>
-struct is_signed<float> : true_type {};
-
-template <>
-struct is_signed<double> : true_type {};
+namespace ARDUINOJSON_NAMESPACE {
 
+// clang-format off
+template <typename T>
+struct is_signed : integral_constant<bool, 
+    is_same<typename remove_cv<T>::type, char>::value ||
+    is_same<typename remove_cv<T>::type, signed char>::value ||
+    is_same<typename remove_cv<T>::type, signed short>::value ||
+    is_same<typename remove_cv<T>::type, signed int>::value ||
+    is_same<typename remove_cv<T>::type, signed long>::value ||
 #if ARDUINOJSON_HAS_LONG_LONG
-template <>
-struct is_signed<signed long long> : true_type {};
+    is_same<typename remove_cv<T>::type, signed long long>::value ||
 #endif
-
 #if ARDUINOJSON_HAS_INT64
-template <>
-struct is_signed<signed __int64> : true_type {};
+    is_same<typename remove_cv<T>::type, signed __int64>::value ||
 #endif
+    is_same<typename remove_cv<T>::type, float>::value ||
+    is_same<typename remove_cv<T>::type, double>::value> {};
+// clang-format on
 }  // namespace ARDUINOJSON_NAMESPACE

+ 14 - 23
src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp

@@ -5,33 +5,24 @@
 #pragma once
 
 #include "integral_constant.hpp"
-namespace ARDUINOJSON_NAMESPACE {
-
-template <typename>
-struct is_unsigned : false_type {};
-
-template <>
-struct is_unsigned<bool> : true_type {};
-
-template <>
-struct is_unsigned<unsigned char> : true_type {};
+#include "is_same.hpp"
+#include "remove_cv.hpp"
 
-template <>
-struct is_unsigned<unsigned short> : true_type {};
-
-template <>
-struct is_unsigned<unsigned int> : true_type {};
-
-template <>
-struct is_unsigned<unsigned long> : true_type {};
+namespace ARDUINOJSON_NAMESPACE {
 
+// clang-format off
+template <typename T>
+struct is_unsigned : integral_constant<bool,
+    is_same<typename remove_cv<T>::type, unsigned char>::value ||
+    is_same<typename remove_cv<T>::type, unsigned short>::value ||
+    is_same<typename remove_cv<T>::type, unsigned int>::value ||
+    is_same<typename remove_cv<T>::type, unsigned long>::value ||
 #if ARDUINOJSON_HAS_INT64
-template <>
-struct is_unsigned<unsigned __int64> : true_type {};
+    is_same<typename remove_cv<T>::type, unsigned __int64>::value ||
 #endif
-
 #if ARDUINOJSON_HAS_LONG_LONG
-template <>
-struct is_unsigned<unsigned long long> : true_type {};
+    is_same<typename remove_cv<T>::type, unsigned long long>::value ||
 #endif
+    is_same<typename remove_cv<T>::type, bool>::value> {};
+// clang-format on
 }  // namespace ARDUINOJSON_NAMESPACE

+ 27 - 0
src/ArduinoJson/Polyfills/type_traits/remove_cv.hpp

@@ -0,0 +1,27 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct remove_cv {
+  typedef T type;
+};
+template <typename T>
+struct remove_cv<const T> {
+  typedef T type;
+};
+template <typename T>
+struct remove_cv<volatile T> {
+  typedef T type;
+};
+template <typename T>
+struct remove_cv<const volatile T> {
+  typedef T type;
+};
+}  // namespace ARDUINOJSON_NAMESPACE