diff --git a/src/ArduinoJson/Namespace.hpp b/src/ArduinoJson/Namespace.hpp index 76c4dcf9..8108c5da 100644 --- a/src/ArduinoJson/Namespace.hpp +++ b/src/ArduinoJson/Namespace.hpp @@ -10,19 +10,18 @@ #define ARDUINOJSON_DO_CONCAT(A, B) A##B #define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_DO_CONCAT(A, B) -#define ARDUINOJSON_CONCAT3(A, B, C) \ - ARDUINOJSON_CONCAT2(A, ARDUINOJSON_CONCAT2(B, C)) #define ARDUINOJSON_CONCAT4(A, B, C, D) \ ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D)) #define ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, H) \ ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT4(A, B, C, D), \ ARDUINOJSON_CONCAT4(E, F, G, H)) -#define ARDUINOJSON_CONCAT10(A, B, C, D, E, F, G, H, I, J) \ - ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, ARDUINOJSON_CONCAT3(H, I, J)) +#define ARDUINOJSON_CONCAT11(A, B, C, D, E, F, G, H, I, J, K) \ + ARDUINOJSON_CONCAT8(A, B, C, D, E, F, G, ARDUINOJSON_CONCAT4(H, I, J, K)) #define ARDUINOJSON_NAMESPACE \ - ARDUINOJSON_CONCAT10( \ + ARDUINOJSON_CONCAT11( \ ArduinoJson, ARDUINOJSON_VERSION_MAJOR, ARDUINOJSON_VERSION_MINOR, \ ARDUINOJSON_VERSION_REVISION, _, ARDUINOJSON_USE_LONG_LONG, \ ARDUINOJSON_USE_DOUBLE, ARDUINOJSON_DECODE_UNICODE, \ - ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY) + ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ + ARDUINOJSON_ENABLE_PROGMEM) diff --git a/src/ArduinoJson/Strings/FlashStringAdapter.hpp b/src/ArduinoJson/Strings/FlashStringAdapter.hpp index bb0fdd68..d1b094ad 100644 --- a/src/ArduinoJson/Strings/FlashStringAdapter.hpp +++ b/src/ArduinoJson/Strings/FlashStringAdapter.hpp @@ -14,7 +14,7 @@ class FlashStringAdapter { if (!other && !_str) return 0; if (!_str) return -1; if (!other) return 1; - return -strcmp_P(other, reinterpret_cast(_str)); + return int8_t(-strcmp_P(other, reinterpret_cast(_str))); } bool equals(const char* expected) const { diff --git a/src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp b/src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp index 323078af..a444c5f6 100644 --- a/src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp +++ b/src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp @@ -15,7 +15,8 @@ class SizedFlashStringAdapter { if (!other && !_str) return 0; if (!_str) return -1; if (!other) return 1; - return -strncmp_P(other, reinterpret_cast(_str), _size); + return int8_t( + -strncmp_P(other, reinterpret_cast(_str), _size)); } bool equals(const char* expected) const { @@ -29,7 +30,7 @@ class SizedFlashStringAdapter { char* save(MemoryPool* pool) const { if (!_str) return NULL; char* dup = pool->allocFrozenString(_size); - if (dup) memcpy_P(dup, (const char*)_str, _size); + if (dup) memcpy_P(dup, reinterpret_cast(_str), _size); return dup; } diff --git a/test/MixedConfiguration/CMakeLists.txt b/test/MixedConfiguration/CMakeLists.txt index 038317d3..afcf514b 100644 --- a/test/MixedConfiguration/CMakeLists.txt +++ b/test/MixedConfiguration/CMakeLists.txt @@ -17,6 +17,7 @@ add_executable(MixedConfigurationTests use_double_1.cpp use_long_long_0.cpp use_long_long_1.cpp + enable_progmem_1.cpp ) target_link_libraries(MixedConfigurationTests catch) diff --git a/test/MixedConfiguration/enable_progmem_1.cpp b/test/MixedConfiguration/enable_progmem_1.cpp new file mode 100644 index 00000000..187ec30a --- /dev/null +++ b/test/MixedConfiguration/enable_progmem_1.cpp @@ -0,0 +1,53 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2019 +// MIT License + +#include "progmem_emulation.hpp" + +#define ARDUINOJSON_ENABLE_PROGMEM 1 +#include + +#include + +TEST_CASE("Flash strings") { + DynamicJsonDocument doc(2048); + + SECTION("deserializeJson()") { + DeserializationError err = deserializeJson(doc, F("{'hello':'world'}")); + + REQUIRE(err == DeserializationError::Ok); + REQUIRE(doc["hello"] == "world"); + } + + SECTION("JsonDocument::operator[]") { + doc[F("hello")] = F("world"); + + REQUIRE(doc["hello"] == "world"); + } + + SECTION("JsonDocument::add()") { + doc.add(F("world")); + + REQUIRE(doc[0] == "world"); + } + + SECTION("JsonVariant::set()") { + JsonVariant var = doc.to(); + + var.set(F("world")); + + REQUIRE(var == "world"); + } + + SECTION("MemberProxy::operator==") { + doc["hello"] = "world"; + + REQUIRE(doc["hello"] == F("world")); + } + + SECTION("ElementProxy::operator==") { + doc.add("world"); + + REQUIRE(doc[0] == F("world")); + } +} diff --git a/test/MixedConfiguration/progmem_emulation.hpp b/test/MixedConfiguration/progmem_emulation.hpp new file mode 100644 index 00000000..b0bc8b50 --- /dev/null +++ b/test/MixedConfiguration/progmem_emulation.hpp @@ -0,0 +1,41 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2019 +// MIT License + +#include // uint8_t +#include // strcmp, strlen... + +class __FlashStringHelper; + +typedef char prog_char; +typedef void prog_void; + +inline const void* convertPtrToFlash(const void* s) { + return reinterpret_cast(s) + 42; +} + +inline const void* convertFlashToPtr(const void* s) { + return reinterpret_cast(s) - 42; +} + +#define F(X) reinterpret_cast(convertPtrToFlash(X)) + +inline uint8_t pgm_read_byte_near(const void* p) { + return *reinterpret_cast(convertFlashToPtr(p)); +} + +inline void* memcpy_P(void* a, const prog_void* b, size_t n) { + return memcpy(a, convertFlashToPtr(b), n); +} + +inline int strcmp_P(const char* a, const prog_char* b) { + return strcmp(a, reinterpret_cast(convertFlashToPtr(b))); +} + +inline int strncmp_P(const char* a, const prog_char* b, size_t n) { + return strncmp(a, reinterpret_cast(convertFlashToPtr(b)), n); +} + +inline size_t strlen_P(const prog_char* s) { + return strlen(reinterpret_cast(convertFlashToPtr(s))); +}