diff --git a/CHANGELOG.md b/CHANGELOG.md index 608efda3..6ec9cbc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ HEAD * Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358) * Added `DeserializationError::EmptyInput` which tells if the input was empty * Added `DeserializationError::f_str()` which returns a `const __FlashStringHelper*` (issue #846) +* Moved float convertion tables to PROGMEM * Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368) * Fixed error `No such file or directory #include ` (issue #1381) diff --git a/extras/tests/Helpers/progmem_emulation.hpp b/extras/tests/Helpers/progmem_emulation.hpp index f3c9246c..bd882bb2 100644 --- a/extras/tests/Helpers/progmem_emulation.hpp +++ b/extras/tests/Helpers/progmem_emulation.hpp @@ -28,7 +28,15 @@ inline void* pgm_read_ptr(const void* p) { return *reinterpret_cast(convertFlashToPtr(p)); } -#define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, value) \ +inline float pgm_read_float(const void* p) { + return *reinterpret_cast(convertFlashToPtr(p)); +} + +inline uint32_t pgm_read_dword(const void* p) { + return *reinterpret_cast(convertFlashToPtr(p)); +} + +#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ static type const ARDUINOJSON_CONCAT2(name, _progmem)[] = value; \ static type const* name = reinterpret_cast( \ convertPtrToFlash(ARDUINOJSON_CONCAT2(name, _progmem))); diff --git a/src/ArduinoJson/Deserialization/DeserializationError.hpp b/src/ArduinoJson/Deserialization/DeserializationError.hpp index 0c3c9423..e8902f09 100644 --- a/src/ArduinoJson/Deserialization/DeserializationError.hpp +++ b/src/ArduinoJson/Deserialization/DeserializationError.hpp @@ -5,6 +5,8 @@ #pragma once #include +#include +#include #if ARDUINOJSON_ENABLE_STD_STREAM #include @@ -86,22 +88,20 @@ class DeserializationError { return messages[_code]; } -#define ARDUINOJSON_EXPAND7(a, b, c, d, e, f, g) a, b, c, d, e, f, g - #if ARDUINOJSON_ENABLE_PROGMEM const __FlashStringHelper* f_str() const { - ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s0, "Ok"); - ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s1, "EmptyInput"); - ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s2, "IncompleteInput"); - ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s3, "InvalidInput"); - ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s4, "NoMemory"); - ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s5, "NotSupported"); - ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s6, "TooDeep"); - ARDUINOJSON_DEFINE_PROGMEM_ARRAY( + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "NotSupported"); + ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s6, "TooDeep"); + ARDUINOJSON_DEFINE_STATIC_ARRAY( const char*, messages, ARDUINOJSON_EXPAND7({s0, s1, s2, s3, s4, s5, s6})); - return reinterpret_cast( - pgm_read_ptr(messages + _code)); + return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages, + _code); } #endif diff --git a/src/ArduinoJson/Namespace.hpp b/src/ArduinoJson/Namespace.hpp index 7522d569..085ac273 100644 --- a/src/ArduinoJson/Namespace.hpp +++ b/src/ArduinoJson/Namespace.hpp @@ -5,45 +5,22 @@ #pragma once #include +#include #include #ifndef ARDUINOJSON_NAMESPACE -#define ARDUINOJSON_HEX_DIGIT_0000() 0 -#define ARDUINOJSON_HEX_DIGIT_0001() 1 -#define ARDUINOJSON_HEX_DIGIT_0010() 2 -#define ARDUINOJSON_HEX_DIGIT_0011() 3 -#define ARDUINOJSON_HEX_DIGIT_0100() 4 -#define ARDUINOJSON_HEX_DIGIT_0101() 5 -#define ARDUINOJSON_HEX_DIGIT_0110() 6 -#define ARDUINOJSON_HEX_DIGIT_0111() 7 -#define ARDUINOJSON_HEX_DIGIT_1000() 8 -#define ARDUINOJSON_HEX_DIGIT_1001() 9 -#define ARDUINOJSON_HEX_DIGIT_1010() A -#define ARDUINOJSON_HEX_DIGIT_1011() B -#define ARDUINOJSON_HEX_DIGIT_1100() C -#define ARDUINOJSON_HEX_DIGIT_1101() D -#define ARDUINOJSON_HEX_DIGIT_1110() E -#define ARDUINOJSON_HEX_DIGIT_1111() F -#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D() -#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D) - -#define ARDUINOJSON_CONCAT_(A, B) A##B -#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B) -#define ARDUINOJSON_CONCAT4(A, B, C, D) \ - ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D)) - -#define ARDUINOJSON_NAMESPACE \ - ARDUINOJSON_CONCAT4( \ - ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ - ARDUINOJSON_VERSION_MINOR, \ - ARDUINOJSON_VERSION_REVISION), \ - _, \ - ARDUINOJSON_HEX_DIGIT(0, ARDUINOJSON_USE_LONG_LONG, \ - ARDUINOJSON_USE_DOUBLE, \ - ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ - ARDUINOJSON_HEX_DIGIT( \ - ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ +#define ARDUINOJSON_NAMESPACE \ + ARDUINOJSON_CONCAT4( \ + ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ + ARDUINOJSON_VERSION_MINOR, \ + ARDUINOJSON_VERSION_REVISION), \ + _, \ + ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \ + ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \ + ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ + ARDUINOJSON_HEX_DIGIT( \ + ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE)) #endif diff --git a/src/ArduinoJson/Numbers/FloatTraits.hpp b/src/ArduinoJson/Numbers/FloatTraits.hpp index 6f4df596..78bf617c 100644 --- a/src/ArduinoJson/Numbers/FloatTraits.hpp +++ b/src/ArduinoJson/Numbers/FloatTraits.hpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include namespace ARDUINOJSON_NAMESPACE { @@ -46,48 +48,60 @@ struct FloatTraits { } static T positiveBinaryPowerOfTen(int index) { - static T factors[] = { - 1e1, - 1e2, - 1e4, - 1e8, - 1e16, - forge(0x4693B8B5, 0xB5056E17), // 1e32 - forge(0x4D384F03, 0xE93FF9F5), // 1e64 - forge(0x5A827748, 0xF9301D32), // 1e128 - forge(0x75154FDD, 0x7F73BF3C) // 1e256 - }; - return factors[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) { - static T factors[] = { - forge(0x3FB99999, 0x9999999A), // 1e-1 - forge(0x3F847AE1, 0x47AE147B), // 1e-2 - forge(0x3F1A36E2, 0xEB1C432D), // 1e-4 - forge(0x3E45798E, 0xE2308C3A), // 1e-8 - forge(0x3C9CD2B2, 0x97D889BC), // 1e-16 - forge(0x3949F623, 0xD5A8A733), // 1e-32 - forge(0x32A50FFD, 0x44F4A73D), // 1e-64 - forge(0x255BBA08, 0xCF8C979D), // 1e-128 - forge(0x0AC80628, 0x64AC6F43) // 1e-256 - }; - return factors[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) { - static T factors[] = { - 1e0, - forge(0x3FB99999, 0x9999999A), // 1e-1 - forge(0x3F50624D, 0xD2F1A9FC), // 1e-3 - forge(0x3E7AD7F2, 0x9ABCAF48), // 1e-7 - forge(0x3CD203AF, 0x9EE75616), // 1e-15 - forge(0x398039D6, 0x65896880), // 1e-31 - forge(0x32DA53FC, 0x9631D10D), // 1e-63 - forge(0x25915445, 0x81B7DEC2), // 1e-127 - forge(0x0AFE07B2, 0x7DD78B14) // 1e-255 - }; - return factors[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() { @@ -144,18 +158,24 @@ struct FloatTraits { } static T positiveBinaryPowerOfTen(int index) { - static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T negativeBinaryPowerOfTen(int index) { - static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T negativeBinaryPowerOfTenPlusOne(int index) { - static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}; - return factors[index]; + ARDUINOJSON_DEFINE_STATIC_ARRAY( + T, factors, + ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f})); + return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index); } static T forge(uint32_t bits) { diff --git a/src/ArduinoJson/Polyfills/pgmspace.hpp b/src/ArduinoJson/Polyfills/pgmspace.hpp index 8c1b5ac6..0cdc5cb7 100644 --- a/src/ArduinoJson/Polyfills/pgmspace.hpp +++ b/src/ArduinoJson/Polyfills/pgmspace.hpp @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -76,13 +77,3 @@ inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) { return dst; } #endif - -#ifndef ARDUINOJSON_DEFINE_PROGMEM_ARRAY -#ifdef PROGMEM -#define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, value) \ - static type const name[] PROGMEM = value; -#else -#define ARDUINOJSON_DEFINE_PROGMEM_ARRAY(type, name, value) \ - static type const name[] = value; -#endif -#endif diff --git a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp new file mode 100644 index 00000000..70f715fd --- /dev/null +++ b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp @@ -0,0 +1,28 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include +#include + +namespace ARDUINOJSON_NAMESPACE { + +template +typename enable_if::value, T>::type pgm_read(const void* p) { + return reinterpret_cast(pgm_read_ptr(p)); +} + +template +typename enable_if::value, T>::type pgm_read(const void* p) { + return pgm_read_float(p); +} + +template +typename enable_if::value, T>::type pgm_read( + const void* p) { + return pgm_read_dword(p); +} + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Polyfills/preprocessor.hpp b/src/ArduinoJson/Polyfills/preprocessor.hpp new file mode 100644 index 00000000..4df13d8b --- /dev/null +++ b/src/ArduinoJson/Polyfills/preprocessor.hpp @@ -0,0 +1,36 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#define ARDUINOJSON_EXPAND6(a, b, c, d, e, f) a, b, c, d, e, f +#define ARDUINOJSON_EXPAND7(a, b, c, d, e, f, g) a, b, c, d, e, f, g +#define ARDUINOJSON_EXPAND9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i +#define ARDUINOJSON_EXPAND18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, \ + q, r) \ + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r + +#define ARDUINOJSON_CONCAT_(A, B) A##B +#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B) +#define ARDUINOJSON_CONCAT4(A, B, C, D) \ + ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D)) + +#define ARDUINOJSON_HEX_DIGIT_0000() 0 +#define ARDUINOJSON_HEX_DIGIT_0001() 1 +#define ARDUINOJSON_HEX_DIGIT_0010() 2 +#define ARDUINOJSON_HEX_DIGIT_0011() 3 +#define ARDUINOJSON_HEX_DIGIT_0100() 4 +#define ARDUINOJSON_HEX_DIGIT_0101() 5 +#define ARDUINOJSON_HEX_DIGIT_0110() 6 +#define ARDUINOJSON_HEX_DIGIT_0111() 7 +#define ARDUINOJSON_HEX_DIGIT_1000() 8 +#define ARDUINOJSON_HEX_DIGIT_1001() 9 +#define ARDUINOJSON_HEX_DIGIT_1010() A +#define ARDUINOJSON_HEX_DIGIT_1011() B +#define ARDUINOJSON_HEX_DIGIT_1100() C +#define ARDUINOJSON_HEX_DIGIT_1101() D +#define ARDUINOJSON_HEX_DIGIT_1110() E +#define ARDUINOJSON_HEX_DIGIT_1111() F +#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D() +#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D) diff --git a/src/ArduinoJson/Polyfills/static_array.hpp b/src/ArduinoJson/Polyfills/static_array.hpp new file mode 100644 index 00000000..c642b270 --- /dev/null +++ b/src/ArduinoJson/Polyfills/static_array.hpp @@ -0,0 +1,34 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include + +#if ARDUINOJSON_ENABLE_PROGMEM + +#include + +#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] PROGMEM = value; +#endif + +#ifndef ARDUINOJSON_READ_STATIC_ARRAY +#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \ + pgm_read(name + index) +#endif + +#else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0 + +#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] = value; +#endif + +#ifndef ARDUINOJSON_READ_STATIC_ARRAY +#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index] +#endif + +#endif diff --git a/src/ArduinoJson/Polyfills/type_traits.hpp b/src/ArduinoJson/Polyfills/type_traits.hpp index 324f1444..43dc4e01 100644 --- a/src/ArduinoJson/Polyfills/type_traits.hpp +++ b/src/ArduinoJson/Polyfills/type_traits.hpp @@ -15,6 +15,7 @@ #include "type_traits/is_enum.hpp" #include "type_traits/is_floating_point.hpp" #include "type_traits/is_integral.hpp" +#include "type_traits/is_pointer.hpp" #include "type_traits/is_same.hpp" #include "type_traits/is_signed.hpp" #include "type_traits/is_unsigned.hpp" diff --git a/src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp b/src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp new file mode 100644 index 00000000..92ba098a --- /dev/null +++ b/src/ArduinoJson/Polyfills/type_traits/is_pointer.hpp @@ -0,0 +1,16 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2020 +// MIT License + +#pragma once + +#include "integral_constant.hpp" + +namespace ARDUINOJSON_NAMESPACE { + +template +struct is_pointer : false_type {}; + +template +struct is_pointer : true_type {}; +} // namespace ARDUINOJSON_NAMESPACE