/src/arduinojson/src/ArduinoJson/Numbers/convertNumber.hpp
Line | Count | Source |
1 | | // ArduinoJson - https://arduinojson.org |
2 | | // Copyright © 2014-2026, Benoit BLANCHON |
3 | | // MIT License |
4 | | |
5 | | #pragma once |
6 | | |
7 | | #if defined(__clang__) |
8 | | # pragma clang diagnostic push |
9 | | # pragma clang diagnostic ignored "-Wconversion" |
10 | | #elif defined(__GNUC__) |
11 | | # pragma GCC diagnostic push |
12 | | # pragma GCC diagnostic ignored "-Wconversion" |
13 | | #endif |
14 | | |
15 | | #include <ArduinoJson/Numbers/FloatTraits.hpp> |
16 | | #include <ArduinoJson/Numbers/JsonFloat.hpp> |
17 | | #include <ArduinoJson/Polyfills/limits.hpp> |
18 | | #include <ArduinoJson/Polyfills/type_traits.hpp> |
19 | | |
20 | | ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE |
21 | | |
22 | | // uint32 -> int32 |
23 | | // uint64 -> int32 |
24 | | template <typename TOut, typename TIn> |
25 | | enable_if_t<is_integral<TIn>::value && is_unsigned<TIn>::value && |
26 | | is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn), |
27 | | bool> |
28 | 11.0k | canConvertNumber(TIn value) { |
29 | 11.0k | return value <= TIn(numeric_limits<TOut>::highest()); |
30 | 11.0k | } |
31 | | |
32 | | // uint32 -> int64 |
33 | | template <typename TOut, typename TIn> |
34 | | enable_if_t<is_integral<TIn>::value && is_unsigned<TIn>::value && |
35 | | is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut), |
36 | | bool> |
37 | | canConvertNumber(TIn) { |
38 | | return true; |
39 | | } |
40 | | |
41 | | // uint32 -> float |
42 | | // int32 -> float |
43 | | template <typename TOut, typename TIn> |
44 | | enable_if_t<is_integral<TIn>::value && is_floating_point<TOut>::value, bool> |
45 | | canConvertNumber(TIn) { |
46 | | return true; |
47 | | } |
48 | | |
49 | | // int64 -> int32 |
50 | | template <typename TOut, typename TIn> |
51 | | enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value && |
52 | | is_integral<TOut>::value && is_signed<TOut>::value && |
53 | | sizeof(TOut) < sizeof(TIn), |
54 | | bool> |
55 | 1.30k | canConvertNumber(TIn value) { |
56 | 1.30k | return value >= TIn(numeric_limits<TOut>::lowest()) && |
57 | 773 | value <= TIn(numeric_limits<TOut>::highest()); |
58 | 1.30k | } |
59 | | |
60 | | // int32 -> int32 |
61 | | // int32 -> int64 |
62 | | template <typename TOut, typename TIn> |
63 | | enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value && |
64 | | is_integral<TOut>::value && is_signed<TOut>::value && |
65 | | sizeof(TIn) <= sizeof(TOut), |
66 | | bool> |
67 | | canConvertNumber(TIn) { |
68 | | return true; |
69 | | } |
70 | | |
71 | | // int32 -> uint32 |
72 | | // int32 -> uint64 |
73 | | template <typename TOut, typename TIn> |
74 | | enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value && |
75 | | is_integral<TOut>::value && is_unsigned<TOut>::value && |
76 | | sizeof(TOut) >= sizeof(TIn), |
77 | | bool> |
78 | | canConvertNumber(TIn value) { |
79 | | if (value < 0) |
80 | | return false; |
81 | | return TOut(value) <= numeric_limits<TOut>::highest(); |
82 | | } |
83 | | |
84 | | // int32 -> uint16 |
85 | | template <typename TOut, typename TIn> |
86 | | enable_if_t<is_integral<TIn>::value && is_signed<TIn>::value && |
87 | | is_integral<TOut>::value && is_unsigned<TOut>::value && |
88 | | sizeof(TOut) < sizeof(TIn), |
89 | | bool> |
90 | | canConvertNumber(TIn value) { |
91 | | if (value < 0) |
92 | | return false; |
93 | | return value <= TIn(numeric_limits<TOut>::highest()); |
94 | | } |
95 | | |
96 | | // float32 -> int16 |
97 | | // float64 -> int32 |
98 | | template <typename TOut, typename TIn> |
99 | | enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value && |
100 | | sizeof(TOut) < sizeof(TIn), |
101 | | bool> |
102 | | canConvertNumber(TIn value) { |
103 | | return value >= numeric_limits<TOut>::lowest() && |
104 | | value <= numeric_limits<TOut>::highest(); |
105 | | } |
106 | | |
107 | | // float32 -> int32 |
108 | | // float32 -> uint32 |
109 | | // float32 -> int64 |
110 | | // float32 -> uint64 |
111 | | // float64 -> int64 |
112 | | // float64 -> uint64 |
113 | | template <typename TOut, typename TIn> |
114 | | enable_if_t<is_floating_point<TIn>::value && is_integral<TOut>::value && |
115 | | sizeof(TOut) >= sizeof(TIn), |
116 | | bool> |
117 | 0 | canConvertNumber(TIn value) { |
118 | 0 | // Avoid error "9.22337e+18 is outside the range of representable values of |
119 | 0 | // type 'long'" |
120 | 0 | return value >= numeric_limits<TOut>::lowest() && |
121 | 0 | value <= FloatTraits<TIn>::template highest_for<TOut>(); |
122 | 0 | } |
123 | | |
124 | | // float32 -> float32 |
125 | | // float64 -> float64 |
126 | | // float64 -> float32 |
127 | | template <typename TOut, typename TIn> |
128 | | enable_if_t<is_floating_point<TIn>::value && is_floating_point<TOut>::value, |
129 | | bool> |
130 | | canConvertNumber(TIn) { |
131 | | return true; |
132 | | } |
133 | | |
134 | | template <typename TOut, typename TIn> |
135 | | TOut convertNumber(TIn value) { |
136 | | return canConvertNumber<TOut>(value) ? TOut(value) : 0; |
137 | | } |
138 | | |
139 | | ARDUINOJSON_END_PRIVATE_NAMESPACE |
140 | | |
141 | | #if defined(__clang__) |
142 | | # pragma clang diagnostic pop |
143 | | #elif defined(__GNUC__) |
144 | | # pragma GCC diagnostic pop |
145 | | #endif |