From 4e7099dc7300498b17042e1db6662206b1ae4bba Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 22 Feb 2023 11:54:18 +0100 Subject: [PATCH] Add `pgm_ptr` --- src/ArduinoJson/Numbers/FloatParts.hpp | 8 ++--- src/ArduinoJson/Numbers/FloatTraits.hpp | 32 +++++++++---------- src/ArduinoJson/Polyfills/pgmspace.hpp | 23 +++++++++++++ .../Polyfills/pgmspace_generic.hpp | 24 +++++++++++--- 4 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/ArduinoJson/Numbers/FloatParts.hpp b/src/ArduinoJson/Numbers/FloatParts.hpp index 67344494..b9291ce1 100644 --- a/src/ArduinoJson/Numbers/FloatParts.hpp +++ b/src/ArduinoJson/Numbers/FloatParts.hpp @@ -63,8 +63,8 @@ struct FloatParts { if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) { for (; index >= 0; index--) { - if (value >= traits::positiveBinaryPowerOfTen(index)) { - value *= traits::negativeBinaryPowerOfTen(index); + if (value >= traits::positiveBinaryPowersOfTen()[index]) { + value *= traits::negativeBinaryPowersOfTen()[index]; powersOf10 = int16_t(powersOf10 + bit); } bit >>= 1; @@ -73,8 +73,8 @@ struct FloatParts { if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) { for (; index >= 0; index--) { - if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) { - value *= traits::positiveBinaryPowerOfTen(index); + if (value < traits::negativeBinaryPowersOfTenPlusOne()[index]) { + value *= traits::positiveBinaryPowersOfTen()[index]; powersOf10 = int16_t(powersOf10 - bit); } bit >>= 1; diff --git a/src/ArduinoJson/Numbers/FloatTraits.hpp b/src/ArduinoJson/Numbers/FloatTraits.hpp index 030fd54d..5736f599 100644 --- a/src/ArduinoJson/Numbers/FloatTraits.hpp +++ b/src/ArduinoJson/Numbers/FloatTraits.hpp @@ -34,21 +34,21 @@ struct FloatTraits { if (e > 0) { for (uint8_t index = 0; e != 0; index++) { if (e & 1) - m *= positiveBinaryPowerOfTen(index); + m *= positiveBinaryPowersOfTen()[index]; e >>= 1; } } else { e = TExponent(-e); for (uint8_t index = 0; e != 0; index++) { if (e & 1) - m *= negativeBinaryPowerOfTen(index); + m *= negativeBinaryPowersOfTen()[index]; e >>= 1; } } return m; } - static T positiveBinaryPowerOfTen(int index) { + static pgm_ptr positiveBinaryPowersOfTen() { ARDUINOJSON_DEFINE_PROGMEM_ARRAY( // uint64_t, factors, { @@ -62,10 +62,10 @@ struct FloatTraits { 0x5A827748F9301D32, // 1e128 0x75154FDD7F73BF3C, // 1e256 }); - return forge(pgm_read(factors + index)); + return pgm_ptr(reinterpret_cast(factors)); } - static T negativeBinaryPowerOfTen(int index) { + static pgm_ptr negativeBinaryPowersOfTen() { ARDUINOJSON_DEFINE_PROGMEM_ARRAY( // uint64_t, factors, { @@ -79,10 +79,10 @@ struct FloatTraits { 0x255BBA08CF8C979D, // 1e-128 0x0AC8062864AC6F43 // 1e-256 }); - return forge(pgm_read(factors + index)); + return pgm_ptr(reinterpret_cast(factors)); } - static T negativeBinaryPowerOfTenPlusOne(int index) { + static pgm_ptr negativeBinaryPowersOfTenPlusOne() { ARDUINOJSON_DEFINE_PROGMEM_ARRAY( // uint64_t, factors, { @@ -96,7 +96,7 @@ struct FloatTraits { 0x2591544581B7DEC2, // 1e-127 0x0AFE07B27DD78B14 // 1e-255 }); - return forge(pgm_read(factors + index)); + return pgm_ptr(reinterpret_cast(factors)); } static T nan() { @@ -154,21 +154,21 @@ struct FloatTraits { if (e > 0) { for (uint8_t index = 0; e != 0; index++) { if (e & 1) - m *= positiveBinaryPowerOfTen(index); + m *= positiveBinaryPowersOfTen()[index]; e >>= 1; } } else { e = -e; for (uint8_t index = 0; e != 0; index++) { if (e & 1) - m *= negativeBinaryPowerOfTen(index); + m *= negativeBinaryPowersOfTen()[index]; e >>= 1; } } return m; } - static T positiveBinaryPowerOfTen(int index) { + static pgm_ptr positiveBinaryPowersOfTen() { ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors, { 0x41200000, // 1e1f @@ -178,10 +178,10 @@ struct FloatTraits { 0x5a0e1bca, // 1e16f 0x749dc5ae // 1e32f }); - return forge(pgm_read(factors + index)); + return pgm_ptr(reinterpret_cast(factors)); } - static T negativeBinaryPowerOfTen(int index) { + static pgm_ptr negativeBinaryPowersOfTen() { ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors, { 0x3dcccccd, // 1e-1f @@ -191,10 +191,10 @@ struct FloatTraits { 0x24e69595, // 1e-16f 0x0a4fb11f // 1e-32f }); - return forge(pgm_read(factors + index)); + return pgm_ptr(reinterpret_cast(factors)); } - static T negativeBinaryPowerOfTenPlusOne(int index) { + static pgm_ptr negativeBinaryPowersOfTenPlusOne() { ARDUINOJSON_DEFINE_PROGMEM_ARRAY(uint32_t, factors, { 0x3f800000, // 1e0f @@ -204,7 +204,7 @@ struct FloatTraits { 0x26901d7d, // 1e-15f 0x0c01ceb3 // 1e-31f }); - return forge(pgm_read(factors + index)); + return pgm_ptr(reinterpret_cast(factors)); } static T forge(uint32_t bits) { diff --git a/src/ArduinoJson/Polyfills/pgmspace.hpp b/src/ArduinoJson/Polyfills/pgmspace.hpp index 5cfd28cb..03adc6f1 100644 --- a/src/ArduinoJson/Polyfills/pgmspace.hpp +++ b/src/ArduinoJson/Polyfills/pgmspace.hpp @@ -106,6 +106,29 @@ inline uint32_t pgm_read_dword(ArduinoJson::detail::pgm_p p) { } #endif +#ifndef pgm_read_float +inline float pgm_read_float(ArduinoJson::detail::pgm_p p) { + float result; + memcpy_P(&result, p.address, sizeof(float)); + return result; +} +#endif + +#ifndef pgm_read_double +# if defined(__SIZEOF_DOUBLE__) && defined(__SIZEOF_FLOAT__) && \ + __SIZEOF_DOUBLE__ == __SIZEOF_FLOAT__ +inline double pgm_read_double(ArduinoJson::detail::pgm_p p) { + return pgm_read_float(p.address); +} +# else +inline double pgm_read_double(ArduinoJson::detail::pgm_p p) { + double result; + memcpy_P(&result, p.address, sizeof(double)); + return result; +} +# endif +#endif + #ifndef pgm_read_ptr inline void* pgm_read_ptr(ArduinoJson::detail::pgm_p p) { void* result; diff --git a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp index f5b50b8d..750bb438 100644 --- a/src/ArduinoJson/Polyfills/pgmspace_generic.hpp +++ b/src/ArduinoJson/Polyfills/pgmspace_generic.hpp @@ -29,11 +29,12 @@ inline uint32_t pgm_read(const uint32_t* p) { return pgm_read_dword(p); } -template -inline T pgm_read(const T* p) { - T result; - memcpy_P(&result, p, sizeof(T)); - return result; +inline double pgm_read(const double* p) { + return pgm_read_double(p); +} + +inline float pgm_read(const float* p) { + return pgm_read_float(p); } #else @@ -50,4 +51,17 @@ inline T pgm_read(const T* p) { #endif +template +class pgm_ptr { + public: + explicit pgm_ptr(const T* ptr) : _ptr(ptr) {} + + T operator[](intptr_t index) const { + return pgm_read(_ptr + index); + } + + private: + const T* _ptr; +}; + ARDUINOJSON_END_PRIVATE_NAMESPACE