diff --git a/src/ArduinoJson/Numbers/FloatTraits.hpp b/src/ArduinoJson/Numbers/FloatTraits.hpp index 94529a9c..1c4559d8 100644 --- a/src/ArduinoJson/Numbers/FloatTraits.hpp +++ b/src/ArduinoJson/Numbers/FloatTraits.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace ARDUINOJSON_NAMESPACE { @@ -116,11 +117,28 @@ struct FloatTraits { return forge(0x7FEFFFFF, 0xFFFFFFFF); } - static T highest_for(int64_t) { + template + static + typename enable_if::value && sizeof(TOut) < sizeof(T), + T>::type + highest_for() { + // This conversion is safe because the destination type is smaller + return highest(); + } + + template + static typename enable_if::value && + is_signed::value && sizeof(TOut) == 8, + T>::type // TOut == int64_t + highest_for() { return forge(0x43DFFFFF, 0xFFFFFFFF); // 9.2233720368547748e+18 } - static T highest_for(uint64_t) { + template + static typename enable_if::value && + is_unsigned::value && sizeof(TOut) == 8, + T>::type // TOut == uint64_t + highest_for() { return forge(0x43EFFFFF, 0xFFFFFFFF); // 1.8446744073709549568e+19 } @@ -220,19 +238,44 @@ struct FloatTraits { return forge(0x7f7fffff); } - static T highest_for(int32_t) { + template + static + typename enable_if::value && sizeof(TOut) < sizeof(T), + T>::type + highest_for() { + // This conversion is safe because the destination type is smaller + return highest(); + } + + template + static typename enable_if::value && + is_signed::value && sizeof(TOut) == 4, + T>::type // TOut == int32_t + highest_for() { return forge(0x4EFFFFFF); // 2.14748352E9 } - static T highest_for(uint32_t) { + template + static typename enable_if::value && + is_unsigned::value && sizeof(TOut) == 4, + T>::type // TOut == uint32_t + highest_for() { return forge(0x4F7FFFFF); // 4.29496704E9 } - static T highest_for(int64_t) { + template + static typename enable_if::value && + is_signed::value && sizeof(TOut) == 8, + T>::type // TOut == int64_t + highest_for() { return forge(0x5EFFFFFF); // 9.22337148709896192E18 } - static T highest_for(uint64_t) { + template + static typename enable_if::value && + is_unsigned::value && sizeof(TOut) == 8, + T>::type // TOut == uint64_t + highest_for() { return forge(0x5F7FFFFF); // 1.844674297419792384E19 } diff --git a/src/ArduinoJson/Numbers/convertNumber.hpp b/src/ArduinoJson/Numbers/convertNumber.hpp index 52a3f677..9bf54e8d 100644 --- a/src/ArduinoJson/Numbers/convertNumber.hpp +++ b/src/ArduinoJson/Numbers/convertNumber.hpp @@ -96,33 +96,22 @@ canConvertNumber(TIn value) { return value <= TIn(numeric_limits::highest()); } -// float32 -> int8 // float32 -> int16 -// float64 -> int32 -template -typename enable_if::value && is_integral::value && - sizeof(TOut) < sizeof(TIn), - bool>::type -canConvertNumber(TIn value) { - return value >= numeric_limits::lowest() && - value <= numeric_limits::highest(); -} - // float32 -> int32 -// float32 -> uint32 // float32 -> int64 +// float32 -> int8 +// float32 -> uint32 // float32 -> uint64 +// float64 -> int32 // float64 -> int64 // float64 -> uint64 template -typename enable_if::value && is_integral::value && - sizeof(TOut) >= sizeof(TIn), +typename enable_if::value && is_integral::value, bool>::type canConvertNumber(TIn value) { - // Avoid error "9.22337e+18 is outside the range of representable values of - // type 'long'" return value >= numeric_limits::lowest() && - value <= FloatTraits::highest_for(TOut()); + value <= numeric_limits::highest() && + value <= FloatTraits::template highest_for(); } template