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