diff --git a/images/macbook-pro-space-gray-on-the-wooden-table.jpg b/images/macbook-pro-space-gray-on-the-wooden-table.jpg
index 64f645b3d..25f46cc1b 100644
Binary files a/images/macbook-pro-space-gray-on-the-wooden-table.jpg and b/images/macbook-pro-space-gray-on-the-wooden-table.jpg differ
diff --git a/images/wled_logo.png b/images/wled_logo.png
index 905c793f7..116eda0a8 100644
Binary files a/images/wled_logo.png and b/images/wled_logo.png differ
diff --git a/images/wled_logo_akemi.png b/images/wled_logo_akemi.png
index c0bf93db6..4f52d3708 100644
Binary files a/images/wled_logo_akemi.png and b/images/wled_logo_akemi.png differ
diff --git a/images/wled_logo_clean.png b/images/wled_logo_clean.png
index c553f1186..26a0ebeda 100644
Binary files a/images/wled_logo_clean.png and b/images/wled_logo_clean.png differ
diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg b/usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg
index d518ca3e3..755bfefb3 100644
Binary files a/usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg and b/usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg differ
diff --git a/usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png b/usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png
index cf146918a..a4b81ad05 100644
Binary files a/usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png and b/usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png differ
diff --git a/usermods/PIR_sensor_switch/PIR_Highlight_Standby b/usermods/PIR_sensor_switch/PIR_Highlight_Standby
new file mode 100644
index 000000000..ddbbddeae
--- /dev/null
+++ b/usermods/PIR_sensor_switch/PIR_Highlight_Standby
@@ -0,0 +1,347 @@
+#pragma once
+
+#include "wled.h"
+
+/*
+ * --------------------
+ * Rawframe edit:
+ * - TESTED ON WLED VS.0.10.1 - WHERE ONLY PRESET 16 SAVES SEGMENTS - some macros may not be needed if this changes.
+ * - Code has been modified as my usage changed, as such it has poor use of functions vs if thens, but feel free to change it for me :)
+ *
+ * Edited to SWITCH between two lighting scenes/modes : STANDBY and HIGHLIGHT
+ *
+ * Usage:
+ * - Standby is the default mode and Highlight is activated when the PIR detects activity.
+ * - PIR delay now set to same value as Nightlight feature on boot but otherwise controlled as normal.
+ * - Standby and Highlight brightness can be set on the fly (default values set on boot via macros calling presets).
+ * - Macros are used to set Standby and Highlight states (macros can load saved presets etc).
+ *
+ * - Macro short button press = Highlight state default (used on boot only and sets default brightness).
+ * - Macro double button press = Standby state default (used on boot only and sets default brightness).
+ * - Macro long button press = Highlight state (after boot).
+ * - Macro 16 = Standby state (after boot).
+ *
+ * ! It is advised not to set 'Apply preset at boot' or a boot macro (that activates a preset) as we will call our own macros on boot.
+ *
+ * - When the strip is off before PIR activates the strip will return to off for Standby mode, and vice versa.
+ * - When the strip is turned off while in Highlight mode, it will return to standby mode. (This behaviour could be changed easily if for some reason you wanted the lights to go out when the pir is activated).
+ * - Macros can be chained so you could do almost anything, such as have standby mode also turn on the nightlight function with a new time delay.
+ *
+ * Segment Notes:
+ * - It's easier to save the segment selections in preset than apply via macro while we a limited to preset 16. (Ie, instead of selecting sections at the point of activating standby/highlight modes).
+ * - Because only preset 16 saves segments, for now we are having to use addiotional macros to control segments where they are involved. Macros can be chained so this works but it would be better if macros also accepted json-api commands. (Testing http api segement behaviour of SS with SB left me a little confused).
+ *
+ * Future:
+ * - Maybe a second timer/timetable that turns on/off standby mode also after set inactivity period / date & times. For now this can be achieved others ways so may not be worth eating more processing power.
+ *
+ * --------------------
+ *
+ * This usermod handles PIR sensor states.
+ * The strip will be switched on and the off timer will be resetted when the sensor goes HIGH.
+ * When the sensor state goes LOW, the off timer is started and when it expires, the strip is switched off.
+ *
+ *
+ * Usermods allow you to add own functionality to WLED more easily
+ * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
+ *
+ * v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
+ * Multiple v2 usermods can be added to one compilation easily.
+ *
+ * Creating a usermod:
+ * This file serves as an example. If you want to create a usermod, it is recommended to use usermod_v2_empty.h from the usermods folder as a template.
+ * Please remember to rename the class and file to a descriptive name.
+ * You may also use multiple .h and .cpp files.
+ *
+ * Using a usermod:
+ * 1. Copy the usermod into the sketch folder (same folder as wled00.ino)
+ * 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
+ */
+
+class PIRsensorSwitch : public Usermod {
+ private:
+ // PIR sensor pin
+ const uint8_t PIRsensorPin = 13; // D7 on D1 mini
+ // notification mode for colorUpdated()
+ const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE
+ // 1 min delay before switch off after the sensor state goes LOW
+ uint32_t m_switchOffDelay = 60000;
+ // off timer start time
+ uint32_t m_offTimerStart = 0;
+ // current PIR sensor pin state
+ byte m_PIRsensorPinState = LOW;
+ // PIR sensor enabled - ISR attached
+ bool m_PIRenabled = true;
+ // temp standby brightness store. initial value set as nightlight default target brightness
+ byte briStandby _INIT(nightlightTargetBri);
+ // temp hightlight brightness store. initial value set as current brightness
+ byte briHighlight _INIT(bri);
+ // highlight active/deactive monitor
+ bool highlightActive = false;
+ // wled on/off state in standby mode
+ bool standbyoff = false;
+
+ /*
+ * return or change if new PIR sensor state is available
+ */
+ static volatile bool newPIRsensorState(bool changeState = false, bool newState = false) {
+ static volatile bool s_PIRsensorState = false;
+ if (changeState) {
+ s_PIRsensorState = newState;
+ }
+ return s_PIRsensorState;
+ }
+
+ /*
+ * PIR sensor state has changed
+ */
+ static void IRAM_ATTR ISR_PIRstateChange() {
+ newPIRsensorState(true, true);
+ }
+
+ /*
+ * switch strip on/off
+ */
+ // now allowing adjustable standby and highlight brightness
+ void switchStrip(bool switchOn) {
+ //if (switchOn && bri == 0) {
+ if (switchOn) { // **pir sensor is on and activated**
+ //bri = briLast;
+ if (bri != 0) { // is WLED currently on
+ if (highlightActive) { // and is Highlight already on
+ briHighlight = bri; // then update highlight brightness with current brightness
+ }
+ else {
+ briStandby = bri; // else update standby brightness with current brightness
+ }
+ }
+ else { // WLED is currently off
+ if (!highlightActive) { // and Highlight is not already on
+ briStandby = briLast; // then update standby brightness with last active brightness (before turned off)
+ standbyoff = true;
+ }
+ else { // and Highlight is already on
+ briHighlight = briLast; // then set hightlight brightness to last active brightness (before turned off)
+ }
+ }
+ applyMacro(16); // apply highlight lighting without brightness
+ if (bri != briHighlight) {
+ bri = briHighlight; // set current highlight brightness to last set highlight brightness
+ }
+ colorUpdated(NotifyUpdateMode);
+ highlightActive = true; // flag highlight is on
+ }
+ else { // **pir timer has elapsed**
+ //briLast = bri;
+ //bri = 0;
+ if (bri != 0) { // is WLED currently on
+ briHighlight = bri; // update highlight brightness with current brightness
+ if (!standbyoff) { //
+ bri = briStandby; // set standby brightness to last set standby brightness
+ }
+ else { //
+ briLast = briStandby; // set standby off brightness
+ bri = 0; // set power off in standby
+ standbyoff = false; // turn off flag
+ }
+ applyMacro(macroLongPress); // apply standby lighting without brightness
+ }
+ else { // WLED is currently off
+ briHighlight = briLast; // set last active brightness (before turned off) to highlight lighting brightness
+ if (!standbyoff) { //
+ bri = briStandby; // set standby brightness to last set standby brightness
+ }
+ else { //
+ briLast = briStandby; // set standby off brightness
+ bri = 0; // set power off in standby
+ standbyoff = false; // turn off flag
+ }
+ applyMacro(macroLongPress); // apply standby lighting without brightness
+ }
+ colorUpdated(NotifyUpdateMode);
+ highlightActive = false; // flag highlight is off
+ }
+ }
+
+ /*
+ * Read and update PIR sensor state.
+ * Initilize/reset switch off timer
+ */
+ bool updatePIRsensorState() {
+ if (newPIRsensorState()) {
+ m_PIRsensorPinState = digitalRead(PIRsensorPin);
+
+ if (m_PIRsensorPinState == HIGH) {
+ m_offTimerStart = 0;
+ switchStrip(true);
+ }
+ else if (bri != 0) {
+ // start switch off timer
+ m_offTimerStart = millis();
+ }
+ newPIRsensorState(true, false);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * switch off the strip if the delay has elapsed
+ */
+ bool handleOffTimer() {
+ if (m_offTimerStart > 0) {
+ if ((millis() - m_offTimerStart > m_switchOffDelay) || bri == 0 ) { // now also checking for manual power off during highlight mode
+ switchStrip(false);
+ m_offTimerStart = 0;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public:
+ //Functions called by WLED
+
+ /*
+ * setup() is called once at boot. WiFi is not yet connected at this point.
+ * You can use it to initialize variables, sensors or similar.
+ */
+ void setup() {
+ // PIR Sensor mode INPUT_PULLUP
+ pinMode(PIRsensorPin, INPUT_PULLUP);
+ // assign interrupt function and set CHANGE mode
+ attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
+ // set delay to nightlight default duration on boot (after which json PIRoffSec overides if needed)
+ m_switchOffDelay = (nightlightDelayMins*60000);
+ applyMacro(macroButton); // apply default highlight lighting
+ briHighlight = bri;
+ applyMacro(macroDoublePress); // apply default standby lighting with brightness
+ briStandby = bri;
+ }
+
+
+ /*
+ * connected() is called every time the WiFi is (re)connected
+ * Use it to initialize network interfaces
+ */
+ void connected() {
+
+ }
+
+
+ /*
+ * loop() is called continuously. Here you can check for events, read sensors, etc.
+ */
+ void loop() {
+ if (!updatePIRsensorState()) {
+ handleOffTimer();
+ }
+ }
+
+ /*
+ * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
+ *
+ * Add PIR sensor state and switch off timer duration to jsoninfo
+ */
+ void addToJsonInfo(JsonObject& root)
+ {
+ //this code adds "u":{"⏲ PIR sensor state":uiDomString} to the info object
+ // the value contains a button to toggle the sensor enabled/disabled
+ JsonObject user = root["u"];
+ if (user.isNull()) user = root.createNestedObject("u");
+
+ JsonArray infoArr = user.createNestedArray("⏲ PIR sensor state"); //name
+ String uiDomString = "";
+ infoArr.add(uiDomString); //value
+
+ //this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
+ infoArr = user.createNestedArray("⏲ switch off timer"); //name
+
+ // off timer
+ if (m_offTimerStart > 0) {
+ uiDomString = "";
+ unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000;
+ if (offSeconds >= 3600) {
+ uiDomString += (offSeconds / 3600);
+ uiDomString += " hours ";
+ offSeconds %= 3600;
+ }
+ if (offSeconds >= 60) {
+ uiDomString += (offSeconds / 60);
+ offSeconds %= 60;
+ } else if (uiDomString.length() > 0){
+ uiDomString += 0;
+ }
+ if (uiDomString.length() > 0){
+ uiDomString += " min ";
+ }
+ uiDomString += (offSeconds);
+ infoArr.add(uiDomString + " sec");
+ } else {
+ infoArr.add("inactive");
+ }
+ }
+
+
+ /*
+ * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
+ * Values in the state object may be modified by connected clients
+ * Add "PIRenabled" to json state. This can be used to disable/enable the sensor.
+ * Add "PIRoffSec" to json state. This can be used to adjust milliseconds .
+ */
+ void addToJsonState(JsonObject& root)
+ {
+ root["PIRenabled"] = m_PIRenabled;
+ root["PIRoffSec"] = (m_switchOffDelay / 1000);
+ }
+
+
+ /*
+ * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
+ * Values in the state object may be modified by connected clients
+ * Read "PIRenabled" from json state and switch enable/disable the PIR sensor.
+ * Read "PIRoffSec" from json state and adjust milliseconds .
+ */
+ void readFromJsonState(JsonObject& root)
+ {
+ if (root["PIRoffSec"] != nullptr) {
+ m_switchOffDelay = (1000 * max(60UL, min(43200UL, root["PIRoffSec"].as())));
+ }
+
+ if (root["PIRenabled"] != nullptr) {
+ if (root["PIRenabled"] && !m_PIRenabled) {
+ attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
+ newPIRsensorState(true, true);
+ }
+ else if(m_PIRenabled) {
+ detachInterrupt(PIRsensorPin);
+ }
+ m_PIRenabled = root["PIRenabled"];
+ }
+ }
+
+
+ /*
+ * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
+ * This could be used in the future for the system to determine whether your usermod is installed.
+ */
+ uint16_t getId()
+ {
+ return USERMOD_ID_PIRSWITCH;
+ }
+
+ //More methods can be added in the future, this example will then be extended.
+ //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
+};
diff --git a/usermods/PIR_sensor_switch/readme.md b/usermods/PIR_sensor_switch/readme.md
index 447f541cb..79556db7f 100644
--- a/usermods/PIR_sensor_switch/readme.md
+++ b/usermods/PIR_sensor_switch/readme.md
@@ -72,4 +72,26 @@ void registerUsermods()
}
```
+## Usermod installation (advanced mode)
+
+In this mode IR sensor will disable PIR when light ON by remote controller and enable PIR when light OFF.
+
+1. Copy the file `usermod_PIR_sensor_switch.h` to the `wled00` directory.
+2. Register the usermod by adding `#include "usermod_PIR_sensor_switch.h"` in the top and `registerUsermod(new PIRsensorSwitch());` in the bottom of `usermods_list.cpp`.
+3. Add to the line 237, on `wled.h` in the `wled00` directory:
+
+ `WLED_GLOBAL bool m_PIRenabled _INIT(true); // enable PIR sensor`
+
+4. On `ir.cpp` in the `wled00` directory, add to the IR controller's mapping (beyond line 200):
+
+- To the off button:
+ `m_PIRenabled = true;`
+
+- To the on button:
+ `m_PIRenabled = false;`
+
+5. Edit line 40, on `usermod_PIR_sensor_switch.h` in the `wled00` directory:
+
+ `\\bool m_PIRenabled = true;`
+
Have fun - @gegu
diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
index 6d71a426e..e87147a1a 100644
--- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
+++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h
@@ -99,7 +99,9 @@ class PIRsensorSwitch : public Usermod {
*/
bool handleOffTimer() {
if (m_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay) {
- switchStrip(false);
+ if (m_PIRenabled == true){
+ switchStrip(false);
+ }
m_offTimerStart = 0;
return true;
}
diff --git a/usermods/TTGO-T-Display/assets/ttgo_hardware1.png b/usermods/TTGO-T-Display/assets/ttgo_hardware1.png
index 42d338db1..3d2b940d6 100644
Binary files a/usermods/TTGO-T-Display/assets/ttgo_hardware1.png and b/usermods/TTGO-T-Display/assets/ttgo_hardware1.png differ
diff --git a/usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg b/usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg
index f352ba3a3..459151e8d 100644
Binary files a/usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg and b/usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg differ
diff --git a/usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg b/usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg
index 2bf359d36..b89302a8c 100644
Binary files a/usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg and b/usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg differ
diff --git a/usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg b/usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg
index 892b13ff3..6e2a5bf00 100644
Binary files a/usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg and b/usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg differ
diff --git a/wled00/FX.h b/wled00/FX.h
index e3c170f77..622bda227 100644
--- a/wled00/FX.h
+++ b/wled00/FX.h
@@ -650,6 +650,7 @@ class WS2812FX {
void handle_palette(void);
bool
+ shouldStartBus = false,
_useRgbw = false,
_skipFirstMode,
_triggered;
diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp
index 56fdb98a8..ad459aba5 100644
--- a/wled00/FX_fcn.cpp
+++ b/wled00/FX_fcn.cpp
@@ -396,6 +396,18 @@ void WS2812FX::setBrightness(uint8_t b) {
{
_segments[i].setOption(SEG_OPTION_FREEZE, false);
}
+ #if LEDPIN == LED_BUILTIN
+ if (!shouldStartBus)
+ shouldStartBus = true;
+ #endif
+ } else {
+ #if LEDPIN == LED_BUILTIN
+ if (shouldStartBus) {
+ shouldStartBus = false;
+ const uint8_t ty = _useRgbw ? 2 : 1;
+ bus->Begin((NeoPixelType)ty, _lengthRaw);
+ }
+ #endif
}
if (SEGENV.next_time > millis() + 22 && millis() - _lastShow > MIN_SHOW_DELAY) show();//apply brightness change immediately if no refresh soon
}
diff --git a/wled00/button.cpp b/wled00/button.cpp
index 3c7b7f14a..280a571af 100644
--- a/wled00/button.cpp
+++ b/wled00/button.cpp
@@ -87,7 +87,7 @@ void handleIO()
{
lastOnTime = millis();
if (offMode)
- {
+ {
#if RLYPIN >= 0
digitalWrite(RLYPIN, RLYMDE);
#endif
@@ -95,9 +95,15 @@ void handleIO()
}
} else if (millis() - lastOnTime > 600)
{
- #if RLYPIN >= 0
- if (!offMode) digitalWrite(RLYPIN, !RLYMDE);
- #endif
+ if (!offMode) {
+ #if LEDPIN == LED_BUILTIN
+ pinMode(LED_BUILTIN, OUTPUT);
+ digitalWrite(LED_BUILTIN, HIGH);
+ #endif
+ #if RLYPIN >= 0
+ digitalWrite(RLYPIN, !RLYMDE);
+ #endif
+ }
offMode = true;
}
diff --git a/wled00/src/dependencies/json/ArduinoJson-v6.h b/wled00/src/dependencies/json/ArduinoJson-v6.h
index 5d8d40799..3913d7110 100644
--- a/wled00/src/dependencies/json/ArduinoJson-v6.h
+++ b/wled00/src/dependencies/json/ArduinoJson-v6.h
@@ -164,6 +164,9 @@
#define ARDUINOJSON_DEBUG 0
#endif
#endif
+#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr)
+#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
+#endif
#if !ARDUINOJSON_DEBUG
#ifdef __clang__
#pragma clang system_header
@@ -171,11 +174,16 @@
#pragma GCC system_header
#endif
#endif
-#define ARDUINOJSON_VERSION "6.16.1"
-#define ARDUINOJSON_VERSION_MAJOR 6
-#define ARDUINOJSON_VERSION_MINOR 16
-#define ARDUINOJSON_VERSION_REVISION 1
-#ifndef ARDUINOJSON_NAMESPACE
+#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
@@ -194,21 +202,22 @@
#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_VERSION "6.17.0"
+#define ARDUINOJSON_VERSION_MAJOR 6
+#define ARDUINOJSON_VERSION_MINOR 17
+#define ARDUINOJSON_VERSION_REVISION 0
+#ifndef ARDUINOJSON_NAMESPACE
+#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
#if ARDUINOJSON_DEBUG
@@ -264,12 +273,13 @@ class CollectionData {
inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
return arr ? arr->addElement(pool) : 0;
}
-template
-inline void arrayAccept(const CollectionData *arr, Visitor &visitor) {
+template
+inline typename TVisitor::result_type arrayAccept(const CollectionData *arr,
+ TVisitor &visitor) {
if (arr)
- visitor.visitArray(*arr);
+ return visitor.visitArray(*arr);
else
- visitor.visitNull();
+ return visitor.visitNull();
}
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs)
@@ -314,13 +324,6 @@ inline T *addPadding(T *p) {
size_t address = addPadding(reinterpret_cast(p));
return reinterpret_cast(address);
}
-} // namespace ARDUINOJSON_NAMESPACE
-#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
-namespace ARDUINOJSON_NAMESPACE {
-struct StringSlot {
- char *value;
- size_t size;
-};
template Y)>
struct Max {};
template
@@ -334,24 +337,6 @@ struct Max {
} // namespace ARDUINOJSON_NAMESPACE
#include
namespace ARDUINOJSON_NAMESPACE {
-template
-class not_null {
- public:
- explicit not_null(T ptr) : _ptr(ptr) {
- ARDUINOJSON_ASSERT(ptr != NULL);
- }
- T get() const {
- ARDUINOJSON_ASSERT(_ptr != NULL);
- return _ptr;
- }
- private:
- T _ptr;
-};
-template
-not_null make_not_null(T ptr) {
- ARDUINOJSON_ASSERT(ptr != NULL);
- return not_null(ptr);
-}
template
struct conditional {
typedef TrueType type;
@@ -469,6 +454,10 @@ struct is_enum {
!is_class::value && !is_integral::value &&
!is_floating_point::value;
};
+template
+struct is_pointer : false_type {};
+template
+struct is_pointer : true_type {};
template
struct is_signed : false_type {};
template <>
@@ -694,6 +683,7 @@ class VariantSlot {
};
} // namespace ARDUINOJSON_NAMESPACE
#include
+#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
namespace ARDUINOJSON_NAMESPACE {
class MemoryPool {
public:
@@ -701,7 +691,8 @@ class MemoryPool {
: _begin(buf),
_left(buf),
_right(buf ? buf + capa : 0),
- _end(buf ? buf + capa : 0) {
+ _end(buf ? buf + capa : 0),
+ _overflowed(false) {
ARDUINOJSON_ASSERT(isAligned(_begin));
ARDUINOJSON_ASSERT(isAligned(_right));
ARDUINOJSON_ASSERT(isAligned(_end));
@@ -715,6 +706,9 @@ class MemoryPool {
size_t size() const {
return size_t(_left - _begin + _end - _right);
}
+ bool overflowed() const {
+ return _overflowed;
+ }
VariantSlot* allocVariant() {
return allocRight();
}
@@ -750,9 +744,13 @@ class MemoryPool {
checkInvariants();
return str;
}
+ void markAsOverflowed() {
+ _overflowed = true;
+ }
void clear() {
_left = _begin;
_right = _end;
+ _overflowed = false;
}
bool canAlloc(size_t bytes) const {
return _left + bytes <= _right;
@@ -781,9 +779,6 @@ class MemoryPool {
_end += offset;
}
private:
- StringSlot* allocStringSlot() {
- return allocRight();
- }
void checkInvariants() {
ARDUINOJSON_ASSERT(_begin <= _left);
ARDUINOJSON_ASSERT(_left <= _right);
@@ -805,8 +800,10 @@ class MemoryPool {
}
#endif
char* allocString(size_t n) {
- if (!canAlloc(n))
+ if (!canAlloc(n)) {
+ _overflowed = true;
return 0;
+ }
char* s = _left;
_left += n;
checkInvariants();
@@ -817,12 +814,15 @@ class MemoryPool {
return reinterpret_cast(allocRight(sizeof(T)));
}
void* allocRight(size_t bytes) {
- if (!canAlloc(bytes))
+ if (!canAlloc(bytes)) {
+ _overflowed = true;
return 0;
+ }
_right -= bytes;
return _right;
}
char *_begin, *_left, *_right, *_end;
+ bool _overflowed;
};
inline int safe_strcmp(const char* a, const char* b) {
if (a == b)
@@ -940,9 +940,9 @@ inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) {
#include
namespace ARDUINOJSON_NAMESPACE {
template
-class StlStringAdapter {
+class StdStringAdapter {
public:
- StlStringAdapter(const TString& str) : _str(&str) {}
+ StdStringAdapter(const TString& str) : _str(&str) {}
void copyTo(char* p, size_t n) const {
memcpy(p, _str->c_str(), n);
}
@@ -973,15 +973,14 @@ template
struct IsString > : true_type {
};
template
-inline StlStringAdapter >
+inline StdStringAdapter >
adaptString(const std::basic_string& str) {
- return StlStringAdapter >(
+ return StdStringAdapter >(
str);
}
} // namespace ARDUINOJSON_NAMESPACE
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
-#include
namespace ARDUINOJSON_NAMESPACE {
class ArduinoStringAdapter {
public:
@@ -1269,6 +1268,44 @@ T alias_cast(F raw_data) {
ac.raw = raw_data;
return ac.data;
}
+} // namespace ARDUINOJSON_NAMESPACE
+#if ARDUINOJSON_ENABLE_PROGMEM
+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 &&
+ sizeof(T) == sizeof(float), // on AVR sizeof(double) ==
+ 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
+#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
+namespace ARDUINOJSON_NAMESPACE {
template
struct FloatTraits {};
template
@@ -1298,46 +1335,58 @@ struct FloatTraits {
return m;
}
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() {
return forge(0x7ff80000, 0x00000000);
@@ -1382,16 +1431,22 @@ struct FloatTraits {
return m;
}
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) {
return alias_cast(bits);
@@ -1524,8 +1579,11 @@ class VariantData {
VariantContent _content; // must be first to allow cast from array to variant
uint8_t _flags;
public:
- template
- void accept(Visitor &visitor) const {
+ void init() {
+ _flags = 0;
+ }
+ template
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
switch (type()) {
case VALUE_IS_FLOAT:
return visitor.visitFloat(_content.asFloat);
@@ -1690,23 +1748,13 @@ class VariantData {
void setNull() {
setType(VALUE_IS_NULL);
}
- void setString(not_null s, storage_policies::store_by_copy) {
+ void setStringPointer(const char *s, storage_policies::store_by_copy) {
setType(VALUE_IS_OWNED_STRING);
- _content.asString = s.get();
+ _content.asString = s;
}
- void setString(not_null s, storage_policies::store_by_address) {
+ void setStringPointer(const char *s, storage_policies::store_by_address) {
setType(VALUE_IS_LINKED_STRING);
- _content.asString = s.get();
- }
- template
- bool setString(const char *s, TStoragePolicy storage_policy) {
- if (s) {
- setString(make_not_null(s), storage_policy);
- return true;
- } else {
- setType(VALUE_IS_NULL);
- return false;
- }
+ _content.asString = s;
}
template
bool setString(TAdaptedString value, MemoryPool *pool) {
@@ -1723,13 +1771,26 @@ class VariantData {
template
inline bool setString(TAdaptedString value, MemoryPool *,
storage_policies::store_by_address) {
- return setString(value.data(), storage_policies::store_by_address());
+ if (value.isNull())
+ setNull();
+ else
+ setStringPointer(value.data(), storage_policies::store_by_address());
+ return true;
}
template
inline bool setString(TAdaptedString value, MemoryPool *pool,
storage_policies::store_by_copy) {
- return setString(pool->saveString(value),
- storage_policies::store_by_copy());
+ if (value.isNull()) {
+ setNull();
+ return true;
+ }
+ const char *copy = pool->saveString(value);
+ if (!copy) {
+ setNull();
+ return false;
+ }
+ setStringPointer(copy, storage_policies::store_by_copy());
+ return true;
}
CollectionData &toArray() {
setType(VALUE_IS_ARRAY);
@@ -1795,10 +1856,10 @@ class VariantData {
if (_flags & COLLECTION_MASK)
_content.asCollection.movePointers(stringDistance, variantDistance);
}
- private:
uint8_t type() const {
return _flags & VALUE_MASK;
}
+ private:
void setType(uint8_t t) {
_flags &= KEY_IS_OWNED;
_flags |= t;
@@ -1854,6 +1915,10 @@ inline size_t slotSize(const VariantSlot* var) {
inline VariantData* slotData(VariantSlot* slot) {
return reinterpret_cast(slot);
}
+template
+struct Visitor {
+ typedef TResult result_type;
+};
struct Visitable {
};
template
@@ -1985,12 +2050,13 @@ inline typename enable_if::value, T>::type variantAs(
#define ARDUINOJSON_NO_SANITIZE(check)
#endif
namespace ARDUINOJSON_NAMESPACE {
-template
-inline void variantAccept(const VariantData *var, Visitor &visitor) {
+template
+inline typename TVisitor::result_type variantAccept(const VariantData *var,
+ TVisitor &visitor) {
if (var != 0)
- var->accept(visitor);
+ return var->accept(visitor);
else
- visitor.visitNull();
+ return visitor.visitNull();
}
inline const CollectionData *variantAsArray(const VariantData *var) {
return var != 0 ? var->asArray() : 0;
@@ -2211,14 +2277,16 @@ CompareResult compare(const T1 &lhs, const T2 &rhs); // VariantCompare.cpp
template
struct VariantOperators {
template
- friend T operator|(const TVariant &variant, const T &defaultValue) {
+ friend typename enable_if::value, T>::type operator|(
+ const TVariant &variant, const T &defaultValue) {
if (variant.template is())
return variant.template as();
else
return defaultValue;
}
- friend const char *operator|(const TVariant &variant,
- const char *defaultValue) {
+ template
+ friend typename enable_if::value, T>::type operator|(
+ const TVariant &variant, T defaultValue) {
const char *value = variant.template as();
return value ? value : defaultValue;
}
@@ -2536,9 +2604,9 @@ class VariantRef : public VariantRefBase,
FORCE_INLINE operator T() const {
return variantAs(_data, _pool);
}
- template
- void accept(Visitor &visitor) const {
- variantAccept(_data, visitor);
+ template
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
+ return variantAccept(_data, visitor);
}
template
typename enable_if::value, ArrayRef>::type to() const;
@@ -2588,9 +2656,9 @@ class VariantConstRef : public VariantRefBase,
VariantConstRef() : base_type(0) {}
VariantConstRef(const VariantData *data) : base_type(data) {}
VariantConstRef(VariantRef var) : base_type(var._data) {}
- template
- void accept(Visitor &visitor) const {
- variantAccept(_data, visitor);
+ template
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
+ return variantAccept(_data, visitor);
}
template
FORCE_INLINE typename VariantConstAs::type as() const {
@@ -2727,9 +2795,9 @@ class ArrayRefBase {
const void* data = _data; // prevent warning cast-align
return VariantConstRef(reinterpret_cast(data));
}
- template
- FORCE_INLINE void accept(Visitor& visitor) const {
- arrayAccept(_data, visitor);
+ template
+ FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const {
+ return arrayAccept(_data, visitor);
}
FORCE_INLINE bool isNull() const {
return _data == 0;
@@ -2830,12 +2898,13 @@ class ArrayRef : public ArrayRefBase,
private:
MemoryPool* _pool;
};
-template
-void objectAccept(const CollectionData *obj, Visitor &visitor) {
+template
+typename TVisitor::result_type objectAccept(const CollectionData *obj,
+ TVisitor &visitor) {
if (obj)
- visitor.visitObject(*obj);
+ return visitor.visitObject(*obj);
else
- visitor.visitNull();
+ return visitor.visitNull();
}
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs)
@@ -3049,9 +3118,9 @@ class ObjectRefBase {
const void* data = _data; // prevent warning cast-align
return VariantConstRef(reinterpret_cast(data));
}
- template
- FORCE_INLINE void accept(Visitor& visitor) const {
- objectAccept(_data, visitor);
+ template
+ typename TVisitor::result_type accept(TVisitor& visitor) const {
+ return objectAccept(_data, visitor);
}
FORCE_INLINE bool isNull() const {
return _data == 0;
@@ -3273,8 +3342,8 @@ class ElementProxy : public VariantOperators >,
FORCE_INLINE bool set(TValue* value) const {
return getOrAddUpstreamElement().set(value);
}
- template
- void accept(Visitor& visitor) const {
+ template
+ typename TVisitor::result_type accept(TVisitor& visitor) const {
return getUpstreamElement().accept(visitor);
}
FORCE_INLINE size_t size() const {
@@ -3411,8 +3480,8 @@ class MemberProxy : public VariantOperators >,
FORCE_INLINE bool set(TChar *value) {
return getOrAddUpstreamMember().set(value);
}
- template
- void accept(Visitor &visitor) const {
+ template
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
return getUpstreamMember().accept(visitor);
}
FORCE_INLINE VariantRef addElement() const {
@@ -3457,8 +3526,8 @@ class MemberProxy : public VariantOperators >,
namespace ARDUINOJSON_NAMESPACE {
class JsonDocument : public Visitable {
public:
- template
- void accept(Visitor& visitor) const {
+ template
+ typename TVisitor::result_type accept(TVisitor& visitor) const {
return getVariant().accept(visitor);
}
template
@@ -3483,6 +3552,9 @@ class JsonDocument : public Visitable {
size_t memoryUsage() const {
return _pool.size();
}
+ bool overflowed() const {
+ return _pool.overflowed();
+ }
size_t nesting() const {
return _data.nesting();
}
@@ -3888,35 +3960,49 @@ inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) {
return copyArray(src, dst.to());
}
template
-class ArrayCopier1D {
+class ArrayCopier1D : public Visitor {
public:
ArrayCopier1D(T* destination, size_t capacity)
- : _destination(destination), _capacity(capacity), _size(0) {}
- void visitArray(const CollectionData& array) {
+ : _destination(destination), _capacity(capacity) {}
+ size_t visitArray(const CollectionData& array) {
+ size_t size = 0;
VariantSlot* slot = array.head();
- while (slot != 0 && _size < _capacity) {
- _destination[_size++] = variantAs(slot->data());
+ while (slot != 0 && size < _capacity) {
+ _destination[size++] = variantAs(slot->data());
slot = slot->next();
}
+ return size;
}
- void visitObject(const CollectionData&) {}
- void visitFloat(Float) {}
- void visitString(const char*) {}
- void visitRawJson(const char*, size_t) {}
- void visitNegativeInteger(UInt) {}
- void visitPositiveInteger(UInt) {}
- void visitBoolean(bool) {}
- void visitNull() {}
- size_t result() const {
- return _size;
+ size_t visitObject(const CollectionData&) {
+ return 0;
+ }
+ size_t visitFloat(Float) {
+ return 0;
+ }
+ size_t visitString(const char*) {
+ return 0;
+ }
+ size_t visitRawJson(const char*, size_t) {
+ return 0;
+ }
+ size_t visitNegativeInteger(UInt) {
+ return 0;
+ }
+ size_t visitPositiveInteger(UInt) {
+ return 0;
+ }
+ size_t visitBoolean(bool) {
+ return 0;
+ }
+ size_t visitNull() {
+ return 0;
}
private:
T* _destination;
size_t _capacity;
- size_t _size;
};
template
-class ArrayCopier2D {
+class ArrayCopier2D : public Visitor {
public:
ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {}
void visitArray(const CollectionData& array) {
@@ -3948,8 +4034,7 @@ inline typename enable_if::value, size_t>::type copyArray(
template
inline size_t copyArray(const TSource& src, T* dst, size_t len) {
ArrayCopier1D copier(dst, len);
- src.accept(copier);
- return copier.result();
+ return src.accept(copier);
}
template
inline void copyArray(const TSource& src, T (&dst)[N1][N2]) {
@@ -4234,18 +4319,34 @@ inline VariantRef variantAs(VariantData* data, MemoryPool* pool) {
return VariantRef(pool, data);
}
class CollectionData;
-struct ComparerBase {
- CompareResult result;
- ComparerBase() : result(COMPARE_RESULT_DIFFER) {}
- void visitArray(const CollectionData &) {}
- void visitBoolean(bool) {}
- void visitFloat(Float) {}
- void visitNegativeInteger(UInt) {}
- void visitNull() {}
- void visitObject(const CollectionData &) {}
- void visitPositiveInteger(UInt) {}
- void visitRawJson(const char *, size_t) {}
- void visitString(const char *) {}
+struct ComparerBase : Visitor {
+ CompareResult visitArray(const CollectionData &) {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitBoolean(bool) {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitFloat(Float) {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitNegativeInteger(UInt) {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitNull() {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitObject(const CollectionData &) {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitPositiveInteger(UInt) {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitRawJson(const char *, size_t) {
+ return COMPARE_RESULT_DIFFER;
+ }
+ CompareResult visitString(const char *) {
+ return COMPARE_RESULT_DIFFER;
+ }
};
template
struct Comparer;
@@ -4254,18 +4355,20 @@ struct Comparer::value>::type>
: ComparerBase {
T rhs;
explicit Comparer(T value) : rhs(value) {}
- void visitString(const char *lhs) {
+ CompareResult visitString(const char *lhs) {
int i = adaptString(rhs).compare(lhs);
if (i < 0)
- result = COMPARE_RESULT_GREATER;
+ return COMPARE_RESULT_GREATER;
else if (i > 0)
- result = COMPARE_RESULT_LESS;
+ return COMPARE_RESULT_LESS;
else
- result = COMPARE_RESULT_EQUAL;
+ return COMPARE_RESULT_EQUAL;
}
- void visitNull() {
+ CompareResult visitNull() {
if (adaptString(rhs).isNull())
- result = COMPARE_RESULT_EQUAL;
+ return COMPARE_RESULT_EQUAL;
+ else
+ return COMPARE_RESULT_DIFFER;
}
};
template
@@ -4274,22 +4377,22 @@ struct Comparer::value ||
: ComparerBase {
T rhs;
explicit Comparer(T value) : rhs(value) {}
- void visitFloat(Float lhs) {
- result = arithmeticCompare(lhs, rhs);
+ CompareResult visitFloat(Float lhs) {
+ return arithmeticCompare(lhs, rhs);
}
- void visitNegativeInteger(UInt lhs) {
- result = arithmeticCompareNegateLeft(lhs, rhs);
+ CompareResult visitNegativeInteger(UInt lhs) {
+ return arithmeticCompareNegateLeft(lhs, rhs);
}
- void visitPositiveInteger(UInt lhs) {
- result = arithmeticCompare(lhs, rhs);
+ CompareResult visitPositiveInteger(UInt lhs) {
+ return arithmeticCompare(lhs, rhs);
}
- void visitBoolean(bool lhs) {
- visitPositiveInteger(static_cast(lhs));
+ CompareResult visitBoolean(bool lhs) {
+ return visitPositiveInteger(static_cast(lhs));
}
};
struct NullComparer : ComparerBase {
- void visitNull() {
- result = COMPARE_RESULT_EQUAL;
+ CompareResult visitNull() {
+ return COMPARE_RESULT_EQUAL;
}
};
#if ARDUINOJSON_HAS_NULLPTR
@@ -4301,33 +4404,37 @@ struct Comparer : NullComparer {
struct ArrayComparer : ComparerBase {
const CollectionData *_rhs;
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
- void visitArray(const CollectionData &lhs) {
+ CompareResult visitArray(const CollectionData &lhs) {
if (lhs.equalsArray(*_rhs))
- result = COMPARE_RESULT_EQUAL;
+ return COMPARE_RESULT_EQUAL;
+ else
+ return COMPARE_RESULT_DIFFER;
}
};
struct NegativeIntegerComparer : ComparerBase {
UInt _rhs;
explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
- void visitFloat(Float lhs) {
- result = arithmeticCompareNegateRight(lhs, _rhs);
+ CompareResult visitFloat(Float lhs) {
+ return arithmeticCompareNegateRight(lhs, _rhs);
}
- void visitNegativeInteger(UInt lhs) {
- result = arithmeticCompare(_rhs, lhs);
+ CompareResult visitNegativeInteger(UInt lhs) {
+ return arithmeticCompare(_rhs, lhs);
}
- void visitPositiveInteger(UInt) {
- result = COMPARE_RESULT_GREATER;
+ CompareResult visitPositiveInteger(UInt) {
+ return COMPARE_RESULT_GREATER;
}
- void visitBoolean(bool) {
- result = COMPARE_RESULT_GREATER;
+ CompareResult visitBoolean(bool) {
+ return COMPARE_RESULT_GREATER;
}
};
struct ObjectComparer : ComparerBase {
const CollectionData *_rhs;
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
- void visitObject(const CollectionData &lhs) {
+ CompareResult visitObject(const CollectionData &lhs) {
if (lhs.equalsObject(*_rhs))
- result = COMPARE_RESULT_EQUAL;
+ return COMPARE_RESULT_EQUAL;
+ else
+ return COMPARE_RESULT_DIFFER;
}
};
struct RawComparer : ComparerBase {
@@ -4335,15 +4442,15 @@ struct RawComparer : ComparerBase {
size_t _rhsSize;
explicit RawComparer(const char *rhsData, size_t rhsSize)
: _rhsData(rhsData), _rhsSize(rhsSize) {}
- void visitRawJson(const char *lhsData, size_t lhsSize) {
+ CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
int n = memcmp(lhsData, _rhsData, size);
if (n < 0)
- result = COMPARE_RESULT_LESS;
+ return COMPARE_RESULT_LESS;
else if (n > 0)
- result = COMPARE_RESULT_GREATER;
+ return COMPARE_RESULT_GREATER;
else
- result = COMPARE_RESULT_EQUAL;
+ return COMPARE_RESULT_EQUAL;
}
};
template
@@ -4351,64 +4458,60 @@ struct Comparer::value>::type>
: ComparerBase {
T rhs;
explicit Comparer(T value) : rhs(value) {}
- void visitArray(const CollectionData &lhs) {
+ CompareResult visitArray(const CollectionData &lhs) {
ArrayComparer comparer(lhs);
- accept(comparer);
+ return accept(comparer);
}
- void visitObject(const CollectionData &lhs) {
+ CompareResult visitObject(const CollectionData &lhs) {
ObjectComparer comparer(lhs);
- accept(comparer);
+ return accept(comparer);
}
- void visitFloat(Float lhs) {
+ CompareResult visitFloat(Float lhs) {
Comparer comparer(lhs);
- accept(comparer);
+ return accept(comparer);
}
- void visitString(const char *lhs) {
+ CompareResult visitString(const char *lhs) {
Comparer comparer(lhs);
- accept(comparer);
+ return accept(comparer);
}
- void visitRawJson(const char *lhsData, size_t lhsSize) {
+ CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
RawComparer comparer(lhsData, lhsSize);
- accept(comparer);
+ return accept(comparer);
}
- void visitNegativeInteger(UInt lhs) {
+ CompareResult visitNegativeInteger(UInt lhs) {
NegativeIntegerComparer comparer(lhs);
- accept(comparer);
+ return accept(comparer);
}
- void visitPositiveInteger(UInt lhs) {
+ CompareResult visitPositiveInteger(UInt lhs) {
Comparer comparer(lhs);
- accept(comparer);
+ return accept(comparer);
}
- void visitBoolean(bool lhs) {
+ CompareResult visitBoolean(bool lhs) {
Comparer comparer(lhs);
- accept(comparer);
+ return accept(comparer);
}
- void visitNull() {
+ CompareResult visitNull() {
NullComparer comparer;
- accept(comparer);
+ return accept(comparer);
}
private:
template
- void accept(TComparer &comparer) {
- rhs.accept(comparer);
- switch (comparer.result) {
+ CompareResult accept(TComparer &comparer) {
+ CompareResult reversedResult = rhs.accept(comparer);
+ switch (reversedResult) {
case COMPARE_RESULT_GREATER:
- result = COMPARE_RESULT_LESS;
- break;
+ return COMPARE_RESULT_LESS;
case COMPARE_RESULT_LESS:
- result = COMPARE_RESULT_GREATER;
- break;
+ return COMPARE_RESULT_GREATER;
default:
- result = comparer.result;
- break;
+ return reversedResult;
}
}
};
template
CompareResult compare(const T1 &lhs, const T2 &rhs) {
Comparer comparer(rhs);
- lhs.accept(comparer);
- return comparer.result;
+ return lhs.accept(comparer);
}
inline int variantCompare(const VariantData *a, const VariantData *b) {
return compare(VariantConstRef(a), VariantConstRef(b));
@@ -4419,48 +4522,12 @@ inline bool isdigit(char c) {
inline bool issign(char c) {
return '-' == c || c == '+';
}
-template
-struct ParsedNumber {
- ParsedNumber() : _type(VALUE_IS_NULL) {}
- void setInteger(TUInt value, bool is_negative) {
- uintValue = value;
- _type = uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER
- : VALUE_IS_POSITIVE_INTEGER);
- }
- void setFloat(TFloat value) {
- floatValue = value;
- _type = VALUE_IS_FLOAT;
- }
- template
- T as() const {
- switch (_type) {
- case VALUE_IS_NEGATIVE_INTEGER:
- return convertNegativeInteger(uintValue);
- case VALUE_IS_POSITIVE_INTEGER:
- return convertPositiveInteger(uintValue);
- case VALUE_IS_FLOAT:
- return convertFloat(floatValue);
- default:
- return 0;
- }
- }
- uint8_t type() const {
- return _type;
- }
- union {
- TUInt uintValue;
- TFloat floatValue;
- };
- uint8_t _type;
-}; // namespace ARDUINOJSON_NAMESPACE
template
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
-template
-inline void parseNumber(const char* s, ParsedNumber& result) {
- typedef FloatTraits traits;
- typedef typename choose_largest::type
- mantissa_t;
- typedef typename traits::exponent_type exponent_t;
+inline bool parseNumber(const char* s, VariantData& result) {
+ typedef FloatTraits traits;
+ typedef choose_largest::type mantissa_t;
+ typedef traits::exponent_type exponent_t;
ARDUINOJSON_ASSERT(s != 0);
bool is_negative = false;
switch (*s) {
@@ -4475,20 +4542,20 @@ inline void parseNumber(const char* s, ParsedNumber& result) {
#if ARDUINOJSON_ENABLE_NAN
if (*s == 'n' || *s == 'N') {
result.setFloat(traits::nan());
- return;
+ return true;
}
#endif
#if ARDUINOJSON_ENABLE_INFINITY
if (*s == 'i' || *s == 'I') {
result.setFloat(is_negative ? -traits::inf() : traits::inf());
- return;
+ return true;
}
#endif
if (!isdigit(*s) && *s != '.')
- return;
+ return false;
mantissa_t mantissa = 0;
exponent_t exponent_offset = 0;
- const mantissa_t maxUint = TUInt(-1);
+ const mantissa_t maxUint = UInt(-1);
while (isdigit(*s)) {
uint8_t digit = uint8_t(*s - '0');
if (mantissa > maxUint / 10)
@@ -4500,8 +4567,11 @@ inline void parseNumber(const char* s, ParsedNumber& result) {
s++;
}
if (*s == '\0') {
- result.setInteger(TUInt(mantissa), is_negative);
- return;
+ if (is_negative)
+ result.setNegativeInteger(UInt(mantissa));
+ else
+ result.setPositiveInteger(UInt(mantissa));
+ return true;
}
while (mantissa > traits::mantissa_max) {
mantissa /= 10;
@@ -4538,7 +4608,7 @@ inline void parseNumber(const char* s, ParsedNumber& result) {
result.setFloat(is_negative ? -0.0f : 0.0f);
else
result.setFloat(is_negative ? -traits::inf() : traits::inf());
- return;
+ return true;
}
s++;
}
@@ -4547,25 +4617,18 @@ inline void parseNumber(const char* s, ParsedNumber& result) {
}
exponent += exponent_offset;
if (*s != '\0')
- return;
- TFloat final_result =
- traits::make_float(static_cast(mantissa), exponent);
+ return false;
+ Float final_result =
+ traits::make_float(static_cast(mantissa), exponent);
result.setFloat(is_negative ? -final_result : final_result);
+ return true;
}
template
-inline T parseFloat(const char* s) {
- typedef typename choose_largest::type TFloat;
- ParsedNumber value;
+inline T parseNumber(const char* s) {
+ VariantData value;
+ value.init(); // VariantData is a POD, so it has no constructor
parseNumber(s, value);
- return value.template as();
-}
-template
-T parseInteger(const char *s) {
- typedef typename choose_largest::type>::type
- TUInt;
- ParsedNumber value;
- parseNumber(s, value);
- return value.template as();
+ return variantAs(&value);
}
template
inline T VariantData::asIntegral() const {
@@ -4577,7 +4640,7 @@ inline T VariantData::asIntegral() const {
return convertNegativeInteger(_content.asInteger);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
- return parseInteger(_content.asString);
+ return parseNumber(_content.asString);
case VALUE_IS_FLOAT:
return convertFloat(_content.asFloat);
default:
@@ -4608,7 +4671,7 @@ inline T VariantData::asFloat() const {
return -static_cast(_content.asInteger);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
- return parseFloat(_content.asString);
+ return parseNumber(_content.asString);
case VALUE_IS_FLOAT:
return static_cast(_content.asFloat);
default:
@@ -4675,6 +4738,10 @@ template
inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
}
+inline VariantConstRef operator|(VariantConstRef preferedValue,
+ VariantConstRef defaultValue) {
+ return preferedValue ? preferedValue : defaultValue;
+}
} // namespace ARDUINOJSON_NAMESPACE
#if ARDUINOJSON_ENABLE_STD_STREAM
#include
@@ -4686,6 +4753,7 @@ class DeserializationError {
public:
enum Code {
Ok,
+ EmptyInput,
IncompleteInput,
InvalidInput,
NoMemory,
@@ -4733,23 +4801,29 @@ class DeserializationError {
return _code;
}
const char* c_str() const {
- switch (_code) {
- case Ok:
- return "Ok";
- case TooDeep:
- return "TooDeep";
- case NoMemory:
- return "NoMemory";
- case InvalidInput:
- return "InvalidInput";
- case IncompleteInput:
- return "IncompleteInput";
- case NotSupported:
- return "NotSupported";
- default:
- return "???";
- }
+ static const char* messages[] = {
+ "Ok", "EmptyInput", "IncompleteInput", "InvalidInput",
+ "NoMemory", "NotSupported", "TooDeep"};
+ ARDUINOJSON_ASSERT(static_cast(_code) <
+ sizeof(messages) / sizeof(messages[0]));
+ return messages[_code];
}
+#if ARDUINOJSON_ENABLE_PROGMEM
+ const __FlashStringHelper* f_str() const {
+ 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 ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages,
+ _code);
+ }
+#endif
private:
Code _code;
};
@@ -4784,7 +4858,7 @@ class Filter {
if (_variant == true) // "true" means "allow recursively"
return *this;
else
- return Filter(_variant[key]);
+ return Filter(_variant[key] | _variant["*"]);
}
private:
VariantConstRef _variant;
@@ -4919,7 +4993,6 @@ struct Reader : Reader {
};
} // namespace ARDUINOJSON_NAMESPACE
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
-#include
namespace ARDUINOJSON_NAMESPACE {
template
struct ReadergetFreeZone(&_ptr, &_capacity);
+ StringCopier(MemoryPool& pool) : _pool(&pool) {}
+ void startString() {
+ _pool->getFreeZone(&_ptr, &_capacity);
_size = 0;
}
- const char* save(MemoryPool* pool) {
+ const char* save() {
ARDUINOJSON_ASSERT(_ptr);
- return pool->saveStringFromFreeZone(_size);
+ return _pool->saveStringFromFreeZone(_size);
}
void append(const char* s) {
while (*s) append(*s++);
@@ -5032,6 +5106,7 @@ class StringCopier {
return;
if (_size >= _capacity) {
_ptr = 0;
+ _pool->markAsOverflowed();
return;
}
_ptr[_size++] = c;
@@ -5044,6 +5119,7 @@ class StringCopier {
}
typedef storage_policies::store_by_copy storage_policy;
private:
+ MemoryPool* _pool;
char* _ptr;
size_t _size;
size_t _capacity;
@@ -5051,10 +5127,10 @@ class StringCopier {
class StringMover {
public:
StringMover(char* ptr) : _writePtr(ptr) {}
- void startString(MemoryPool*) {
+ void startString() {
_startPtr = _writePtr;
}
- const char* save(MemoryPool*) const {
+ const char* save() const {
return _startPtr;
}
void append(char c) {
@@ -5071,28 +5147,15 @@ class StringMover {
char* _writePtr;
char* _startPtr;
};
-template
-struct StringStorage {
- typedef StringCopier type;
- static type create(TInput&) {
- return type();
- }
-};
-template
-struct StringStorage::value>::type> {
- typedef StringMover type;
- static type create(TChar* input) {
- return type(reinterpret_cast(input));
- }
-};
template
-typename StringStorage::type makeStringStorage(TInput& input) {
- return StringStorage::create(input);
+StringCopier makeStringStorage(TInput&, MemoryPool& pool) {
+ return StringCopier(pool);
}
template
-typename StringStorage::type makeStringStorage(TChar* input) {
- return StringStorage::create(input);
+StringMover makeStringStorage(
+ TChar* input, MemoryPool&,
+ typename enable_if::value>::type* = 0) {
+ return StringMover(reinterpret_cast(input));
}
template class TDeserializer, typename TReader,
typename TWriter>
@@ -5108,8 +5171,9 @@ deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
TFilter filter) {
Reader reader(input);
doc.clear();
- return makeDeserializer(doc.memoryPool(), reader,
- makeStringStorage(input))
+ return makeDeserializer(
+ doc.memoryPool(), reader,
+ makeStringStorage(input, doc.memoryPool()))
.parse(doc.data(), filter, nestingLimit);
}
template class TDeserializer, typename TChar,
@@ -5119,8 +5183,9 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
TFilter filter) {
BoundedReader reader(input, inputSize);
doc.clear();
- return makeDeserializer(doc.memoryPool(), reader,
- makeStringStorage(input))
+ return makeDeserializer(
+ doc.memoryPool(), reader,
+ makeStringStorage(input, doc.memoryPool()))
.parse(doc.data(), filter, nestingLimit);
}
template class TDeserializer, typename TStream,
@@ -5129,8 +5194,9 @@ DeserializationError deserialize(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit, TFilter filter) {
Reader reader(input);
doc.clear();
- return makeDeserializer(doc.memoryPool(), reader,
- makeStringStorage(input))
+ return makeDeserializer(
+ doc.memoryPool(), reader,
+ makeStringStorage(input, doc.memoryPool()))
.parse(doc.data(), filter, nestingLimit);
}
class EscapeSequence {
@@ -5277,6 +5343,7 @@ class JsonDeserializer {
JsonDeserializer(MemoryPool &pool, TReader reader,
TStringStorage stringStorage)
: _stringStorage(stringStorage),
+ _foundSomething(false),
_latch(reader),
_pool(&pool),
_error(DeserializationError::Ok) {}
@@ -5285,7 +5352,7 @@ class JsonDeserializer {
NestingLimit nestingLimit) {
parseVariant(variant, filter, nestingLimit);
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
- _error = DeserializationError::InvalidInput;
+ return DeserializationError::InvalidInput;
}
return _error;
}
@@ -5431,7 +5498,7 @@ class JsonDeserializer {
if (memberFilter.allow()) {
VariantData *variant = object.getMember(adaptString(key));
if (!variant) {
- key = _stringStorage.save(_pool);
+ key = _stringStorage.save();
VariantSlot *slot = object.addSlot(_pool);
if (!slot) {
_error = DeserializationError::NoMemory;
@@ -5491,7 +5558,7 @@ class JsonDeserializer {
}
}
bool parseKey() {
- _stringStorage.startString(_pool);
+ _stringStorage.startString();
if (isQuote(current())) {
return parseQuotedString();
} else {
@@ -5499,12 +5566,11 @@ class JsonDeserializer {
}
}
bool parseStringValue(VariantData &variant) {
- _stringStorage.startString(_pool);
+ _stringStorage.startString();
if (!parseQuotedString())
return false;
- const char *value = _stringStorage.save(_pool);
- variant.setString(make_not_null(value),
- typename TStringStorage::storage_policy());
+ const char *value = _stringStorage.save();
+ variant.setStringPointer(value, typename TStringStorage::storage_policy());
return true;
}
bool parseQuotedString() {
@@ -5630,22 +5696,11 @@ class JsonDeserializer {
}
return true;
}
- ParsedNumber num;
- parseNumber(_buffer, num);
- switch (num.type()) {
- case VALUE_IS_NEGATIVE_INTEGER:
- result.setNegativeInteger(num.uintValue);
- return true;
- case VALUE_IS_POSITIVE_INTEGER:
- result.setPositiveInteger(num.uintValue);
- return true;
- case VALUE_IS_FLOAT:
- result.setFloat(num.floatValue);
- return true;
- default:
- _error = DeserializationError::InvalidInput;
- return false;
+ if (!parseNumber(_buffer, result)) {
+ _error = DeserializationError::InvalidInput;
+ return false;
}
+ return true;
}
bool skipNumericValue() {
char c = current();
@@ -5693,7 +5748,8 @@ class JsonDeserializer {
for (;;) {
switch (current()) {
case '\0':
- _error = DeserializationError::IncompleteInput;
+ _error = _foundSomething ? DeserializationError::IncompleteInput
+ : DeserializationError::EmptyInput;
return false;
case ' ':
case '\t':
@@ -5742,49 +5798,51 @@ class JsonDeserializer {
break;
#endif
default:
+ _foundSomething = true;
return true;
}
}
}
TStringStorage _stringStorage;
+ bool _foundSomething;
Latch _latch;
MemoryPool *_pool;
char _buffer[64]; // using a member instead of a local variable because it
DeserializationError _error;
};
-template
+template
DeserializationError deserializeJson(
- JsonDocument &doc, const TInput &input,
+ JsonDocument &doc, const TString &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize(doc, input, nestingLimit,
AllowAllFilter());
}
-template
+template
DeserializationError deserializeJson(
- JsonDocument &doc, const TInput &input, Filter filter,
+ JsonDocument &doc, const TString &input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize(doc, input, nestingLimit, filter);
}
-template
-DeserializationError deserializeJson(JsonDocument &doc, const TInput &input,
+template
+DeserializationError deserializeJson(JsonDocument &doc, const TString &input,
NestingLimit nestingLimit, Filter filter) {
return deserialize(doc, input, nestingLimit, filter);
}
-template
+template
DeserializationError deserializeJson(
- JsonDocument &doc, TInput &input,
+ JsonDocument &doc, TStream &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize(doc, input, nestingLimit,
AllowAllFilter());
}
-template
+template
DeserializationError deserializeJson(
- JsonDocument &doc, TInput &input, Filter filter,
+ JsonDocument &doc, TStream &input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize(doc, input, nestingLimit, filter);
}
-template
-DeserializationError deserializeJson(JsonDocument &doc, TInput &input,
+template
+DeserializationError deserializeJson(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit, Filter filter) {
return deserialize(doc, input, nestingLimit, filter);
}
@@ -5886,11 +5944,28 @@ struct FloatParts {
}
};
template
+class CountingDecorator {
+ public:
+ explicit CountingDecorator(TWriter& writer) : _writer(writer), _count(0) {}
+ void write(uint8_t c) {
+ _count += _writer.write(c);
+ }
+ void write(const uint8_t* s, size_t n) {
+ _count += _writer.write(s, n);
+ }
+ size_t count() const {
+ return _count;
+ }
+ private:
+ TWriter _writer;
+ size_t _count;
+};
+template
class TextFormatter {
public:
- explicit TextFormatter(TWriter writer) : _writer(writer), _length(0) {}
+ explicit TextFormatter(TWriter writer) : _writer(writer) {}
size_t bytesWritten() const {
- return _length;
+ return _writer.count();
}
void writeBoolean(bool value) {
if (value)
@@ -5972,24 +6047,24 @@ class TextFormatter {
writeRaw(begin, end);
}
void writeRaw(const char *s) {
- _length += _writer.write(reinterpret_cast(s), strlen(s));
+ _writer.write(reinterpret_cast(s), strlen(s));
}
void writeRaw(const char *s, size_t n) {
- _length += _writer.write(reinterpret_cast(s), n);
+ _writer.write(reinterpret_cast(s), n);
}
void writeRaw(const char *begin, const char *end) {
- _length += _writer.write(reinterpret_cast(begin),
- static_cast(end - begin));
+ _writer.write(reinterpret_cast(begin),
+ static_cast(end - begin));
}
template
void writeRaw(const char (&s)[N]) {
- _length += _writer.write(reinterpret_cast(s), N - 1);
+ _writer.write(reinterpret_cast(s), N - 1);
}
void writeRaw(char c) {
- _length += _writer.write(static_cast(c));
+ _writer.write(static_cast(c));
}
protected:
- TWriter _writer;
+ CountingDecorator _writer;
size_t _length;
private:
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
@@ -6007,8 +6082,7 @@ template class TSerializer, typename TSource>
size_t measure(const TSource &source) {
DummyWriter dp;
TSerializer serializer(dp);
- source.accept(serializer);
- return serializer.bytesWritten();
+ return source.accept(serializer);
}
template
class Writer {
@@ -6158,8 +6232,7 @@ template class TSerializer, typename TSource,
typename TWriter>
size_t doSerialize(const TSource &source, TWriter writer) {
TSerializer serializer(writer);
- source.accept(serializer);
- return serializer.bytesWritten();
+ return source.accept(serializer);
}
template class TSerializer, typename TSource,
typename TDestination>
@@ -6184,10 +6257,10 @@ serialize(const TSource &source, TChar (&buffer)[N]) {
return doSerialize(source, writer);
}
template
-class JsonSerializer {
+class JsonSerializer : public Visitor {
public:
JsonSerializer(TWriter writer) : _formatter(writer) {}
- FORCE_INLINE void visitArray(const CollectionData &array) {
+ FORCE_INLINE size_t visitArray(const CollectionData &array) {
write('[');
VariantSlot *slot = array.head();
while (slot != 0) {
@@ -6198,8 +6271,9 @@ class JsonSerializer {
write(',');
}
write(']');
+ return bytesWritten();
}
- void visitObject(const CollectionData &object) {
+ size_t visitObject(const CollectionData &object) {
write('{');
VariantSlot *slot = object.head();
while (slot != 0) {
@@ -6212,32 +6286,40 @@ class JsonSerializer {
write(',');
}
write('}');
+ return bytesWritten();
}
- void visitFloat(Float value) {
+ size_t visitFloat(Float value) {
_formatter.writeFloat(value);
+ return bytesWritten();
}
- void visitString(const char *value) {
+ size_t visitString(const char *value) {
_formatter.writeString(value);
+ return bytesWritten();
}
- void visitRawJson(const char *data, size_t n) {
+ size_t visitRawJson(const char *data, size_t n) {
_formatter.writeRaw(data, n);
+ return bytesWritten();
}
- void visitNegativeInteger(UInt value) {
+ size_t visitNegativeInteger(UInt value) {
_formatter.writeNegativeInteger(value);
+ return bytesWritten();
}
- void visitPositiveInteger(UInt value) {
+ size_t visitPositiveInteger(UInt value) {
_formatter.writePositiveInteger(value);
+ return bytesWritten();
}
- void visitBoolean(bool value) {
+ size_t visitBoolean(bool value) {
_formatter.writeBoolean(value);
+ return bytesWritten();
}
- void visitNull() {
+ size_t visitNull() {
_formatter.writeRaw("null");
+ return bytesWritten();
}
+ protected:
size_t bytesWritten() const {
return _formatter.bytesWritten();
}
- protected:
void write(char c) {
_formatter.writeRaw(c);
}
@@ -6272,39 +6354,45 @@ class PrettyJsonSerializer : public JsonSerializer {
typedef JsonSerializer base;
public:
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
- void visitArray(const CollectionData &array) {
+ size_t visitArray(const CollectionData &array) {
VariantSlot *slot = array.head();
- if (!slot)
- return base::write("[]");
- base::write("[\r\n");
- _nesting++;
- while (slot != 0) {
+ if (slot) {
+ base::write("[\r\n");
+ _nesting++;
+ while (slot != 0) {
+ indent();
+ slot->data()->accept(*this);
+ slot = slot->next();
+ base::write(slot ? ",\r\n" : "\r\n");
+ }
+ _nesting--;
indent();
- slot->data()->accept(*this);
- slot = slot->next();
- base::write(slot ? ",\r\n" : "\r\n");
+ base::write("]");
+ } else {
+ base::write("[]");
}
- _nesting--;
- indent();
- base::write("]");
+ return this->bytesWritten();
}
- void visitObject(const CollectionData &object) {
+ size_t visitObject(const CollectionData &object) {
VariantSlot *slot = object.head();
- if (!slot)
- return base::write("{}");
- base::write("{\r\n");
- _nesting++;
- while (slot != 0) {
+ if (slot) {
+ base::write("{\r\n");
+ _nesting++;
+ while (slot != 0) {
+ indent();
+ base::visitString(slot->key());
+ base::write(": ");
+ slot->data()->accept(*this);
+ slot = slot->next();
+ base::write(slot ? ",\r\n" : "\r\n");
+ }
+ _nesting--;
indent();
- base::visitString(slot->key());
- base::write(": ");
- slot->data()->accept(*this);
- slot = slot->next();
- base::write(slot ? ",\r\n" : "\r\n");
+ base::write("}");
+ } else {
+ base::write("{}");
}
- _nesting--;
- indent();
- base::write("}");
+ return this->bytesWritten();
}
private:
void indent() {
@@ -6380,90 +6468,198 @@ class MsgPackDeserializer {
: _pool(&pool),
_reader(reader),
_stringStorage(stringStorage),
- _error(DeserializationError::Ok) {}
- DeserializationError parse(VariantData &variant, AllowAllFilter,
+ _error(DeserializationError::Ok),
+ _foundSomething(false) {}
+ template
+ DeserializationError parse(VariantData &variant, TFilter filter,
NestingLimit nestingLimit) {
- parseVariant(variant, nestingLimit);
- return _error;
- }
- private:
- bool parseVariant(VariantData &variant, NestingLimit nestingLimit) {
- uint8_t code;
- if (!readByte(code)) {
- _error = DeserializationError::IncompleteInput;
- return false;
- }
- if ((code & 0x80) == 0) {
- variant.setUnsignedInteger(code);
- return true;
- }
- if ((code & 0xe0) == 0xe0) {
- variant.setSignedInteger(static_cast(code));
- return true;
- }
- if ((code & 0xe0) == 0xa0) {
- return readString(variant, code & 0x1f);
- }
- if ((code & 0xf0) == 0x90) {
- return readArray(variant.toArray(), code & 0x0F, nestingLimit);
- }
- if ((code & 0xf0) == 0x80) {
- return readObject(variant.toObject(), code & 0x0F, nestingLimit);
- }
- switch (code) {
- case 0xc0:
- return true;
- case 0xc2:
- variant.setBoolean(false);
- return true;
- case 0xc3:
- variant.setBoolean(true);
- return true;
- case 0xcc:
- return readInteger(variant);
- case 0xcd:
- return readInteger(variant);
- case 0xce:
- return readInteger(variant);
-#if ARDUINOJSON_USE_LONG_LONG
- case 0xcf:
- return readInteger(variant);
-#endif
- case 0xd0:
- return readInteger(variant);
- case 0xd1:
- return readInteger(variant);
- case 0xd2:
- return readInteger(variant);
-#if ARDUINOJSON_USE_LONG_LONG
- case 0xd3:
- return readInteger(variant);
-#endif
- case 0xca:
- return readFloat(variant);
- case 0xcb:
- return readDouble