Skip to content

Commit 622e7dd

Browse files
committed
Fixed support for volatile float and double (fixes #1557)
1 parent 68082e6 commit 622e7dd

File tree

8 files changed

+218
-75
lines changed

8 files changed

+218
-75
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
ArduinoJson: change log
22
=======================
33

4+
HEAD
5+
----
6+
7+
* Fixed support for `volatile float` and `volatile double` (issue #1557)
8+
49
v6.18.0 (2021-05-05)
510
-------
611

extras/tests/JsonVariant/types.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,29 @@ TEST_CASE("JsonVariant set()/get()") {
135135
checkValue<JsonObject>(object);
136136
}
137137
}
138+
139+
TEST_CASE("volatile") {
140+
DynamicJsonDocument doc(4096);
141+
JsonVariant variant = doc.to<JsonVariant>();
142+
143+
SECTION("volatile int") {
144+
volatile int f = 42;
145+
variant.set(f);
146+
CHECK(variant.is<int>() == true);
147+
CHECK(variant.as<int>() == 42);
148+
}
149+
150+
SECTION("volatile float") { // issue #1557
151+
volatile float f = 3.14f;
152+
variant.set(f);
153+
CHECK(variant.is<float>() == true);
154+
CHECK(variant.as<float>() == 3.14f);
155+
}
156+
157+
SECTION("volatile double") {
158+
volatile double f = 3.14;
159+
variant.set(f);
160+
CHECK(variant.is<double>() == true);
161+
CHECK(variant.as<double>() == 3.14);
162+
}
163+
}

extras/tests/Misc/TypeTraits.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ TEST_CASE("Polyfills/type_traits") {
3232
SECTION("is_integral") {
3333
CHECK(is_integral<double>::value == false);
3434
CHECK(is_integral<float>::value == false);
35+
CHECK(is_integral<const double>::value == false);
36+
CHECK(is_integral<const float>::value == false);
37+
CHECK(is_integral<volatile double>::value == false);
38+
CHECK(is_integral<volatile float>::value == false);
39+
CHECK(is_integral<const volatile double>::value == false);
40+
CHECK(is_integral<const volatile float>::value == false);
3541

3642
CHECK(is_integral<bool>::value == true);
3743
CHECK(is_integral<char>::value == true);
@@ -43,6 +49,36 @@ TEST_CASE("Polyfills/type_traits") {
4349
CHECK(is_integral<unsigned int>::value == true);
4450
CHECK(is_integral<unsigned long>::value == true);
4551
CHECK(is_integral<unsigned short>::value == true);
52+
CHECK(is_integral<const bool>::value == true);
53+
CHECK(is_integral<const char>::value == true);
54+
CHECK(is_integral<const signed char>::value == true);
55+
CHECK(is_integral<const signed int>::value == true);
56+
CHECK(is_integral<const signed long>::value == true);
57+
CHECK(is_integral<const signed short>::value == true);
58+
CHECK(is_integral<const unsigned char>::value == true);
59+
CHECK(is_integral<const unsigned int>::value == true);
60+
CHECK(is_integral<const unsigned long>::value == true);
61+
CHECK(is_integral<const unsigned short>::value == true);
62+
CHECK(is_integral<volatile bool>::value == true);
63+
CHECK(is_integral<volatile char>::value == true);
64+
CHECK(is_integral<volatile signed char>::value == true);
65+
CHECK(is_integral<volatile signed int>::value == true);
66+
CHECK(is_integral<volatile signed long>::value == true);
67+
CHECK(is_integral<volatile signed short>::value == true);
68+
CHECK(is_integral<volatile unsigned char>::value == true);
69+
CHECK(is_integral<volatile unsigned int>::value == true);
70+
CHECK(is_integral<volatile unsigned long>::value == true);
71+
CHECK(is_integral<volatile unsigned short>::value == true);
72+
CHECK(is_integral<const volatile bool>::value == true);
73+
CHECK(is_integral<const volatile char>::value == true);
74+
CHECK(is_integral<const volatile signed char>::value == true);
75+
CHECK(is_integral<const volatile signed int>::value == true);
76+
CHECK(is_integral<const volatile signed long>::value == true);
77+
CHECK(is_integral<const volatile signed short>::value == true);
78+
CHECK(is_integral<const volatile unsigned char>::value == true);
79+
CHECK(is_integral<const volatile unsigned int>::value == true);
80+
CHECK(is_integral<const volatile unsigned long>::value == true);
81+
CHECK(is_integral<const volatile unsigned short>::value == true);
4682

4783
CHECK(is_integral<UInt>::value == true);
4884
}
@@ -56,6 +92,33 @@ TEST_CASE("Polyfills/type_traits") {
5692
CHECK(is_signed<float>::value == true);
5793
CHECK(is_signed<double>::value == true);
5894
CHECK(is_signed<bool>::value == false);
95+
96+
CHECK(is_signed<const char>::value == true);
97+
CHECK(is_signed<const signed char>::value == true);
98+
CHECK(is_signed<const signed int>::value == true);
99+
CHECK(is_signed<const signed short>::value == true);
100+
CHECK(is_signed<const signed long>::value == true);
101+
CHECK(is_signed<const float>::value == true);
102+
CHECK(is_signed<const double>::value == true);
103+
CHECK(is_signed<const bool>::value == false);
104+
105+
CHECK(is_signed<volatile char>::value == true);
106+
CHECK(is_signed<volatile signed char>::value == true);
107+
CHECK(is_signed<volatile signed int>::value == true);
108+
CHECK(is_signed<volatile signed short>::value == true);
109+
CHECK(is_signed<volatile signed long>::value == true);
110+
CHECK(is_signed<volatile float>::value == true);
111+
CHECK(is_signed<volatile double>::value == true);
112+
CHECK(is_signed<volatile bool>::value == false);
113+
114+
CHECK(is_signed<const volatile char>::value == true);
115+
CHECK(is_signed<const volatile signed char>::value == true);
116+
CHECK(is_signed<const volatile signed int>::value == true);
117+
CHECK(is_signed<const volatile signed short>::value == true);
118+
CHECK(is_signed<const volatile signed long>::value == true);
119+
CHECK(is_signed<const volatile float>::value == true);
120+
CHECK(is_signed<const volatile double>::value == true);
121+
CHECK(is_signed<const volatile bool>::value == false);
59122
}
60123

61124
SECTION("is_unsigned") {
@@ -67,6 +130,45 @@ TEST_CASE("Polyfills/type_traits") {
67130
CHECK(is_unsigned<char>::value == false);
68131
CHECK(is_unsigned<float>::value == false);
69132
CHECK(is_unsigned<double>::value == false);
133+
134+
CHECK(is_unsigned<const unsigned char>::value == true);
135+
CHECK(is_unsigned<const unsigned int>::value == true);
136+
CHECK(is_unsigned<const unsigned short>::value == true);
137+
CHECK(is_unsigned<const unsigned long>::value == true);
138+
CHECK(is_unsigned<const bool>::value == true);
139+
CHECK(is_unsigned<const char>::value == false);
140+
CHECK(is_unsigned<const float>::value == false);
141+
CHECK(is_unsigned<const double>::value == false);
142+
143+
CHECK(is_unsigned<volatile unsigned char>::value == true);
144+
CHECK(is_unsigned<volatile unsigned int>::value == true);
145+
CHECK(is_unsigned<volatile unsigned short>::value == true);
146+
CHECK(is_unsigned<volatile unsigned long>::value == true);
147+
CHECK(is_unsigned<volatile bool>::value == true);
148+
CHECK(is_unsigned<volatile char>::value == false);
149+
CHECK(is_unsigned<volatile float>::value == false);
150+
CHECK(is_unsigned<volatile double>::value == false);
151+
152+
CHECK(is_unsigned<const volatile unsigned char>::value == true);
153+
CHECK(is_unsigned<const volatile unsigned int>::value == true);
154+
CHECK(is_unsigned<const volatile unsigned short>::value == true);
155+
CHECK(is_unsigned<const volatile unsigned long>::value == true);
156+
CHECK(is_unsigned<const volatile bool>::value == true);
157+
CHECK(is_unsigned<const volatile char>::value == false);
158+
CHECK(is_unsigned<const volatile float>::value == false);
159+
CHECK(is_unsigned<const volatile double>::value == false);
160+
}
161+
162+
SECTION("is_floating_point") {
163+
CHECK(is_floating_point<int>::value == false);
164+
CHECK(is_floating_point<float>::value == true);
165+
CHECK(is_floating_point<double>::value == true);
166+
CHECK(is_floating_point<const float>::value == true);
167+
CHECK(is_floating_point<const double>::value == true);
168+
CHECK(is_floating_point<volatile float>::value == true);
169+
CHECK(is_floating_point<volatile double>::value == true);
170+
CHECK(is_floating_point<const volatile float>::value == true);
171+
CHECK(is_floating_point<const volatile double>::value == true);
70172
}
71173

72174
SECTION("is_convertible") {

src/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
#pragma once
66

77
#include "integral_constant.hpp"
8+
#include "is_same.hpp"
9+
#include "remove_cv.hpp"
810

911
namespace ARDUINOJSON_NAMESPACE {
1012

11-
template <typename>
12-
struct is_floating_point : false_type {};
13+
template <class T>
14+
struct is_floating_point
15+
: integral_constant<
16+
bool, //
17+
is_same<float, typename remove_cv<T>::type>::value ||
18+
is_same<double, typename remove_cv<T>::type>::value> {};
1319

14-
template <>
15-
struct is_floating_point<float> : true_type {};
16-
17-
template <>
18-
struct is_floating_point<double> : true_type {};
1920
} // namespace ARDUINOJSON_NAMESPACE

src/ArduinoJson/Polyfills/type_traits/is_integral.hpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,33 @@
55
#pragma once
66

77
#include <ArduinoJson/Configuration.hpp>
8+
9+
#include "integral_constant.hpp"
810
#include "is_same.hpp"
11+
#include "remove_cv.hpp"
912

1013
namespace ARDUINOJSON_NAMESPACE {
1114

12-
// A meta-function that returns true if T is an integral type.
15+
// clang-format off
1316
template <typename T>
14-
struct is_integral {
15-
static const bool value =
16-
is_same<T, signed char>::value || is_same<T, unsigned char>::value ||
17-
is_same<T, signed short>::value || is_same<T, unsigned short>::value ||
18-
is_same<T, signed int>::value || is_same<T, unsigned int>::value ||
19-
is_same<T, signed long>::value || is_same<T, unsigned long>::value ||
17+
struct is_integral : integral_constant<bool,
18+
is_same<typename remove_cv<T>::type, signed char>::value ||
19+
is_same<typename remove_cv<T>::type, unsigned char>::value ||
20+
is_same<typename remove_cv<T>::type, signed short>::value ||
21+
is_same<typename remove_cv<T>::type, unsigned short>::value ||
22+
is_same<typename remove_cv<T>::type, signed int>::value ||
23+
is_same<typename remove_cv<T>::type, unsigned int>::value ||
24+
is_same<typename remove_cv<T>::type, signed long>::value ||
25+
is_same<typename remove_cv<T>::type, unsigned long>::value ||
2026
#if ARDUINOJSON_HAS_LONG_LONG
21-
is_same<T, signed long long>::value ||
22-
is_same<T, unsigned long long>::value ||
27+
is_same<typename remove_cv<T>::type, signed long long>::value ||
28+
is_same<typename remove_cv<T>::type, unsigned long long>::value ||
2329
#endif
2430
#if ARDUINOJSON_HAS_INT64
25-
is_same<T, signed __int64>::value ||
26-
is_same<T, unsigned __int64>::value ||
31+
is_same<typename remove_cv<T>::type, signed __int64>::value ||
32+
is_same<typename remove_cv<T>::type, unsigned __int64>::value ||
2733
#endif
28-
is_same<T, char>::value || is_same<T, bool>::value;
29-
};
30-
31-
template <typename T>
32-
struct is_integral<const T> : is_integral<T> {};
34+
is_same<typename remove_cv<T>::type, char>::value ||
35+
is_same<typename remove_cv<T>::type, bool>::value> {};
36+
// clang-format on
3337
} // namespace ARDUINOJSON_NAMESPACE

src/ArduinoJson/Polyfills/type_traits/is_signed.hpp

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,26 @@
55
#pragma once
66

77
#include "integral_constant.hpp"
8-
namespace ARDUINOJSON_NAMESPACE {
9-
10-
template <typename>
11-
struct is_signed : false_type {};
12-
13-
template <>
14-
struct is_signed<char> : true_type {};
15-
16-
template <>
17-
struct is_signed<signed char> : true_type {};
18-
19-
template <>
20-
struct is_signed<signed short> : true_type {};
8+
#include "is_same.hpp"
9+
#include "remove_cv.hpp"
2110

22-
template <>
23-
struct is_signed<signed int> : true_type {};
24-
25-
template <>
26-
struct is_signed<signed long> : true_type {};
27-
28-
template <>
29-
struct is_signed<float> : true_type {};
30-
31-
template <>
32-
struct is_signed<double> : true_type {};
11+
namespace ARDUINOJSON_NAMESPACE {
3312

13+
// clang-format off
14+
template <typename T>
15+
struct is_signed : integral_constant<bool,
16+
is_same<typename remove_cv<T>::type, char>::value ||
17+
is_same<typename remove_cv<T>::type, signed char>::value ||
18+
is_same<typename remove_cv<T>::type, signed short>::value ||
19+
is_same<typename remove_cv<T>::type, signed int>::value ||
20+
is_same<typename remove_cv<T>::type, signed long>::value ||
3421
#if ARDUINOJSON_HAS_LONG_LONG
35-
template <>
36-
struct is_signed<signed long long> : true_type {};
22+
is_same<typename remove_cv<T>::type, signed long long>::value ||
3723
#endif
38-
3924
#if ARDUINOJSON_HAS_INT64
40-
template <>
41-
struct is_signed<signed __int64> : true_type {};
25+
is_same<typename remove_cv<T>::type, signed __int64>::value ||
4226
#endif
27+
is_same<typename remove_cv<T>::type, float>::value ||
28+
is_same<typename remove_cv<T>::type, double>::value> {};
29+
// clang-format on
4330
} // namespace ARDUINOJSON_NAMESPACE

src/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,24 @@
55
#pragma once
66

77
#include "integral_constant.hpp"
8-
namespace ARDUINOJSON_NAMESPACE {
9-
10-
template <typename>
11-
struct is_unsigned : false_type {};
12-
13-
template <>
14-
struct is_unsigned<bool> : true_type {};
15-
16-
template <>
17-
struct is_unsigned<unsigned char> : true_type {};
8+
#include "is_same.hpp"
9+
#include "remove_cv.hpp"
1810

19-
template <>
20-
struct is_unsigned<unsigned short> : true_type {};
21-
22-
template <>
23-
struct is_unsigned<unsigned int> : true_type {};
24-
25-
template <>
26-
struct is_unsigned<unsigned long> : true_type {};
11+
namespace ARDUINOJSON_NAMESPACE {
2712

13+
// clang-format off
14+
template <typename T>
15+
struct is_unsigned : integral_constant<bool,
16+
is_same<typename remove_cv<T>::type, unsigned char>::value ||
17+
is_same<typename remove_cv<T>::type, unsigned short>::value ||
18+
is_same<typename remove_cv<T>::type, unsigned int>::value ||
19+
is_same<typename remove_cv<T>::type, unsigned long>::value ||
2820
#if ARDUINOJSON_HAS_INT64
29-
template <>
30-
struct is_unsigned<unsigned __int64> : true_type {};
21+
is_same<typename remove_cv<T>::type, unsigned __int64>::value ||
3122
#endif
32-
3323
#if ARDUINOJSON_HAS_LONG_LONG
34-
template <>
35-
struct is_unsigned<unsigned long long> : true_type {};
24+
is_same<typename remove_cv<T>::type, unsigned long long>::value ||
3625
#endif
26+
is_same<typename remove_cv<T>::type, bool>::value> {};
27+
// clang-format on
3728
} // namespace ARDUINOJSON_NAMESPACE
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// ArduinoJson - https://arduinojson.org
2+
// Copyright Benoit Blanchon 2014-2021
3+
// MIT License
4+
5+
#pragma once
6+
7+
#include <ArduinoJson/Namespace.hpp>
8+
9+
namespace ARDUINOJSON_NAMESPACE {
10+
11+
template <typename T>
12+
struct remove_cv {
13+
typedef T type;
14+
};
15+
template <typename T>
16+
struct remove_cv<const T> {
17+
typedef T type;
18+
};
19+
template <typename T>
20+
struct remove_cv<volatile T> {
21+
typedef T type;
22+
};
23+
template <typename T>
24+
struct remove_cv<const volatile T> {
25+
typedef T type;
26+
};
27+
} // namespace ARDUINOJSON_NAMESPACE

0 commit comments

Comments
 (0)