mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			287 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			287 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // ArduinoJson - https://arduinojson.org
 | |
| // Copyright © 2014-2022, Benoit BLANCHON
 | |
| // MIT License
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <stddef.h>  // for size_t
 | |
| #include <stdint.h>
 | |
| 
 | |
| #include <ArduinoJson/Configuration.hpp>
 | |
| #include <ArduinoJson/Polyfills/alias_cast.hpp>
 | |
| #include <ArduinoJson/Polyfills/math.hpp>
 | |
| #include <ArduinoJson/Polyfills/preprocessor.hpp>
 | |
| #include <ArduinoJson/Polyfills/static_array.hpp>
 | |
| #include <ArduinoJson/Polyfills/type_traits.hpp>
 | |
| 
 | |
| namespace ARDUINOJSON_NAMESPACE {
 | |
| 
 | |
| template <typename T, size_t = sizeof(T)>
 | |
| struct FloatTraits {};
 | |
| 
 | |
| template <typename T>
 | |
| struct FloatTraits<T, 8 /*64bits*/> {
 | |
|   typedef uint64_t mantissa_type;
 | |
|   static const short mantissa_bits = 52;
 | |
|   static const mantissa_type mantissa_max =
 | |
|       (mantissa_type(1) << mantissa_bits) - 1;
 | |
| 
 | |
|   typedef int16_t exponent_type;
 | |
|   static const exponent_type exponent_max = 308;
 | |
| 
 | |
|   template <typename TExponent>
 | |
|   static T make_float(T m, TExponent e) {
 | |
|     if (e > 0) {
 | |
|       for (uint8_t index = 0; e != 0; index++) {
 | |
|         if (e & 1)
 | |
|           m *= positiveBinaryPowerOfTen(index);
 | |
|         e >>= 1;
 | |
|       }
 | |
|     } else {
 | |
|       e = TExponent(-e);
 | |
|       for (uint8_t index = 0; e != 0; index++) {
 | |
|         if (e & 1)
 | |
|           m *= negativeBinaryPowerOfTen(index);
 | |
|         e >>= 1;
 | |
|       }
 | |
|     }
 | |
|     return m;
 | |
|   }
 | |
| 
 | |
|   static T positiveBinaryPowerOfTen(int index) {
 | |
|     ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
 | |
|         uint32_t, factors,
 | |
|         ARDUINOJSON_EXPAND18({
 | |
|             0x40240000, 0x00000000,  // 1e1
 | |
|             0x40590000, 0x00000000,  // 1e2
 | |
|             0x40C38800, 0x00000000,  // 1e4
 | |
|             0x4197D784, 0x00000000,  // 1e8
 | |
|             0x4341C379, 0x37E08000,  // 1e16
 | |
|             0x4693B8B5, 0xB5056E17,  // 1e32
 | |
|             0x4D384F03, 0xE93FF9F5,  // 1e64
 | |
|             0x5A827748, 0xF9301D32,  // 1e128
 | |
|             0x75154FDD, 0x7F73BF3C   // 1e256
 | |
|         }));
 | |
|     return forge(
 | |
|         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
 | |
|         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
 | |
|   }
 | |
| 
 | |
|   static T negativeBinaryPowerOfTen(int index) {
 | |
|     ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
 | |
|         uint32_t, factors,
 | |
|         ARDUINOJSON_EXPAND18({
 | |
|             0x3FB99999, 0x9999999A,  // 1e-1
 | |
|             0x3F847AE1, 0x47AE147B,  // 1e-2
 | |
|             0x3F1A36E2, 0xEB1C432D,  // 1e-4
 | |
|             0x3E45798E, 0xE2308C3A,  // 1e-8
 | |
|             0x3C9CD2B2, 0x97D889BC,  // 1e-16
 | |
|             0x3949F623, 0xD5A8A733,  // 1e-32
 | |
|             0x32A50FFD, 0x44F4A73D,  // 1e-64
 | |
|             0x255BBA08, 0xCF8C979D,  // 1e-128
 | |
|             0x0AC80628, 0x64AC6F43   // 1e-256
 | |
|         }));
 | |
|     return forge(
 | |
|         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
 | |
|         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
 | |
|   }
 | |
| 
 | |
|   static T negativeBinaryPowerOfTenPlusOne(int index) {
 | |
|     ARDUINOJSON_DEFINE_STATIC_ARRAY(  //
 | |
|         uint32_t, factors,
 | |
|         ARDUINOJSON_EXPAND18({
 | |
|             0x3FF00000, 0x00000000,  // 1e0
 | |
|             0x3FB99999, 0x9999999A,  // 1e-1
 | |
|             0x3F50624D, 0xD2F1A9FC,  // 1e-3
 | |
|             0x3E7AD7F2, 0x9ABCAF48,  // 1e-7
 | |
|             0x3CD203AF, 0x9EE75616,  // 1e-15
 | |
|             0x398039D6, 0x65896880,  // 1e-31
 | |
|             0x32DA53FC, 0x9631D10D,  // 1e-63
 | |
|             0x25915445, 0x81B7DEC2,  // 1e-127
 | |
|             0x0AFE07B2, 0x7DD78B14   // 1e-255
 | |
|         }));
 | |
|     return forge(
 | |
|         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
 | |
|         ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
 | |
|   }
 | |
| 
 | |
|   static T nan() {
 | |
|     return forge(0x7ff80000, 0x00000000);
 | |
|   }
 | |
| 
 | |
|   static T inf() {
 | |
|     return forge(0x7ff00000, 0x00000000);
 | |
|   }
 | |
| 
 | |
|   static T highest() {
 | |
|     return forge(0x7FEFFFFF, 0xFFFFFFFF);
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static
 | |
|       typename enable_if<is_integral<TOut>::value && sizeof(TOut) < sizeof(T),
 | |
|                          T>::type
 | |
|       highest_for() {
 | |
|     // This conversion is safe because the destination type is smaller
 | |
|     return highest();
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static typename enable_if<is_integral<TOut>::value &&
 | |
|                                 is_signed<TOut>::value && sizeof(TOut) == 8,
 | |
|                             T>::type  // TOut == int64_t
 | |
|   highest_for() {
 | |
|     return forge(0x43DFFFFF, 0xFFFFFFFF);  //  9.2233720368547748e+18
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static typename enable_if<is_integral<TOut>::value &&
 | |
|                                 is_unsigned<TOut>::value && sizeof(TOut) == 8,
 | |
|                             T>::type  // TOut == uint64_t
 | |
|   highest_for() {
 | |
|     return forge(0x43EFFFFF, 0xFFFFFFFF);  //  1.8446744073709549568e+19
 | |
|   }
 | |
| 
 | |
|   static T lowest() {
 | |
|     return forge(0xFFEFFFFF, 0xFFFFFFFF);
 | |
|   }
 | |
| 
 | |
|   // constructs a double floating point values from its binary representation
 | |
|   // we use this function to workaround platforms with single precision literals
 | |
|   // (for example, when -fsingle-precision-constant is passed to GCC)
 | |
|   static T forge(uint32_t msb, uint32_t lsb) {
 | |
|     return alias_cast<T>((uint64_t(msb) << 32) | lsb);
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T>
 | |
| struct FloatTraits<T, 4 /*32bits*/> {
 | |
|   typedef uint32_t mantissa_type;
 | |
|   static const short mantissa_bits = 23;
 | |
|   static const mantissa_type mantissa_max =
 | |
|       (mantissa_type(1) << mantissa_bits) - 1;
 | |
| 
 | |
|   typedef int8_t exponent_type;
 | |
|   static const exponent_type exponent_max = 38;
 | |
| 
 | |
|   template <typename TExponent>
 | |
|   static T make_float(T m, TExponent e) {
 | |
|     if (e > 0) {
 | |
|       for (uint8_t index = 0; e != 0; index++) {
 | |
|         if (e & 1)
 | |
|           m *= positiveBinaryPowerOfTen(index);
 | |
|         e >>= 1;
 | |
|       }
 | |
|     } else {
 | |
|       e = -e;
 | |
|       for (uint8_t index = 0; e != 0; index++) {
 | |
|         if (e & 1)
 | |
|           m *= negativeBinaryPowerOfTen(index);
 | |
|         e >>= 1;
 | |
|       }
 | |
|     }
 | |
|     return m;
 | |
|   }
 | |
| 
 | |
|   static T positiveBinaryPowerOfTen(int index) {
 | |
|     ARDUINOJSON_DEFINE_STATIC_ARRAY(uint32_t, factors,
 | |
|                                     ARDUINOJSON_EXPAND6({
 | |
|                                         0x41200000,  // 1e1f
 | |
|                                         0x42c80000,  // 1e2f
 | |
|                                         0x461c4000,  // 1e4f
 | |
|                                         0x4cbebc20,  // 1e8f
 | |
|                                         0x5a0e1bca,  // 1e16f
 | |
|                                         0x749dc5ae   // 1e32f
 | |
|                                     }));
 | |
|     return forge(ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, index));
 | |
|   }
 | |
| 
 | |
|   static T negativeBinaryPowerOfTen(int index) {
 | |
|     ARDUINOJSON_DEFINE_STATIC_ARRAY(uint32_t, factors,
 | |
|                                     ARDUINOJSON_EXPAND6({
 | |
|                                         0x3dcccccd,  // 1e-1f
 | |
|                                         0x3c23d70a,  // 1e-2f
 | |
|                                         0x38d1b717,  // 1e-4f
 | |
|                                         0x322bcc77,  // 1e-8f
 | |
|                                         0x24e69595,  // 1e-16f
 | |
|                                         0x0a4fb11f   // 1e-32f
 | |
|                                     }));
 | |
|     return forge(ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, index));
 | |
|   }
 | |
| 
 | |
|   static T negativeBinaryPowerOfTenPlusOne(int index) {
 | |
|     ARDUINOJSON_DEFINE_STATIC_ARRAY(uint32_t, factors,
 | |
|                                     ARDUINOJSON_EXPAND6({
 | |
|                                         0x3f800000,  // 1e0f
 | |
|                                         0x3dcccccd,  // 1e-1f
 | |
|                                         0x3a83126f,  // 1e-3f
 | |
|                                         0x33d6bf95,  // 1e-7f
 | |
|                                         0x26901d7d,  // 1e-15f
 | |
|                                         0x0c01ceb3   // 1e-31f
 | |
|                                     }));
 | |
|     return forge(ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, index));
 | |
|   }
 | |
| 
 | |
|   static T forge(uint32_t bits) {
 | |
|     return alias_cast<T>(bits);
 | |
|   }
 | |
| 
 | |
|   static T nan() {
 | |
|     return forge(0x7fc00000);
 | |
|   }
 | |
| 
 | |
|   static T inf() {
 | |
|     return forge(0x7f800000);
 | |
|   }
 | |
| 
 | |
|   static T highest() {
 | |
|     return forge(0x7f7fffff);
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static
 | |
|       typename enable_if<is_integral<TOut>::value && sizeof(TOut) < sizeof(T),
 | |
|                          T>::type
 | |
|       highest_for() {
 | |
|     // This conversion is safe because the destination type is smaller
 | |
|     return highest();
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static typename enable_if<is_integral<TOut>::value &&
 | |
|                                 is_signed<TOut>::value && sizeof(TOut) == 4,
 | |
|                             T>::type  // TOut == int32_t
 | |
|   highest_for() {
 | |
|     return forge(0x4EFFFFFF);  // 2.14748352E9
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static typename enable_if<is_integral<TOut>::value &&
 | |
|                                 is_unsigned<TOut>::value && sizeof(TOut) == 4,
 | |
|                             T>::type  // TOut == uint32_t
 | |
|   highest_for() {
 | |
|     return forge(0x4F7FFFFF);  // 4.29496704E9
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static typename enable_if<is_integral<TOut>::value &&
 | |
|                                 is_signed<TOut>::value && sizeof(TOut) == 8,
 | |
|                             T>::type  // TOut == int64_t
 | |
|   highest_for() {
 | |
|     return forge(0x5EFFFFFF);  // 9.22337148709896192E18
 | |
|   }
 | |
| 
 | |
|   template <typename TOut>
 | |
|   static typename enable_if<is_integral<TOut>::value &&
 | |
|                                 is_unsigned<TOut>::value && sizeof(TOut) == 8,
 | |
|                             T>::type  // TOut == uint64_t
 | |
|   highest_for() {
 | |
|     return forge(0x5F7FFFFF);  // 1.844674297419792384E19
 | |
|   }
 | |
| 
 | |
|   static T lowest() {
 | |
|     return forge(0xFf7fffff);
 | |
|   }
 | |
| };
 | |
| }  // namespace ARDUINOJSON_NAMESPACE
 |