From 1ce16ce449e37235f6cb4c6d7d4fb7dda81ac17a Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sun, 13 Nov 2016 20:16:12 +0100 Subject: [PATCH] Added support for PROGMEM (issue #76) --- CHANGELOG.md | 5 ++ examples/ProgmemExample/ProgmemExample.ino | 51 +++++++++++++++++++ include/ArduinoJson/Configuration.hpp | 14 +++++ include/ArduinoJson/Internals/StringFuncs.hpp | 21 ++++++++ 4 files changed, 91 insertions(+) create mode 100644 examples/ProgmemExample/ProgmemExample.ino diff --git a/CHANGELOG.md b/CHANGELOG.md index f8499dd9..1689b4ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ ArduinoJson: change log ======================= +HEAD +---- + +* Added support for PROGMEM (issue #76) + v5.7.0 ------ diff --git a/examples/ProgmemExample/ProgmemExample.ino b/examples/ProgmemExample/ProgmemExample.ino new file mode 100644 index 00000000..45bc3d1e --- /dev/null +++ b/examples/ProgmemExample/ProgmemExample.ino @@ -0,0 +1,51 @@ +// Copyright Benoit Blanchon 2014-2016 +// MIT License +// +// Arduino JSON library +// https://github.com/bblanchon/ArduinoJson +// If you like this project, please add a star! + +#include + +// About +// ----- +// This example shows the different ways you can use PROGMEM with ArduinoJson. +// Please don't see this as an invitation to use PROGMEM. +// On the contrary, you should always use char[] when possible, it's much more +// efficient in term of code size, speed and memory usage. + +void setup() { +#if ARDUINO_ARCH_AVR + DynamicJsonBuffer jsonBuffer; + + // You can use a Flash String as your JSON input. + // WARNING: the content of the Flash String will be duplicated in the + // JsonBuffer. + JsonObject& root = + jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120," + "\"data\":[48.756080,2.302038]}")); + + // You can use a Flash String to get an element of a JsonObject + // No duplication is done. + long time = root[F("time")]; + + // You can use a Flash String to set an element of a JsonObject + // WARNING: the content of the Flash String will be duplicated in the + // JsonBuffer. + root[F("time")] = time; + + // You can set a Flash String to a JsonObject or JsonArray: + // WARNING: the content of the Flash String will be duplicated in the + // JsonBuffer. + root["sensor"] = F("gps"); + +#else + +#warning PROGMEM is only supported on AVR architecture + +#endif +} + +void loop() { + // not used in this example +} diff --git a/include/ArduinoJson/Configuration.hpp b/include/ArduinoJson/Configuration.hpp index 32b71b7d..93edc187 100644 --- a/include/ArduinoJson/Configuration.hpp +++ b/include/ArduinoJson/Configuration.hpp @@ -27,6 +27,15 @@ #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 #endif +// On AVR archiecture, we can use PROGMEM +#ifndef ARDUINOJSON_ENABLE_PROGMEM +#ifdef ARDUINO_ARCH_AVR +#define ARDUINOJSON_ENABLE_PROGMEM 1 +#else +#define ARDUINOJSON_ENABLE_PROGMEM 0 +#endif +#endif + // Arduino doesn't have std::string #ifndef ARDUINOJSON_ENABLE_STD_STRING #define ARDUINOJSON_ENABLE_STD_STRING 0 @@ -87,6 +96,11 @@ #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 #endif +// PROGMEM is only available on AVR architecture +#ifndef ARDUINOJSON_ENABLE_PROGMEM +#define ARDUINOJSON_ENABLE_PROGMEM 0 +#endif + // on a computer, we can assume that the STL is there #ifndef ARDUINOJSON_ENABLE_STD_STREAM #define ARDUINOJSON_ENABLE_STD_STREAM 1 diff --git a/include/ArduinoJson/Internals/StringFuncs.hpp b/include/ArduinoJson/Internals/StringFuncs.hpp index bba4e603..cb6b5cb1 100644 --- a/include/ArduinoJson/Internals/StringFuncs.hpp +++ b/include/ArduinoJson/Internals/StringFuncs.hpp @@ -90,5 +90,26 @@ struct StringFuncs : StdStringFuncs {}; template <> struct StringFuncs : StdStringFuncs {}; #endif + +#if ARDUINOJSON_ENABLE_PROGMEM +template <> +struct StringFuncs { + static bool equals(const __FlashStringHelper* str, const char* expected) { + return strcmp_P((PGM_P)str, expected) == 0; + } + + template + static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) { + if (!str) return NULL; + size_t size = strlen_P((PGM_P)str) + 1; + void* dup = buffer->alloc(size); + if (dup != NULL) memcpy_P(dup, (PGM_P)str, size); + return static_cast(dup); + } + + static const bool has_append = false; + static const bool should_duplicate = true; +}; +#endif } }