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

This commit is contained in:
Benoit Blanchon
2021-05-19 15:01:51 +02:00
parent 68082e6fc1
commit 622e7dd287
8 changed files with 218 additions and 75 deletions

View File

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

View File

@ -135,3 +135,29 @@ TEST_CASE("JsonVariant set()/get()") {
checkValue<JsonObject>(object); 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);
}
}

View File

@ -32,6 +32,12 @@ TEST_CASE("Polyfills/type_traits") {
SECTION("is_integral") { SECTION("is_integral") {
CHECK(is_integral<double>::value == false); CHECK(is_integral<double>::value == false);
CHECK(is_integral<float>::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<bool>::value == true);
CHECK(is_integral<char>::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 int>::value == true);
CHECK(is_integral<unsigned long>::value == true); CHECK(is_integral<unsigned long>::value == true);
CHECK(is_integral<unsigned short>::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); CHECK(is_integral<UInt>::value == true);
} }
@ -56,6 +92,33 @@ TEST_CASE("Polyfills/type_traits") {
CHECK(is_signed<float>::value == true); CHECK(is_signed<float>::value == true);
CHECK(is_signed<double>::value == true); CHECK(is_signed<double>::value == true);
CHECK(is_signed<bool>::value == false); 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") { SECTION("is_unsigned") {
@ -67,6 +130,45 @@ TEST_CASE("Polyfills/type_traits") {
CHECK(is_unsigned<char>::value == false); CHECK(is_unsigned<char>::value == false);
CHECK(is_unsigned<float>::value == false); CHECK(is_unsigned<float>::value == false);
CHECK(is_unsigned<double>::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") { SECTION("is_convertible") {

View File

@ -5,15 +5,16 @@
#pragma once #pragma once
#include "integral_constant.hpp" #include "integral_constant.hpp"
#include "is_same.hpp"
#include "remove_cv.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename> template <class T>
struct is_floating_point : false_type {}; 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 } // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

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

View File

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

View File

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