From 3f0ef34c9e223416f88d1587f5ccc84e1a646bc3 Mon Sep 17 00:00:00 2001
From: iranl
Date: Wed, 9 Oct 2024 15:06:50 +0200
Subject: [PATCH] Update deps (#482)
---
lib/ArduinoJson/CHANGELOG.md | 36 ++
lib/ArduinoJson/CMakeLists.txt | 2 +-
lib/ArduinoJson/README.md | 3 +
lib/ArduinoJson/appveyor.yml | 2 +-
lib/ArduinoJson/extras/conf_test/avr.cpp | 7 +-
lib/ArduinoJson/extras/conf_test/esp8266.cpp | 5 +-
lib/ArduinoJson/extras/conf_test/x64.cpp | 6 +-
lib/ArduinoJson/extras/conf_test/x86.cpp | 5 +-
.../extras/tests/Deprecated/CMakeLists.txt | 3 +-
.../extras/tests/Deprecated/containsKey.cpp | 210 ++++++++++
.../extras/tests/Helpers/Allocators.hpp | 8 +-
.../extras/tests/JsonArray/remove.cpp | 6 +
.../extras/tests/JsonDeserializer/array.cpp | 24 +-
.../extras/tests/JsonDeserializer/errors.cpp | 42 ++
.../extras/tests/JsonDeserializer/object.cpp | 22 +-
.../extras/tests/JsonDeserializer/string.cpp | 16 +
.../extras/tests/JsonDocument/CMakeLists.txt | 1 -
.../extras/tests/JsonDocument/MemberProxy.cpp | 59 +--
.../extras/tests/JsonDocument/assignment.cpp | 6 +-
.../extras/tests/JsonDocument/shrinkToFit.cpp | 4 +-
.../extras/tests/JsonObject/CMakeLists.txt | 1 -
.../extras/tests/JsonObject/set.cpp | 6 +-
.../extras/tests/JsonObject/std_string.cpp | 7 -
.../extras/tests/JsonObject/subscript.cpp | 10 +-
.../tests/JsonObjectConst/CMakeLists.txt | 1 -
.../tests/JsonSerializer/JsonVariant.cpp | 9 +
.../extras/tests/JsonVariant/CMakeLists.txt | 1 -
.../extras/tests/JsonVariant/as.cpp | 82 ++--
.../extras/tests/JsonVariant/set.cpp | 189 ++++++++-
.../extras/tests/JsonVariant/unbound.cpp | 4 -
.../tests/JsonVariantConst/CMakeLists.txt | 1 -
.../extras/tests/Misc/CMakeLists.txt | 1 -
.../extras/tests/Misc/unsigned_char.cpp | 9 -
.../tests/MixedConfiguration/use_double_0.cpp | 70 +++-
.../MixedConfiguration/use_long_long_0.cpp | 4 -
.../tests/MsgPackDeserializer/errors.cpp | 41 ++
.../extras/tests/Numbers/CMakeLists.txt | 3 +-
.../extras/tests/Numbers/decomposeFloat.cpp | 42 ++
.../extras/tests/Numbers/parseFloat.cpp | 36 +-
.../extras/tests/Numbers/parseNumber.cpp | 46 ++-
.../tests/ResourceManager/StringBuilder.cpp | 1 -
.../tests/ResourceManager/allocVariant.cpp | 50 +--
.../extras/tests/ResourceManager/clear.cpp | 4 +-
.../tests/ResourceManager/saveString.cpp | 1 -
.../tests/ResourceManager/shrinkToFit.cpp | 10 +-
.../extras/tests/ResourceManager/size.cpp | 6 +-
.../extras/tests/ResourceManager/swap.cpp | 36 +-
lib/ArduinoJson/idf_component.yml | 4 +-
lib/ArduinoJson/library.json | 4 +-
lib/ArduinoJson/library.properties | 4 +-
lib/ArduinoJson/src/ArduinoJson.hpp | 2 +-
.../src/ArduinoJson/Array/ArrayData.hpp | 18 +-
.../src/ArduinoJson/Array/ArrayImpl.hpp | 22 +-
.../ArduinoJson/Collection/CollectionData.hpp | 36 +-
.../ArduinoJson/Collection/CollectionImpl.hpp | 98 ++---
.../src/ArduinoJson/Configuration.hpp | 32 +-
.../src/ArduinoJson/Document/JsonDocument.hpp | 9 +-
.../src/ArduinoJson/Json/EscapeSequence.hpp | 4 +-
.../src/ArduinoJson/Json/JsonDeserializer.hpp | 35 +-
.../src/ArduinoJson/Json/JsonSerializer.hpp | 23 +-
.../ArduinoJson/Json/PrettyJsonSerializer.hpp | 20 +-
.../src/ArduinoJson/Json/TextFormatter.hpp | 6 +-
.../src/ArduinoJson/Memory/MemoryPool.hpp | 110 ++++++
.../src/ArduinoJson/Memory/MemoryPoolList.hpp | 214 ++++++++++
.../ArduinoJson/Memory/ResourceManager.hpp | 40 +-
.../Memory/ResourceManagerImpl.hpp | 42 +-
.../src/ArduinoJson/Memory/StringPool.hpp | 3 -
.../src/ArduinoJson/MsgPack/MsgPackBinary.hpp | 2 +-
.../MsgPack/MsgPackDeserializer.hpp | 22 +-
.../ArduinoJson/MsgPack/MsgPackExtension.hpp | 2 +-
.../ArduinoJson/MsgPack/MsgPackSerializer.hpp | 12 +-
.../src/ArduinoJson/Numbers/FloatParts.hpp | 143 +++----
.../src/ArduinoJson/Numbers/convertNumber.hpp | 11 +
.../src/ArduinoJson/Numbers/parseNumber.hpp | 134 +++++--
.../src/ArduinoJson/Object/JsonObject.hpp | 9 +-
.../ArduinoJson/Object/JsonObjectConst.hpp | 9 +-
.../ArduinoJson/Object/JsonObjectIterator.hpp | 6 +-
.../src/ArduinoJson/Object/JsonPair.hpp | 44 +--
.../src/ArduinoJson/Object/ObjectData.hpp | 51 ++-
.../src/ArduinoJson/Object/ObjectImpl.hpp | 41 +-
.../src/ArduinoJson/Serialization/measure.hpp | 7 +-
.../ArduinoJson/Serialization/serialize.hpp | 7 +-
.../src/ArduinoJson/Variant/ConverterImpl.hpp | 40 +-
.../ArduinoJson/Variant/JsonVariantConst.hpp | 9 +-
.../Variant/JsonVariantVisitor.hpp | 2 +-
.../ArduinoJson/Variant/VariantCompare.hpp | 22 +-
.../ArduinoJson/Variant/VariantContent.hpp | 75 ++--
.../src/ArduinoJson/Variant/VariantData.hpp | 369 ++++++++++--------
.../src/ArduinoJson/Variant/VariantImpl.hpp | 141 +++++++
.../ArduinoJson/Variant/VariantRefBase.hpp | 11 +-
.../Variant/VariantRefBaseImpl.hpp | 2 +-
lib/ArduinoJson/src/ArduinoJson/version.hpp | 6 +-
platformio.ini | 2 +-
src/idf_component.yml | 2 +-
updater/platformio.ini | 2 +-
95 files changed, 2250 insertions(+), 797 deletions(-)
create mode 100644 lib/ArduinoJson/extras/tests/Deprecated/containsKey.cpp
create mode 100644 lib/ArduinoJson/extras/tests/Numbers/decomposeFloat.cpp
create mode 100644 lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp
create mode 100644 lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPoolList.hpp
create mode 100644 lib/ArduinoJson/src/ArduinoJson/Variant/VariantImpl.hpp
diff --git a/lib/ArduinoJson/CHANGELOG.md b/lib/ArduinoJson/CHANGELOG.md
index b348d56..aaec586 100644
--- a/lib/ArduinoJson/CHANGELOG.md
+++ b/lib/ArduinoJson/CHANGELOG.md
@@ -1,6 +1,42 @@
ArduinoJson: change log
=======================
+v7.2.0 (2024-09-18)
+------
+
+* Store object members with two slots: one for the key and one for the value
+* Store 64-bit numbers (`double` and `long long`) in an additional slot
+* Reduce the slot size (see table below)
+* Improve message when user forgets third arg of `serializeJson()` et al.
+* Set `ARDUINOJSON_USE_DOUBLE` to `0` by default on 8-bit architectures
+* Deprecate `containsKey()` in favor of `doc["key"].is()`
+* Add support for escape sequence `\'` (issue #2124)
+
+| Architecture | before | after |
+|--------------|----------|----------|
+| 8-bit | 8 bytes | 6 bytes |
+| 32-bit | 16 bytes | 8 bytes |
+| 64-bit | 24 bytes | 16 bytes |
+
+> ### BREAKING CHANGES
+>
+> After being on the death row for years, the `containsKey()` method has finally been deprecated.
+> You should replace `doc.containsKey("key")` with `doc["key"].is()`, which not only checks that the key exists but also that the value is of the expected type.
+>
+> ```cpp
+> // Before
+> if (doc.containsKey("value")) {
+> int value = doc["value"];
+> // ...
+> }
+>
+> // After
+> if (doc["value"].is()) {
+> int value = doc["value"];
+> // ...
+> }
+> ```
+
v7.1.0 (2024-06-27)
------
diff --git a/lib/ArduinoJson/CMakeLists.txt b/lib/ArduinoJson/CMakeLists.txt
index d76b837..2fa0593 100644
--- a/lib/ArduinoJson/CMakeLists.txt
+++ b/lib/ArduinoJson/CMakeLists.txt
@@ -10,7 +10,7 @@ if(ESP_PLATFORM)
return()
endif()
-project(ArduinoJson VERSION 7.1.0)
+project(ArduinoJson VERSION 7.2.0)
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
include(CTest)
diff --git a/lib/ArduinoJson/README.md b/lib/ArduinoJson/README.md
index 2900240..4632534 100644
--- a/lib/ArduinoJson/README.md
+++ b/lib/ArduinoJson/README.md
@@ -148,6 +148,9 @@ ArduinoJson is thankful to its sponsors. Please give them a visit; they deserve
+
+
+
If you run a commercial project that embeds ArduinoJson, think about [sponsoring the library's development](https://github.com/sponsors/bblanchon): it ensures the code that your products rely on stays actively maintained. It can also give your project some exposure to the makers' community.
diff --git a/lib/ArduinoJson/appveyor.yml b/lib/ArduinoJson/appveyor.yml
index edcdb4b..c928a56 100644
--- a/lib/ArduinoJson/appveyor.yml
+++ b/lib/ArduinoJson/appveyor.yml
@@ -1,4 +1,4 @@
-version: 7.1.0.{build}
+version: 7.2.0.{build}
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
diff --git a/lib/ArduinoJson/extras/conf_test/avr.cpp b/lib/ArduinoJson/extras/conf_test/avr.cpp
index e0061ea..769317a 100644
--- a/lib/ArduinoJson/extras/conf_test/avr.cpp
+++ b/lib/ArduinoJson/extras/conf_test/avr.cpp
@@ -6,12 +6,13 @@ static_assert(ARDUINOJSON_USE_LONG_LONG == 0, "ARDUINOJSON_USE_LONG_LONG");
static_assert(ARDUINOJSON_SLOT_ID_SIZE == 1, "ARDUINOJSON_SLOT_ID_SIZE");
+static_assert(ARDUINOJSON_POOL_CAPACITY == 16, "ARDUINOJSON_POOL_CAPACITY");
+
static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
-static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
+static_assert(ARDUINOJSON_USE_DOUBLE == 0, "ARDUINOJSON_USE_DOUBLE");
-static_assert(sizeof(ArduinoJson::detail::VariantSlot) == 8,
- "sizeof(VariantSlot)");
+static_assert(ArduinoJson::detail::ResourceManager::slotSize == 6, "slot size");
void setup() {}
void loop() {}
diff --git a/lib/ArduinoJson/extras/conf_test/esp8266.cpp b/lib/ArduinoJson/extras/conf_test/esp8266.cpp
index b2e6d06..b37bfd6 100644
--- a/lib/ArduinoJson/extras/conf_test/esp8266.cpp
+++ b/lib/ArduinoJson/extras/conf_test/esp8266.cpp
@@ -4,12 +4,13 @@ static_assert(ARDUINOJSON_USE_LONG_LONG == 1, "ARDUINOJSON_USE_LONG_LONG");
static_assert(ARDUINOJSON_SLOT_ID_SIZE == 2, "ARDUINOJSON_SLOT_ID_SIZE");
+static_assert(ARDUINOJSON_POOL_CAPACITY == 128, "ARDUINOJSON_POOL_CAPACITY");
+
static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
-static_assert(sizeof(ArduinoJson::detail::VariantSlot) == 16,
- "sizeof(VariantSlot)");
+static_assert(ArduinoJson::detail::ResourceManager::slotSize == 8, "slot size");
void setup() {}
void loop() {}
diff --git a/lib/ArduinoJson/extras/conf_test/x64.cpp b/lib/ArduinoJson/extras/conf_test/x64.cpp
index 2b533bf..df6b044 100644
--- a/lib/ArduinoJson/extras/conf_test/x64.cpp
+++ b/lib/ArduinoJson/extras/conf_test/x64.cpp
@@ -4,11 +4,13 @@ static_assert(ARDUINOJSON_USE_LONG_LONG == 1, "ARDUINOJSON_USE_LONG_LONG");
static_assert(ARDUINOJSON_SLOT_ID_SIZE == 4, "ARDUINOJSON_SLOT_ID_SIZE");
+static_assert(ARDUINOJSON_POOL_CAPACITY == 256, "ARDUINOJSON_POOL_CAPACITY");
+
static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
-static_assert(sizeof(ArduinoJson::detail::VariantSlot) == 24,
- "sizeof(VariantSlot)");
+static_assert(ArduinoJson::detail::ResourceManager::slotSize == 16,
+ "slot size");
int main() {}
diff --git a/lib/ArduinoJson/extras/conf_test/x86.cpp b/lib/ArduinoJson/extras/conf_test/x86.cpp
index a9874ef..9dff8f1 100644
--- a/lib/ArduinoJson/extras/conf_test/x86.cpp
+++ b/lib/ArduinoJson/extras/conf_test/x86.cpp
@@ -4,11 +4,12 @@ static_assert(ARDUINOJSON_USE_LONG_LONG == 1, "ARDUINOJSON_USE_LONG_LONG");
static_assert(ARDUINOJSON_SLOT_ID_SIZE == 2, "ARDUINOJSON_SLOT_ID_SIZE");
+static_assert(ARDUINOJSON_POOL_CAPACITY == 128, "ARDUINOJSON_POOL_CAPACITY");
+
static_assert(ARDUINOJSON_LITTLE_ENDIAN == 1, "ARDUINOJSON_LITTLE_ENDIAN");
static_assert(ARDUINOJSON_USE_DOUBLE == 1, "ARDUINOJSON_USE_DOUBLE");
-static_assert(sizeof(ArduinoJson::detail::VariantSlot) == 16,
- "sizeof(VariantSlot)");
+static_assert(ArduinoJson::detail::ResourceManager::slotSize == 8, "slot size");
int main() {}
diff --git a/lib/ArduinoJson/extras/tests/Deprecated/CMakeLists.txt b/lib/ArduinoJson/extras/tests/Deprecated/CMakeLists.txt
index 9cefe82..c69fc44 100644
--- a/lib/ArduinoJson/extras/tests/Deprecated/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/Deprecated/CMakeLists.txt
@@ -16,9 +16,10 @@ endif()
add_executable(DeprecatedTests
add.cpp
+ BasicJsonDocument.cpp
+ containsKey.cpp
createNestedArray.cpp
createNestedObject.cpp
- BasicJsonDocument.cpp
DynamicJsonDocument.cpp
macros.cpp
memoryUsage.cpp
diff --git a/lib/ArduinoJson/extras/tests/Deprecated/containsKey.cpp b/lib/ArduinoJson/extras/tests/Deprecated/containsKey.cpp
new file mode 100644
index 0000000..3a429de
--- /dev/null
+++ b/lib/ArduinoJson/extras/tests/Deprecated/containsKey.cpp
@@ -0,0 +1,210 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright © 2014-2024, Benoit BLANCHON
+// MIT License
+
+#include
+#include
+
+#include "Literals.hpp"
+
+TEST_CASE("JsonDocument::containsKey()") {
+ JsonDocument doc;
+
+ SECTION("returns true on object") {
+ doc["hello"] = "world";
+
+ REQUIRE(doc.containsKey("hello") == true);
+ }
+
+ SECTION("returns true when value is null") {
+ doc["hello"] = static_cast(0);
+
+ REQUIRE(doc.containsKey("hello") == true);
+ }
+
+ SECTION("returns true when key is a std::string") {
+ doc["hello"] = "world";
+
+ REQUIRE(doc.containsKey("hello"_s) == true);
+ }
+
+ SECTION("returns false on object") {
+ doc["world"] = "hello";
+
+ REQUIRE(doc.containsKey("hello") == false);
+ }
+
+ SECTION("returns false on array") {
+ doc.add("hello");
+
+ REQUIRE(doc.containsKey("hello") == false);
+ }
+
+ SECTION("returns false on null") {
+ REQUIRE(doc.containsKey("hello") == false);
+ }
+
+ SECTION("support JsonVariant") {
+ doc["hello"] = "world";
+ doc["key"] = "hello";
+
+ REQUIRE(doc.containsKey(doc["key"]) == true);
+ REQUIRE(doc.containsKey(doc["foo"]) == false);
+ }
+}
+
+TEST_CASE("MemberProxy::containsKey()") {
+ JsonDocument doc;
+ auto mp = doc["hello"];
+
+ SECTION("containsKey(const char*)") {
+ mp["key"] = "value";
+
+ REQUIRE(mp.containsKey("key") == true);
+ REQUIRE(mp.containsKey("key") == true);
+ }
+
+ SECTION("containsKey(std::string)") {
+ mp["key"] = "value";
+
+ REQUIRE(mp.containsKey("key"_s) == true);
+ REQUIRE(mp.containsKey("key"_s) == true);
+ }
+}
+
+TEST_CASE("JsonObject::containsKey()") {
+ JsonDocument doc;
+ JsonObject obj = doc.to();
+ obj["hello"] = 42;
+
+ SECTION("returns true only if key is present") {
+ REQUIRE(false == obj.containsKey("world"));
+ REQUIRE(true == obj.containsKey("hello"));
+ }
+
+ SECTION("returns false after remove()") {
+ obj.remove("hello");
+
+ REQUIRE(false == obj.containsKey("hello"));
+ }
+
+#ifdef HAS_VARIABLE_LENGTH_ARRAY
+ SECTION("key is a VLA") {
+ size_t i = 16;
+ char vla[i];
+ strcpy(vla, "hello");
+
+ REQUIRE(true == obj.containsKey(vla));
+ }
+#endif
+
+ SECTION("key is a JsonVariant") {
+ doc["key"] = "hello";
+ REQUIRE(true == obj.containsKey(obj["key"]));
+ REQUIRE(false == obj.containsKey(obj["hello"]));
+ }
+
+ SECTION("std::string") {
+ REQUIRE(true == obj.containsKey("hello"_s));
+ }
+
+ SECTION("unsigned char[]") {
+ unsigned char key[] = "hello";
+ REQUIRE(true == obj.containsKey(key));
+ }
+}
+
+TEST_CASE("JsonObjectConst::containsKey()") {
+ JsonDocument doc;
+ doc["hello"] = 42;
+ auto obj = doc.as();
+
+ SECTION("supports const char*") {
+ REQUIRE(false == obj.containsKey("world"));
+ REQUIRE(true == obj.containsKey("hello"));
+ }
+
+ SECTION("supports std::string") {
+ REQUIRE(false == obj.containsKey("world"_s));
+ REQUIRE(true == obj.containsKey("hello"_s));
+ }
+
+#ifdef HAS_VARIABLE_LENGTH_ARRAY
+ SECTION("supports VLA") {
+ size_t i = 16;
+ char vla[i];
+ strcpy(vla, "hello");
+
+ REQUIRE(true == obj.containsKey(vla));
+ }
+#endif
+
+ SECTION("supports JsonVariant") {
+ doc["key"] = "hello";
+ REQUIRE(true == obj.containsKey(obj["key"]));
+ REQUIRE(false == obj.containsKey(obj["hello"]));
+ }
+}
+
+TEST_CASE("JsonVariant::containsKey()") {
+ JsonDocument doc;
+ JsonVariant var = doc.to();
+
+ SECTION("returns false is unbound") {
+ CHECK_FALSE(JsonVariant().containsKey("hello"));
+ }
+
+ SECTION("containsKey(const char*)") {
+ var["hello"] = "world";
+
+ REQUIRE(var.containsKey("hello") == true);
+ REQUIRE(var.containsKey("world") == false);
+ }
+
+ SECTION("containsKey(std::string)") {
+ var["hello"] = "world";
+
+ REQUIRE(var.containsKey("hello"_s) == true);
+ REQUIRE(var.containsKey("world"_s) == false);
+ }
+
+ SECTION("containsKey(JsonVariant)") {
+ var["hello"] = "world";
+ var["key"] = "hello";
+
+ REQUIRE(var.containsKey(doc["key"]) == true);
+ REQUIRE(var.containsKey(doc["foo"]) == false);
+ }
+}
+
+TEST_CASE("JsonVariantConst::containsKey()") {
+ JsonDocument doc;
+ doc["hello"] = "world";
+ JsonVariantConst var = doc.as();
+
+ SECTION("support const char*") {
+ REQUIRE(var.containsKey("hello") == true);
+ REQUIRE(var.containsKey("world") == false);
+ }
+
+ SECTION("support std::string") {
+ REQUIRE(var.containsKey("hello"_s) == true);
+ REQUIRE(var.containsKey("world"_s) == false);
+ }
+
+#ifdef HAS_VARIABLE_LENGTH_ARRAY
+ SECTION("supports VLA") {
+ size_t i = 16;
+ char vla[i];
+ strcpy(vla, "hello");
+
+ REQUIRE(true == var.containsKey(vla));
+ }
+#endif
+
+ SECTION("support JsonVariant") {
+ doc["key"] = "hello";
+ REQUIRE(var.containsKey(var["key"]) == true);
+ REQUIRE(var.containsKey(var["foo"]) == false);
+ }
+}
diff --git a/lib/ArduinoJson/extras/tests/Helpers/Allocators.hpp b/lib/ArduinoJson/extras/tests/Helpers/Allocators.hpp
index 095d726..a551c31 100644
--- a/lib/ArduinoJson/extras/tests/Helpers/Allocators.hpp
+++ b/lib/ArduinoJson/extras/tests/Helpers/Allocators.hpp
@@ -5,8 +5,8 @@
#pragma once
#include
+#include
#include
-#include
#include
@@ -265,12 +265,14 @@ class TimebombAllocator : public ArduinoJson::Allocator {
} // namespace
inline size_t sizeofPoolList(size_t n = ARDUINOJSON_INITIAL_POOL_COUNT) {
- return sizeof(ArduinoJson::detail::VariantPool) * n;
+ using namespace ArduinoJson::detail;
+ return sizeof(MemoryPool) * n;
}
inline size_t sizeofPool(
ArduinoJson::detail::SlotCount n = ARDUINOJSON_POOL_CAPACITY) {
- return ArduinoJson::detail::VariantPool::slotsToBytes(n);
+ using namespace ArduinoJson::detail;
+ return MemoryPool::slotsToBytes(n);
}
inline size_t sizeofStringBuffer(size_t iteration = 1) {
diff --git a/lib/ArduinoJson/extras/tests/JsonArray/remove.cpp b/lib/ArduinoJson/extras/tests/JsonArray/remove.cpp
index 9cbd90b..82e3bab 100644
--- a/lib/ArduinoJson/extras/tests/JsonArray/remove.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonArray/remove.cpp
@@ -68,6 +68,12 @@ TEST_CASE("JsonArray::remove()") {
REQUIRE(array[1] == 2);
}
+ SECTION("remove end()") {
+ array.remove(array.end());
+
+ REQUIRE(3 == array.size());
+ }
+
SECTION("In a loop") {
for (JsonArray::iterator it = array.begin(); it != array.end(); ++it) {
if (*it == 2)
diff --git a/lib/ArduinoJson/extras/tests/JsonDeserializer/array.cpp b/lib/ArduinoJson/extras/tests/JsonDeserializer/array.cpp
index 71a567d..f61083d 100644
--- a/lib/ArduinoJson/extras/tests/JsonDeserializer/array.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonDeserializer/array.cpp
@@ -69,14 +69,32 @@ TEST_CASE("deserialize JSON array") {
REQUIRE(arr[1] == 84);
}
- SECTION("Double") {
+ SECTION("Float") {
DeserializationError err = deserializeJson(doc, "[4.2,1e2]");
JsonArray arr = doc.as();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(2 == arr.size());
- REQUIRE(arr[0] == 4.2);
- REQUIRE(arr[1] == 1e2);
+ REQUIRE(arr[0].as() == Approx(4.2f));
+ REQUIRE(arr[1] == 1e2f);
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofPool()),
+ Reallocate(sizeofPool(), sizeofPool(2)),
+ });
+ }
+
+ SECTION("Double") {
+ DeserializationError err = deserializeJson(doc, "[4.2123456,-7E89]");
+ JsonArray arr = doc.as();
+
+ REQUIRE(err == DeserializationError::Ok);
+ REQUIRE(2 == arr.size());
+ REQUIRE(arr[0].as() == Approx(4.2123456));
+ REQUIRE(arr[1] == -7E89);
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofPool()),
+ Reallocate(sizeofPool(), sizeofPool(4)),
+ });
}
SECTION("Unsigned long") {
diff --git a/lib/ArduinoJson/extras/tests/JsonDeserializer/errors.cpp b/lib/ArduinoJson/extras/tests/JsonDeserializer/errors.cpp
index 35b4de2..0c2444e 100644
--- a/lib/ArduinoJson/extras/tests/JsonDeserializer/errors.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonDeserializer/errors.cpp
@@ -6,6 +6,8 @@
#include
#include
+#include "Allocators.hpp"
+
TEST_CASE("deserializeJson() returns IncompleteInput") {
const char* testCases[] = {
// strings
@@ -118,3 +120,43 @@ TEST_CASE("deserializeJson() returns NoMemory if string length overflows") {
REQUIRE(err == DeserializationError::NoMemory);
}
}
+
+TEST_CASE("deserializeJson() returns NoMemory if extension allocation fails") {
+ JsonDocument doc(FailingAllocator::instance());
+
+ SECTION("uint32_t should pass") {
+ auto err = deserializeJson(doc, "4294967295");
+
+ REQUIRE(err == DeserializationError::Ok);
+ }
+
+ SECTION("uint64_t should fail") {
+ auto err = deserializeJson(doc, "18446744073709551615");
+
+ REQUIRE(err == DeserializationError::NoMemory);
+ }
+
+ SECTION("int32_t should pass") {
+ auto err = deserializeJson(doc, "-2147483648");
+
+ REQUIRE(err == DeserializationError::Ok);
+ }
+
+ SECTION("int64_t should fail") {
+ auto err = deserializeJson(doc, "-9223372036854775808");
+
+ REQUIRE(err == DeserializationError::NoMemory);
+ }
+
+ SECTION("float should pass") {
+ auto err = deserializeJson(doc, "3.402823e38");
+
+ REQUIRE(err == DeserializationError::Ok);
+ }
+
+ SECTION("double should fail") {
+ auto err = deserializeJson(doc, "1.7976931348623157e308");
+
+ REQUIRE(err == DeserializationError::NoMemory);
+ }
+}
diff --git a/lib/ArduinoJson/extras/tests/JsonDeserializer/object.cpp b/lib/ArduinoJson/extras/tests/JsonDeserializer/object.cpp
index 501e87a..ee62ae4 100644
--- a/lib/ArduinoJson/extras/tests/JsonDeserializer/object.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonDeserializer/object.cpp
@@ -155,15 +155,27 @@ TEST_CASE("deserialize JSON object") {
REQUIRE(obj["key2"] == -42);
}
- SECTION("Double") {
+ SECTION("Float") {
DeserializationError err =
- deserializeJson(doc, "{\"key1\":12.345,\"key2\":-7E89}");
+ deserializeJson(doc, "{\"key1\":12.345,\"key2\":-7E3}");
JsonObject obj = doc.as();
REQUIRE(err == DeserializationError::Ok);
REQUIRE(doc.is());
REQUIRE(obj.size() == 2);
- REQUIRE(obj["key1"] == 12.345);
+ REQUIRE(obj["key1"].as() == Approx(12.345f));
+ REQUIRE(obj["key2"] == -7E3f);
+ }
+
+ SECTION("Double") {
+ DeserializationError err =
+ deserializeJson(doc, "{\"key1\":12.3456789,\"key2\":-7E89}");
+ JsonObject obj = doc.as();
+
+ REQUIRE(err == DeserializationError::Ok);
+ REQUIRE(doc.is());
+ REQUIRE(obj.size() == 2);
+ REQUIRE(obj["key1"].as() == Approx(12.3456789));
REQUIRE(obj["key2"] == -7E89);
}
@@ -308,12 +320,12 @@ TEST_CASE("deserialize JSON object") {
REQUIRE(doc["a"] == 2);
}
- SECTION("NUL in keys") { // we don't support NULs in keys
+ SECTION("NUL in keys") {
DeserializationError err =
deserializeJson(doc, "{\"x\\u0000a\":1,\"x\\u0000b\":2}");
REQUIRE(err == DeserializationError::Ok);
- REQUIRE(doc.as() == "{\"x\":2}");
+ REQUIRE(doc.as() == "{\"x\\u0000a\":1,\"x\\u0000b\":2}");
}
}
diff --git a/lib/ArduinoJson/extras/tests/JsonDeserializer/string.cpp b/lib/ArduinoJson/extras/tests/JsonDeserializer/string.cpp
index a47ab76..a760ae6 100644
--- a/lib/ArduinoJson/extras/tests/JsonDeserializer/string.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonDeserializer/string.cpp
@@ -83,6 +83,22 @@ TEST_CASE("Truncated JSON string") {
}
}
+TEST_CASE("Escape single quote in single quoted string") {
+ JsonDocument doc;
+
+ DeserializationError err = deserializeJson(doc, "'ab\\\'cd'");
+ REQUIRE(err == DeserializationError::Ok);
+ CHECK(doc.as() == "ab\'cd");
+}
+
+TEST_CASE("Escape double quote in double quoted string") {
+ JsonDocument doc;
+
+ DeserializationError err = deserializeJson(doc, "'ab\\\"cd'");
+ REQUIRE(err == DeserializationError::Ok);
+ CHECK(doc.as() == "ab\"cd");
+}
+
TEST_CASE("Invalid JSON string") {
const char* testCases[] = {"'\\u'", "'\\u000g'", "'\\u000'",
"'\\u000G'", "'\\u000/'", "'\\x1234'"};
diff --git a/lib/ArduinoJson/extras/tests/JsonDocument/CMakeLists.txt b/lib/ArduinoJson/extras/tests/JsonDocument/CMakeLists.txt
index e6b6f1d..0caa7b9 100644
--- a/lib/ArduinoJson/extras/tests/JsonDocument/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/JsonDocument/CMakeLists.txt
@@ -9,7 +9,6 @@ add_executable(JsonDocumentTests
clear.cpp
compare.cpp
constructor.cpp
- containsKey.cpp
ElementProxy.cpp
isNull.cpp
issue1120.cpp
diff --git a/lib/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp b/lib/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp
index bb6acdf..b48eda1 100644
--- a/lib/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonDocument/MemberProxy.cpp
@@ -93,25 +93,6 @@ TEST_CASE("MemberProxy::operator==()") {
}
}
-TEST_CASE("MemberProxy::containsKey()") {
- JsonDocument doc;
- MemberProxy mp = doc["hello"];
-
- SECTION("containsKey(const char*)") {
- mp["key"] = "value";
-
- REQUIRE(mp.containsKey("key") == true);
- REQUIRE(mp.containsKey("key") == true);
- }
-
- SECTION("containsKey(std::string)") {
- mp["key"] = "value";
-
- REQUIRE(mp.containsKey("key"_s) == true);
- REQUIRE(mp.containsKey("key"_s) == true);
- }
-}
-
TEST_CASE("MemberProxy::operator|()") {
JsonDocument doc;
@@ -345,12 +326,12 @@ TEST_CASE("Deduplicate keys") {
}
TEST_CASE("MemberProxy under memory constraints") {
- KillswitchAllocator killswitch;
- SpyingAllocator spy(&killswitch);
+ TimebombAllocator timebomb(1);
+ SpyingAllocator spy(&timebomb);
JsonDocument doc(&spy);
- SECTION("key allocation fails") {
- killswitch.on();
+ SECTION("key slot allocation fails") {
+ timebomb.setCountdown(0);
doc["hello"_s] = "world";
@@ -358,6 +339,38 @@ TEST_CASE("MemberProxy under memory constraints") {
REQUIRE(doc.size() == 0);
REQUIRE(doc.overflowed() == true);
REQUIRE(spy.log() == AllocatorLog{
+ AllocateFail(sizeofPool()),
+ });
+ }
+
+ SECTION("value slot allocation fails") {
+ timebomb.setCountdown(1);
+
+ // fill the pool entirely, but leave one slot for the key
+ doc["foo"][ARDUINOJSON_POOL_CAPACITY - 4] = 1;
+ REQUIRE(doc.overflowed() == false);
+
+ doc["hello"_s] = "world";
+
+ REQUIRE(doc.is());
+ REQUIRE(doc.size() == 1);
+ REQUIRE(doc.overflowed() == true);
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofPool()),
+ AllocateFail(sizeofPool()),
+ });
+ }
+
+ SECTION("key string allocation fails") {
+ timebomb.setCountdown(1);
+
+ doc["hello"_s] = "world";
+
+ REQUIRE(doc.is());
+ REQUIRE(doc.size() == 0);
+ REQUIRE(doc.overflowed() == true);
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofPool()),
AllocateFail(sizeofString("hello")),
});
}
diff --git a/lib/ArduinoJson/extras/tests/JsonDocument/assignment.cpp b/lib/ArduinoJson/extras/tests/JsonDocument/assignment.cpp
index 42cef3e..58a8391 100644
--- a/lib/ArduinoJson/extras/tests/JsonDocument/assignment.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonDocument/assignment.cpp
@@ -22,8 +22,8 @@ TEST_CASE("JsonDocument assignment") {
REQUIRE(doc2.as() == "{\"hello\":\"world\"}");
REQUIRE(spyingAllocator.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
Allocate(sizeofString("world")),
});
}
@@ -54,8 +54,8 @@ TEST_CASE("JsonDocument assignment") {
REQUIRE(doc2.as() == "{\"hello\":\"world\"}");
REQUIRE(spyingAllocator.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
Allocate(sizeofString("world")),
});
}
@@ -72,8 +72,8 @@ TEST_CASE("JsonDocument assignment") {
REQUIRE(doc1.as() == "null");
}
REQUIRE(spyingAllocator.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
Allocate(sizeofString("world")),
Deallocate(sizeofString("hello")),
Deallocate(sizeofString("world")),
diff --git a/lib/ArduinoJson/extras/tests/JsonDocument/shrinkToFit.cpp b/lib/ArduinoJson/extras/tests/JsonDocument/shrinkToFit.cpp
index 1d43140..91b9d91 100644
--- a/lib/ArduinoJson/extras/tests/JsonDocument/shrinkToFit.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonDocument/shrinkToFit.cpp
@@ -122,8 +122,8 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
REQUIRE(doc.as() == "{\"abcdefg\":42}");
REQUIRE(spyingAllocator.log() ==
AllocatorLog{
- Allocate(sizeofString("abcdefg")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("abcdefg")),
Reallocate(sizeofPool(), sizeofObject(1)),
});
}
@@ -178,7 +178,7 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
AllocatorLog{
Allocate(sizeofPool()),
Allocate(sizeofString("abcdefg")),
- Reallocate(sizeofPool(), sizeofPool(1)),
+ Reallocate(sizeofPool(), sizeofPool(2)),
});
}
}
diff --git a/lib/ArduinoJson/extras/tests/JsonObject/CMakeLists.txt b/lib/ArduinoJson/extras/tests/JsonObject/CMakeLists.txt
index dd2dfaa..60ba1fe 100644
--- a/lib/ArduinoJson/extras/tests/JsonObject/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/JsonObject/CMakeLists.txt
@@ -5,7 +5,6 @@
add_executable(JsonObjectTests
clear.cpp
compare.cpp
- containsKey.cpp
equals.cpp
isNull.cpp
iterator.cpp
diff --git a/lib/ArduinoJson/extras/tests/JsonObject/set.cpp b/lib/ArduinoJson/extras/tests/JsonObject/set.cpp
index f80f8a8..bad0674 100644
--- a/lib/ArduinoJson/extras/tests/JsonObject/set.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonObject/set.cpp
@@ -52,8 +52,8 @@ TEST_CASE("JsonObject::set()") {
REQUIRE(success == true);
REQUIRE(obj2["hello"] == "world"_s);
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
});
}
@@ -66,8 +66,8 @@ TEST_CASE("JsonObject::set()") {
REQUIRE(success == true);
REQUIRE(obj2["hello"] == "world"_s);
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
Allocate(sizeofString("world")),
});
}
@@ -81,8 +81,8 @@ TEST_CASE("JsonObject::set()") {
REQUIRE(success == true);
REQUIRE(obj2["hello"] == "world"_s);
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
Allocate(sizeofString("world")),
});
}
diff --git a/lib/ArduinoJson/extras/tests/JsonObject/std_string.cpp b/lib/ArduinoJson/extras/tests/JsonObject/std_string.cpp
index 613e0bd..85ca300 100644
--- a/lib/ArduinoJson/extras/tests/JsonObject/std_string.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonObject/std_string.cpp
@@ -34,13 +34,6 @@ TEST_CASE("std::string") {
REQUIRE("value"_s == obj["key"_s]);
}
- SECTION("containsKey()") {
- char json[] = "{\"key\":\"value\"}";
- deserializeJson(doc, json);
- JsonObject obj = doc.as();
- REQUIRE(true == obj.containsKey("key"_s));
- }
-
SECTION("remove()") {
JsonObject obj = doc.to();
obj["key"] = "value";
diff --git a/lib/ArduinoJson/extras/tests/JsonObject/subscript.cpp b/lib/ArduinoJson/extras/tests/JsonObject/subscript.cpp
index 775d149..1a5ceb7 100644
--- a/lib/ArduinoJson/extras/tests/JsonObject/subscript.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonObject/subscript.cpp
@@ -118,16 +118,16 @@ TEST_CASE("JsonObject::operator[]") {
SECTION("should duplicate char* key") {
obj[const_cast("hello")] = "world";
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
});
}
SECTION("should duplicate char* key&value") {
obj[const_cast("hello")] = const_cast("world");
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
Allocate(sizeofString("world")),
});
}
@@ -143,16 +143,16 @@ TEST_CASE("JsonObject::operator[]") {
SECTION("should duplicate std::string key") {
obj["hello"_s] = "world";
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
});
}
SECTION("should duplicate std::string key&value") {
obj["hello"_s] = "world"_s;
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
Allocate(sizeofString("world")),
});
}
@@ -160,8 +160,8 @@ TEST_CASE("JsonObject::operator[]") {
SECTION("should duplicate a non-static JsonString key") {
obj[JsonString("hello", JsonString::Copied)] = "world";
REQUIRE(spy.log() == AllocatorLog{
- Allocate(sizeofString("hello")),
Allocate(sizeofPool()),
+ Allocate(sizeofString("hello")),
});
}
diff --git a/lib/ArduinoJson/extras/tests/JsonObjectConst/CMakeLists.txt b/lib/ArduinoJson/extras/tests/JsonObjectConst/CMakeLists.txt
index dadb910..447e239 100644
--- a/lib/ArduinoJson/extras/tests/JsonObjectConst/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/JsonObjectConst/CMakeLists.txt
@@ -3,7 +3,6 @@
# MIT License
add_executable(JsonObjectConstTests
- containsKey.cpp
equals.cpp
isNull.cpp
iterator.cpp
diff --git a/lib/ArduinoJson/extras/tests/JsonSerializer/JsonVariant.cpp b/lib/ArduinoJson/extras/tests/JsonSerializer/JsonVariant.cpp
index 800c3a9..1ddaea6 100644
--- a/lib/ArduinoJson/extras/tests/JsonSerializer/JsonVariant.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonSerializer/JsonVariant.cpp
@@ -46,6 +46,10 @@ TEST_CASE("serializeJson(JsonVariant)") {
check("fifty/fifty"_s, "\"fifty/fifty\"");
}
+ SECTION("Don't escape single quote") {
+ check("hello'world"_s, "\"hello'world\"");
+ }
+
SECTION("Escape backspace") {
check("hello\bworld"_s, "\"hello\\bworld\"");
}
@@ -83,6 +87,11 @@ TEST_CASE("serializeJson(JsonVariant)") {
check(3.1415927, "3.1415927");
}
+ SECTION("Float") {
+ REQUIRE(sizeof(float) == 4);
+ check(3.1415927f, "3.141593");
+ }
+
SECTION("Zero") {
check(0, "0");
}
diff --git a/lib/ArduinoJson/extras/tests/JsonVariant/CMakeLists.txt b/lib/ArduinoJson/extras/tests/JsonVariant/CMakeLists.txt
index e14e548..282e6ce 100644
--- a/lib/ArduinoJson/extras/tests/JsonVariant/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/JsonVariant/CMakeLists.txt
@@ -7,7 +7,6 @@ add_executable(JsonVariantTests
as.cpp
clear.cpp
compare.cpp
- containsKey.cpp
converters.cpp
copy.cpp
is.cpp
diff --git a/lib/ArduinoJson/extras/tests/JsonVariant/as.cpp b/lib/ArduinoJson/extras/tests/JsonVariant/as.cpp
index fa76b0e..2c6f54b 100644
--- a/lib/ArduinoJson/extras/tests/JsonVariant/as.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonVariant/as.cpp
@@ -31,13 +31,28 @@ TEST_CASE("JsonVariant::as()") {
REQUIRE(variant.as().data() == nullptr);
}
- SECTION("set(4.2)") {
+ SECTION("set(float)") {
+ variant.set(4.2f);
+
+ REQUIRE(variant.as());
+ REQUIRE(0 == variant.as());
+ REQUIRE(variant.as() == "4.2");
+ REQUIRE(variant.as() == 4L);
+ REQUIRE(variant.as() == 4.2f);
+ REQUIRE(variant.as() == 4U);
+ REQUIRE(variant.as().isNull());
+ REQUIRE(variant.as().data() == nullptr);
+ REQUIRE(variant.as().data() == nullptr);
+ }
+
+ SECTION("set(double)") {
variant.set(4.2);
REQUIRE(variant.as());
REQUIRE(0 == variant.as());
REQUIRE(variant.as() == "4.2");
REQUIRE(variant.as() == 4L);
+ REQUIRE(variant.as() == 4.2);
REQUIRE(variant.as() == 4U);
REQUIRE(variant.as().isNull());
REQUIRE(variant.as().data() == nullptr);
@@ -78,43 +93,62 @@ TEST_CASE("JsonVariant::as()") {
REQUIRE(variant.as().data() == nullptr);
}
- SECTION("set(42)") {
- variant.set(42);
+ SECTION("set(uint32_t)") {
+ variant.set(4294967295U);
REQUIRE(variant.as() == true);
- REQUIRE(variant.as() == 42.0);
- REQUIRE(variant.as() == 42);
- REQUIRE(variant.as() == 42U); // issue #1601
- REQUIRE(variant.as() == "42");
+ REQUIRE(variant.as() == 4294967295.0);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == 4294967295U);
+ REQUIRE(variant.as() == 4294967295U);
+ REQUIRE(variant.as() == "4294967295");
REQUIRE(variant.as().isNull());
REQUIRE(variant.as().data() == nullptr);
REQUIRE(variant.as().data() == nullptr);
}
- SECTION("set(42L)") {
- variant.set(42L);
+ SECTION("set(int32_t)") {
+ variant.set(-2147483648LL);
REQUIRE(variant.as() == true);
- REQUIRE(variant.as() == 42.0);
- REQUIRE(variant.as() == "42");
+ REQUIRE(variant.as() == -2147483648LL);
+ REQUIRE(variant.as() == -2147483648LL);
+ REQUIRE(variant.as() == -2147483648LL);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == "-2147483648");
REQUIRE(variant.as().isNull());
+ REQUIRE(variant.as().data() == nullptr);
+ REQUIRE(variant.as().data() == nullptr);
}
- SECTION("set(-42L)") {
- variant.set(-42L);
-
- REQUIRE(variant.as() == -42.0);
- REQUIRE(variant.as() == "-42");
- REQUIRE(variant.as().isNull());
- }
-
- SECTION("set(42UL)") {
- variant.set(42UL);
+ SECTION("set(uint64_t)") {
+ variant.set(4294967296U);
REQUIRE(variant.as() == true);
- REQUIRE(variant.as() == 42.0);
- REQUIRE(variant.as() == "42");
+ REQUIRE(variant.as() == 4294967296.0);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == 4294967296U);
+ REQUIRE(variant.as() == "4294967296");
REQUIRE(variant.as().isNull());
+ REQUIRE(variant.as().data() == nullptr);
+ REQUIRE(variant.as().data() == nullptr);
+ }
+
+ SECTION("set(int64_t)") {
+ variant.set(-2147483649LL);
+
+ REQUIRE(variant.as() == true);
+ REQUIRE(variant.as() == -2147483649LL);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == -2147483649LL);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == 0);
+ REQUIRE(variant.as() == "-2147483649");
+ REQUIRE(variant.as().isNull());
+ REQUIRE(variant.as().data() == nullptr);
+ REQUIRE(variant.as().data() == nullptr);
}
SECTION("set(0L)") {
@@ -169,7 +203,7 @@ TEST_CASE("JsonVariant::as()") {
REQUIRE(variant.as() == true);
REQUIRE(variant.as() == 4L);
- REQUIRE(variant.as() == 4.2);
+ REQUIRE(variant.as() == Approx(4.2));
REQUIRE(variant.as() == "4.2"_s);
REQUIRE(variant.as() == "4.2"_s);
REQUIRE(variant.as() == "4.2");
diff --git a/lib/ArduinoJson/extras/tests/JsonVariant/set.cpp b/lib/ArduinoJson/extras/tests/JsonVariant/set.cpp
index e47c2b4..b10f950 100644
--- a/lib/ArduinoJson/extras/tests/JsonVariant/set.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonVariant/set.cpp
@@ -13,7 +13,8 @@ using ArduinoJson::detail::sizeofObject;
enum ErrorCode { ERROR_01 = 1, ERROR_10 = 10 };
TEST_CASE("JsonVariant::set() when there is enough memory") {
- JsonDocument doc;
+ SpyingAllocator spy;
+ JsonDocument doc(&spy);
JsonVariant variant = doc.to();
SECTION("const char*") {
@@ -25,6 +26,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "world"); // stores by pointer
+ REQUIRE(spy.log() == AllocatorLog{});
}
SECTION("(const char*)0") {
@@ -32,6 +34,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant.isNull());
+ REQUIRE(spy.log() == AllocatorLog{});
}
SECTION("char*") {
@@ -43,6 +46,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "hello"); // stores by copy
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofString("hello")),
+ });
}
SECTION("(char*)0") {
@@ -50,6 +56,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant.isNull());
+ REQUIRE(spy.log() == AllocatorLog{});
}
SECTION("unsigned char*") {
@@ -61,6 +68,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "hello"); // stores by copy
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofString("hello")),
+ });
}
SECTION("signed char*") {
@@ -72,6 +82,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "hello"); // stores by copy
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofString("hello")),
+ });
}
#ifdef HAS_VARIABLE_LENGTH_ARRAY
@@ -85,6 +98,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "hello"); // stores by copy
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofString("hello")),
+ });
}
#endif
@@ -97,6 +113,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "hello"); // stores by copy
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofString("hello")),
+ });
}
SECTION("static JsonString") {
@@ -108,6 +127,7 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "world"); // stores by pointer
+ REQUIRE(spy.log() == AllocatorLog{});
}
SECTION("non-static JsonString") {
@@ -119,6 +139,9 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant == "hello"); // stores by copy
+ REQUIRE(spy.log() == AllocatorLog{
+ Allocate(sizeofString("hello")),
+ });
}
SECTION("enum") {
@@ -129,6 +152,89 @@ TEST_CASE("JsonVariant::set() when there is enough memory") {
REQUIRE(result == true);
REQUIRE(variant.is() == true);
REQUIRE(variant.as() == 10);
+ REQUIRE(spy.log() == AllocatorLog{});
+ }
+
+ SECTION("float") {
+ bool result = variant.set(1.2f);
+
+ REQUIRE(result == true);
+ REQUIRE(variant.is() == true);
+ REQUIRE(variant.as() == 1.2f);
+ REQUIRE(spy.log() == AllocatorLog{});
+ }
+
+ SECTION("double") {
+ bool result = variant.set(1.2);
+ doc.shrinkToFit();
+
+ REQUIRE(result == true);
+ REQUIRE(variant.is() == true);
+ REQUIRE(variant.as() == 1.2);
+ REQUIRE(spy.log() ==
+ AllocatorLog{
+ Allocate(sizeofPool()),
+ Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
+ });
+ }
+
+ SECTION("int32_t") {
+ bool result = variant.set(int32_t(42));
+
+ REQUIRE(result == true);
+ REQUIRE(variant.is() == true);
+ REQUIRE(variant.as() == 42);
+ REQUIRE(spy.log() == AllocatorLog{});
+ }
+
+ SECTION("int64_t") {
+ bool result = variant.set(int64_t(-2147483649LL));
+ doc.shrinkToFit();
+
+ REQUIRE(result == true);
+ REQUIRE(variant.is() == true);
+ REQUIRE(variant.as() == -2147483649LL);
+ REQUIRE(spy.log() ==
+ AllocatorLog{
+ Allocate(sizeofPool()),
+ Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
+ });
+ }
+
+ SECTION("uint32_t") {
+ bool result = variant.set(uint32_t(42));
+
+ REQUIRE(result == true);
+ REQUIRE(variant.is() == true);
+ REQUIRE(variant.as() == 42);
+ REQUIRE(spy.log() == AllocatorLog{});
+ }
+
+ SECTION("uint64_t") {
+ bool result = variant.set(uint64_t(4294967296));
+ doc.shrinkToFit();
+
+ REQUIRE(result == true);
+ REQUIRE(variant.is() == true);
+ REQUIRE(variant.as() == 4294967296);
+ REQUIRE(spy.log() ==
+ AllocatorLog{
+ Allocate(sizeofPool()),
+ Reallocate(sizeofPool(), sizeofPool(1)), // one extension slot
+ });
+ }
+
+ SECTION("JsonDocument") {
+ JsonDocument doc1;
+ doc1["hello"] = "world";
+
+ // Should copy the doc
+ variant.set(doc1);
+ doc1.clear();
+
+ std::string json;
+ serializeJson(doc, json);
+ REQUIRE(json == "{\"hello\":\"world\"}");
}
}
@@ -158,22 +264,48 @@ TEST_CASE("JsonVariant::set() with not enough memory") {
REQUIRE(result == false);
REQUIRE(v.isNull());
}
-}
-TEST_CASE("JsonVariant::set(JsonDocument)") {
- JsonDocument doc1;
- doc1["hello"] = "world";
+ SECTION("float") {
+ bool result = v.set(1.2f);
- JsonDocument doc2;
- JsonVariant v = doc2.to();
+ REQUIRE(result == true);
+ REQUIRE(v.is());
+ }
- // Should copy the doc
- v.set(doc1);
- doc1.clear();
+ SECTION("double") {
+ bool result = v.set(1.2);
- std::string json;
- serializeJson(doc2, json);
- REQUIRE(json == "{\"hello\":\"world\"}");
+ REQUIRE(result == false);
+ REQUIRE(v.isNull());
+ }
+
+ SECTION("int32_t") {
+ bool result = v.set(-42);
+
+ REQUIRE(result == true);
+ REQUIRE(v.is());
+ }
+
+ SECTION("int64_t") {
+ bool result = v.set(-2147483649LL);
+
+ REQUIRE(result == false);
+ REQUIRE(v.isNull());
+ }
+
+ SECTION("uint32_t") {
+ bool result = v.set(42);
+
+ REQUIRE(result == true);
+ REQUIRE(v.is());
+ }
+
+ SECTION("uint64_t") {
+ bool result = v.set(4294967296U);
+
+ REQUIRE(result == false);
+ REQUIRE(v.isNull());
+ }
}
TEST_CASE("JsonVariant::set() releases the previous value") {
@@ -220,3 +352,34 @@ TEST_CASE("JsonVariant::set() releases the previous value") {
});
}
}
+
+TEST_CASE("JsonVariant::set() reuses extension slot") {
+ SpyingAllocator spy;
+ JsonDocument doc(&spy);
+ JsonVariant variant = doc.to();
+
+ variant.set(1.2);
+ doc.shrinkToFit();
+ spy.clearLog();
+
+ SECTION("double") {
+ bool result = variant.set(3.4);
+
+ REQUIRE(result == true);
+ REQUIRE(spy.log() == AllocatorLog{});
+ }
+
+ SECTION("int64_t") {
+ bool result = variant.set(-2147483649LL);
+
+ REQUIRE(result == true);
+ REQUIRE(spy.log() == AllocatorLog{});
+ }
+
+ SECTION("uint64_t") {
+ bool result = variant.set(4294967296U);
+
+ REQUIRE(result == true);
+ REQUIRE(spy.log() == AllocatorLog{});
+ }
+}
diff --git a/lib/ArduinoJson/extras/tests/JsonVariant/unbound.cpp b/lib/ArduinoJson/extras/tests/JsonVariant/unbound.cpp
index ff93625..0f1740b 100644
--- a/lib/ArduinoJson/extras/tests/JsonVariant/unbound.cpp
+++ b/lib/ArduinoJson/extras/tests/JsonVariant/unbound.cpp
@@ -73,10 +73,6 @@ TEST_CASE("Unbound JsonVariant") {
CHECK_FALSE(variant["key"_s].set(1));
}
- SECTION("containsKey()") {
- CHECK_FALSE(variant.containsKey("hello"));
- }
-
SECTION("remove()") {
variant.remove(0);
variant.remove("hello");
diff --git a/lib/ArduinoJson/extras/tests/JsonVariantConst/CMakeLists.txt b/lib/ArduinoJson/extras/tests/JsonVariantConst/CMakeLists.txt
index d0dc65e..b943f16 100644
--- a/lib/ArduinoJson/extras/tests/JsonVariantConst/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/JsonVariantConst/CMakeLists.txt
@@ -4,7 +4,6 @@
add_executable(JsonVariantConstTests
as.cpp
- containsKey.cpp
is.cpp
isnull.cpp
nesting.cpp
diff --git a/lib/ArduinoJson/extras/tests/Misc/CMakeLists.txt b/lib/ArduinoJson/extras/tests/Misc/CMakeLists.txt
index 2fdc613..82f1a0c 100644
--- a/lib/ArduinoJson/extras/tests/Misc/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/Misc/CMakeLists.txt
@@ -5,7 +5,6 @@
add_executable(MiscTests
arithmeticCompare.cpp
conflicts.cpp
- FloatParts.cpp
issue1967.cpp
JsonString.cpp
NoArduinoHeader.cpp
diff --git a/lib/ArduinoJson/extras/tests/Misc/unsigned_char.cpp b/lib/ArduinoJson/extras/tests/Misc/unsigned_char.cpp
index fd780d6..a1bb155 100644
--- a/lib/ArduinoJson/extras/tests/Misc/unsigned_char.cpp
+++ b/lib/ArduinoJson/extras/tests/Misc/unsigned_char.cpp
@@ -176,15 +176,6 @@ TEST_CASE("unsigned char[]") {
}
#endif
- SECTION("containsKey()") {
- unsigned char key[] = "hello";
-
- JsonDocument doc;
- deserializeJson(doc, "{\"hello\":\"world\"}");
- JsonObject obj = doc.as();
- REQUIRE(true == obj.containsKey(key));
- }
-
SECTION("remove()") {
unsigned char key[] = "hello";
diff --git a/lib/ArduinoJson/extras/tests/MixedConfiguration/use_double_0.cpp b/lib/ArduinoJson/extras/tests/MixedConfiguration/use_double_0.cpp
index 8752890..6958bc0 100644
--- a/lib/ArduinoJson/extras/tests/MixedConfiguration/use_double_0.cpp
+++ b/lib/ArduinoJson/extras/tests/MixedConfiguration/use_double_0.cpp
@@ -3,15 +3,65 @@
#include
-TEST_CASE("ARDUINOJSON_USE_DOUBLE == 0") {
- JsonDocument doc;
- JsonObject root = doc.to();
+namespace my {
+using ArduinoJson::detail::isinf;
+} // namespace my
- root["pi"] = 3.14;
- root["e"] = 2.72;
-
- std::string json;
- serializeJson(doc, json);
-
- REQUIRE(json == "{\"pi\":3.14,\"e\":2.72}");
+void checkFloat(const char* input, float expected) {
+ using ArduinoJson::detail::NumberType;
+ using ArduinoJson::detail::parseNumber;
+ CAPTURE(input);
+ auto result = parseNumber(input);
+ REQUIRE(result.type() == NumberType::Float);
+ REQUIRE(result.asFloat() == Approx(expected));
+}
+
+TEST_CASE("ARDUINOJSON_USE_DOUBLE == 0") {
+ SECTION("serializeJson()") {
+ JsonDocument doc;
+ JsonObject root = doc.to();
+
+ root["pi"] = 3.14;
+ root["e"] = 2.72;
+
+ std::string json;
+ serializeJson(doc, json);
+
+ REQUIRE(json == "{\"pi\":3.14,\"e\":2.72}");
+ }
+
+ SECTION("parseNumber()") {
+ using ArduinoJson::detail::NumberType;
+ using ArduinoJson::detail::parseNumber;
+
+ SECTION("Large positive number") {
+ auto result = parseNumber("1e300");
+ REQUIRE(result.type() == NumberType::Float);
+ REQUIRE(result.asFloat() > 0);
+ REQUIRE(my::isinf(result.asFloat()));
+ }
+
+ SECTION("Large negative number") {
+ auto result = parseNumber("-1e300");
+ REQUIRE(result.type() == NumberType::Float);
+ REQUIRE(result.asFloat() < 0);
+ REQUIRE(my::isinf(result.asFloat()));
+ }
+
+ SECTION("Too small to be represented") {
+ auto result = parseNumber("1e-300");
+ REQUIRE(result.type() == NumberType::Float);
+ REQUIRE(result.asFloat() == 0);
+ }
+
+ SECTION("MantissaTooLongToFit") {
+ checkFloat("0.340282346638528861111111111111", 0.34028234663852886f);
+ checkFloat("34028234663852886.11111111111111", 34028234663852886.0f);
+ checkFloat("34028234.66385288611111111111111", 34028234.663852886f);
+
+ checkFloat("-0.340282346638528861111111111111", -0.34028234663852886f);
+ checkFloat("-34028234663852886.11111111111111", -34028234663852886.0f);
+ checkFloat("-34028234.66385288611111111111111", -34028234.663852886f);
+ }
+ }
}
diff --git a/lib/ArduinoJson/extras/tests/MixedConfiguration/use_long_long_0.cpp b/lib/ArduinoJson/extras/tests/MixedConfiguration/use_long_long_0.cpp
index 2781a76..16c07db 100644
--- a/lib/ArduinoJson/extras/tests/MixedConfiguration/use_long_long_0.cpp
+++ b/lib/ArduinoJson/extras/tests/MixedConfiguration/use_long_long_0.cpp
@@ -32,11 +32,7 @@ TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
deserializeMsgPack(doc, "\xcf\x00\x00\x00\x01\x00\x00\x00\x00"_s);
REQUIRE(err == DeserializationError::Ok);
-#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
- REQUIRE(doc.as() == 0x100000000);
-#else
REQUIRE(doc.isNull());
-#endif
}
}
}
diff --git a/lib/ArduinoJson/extras/tests/MsgPackDeserializer/errors.cpp b/lib/ArduinoJson/extras/tests/MsgPackDeserializer/errors.cpp
index 01e761a..dff712a 100644
--- a/lib/ArduinoJson/extras/tests/MsgPackDeserializer/errors.cpp
+++ b/lib/ArduinoJson/extras/tests/MsgPackDeserializer/errors.cpp
@@ -199,3 +199,44 @@ TEST_CASE(
REQUIRE(err == DeserializationError::NoMemory);
}
}
+
+TEST_CASE(
+ "deserializeMsgPack() returns NoMemory if extension allocation fails") {
+ JsonDocument doc(FailingAllocator::instance());
+
+ SECTION("uint32_t should pass") {
+ auto err = deserializeMsgPack(doc, "\xceXXXX");
+
+ REQUIRE(err == DeserializationError::Ok);
+ }
+
+ SECTION("uint64_t should fail") {
+ auto err = deserializeMsgPack(doc, "\xcfXXXXXXXX");
+
+ REQUIRE(err == DeserializationError::NoMemory);
+ }
+
+ SECTION("int32_t should pass") {
+ auto err = deserializeMsgPack(doc, "\xd2XXXX");
+
+ REQUIRE(err == DeserializationError::Ok);
+ }
+
+ SECTION("int64_t should fail") {
+ auto err = deserializeMsgPack(doc, "\xd3XXXXXXXX");
+
+ REQUIRE(err == DeserializationError::NoMemory);
+ }
+
+ SECTION("float should pass") {
+ auto err = deserializeMsgPack(doc, "\xcaXXXX");
+
+ REQUIRE(err == DeserializationError::Ok);
+ }
+
+ SECTION("double should fail") {
+ auto err = deserializeMsgPack(doc, "\xcbXXXXXXXX");
+
+ REQUIRE(err == DeserializationError::NoMemory);
+ }
+}
diff --git a/lib/ArduinoJson/extras/tests/Numbers/CMakeLists.txt b/lib/ArduinoJson/extras/tests/Numbers/CMakeLists.txt
index c3d6dc0..e4ef2dd 100644
--- a/lib/ArduinoJson/extras/tests/Numbers/CMakeLists.txt
+++ b/lib/ArduinoJson/extras/tests/Numbers/CMakeLists.txt
@@ -4,8 +4,9 @@
add_executable(NumbersTests
convertNumber.cpp
- parseFloat.cpp
+ decomposeFloat.cpp
parseDouble.cpp
+ parseFloat.cpp
parseInteger.cpp
parseNumber.cpp
)
diff --git a/lib/ArduinoJson/extras/tests/Numbers/decomposeFloat.cpp b/lib/ArduinoJson/extras/tests/Numbers/decomposeFloat.cpp
new file mode 100644
index 0000000..73de571
--- /dev/null
+++ b/lib/ArduinoJson/extras/tests/Numbers/decomposeFloat.cpp
@@ -0,0 +1,42 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright © 2014-2024, Benoit BLANCHON
+// MIT License
+
+#include
+#include
+
+using namespace ArduinoJson::detail;
+
+TEST_CASE("decomposeFloat()") {
+ SECTION("1.7976931348623157E+308") {
+ auto parts = decomposeFloat(1.7976931348623157E+308, 9);
+ REQUIRE(parts.integral == 1);
+ REQUIRE(parts.decimal == 797693135);
+ REQUIRE(parts.decimalPlaces == 9);
+ REQUIRE(parts.exponent == 308);
+ }
+
+ SECTION("4.94065645841247e-324") {
+ auto parts = decomposeFloat(4.94065645841247e-324, 9);
+ REQUIRE(parts.integral == 4);
+ REQUIRE(parts.decimal == 940656458);
+ REQUIRE(parts.decimalPlaces == 9);
+ REQUIRE(parts.exponent == -324);
+ }
+
+ SECTION("3.4E+38") {
+ auto parts = decomposeFloat(3.4E+38f, 6);
+ REQUIRE(parts.integral == 3);
+ REQUIRE(parts.decimal == 4);
+ REQUIRE(parts.decimalPlaces == 1);
+ REQUIRE(parts.exponent == 38);
+ }
+
+ SECTION("1.17549435e−38") {
+ auto parts = decomposeFloat(1.17549435e-38f, 6);
+ REQUIRE(parts.integral == 1);
+ REQUIRE(parts.decimal == 175494);
+ REQUIRE(parts.decimalPlaces == 6);
+ REQUIRE(parts.exponent == -38);
+ }
+}
diff --git a/lib/ArduinoJson/extras/tests/Numbers/parseFloat.cpp b/lib/ArduinoJson/extras/tests/Numbers/parseFloat.cpp
index 4a42f44..f81428f 100644
--- a/lib/ArduinoJson/extras/tests/Numbers/parseFloat.cpp
+++ b/lib/ArduinoJson/extras/tests/Numbers/parseFloat.cpp
@@ -2,7 +2,6 @@
// Copyright © 2014-2024, Benoit BLANCHON
// MIT License
-#define ARDUINOJSON_USE_DOUBLE 0
#define ARDUINOJSON_ENABLE_NAN 1
#define ARDUINOJSON_ENABLE_INFINITY 1
@@ -13,7 +12,9 @@ using namespace ArduinoJson::detail;
void checkFloat(const char* input, float expected) {
CAPTURE(input);
- REQUIRE(parseNumber(input) == Approx(expected));
+ auto result = parseNumber(input);
+ REQUIRE(result.type() == NumberType::Float);
+ REQUIRE(result.asFloat() == Approx(expected));
}
void checkFloatNaN(const char* input) {
@@ -59,27 +60,15 @@ TEST_CASE("parseNumber()") {
SECTION("VeryLong") {
checkFloat("0.00000000000000000000000000000001", 1e-32f);
- checkFloat("100000000000000000000000000000000.0", 1e+32f);
- checkFloat(
- "100000000000000000000000000000000.00000000000000000000000000000",
- 1e+32f);
- }
- SECTION("MantissaTooLongToFit") {
- checkFloat("0.340282346638528861111111111111", 0.34028234663852886f);
- checkFloat("34028234663852886.11111111111111", 34028234663852886.0f);
- checkFloat("34028234.66385288611111111111111", 34028234.663852886f);
-
- checkFloat("-0.340282346638528861111111111111", -0.34028234663852886f);
- checkFloat("-34028234663852886.11111111111111", -34028234663852886.0f);
- checkFloat("-34028234.66385288611111111111111", -34028234.663852886f);
- }
-
- SECTION("ExponentTooBig") {
- checkFloatInf("1e39", false);
- checkFloatInf("-1e39", true);
- checkFloatInf("1e255", false);
- checkFloat("1e-255", 0.0f);
+ // The following don't work because they have many digits so parseNumber()
+ // treats them as double. But it's not an issue because JsonVariant will use
+ // a float to store them.
+ //
+ // checkFloat("100000000000000000000000000000000.0", 1e+32f);
+ // checkFloat(
+ // "100000000000000000000000000000000.00000000000000000000000000000",
+ // 1e+32f);
}
SECTION("NaN") {
@@ -94,8 +83,5 @@ TEST_CASE("parseNumber()") {
checkFloatInf("inf", false);
checkFloatInf("+inf", false);
checkFloatInf("-inf", true);
-
- checkFloatInf("1e300", false);
- checkFloatInf("-1e300", true);
}
}
diff --git a/lib/ArduinoJson/extras/tests/Numbers/parseNumber.cpp b/lib/ArduinoJson/extras/tests/Numbers/parseNumber.cpp
index ba9412f..bc5d3b3 100644
--- a/lib/ArduinoJson/extras/tests/Numbers/parseNumber.cpp
+++ b/lib/ArduinoJson/extras/tests/Numbers/parseNumber.cpp
@@ -9,45 +9,55 @@ using namespace ArduinoJson;
using namespace ArduinoJson::detail;
TEST_CASE("Test unsigned integer overflow") {
- VariantData first, second;
+ Number first, second;
// Avoids MSVC warning C4127 (conditional expression is constant)
size_t integerSize = sizeof(JsonInteger);
if (integerSize == 8) {
- parseNumber("18446744073709551615", first);
- parseNumber("18446744073709551616", second);
+ first = parseNumber("18446744073709551615");
+ second = parseNumber("18446744073709551616");
} else {
- parseNumber("4294967295", first);
- parseNumber("4294967296", second);
+ first = parseNumber("4294967295");
+ second = parseNumber("4294967296");
}
- REQUIRE(first.type() == uint8_t(VALUE_IS_UNSIGNED_INTEGER));
- REQUIRE(second.type() == uint8_t(VALUE_IS_FLOAT));
+ REQUIRE(first.type() == NumberType::UnsignedInteger);
+ REQUIRE(second.type() == NumberType::Double);
}
TEST_CASE("Test signed integer overflow") {
- VariantData first, second;
+ Number first, second;
// Avoids MSVC warning C4127 (conditional expression is constant)
size_t integerSize = sizeof(JsonInteger);
if (integerSize == 8) {
- parseNumber("-9223372036854775808", first);
- parseNumber("-9223372036854775809", second);
+ first = parseNumber("-9223372036854775808");
+ second = parseNumber("-9223372036854775809");
} else {
- parseNumber("-2147483648", first);
- parseNumber("-2147483649", second);
+ first = parseNumber("-2147483648");
+ second = parseNumber("-2147483649");
}
- REQUIRE(first.type() == uint8_t(VALUE_IS_SIGNED_INTEGER));
- REQUIRE(second.type() == uint8_t(VALUE_IS_FLOAT));
+ REQUIRE(first.type() == NumberType::SignedInteger);
+ REQUIRE(second.type() == NumberType::Double);
}
TEST_CASE("Invalid value") {
- VariantData result;
+ auto result = parseNumber("6a3");
- parseNumber("6a3", result);
-
- REQUIRE(result.type() == uint8_t(VALUE_IS_NULL));
+ REQUIRE(result.type() == NumberType::Invalid);
+}
+
+TEST_CASE("float") {
+ auto result = parseNumber("3.402823e38");
+
+ REQUIRE(result.type() == NumberType::Float);
+}
+
+TEST_CASE("double") {
+ auto result = parseNumber("1.7976931348623157e308");
+
+ REQUIRE(result.type() == NumberType::Double);
}
diff --git a/lib/ArduinoJson/extras/tests/ResourceManager/StringBuilder.cpp b/lib/ArduinoJson/extras/tests/ResourceManager/StringBuilder.cpp
index f839858..b649afe 100644
--- a/lib/ArduinoJson/extras/tests/ResourceManager/StringBuilder.cpp
+++ b/lib/ArduinoJson/extras/tests/ResourceManager/StringBuilder.cpp
@@ -3,7 +3,6 @@
// MIT License
#include
-#include
#include
#include "Allocators.hpp"
diff --git a/lib/ArduinoJson/extras/tests/ResourceManager/allocVariant.cpp b/lib/ArduinoJson/extras/tests/ResourceManager/allocVariant.cpp
index 4a3685d..3cfadf3 100644
--- a/lib/ArduinoJson/extras/tests/ResourceManager/allocVariant.cpp
+++ b/lib/ArduinoJson/extras/tests/ResourceManager/allocVariant.cpp
@@ -9,28 +9,28 @@
using namespace ArduinoJson::detail;
-TEST_CASE("ResourceManager::allocSlot()") {
+TEST_CASE("ResourceManager::allocVariant()") {
SECTION("Returns different pointer") {
ResourceManager resources;
- VariantSlot* s1 = resources.allocSlot();
- REQUIRE(s1 != 0);
- VariantSlot* s2 = resources.allocSlot();
- REQUIRE(s2 != 0);
+ auto s1 = resources.allocVariant();
+ REQUIRE(s1.ptr() != nullptr);
+ auto s2 = resources.allocVariant();
+ REQUIRE(s2.ptr() != nullptr);
- REQUIRE(s1 != s2);
+ REQUIRE(s1.ptr() != s2.ptr());
}
- SECTION("Returns the same slot after calling freeSlot()") {
+ SECTION("Returns the same slot after calling freeVariant()") {
ResourceManager resources;
- auto s1 = resources.allocSlot();
- auto s2 = resources.allocSlot();
- resources.freeSlot(s1);
- resources.freeSlot(s2);
- auto s3 = resources.allocSlot();
- auto s4 = resources.allocSlot();
- auto s5 = resources.allocSlot();
+ auto s1 = resources.allocVariant();
+ auto s2 = resources.allocVariant();
+ resources.freeVariant(s1);
+ resources.freeVariant(s2);
+ auto s3 = resources.allocVariant();
+ auto s4 = resources.allocVariant();
+ auto s5 = resources.allocVariant();
REQUIRE(s2.id() != s1.id());
REQUIRE(s3.id() == s2.id());
@@ -42,26 +42,26 @@ TEST_CASE("ResourceManager::allocSlot()") {
SECTION("Returns aligned pointers") {
ResourceManager resources;
- REQUIRE(isAligned(resources.allocSlot().operator VariantSlot*()));
- REQUIRE(isAligned(resources.allocSlot().operator VariantSlot*()));
+ REQUIRE(isAligned(resources.allocVariant().ptr()));
+ REQUIRE(isAligned(resources.allocVariant().ptr()));
}
SECTION("Returns null if pool list allocation fails") {
ResourceManager resources(FailingAllocator::instance());
- auto variant = resources.allocSlot();
+ auto variant = resources.allocVariant();
REQUIRE(variant.id() == NULL_SLOT);
- REQUIRE(static_cast(variant) == nullptr);
+ REQUIRE(variant.ptr() == nullptr);
}
SECTION("Returns null if pool allocation fails") {
ResourceManager resources(FailingAllocator::instance());
- resources.allocSlot();
+ resources.allocVariant();
- auto variant = resources.allocSlot();
+ auto variant = resources.allocVariant();
REQUIRE(variant.id() == NULL_SLOT);
- REQUIRE(static_cast(variant) == nullptr);
+ REQUIRE(variant.ptr() == nullptr);
}
SECTION("Try overflow pool counter") {
@@ -73,18 +73,18 @@ TEST_CASE("ResourceManager::allocSlot()") {
// fill all the pools
for (SlotId i = 0; i < NULL_SLOT; i++) {
- auto slot = resources.allocSlot();
+ auto slot = resources.allocVariant();
REQUIRE(slot.id() == i); // or != NULL_SLOT
- REQUIRE(static_cast(slot) != nullptr);
+ REQUIRE(slot.ptr() != nullptr);
}
REQUIRE(resources.overflowed() == false);
// now all allocations should fail
for (int i = 0; i < 10; i++) {
- auto slot = resources.allocSlot();
+ auto slot = resources.allocVariant();
REQUIRE(slot.id() == NULL_SLOT);
- REQUIRE(static_cast(slot) == nullptr);
+ REQUIRE(slot.ptr() == nullptr);
}
REQUIRE(resources.overflowed() == true);
diff --git a/lib/ArduinoJson/extras/tests/ResourceManager/clear.cpp b/lib/ArduinoJson/extras/tests/ResourceManager/clear.cpp
index 30afd90..a773603 100644
--- a/lib/ArduinoJson/extras/tests/ResourceManager/clear.cpp
+++ b/lib/ArduinoJson/extras/tests/ResourceManager/clear.cpp
@@ -3,7 +3,7 @@
// MIT License
#include
-#include
+#include
#include
#include
@@ -13,7 +13,7 @@ TEST_CASE("ResourceManager::clear()") {
ResourceManager resources;
SECTION("Discards allocated variants") {
- resources.allocSlot();
+ resources.allocVariant();
resources.clear();
REQUIRE(resources.size() == 0);
diff --git a/lib/ArduinoJson/extras/tests/ResourceManager/saveString.cpp b/lib/ArduinoJson/extras/tests/ResourceManager/saveString.cpp
index f19ac19..88c242f 100644
--- a/lib/ArduinoJson/extras/tests/ResourceManager/saveString.cpp
+++ b/lib/ArduinoJson/extras/tests/ResourceManager/saveString.cpp
@@ -3,7 +3,6 @@
// MIT License
#include
-#include
#include
#include
diff --git a/lib/ArduinoJson/extras/tests/ResourceManager/shrinkToFit.cpp b/lib/ArduinoJson/extras/tests/ResourceManager/shrinkToFit.cpp
index 7419770..d35ee34 100644
--- a/lib/ArduinoJson/extras/tests/ResourceManager/shrinkToFit.cpp
+++ b/lib/ArduinoJson/extras/tests/ResourceManager/shrinkToFit.cpp
@@ -3,7 +3,7 @@
// MIT License
#include
-#include
+#include
#include
#include "Allocators.hpp"
@@ -21,14 +21,14 @@ TEST_CASE("ResourceManager::shrinkToFit()") {
}
SECTION("only one pool") {
- resources.allocSlot();
+ resources.allocVariant();
resources.shrinkToFit();
REQUIRE(spyingAllocator.log() ==
AllocatorLog{
Allocate(sizeofPool()),
- Reallocate(sizeofPool(), sizeof(VariantSlot)),
+ Reallocate(sizeofPool(), sizeofPool(1)),
});
}
@@ -36,7 +36,7 @@ TEST_CASE("ResourceManager::shrinkToFit()") {
for (size_t i = 0;
i < ARDUINOJSON_POOL_CAPACITY * ARDUINOJSON_INITIAL_POOL_COUNT + 1;
i++)
- resources.allocSlot();
+ resources.allocVariant();
REQUIRE(spyingAllocator.log() ==
AllocatorLog{
Allocate(sizeofPool()) * ARDUINOJSON_INITIAL_POOL_COUNT,
@@ -49,7 +49,7 @@ TEST_CASE("ResourceManager::shrinkToFit()") {
REQUIRE(spyingAllocator.log() ==
AllocatorLog{
- Reallocate(sizeofPool(), sizeof(VariantSlot)),
+ Reallocate(sizeofPool(), sizeofPool(1)),
Reallocate(sizeofPoolList(ARDUINOJSON_INITIAL_POOL_COUNT * 2),
sizeofPoolList(ARDUINOJSON_INITIAL_POOL_COUNT + 1)),
});
diff --git a/lib/ArduinoJson/extras/tests/ResourceManager/size.cpp b/lib/ArduinoJson/extras/tests/ResourceManager/size.cpp
index 6b09b17..8d4b799 100644
--- a/lib/ArduinoJson/extras/tests/ResourceManager/size.cpp
+++ b/lib/ArduinoJson/extras/tests/ResourceManager/size.cpp
@@ -3,7 +3,7 @@
// MIT License
#include
-#include
+#include
#include
#include "Allocators.hpp"
@@ -21,10 +21,10 @@ TEST_CASE("ResourceManager::size()") {
SECTION("Doesn't grow when allocation of second pool fails") {
timebomb.setCountdown(1);
for (size_t i = 0; i < ARDUINOJSON_POOL_CAPACITY; i++)
- resources.allocSlot();
+ resources.allocVariant();
size_t size = resources.size();
- resources.allocSlot();
+ resources.allocVariant();
REQUIRE(size == resources.size());
}
diff --git a/lib/ArduinoJson/extras/tests/ResourceManager/swap.cpp b/lib/ArduinoJson/extras/tests/ResourceManager/swap.cpp
index 4fdb45c..a2b1fe9 100644
--- a/lib/ArduinoJson/extras/tests/ResourceManager/swap.cpp
+++ b/lib/ArduinoJson/extras/tests/ResourceManager/swap.cpp
@@ -4,7 +4,7 @@
#include
#include
-#include
+#include
#include
#include "Allocators.hpp"
@@ -14,7 +14,7 @@ using namespace ArduinoJson::detail;
static void fullPreallocatedPools(ResourceManager& resources) {
for (int i = 0;
i < ARDUINOJSON_INITIAL_POOL_COUNT * ARDUINOJSON_POOL_CAPACITY; i++)
- resources.allocSlot();
+ resources.allocVariant();
}
TEST_CASE("ResourceManager::swap()") {
@@ -23,13 +23,13 @@ TEST_CASE("ResourceManager::swap()") {
ResourceManager a(&spy);
ResourceManager b(&spy);
- auto a1 = a.allocSlot();
- auto b1 = b.allocSlot();
+ auto a1 = a.allocVariant();
+ auto b1 = b.allocVariant();
swap(a, b);
- REQUIRE(a1->data() == b.getSlot(a1.id())->data());
- REQUIRE(b1->data() == a.getSlot(b1.id())->data());
+ REQUIRE(a1.ptr() == b.getVariant(a1.id()));
+ REQUIRE(b1.ptr() == a.getVariant(b1.id()));
REQUIRE(spy.log() == AllocatorLog{
Allocate(sizeofPool()) * 2,
@@ -42,12 +42,12 @@ TEST_CASE("ResourceManager::swap()") {
ResourceManager b(&spy);
fullPreallocatedPools(b);
- auto a1 = a.allocSlot();
- auto b1 = b.allocSlot();
+ auto a1 = a.allocVariant();
+ auto b1 = b.allocVariant();
swap(a, b);
- REQUIRE(a1->data() == b.getSlot(a1.id())->data());
- REQUIRE(b1->data() == a.getSlot(b1.id())->data());
+ REQUIRE(a1.ptr() == b.getVariant(a1.id()));
+ REQUIRE(b1.ptr() == a.getVariant(b1.id()));
REQUIRE(spy.log() ==
AllocatorLog{
@@ -63,12 +63,12 @@ TEST_CASE("ResourceManager::swap()") {
fullPreallocatedPools(a);
ResourceManager b(&spy);
- auto a1 = a.allocSlot();
- auto b1 = b.allocSlot();
+ auto a1 = a.allocVariant();
+ auto b1 = b.allocVariant();
swap(a, b);
- REQUIRE(a1->data() == b.getSlot(a1.id())->data());
- REQUIRE(b1->data() == a.getSlot(b1.id())->data());
+ REQUIRE(a1.ptr() == b.getVariant(a1.id()));
+ REQUIRE(b1.ptr() == a.getVariant(b1.id()));
REQUIRE(spy.log() ==
AllocatorLog{
@@ -85,12 +85,12 @@ TEST_CASE("ResourceManager::swap()") {
ResourceManager b(&spy);
fullPreallocatedPools(b);
- auto a1 = a.allocSlot();
- auto b1 = b.allocSlot();
+ auto a1 = a.allocVariant();
+ auto b1 = b.allocVariant();
swap(a, b);
- REQUIRE(a1->data() == b.getSlot(a1.id())->data());
- REQUIRE(b1->data() == a.getSlot(b1.id())->data());
+ REQUIRE(a1.ptr() == b.getVariant(a1.id()));
+ REQUIRE(b1.ptr() == a.getVariant(b1.id()));
}
}
diff --git a/lib/ArduinoJson/idf_component.yml b/lib/ArduinoJson/idf_component.yml
index 2f504e4..bdf8d36 100644
--- a/lib/ArduinoJson/idf_component.yml
+++ b/lib/ArduinoJson/idf_component.yml
@@ -1,7 +1,7 @@
-version: "7.1.0"
+version: "7.2.0"
description: >-
A simple and efficient JSON library for embedded C++.
- ⭐ 6624 stars on GitHub!
+ ⭐ 6690 stars on GitHub!
Supports serialization, deserialization, MessagePack, streams, filtering, and more.
Fully tested and documented.
url: https://arduinojson.org/
diff --git a/lib/ArduinoJson/library.json b/lib/ArduinoJson/library.json
index e1c712a..30da9fc 100644
--- a/lib/ArduinoJson/library.json
+++ b/lib/ArduinoJson/library.json
@@ -1,13 +1,13 @@
{
"name": "ArduinoJson",
"keywords": "json, rest, http, web",
- "description": "A simple and efficient JSON library for embedded C++. ⭐ 6624 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.",
+ "description": "A simple and efficient JSON library for embedded C++. ⭐ 6690 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.",
"homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json",
"repository": {
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
- "version": "7.1.0",
+ "version": "7.2.0",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"
diff --git a/lib/ArduinoJson/library.properties b/lib/ArduinoJson/library.properties
index 9a59308..86866c0 100644
--- a/lib/ArduinoJson/library.properties
+++ b/lib/ArduinoJson/library.properties
@@ -1,9 +1,9 @@
name=ArduinoJson
-version=7.1.0
+version=7.2.0
author=Benoit Blanchon
maintainer=Benoit Blanchon
sentence=A simple and efficient JSON library for embedded C++.
-paragraph=⭐ 6624 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.
+paragraph=⭐ 6690 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.
category=Data Processing
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
architectures=*
diff --git a/lib/ArduinoJson/src/ArduinoJson.hpp b/lib/ArduinoJson/src/ArduinoJson.hpp
index 085507a..a14f2b1 100644
--- a/lib/ArduinoJson/src/ArduinoJson.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson.hpp
@@ -37,12 +37,12 @@
#include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Memory/ResourceManagerImpl.hpp"
-#include "ArduinoJson/Memory/VariantPoolImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Variant/ConverterImpl.hpp"
#include "ArduinoJson/Variant/JsonVariantCopier.hpp"
#include "ArduinoJson/Variant/VariantCompare.hpp"
+#include "ArduinoJson/Variant/VariantImpl.hpp"
#include "ArduinoJson/Variant/VariantRefBaseImpl.hpp"
#include "ArduinoJson/Json/JsonDeserializer.hpp"
diff --git a/lib/ArduinoJson/src/ArduinoJson/Array/ArrayData.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayData.hpp
index 7e15ab1..c2ae1fb 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Array/ArrayData.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayData.hpp
@@ -10,9 +10,7 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class ArrayData : public CollectionData {
public:
- VariantData* addElement(ResourceManager* resources) {
- return addSlot(resources).data();
- }
+ VariantData* addElement(ResourceManager* resources);
static VariantData* addElement(ArrayData* array, ResourceManager* resources) {
if (!array)
@@ -51,14 +49,14 @@ class ArrayData : public CollectionData {
array->removeElement(index, resources);
}
- bool copyFrom(const ArrayData& src, ResourceManager* resources);
+ void remove(iterator it, ResourceManager* resources) {
+ CollectionData::removeOne(it, resources);
+ }
- static bool copy(ArrayData* dst, const ArrayData* src,
- ResourceManager* resources) {
- if (!dst || !src)
- return false;
-
- return dst->copyFrom(*src, resources);
+ static void remove(ArrayData* array, iterator it,
+ ResourceManager* resources) {
+ if (array)
+ return array->remove(it, resources);
}
private:
diff --git a/lib/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp
index 9b96138..9599a5e 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Array/ArrayImpl.hpp
@@ -6,6 +6,7 @@
#include
#include
+#include
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
@@ -19,6 +20,14 @@ inline ArrayData::iterator ArrayData::at(
return it;
}
+inline VariantData* ArrayData::addElement(ResourceManager* resources) {
+ auto slot = resources->allocVariant();
+ if (!slot)
+ return nullptr;
+ CollectionData::appendOne(slot, resources);
+ return slot.ptr();
+}
+
inline VariantData* ArrayData::getOrAddElement(size_t index,
ResourceManager* resources) {
auto it = createIterator(resources);
@@ -50,16 +59,21 @@ inline void ArrayData::removeElement(size_t index, ResourceManager* resources) {
template
inline bool ArrayData::addValue(T&& value, ResourceManager* resources) {
ARDUINOJSON_ASSERT(resources != nullptr);
- auto slot = resources->allocSlot();
+ auto slot = resources->allocVariant();
if (!slot)
return false;
- JsonVariant variant(slot->data(), resources);
+ JsonVariant variant(slot.ptr(), resources);
if (!variant.set(detail::forward(value))) {
- resources->freeSlot(slot);
+ resources->freeVariant(slot);
return false;
}
- addSlot(slot, resources);
+ CollectionData::appendOne(slot, resources);
return true;
}
+// Returns the size (in bytes) of an array with n elements.
+constexpr size_t sizeofArray(size_t n) {
+ return n * ResourceManager::slotSize;
+}
+
ARDUINOJSON_END_PRIVATE_NAMESPACE
diff --git a/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp b/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp
index 07e6982..5817c7a 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionData.hpp
@@ -4,6 +4,7 @@
#pragma once
+#include
#include
#include
@@ -12,7 +13,7 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
class VariantData;
-class VariantSlot;
+class ResourceManager;
class CollectionIterator {
friend class CollectionData;
@@ -49,12 +50,6 @@ class CollectionIterator {
return *data();
}
- const char* key() const;
- bool ownsKey() const;
-
- void setKey(StringNode*);
- void setKey(const char*);
-
VariantData* data() {
return reinterpret_cast(slot_);
}
@@ -64,9 +59,9 @@ class CollectionIterator {
}
private:
- CollectionIterator(VariantSlot* slot, SlotId slotId);
+ CollectionIterator(VariantData* slot, SlotId slotId);
- VariantSlot* slot_;
+ VariantData* slot_;
SlotId currentId_, nextId_;
};
@@ -84,9 +79,7 @@ class CollectionData {
using iterator = CollectionIterator;
- iterator createIterator(const ResourceManager* resources) const {
- return iterator(resources->getSlot(head_), head_);
- }
+ iterator createIterator(const ResourceManager* resources) const;
size_t size(const ResourceManager*) const;
size_t nesting(const ResourceManager*) const;
@@ -99,25 +92,20 @@ class CollectionData {
collection->clear(resources);
}
- void remove(iterator it, ResourceManager* resources);
-
- static void remove(CollectionData* collection, iterator it,
- ResourceManager* resources) {
- if (collection)
- return collection->remove(it, resources);
- }
-
SlotId head() const {
return head_;
}
- void addSlot(SlotWithId slot, ResourceManager* resources);
-
protected:
- iterator addSlot(ResourceManager*);
+ void appendOne(Slot slot, const ResourceManager* resources);
+ void appendPair(Slot key, Slot value,
+ const ResourceManager* resources);
+
+ void removeOne(iterator it, ResourceManager* resources);
+ void removePair(iterator it, ResourceManager* resources);
private:
- SlotWithId getPreviousSlot(VariantSlot*, const ResourceManager*) const;
+ Slot getPreviousSlot(VariantData*, const ResourceManager*) const;
};
inline const VariantData* collectionToVariant(
diff --git a/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp b/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp
index c7e23a3..c0a650c 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Collection/CollectionImpl.hpp
@@ -12,66 +12,48 @@
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
-inline CollectionIterator::CollectionIterator(VariantSlot* slot, SlotId slotId)
+inline CollectionIterator::CollectionIterator(VariantData* slot, SlotId slotId)
: slot_(slot), currentId_(slotId) {
nextId_ = slot_ ? slot_->next() : NULL_SLOT;
}
-inline const char* CollectionIterator::key() const {
- ARDUINOJSON_ASSERT(slot_ != nullptr);
- return slot_->key();
-}
-
-inline void CollectionIterator::setKey(const char* s) {
- ARDUINOJSON_ASSERT(slot_ != nullptr);
- ARDUINOJSON_ASSERT(s != nullptr);
- return slot_->setKey(s);
-}
-
-inline void CollectionIterator::setKey(StringNode* s) {
- ARDUINOJSON_ASSERT(slot_ != nullptr);
- ARDUINOJSON_ASSERT(s != nullptr);
- return slot_->setKey(s);
-}
-
-inline bool CollectionIterator::ownsKey() const {
- ARDUINOJSON_ASSERT(slot_ != nullptr);
- return slot_->ownsKey();
-}
-
inline void CollectionIterator::next(const ResourceManager* resources) {
ARDUINOJSON_ASSERT(currentId_ != NULL_SLOT);
- slot_ = resources->getSlot(nextId_);
+ slot_ = resources->getVariant(nextId_);
currentId_ = nextId_;
if (slot_)
nextId_ = slot_->next();
}
-inline CollectionData::iterator CollectionData::addSlot(
- ResourceManager* resources) {
- auto slot = resources->allocSlot();
- if (!slot)
- return {};
+inline CollectionData::iterator CollectionData::createIterator(
+ const ResourceManager* resources) const {
+ return iterator(resources->getVariant(head_), head_);
+}
+
+inline void CollectionData::appendOne(Slot slot,
+ const ResourceManager* resources) {
if (tail_ != NULL_SLOT) {
- auto tail = resources->getSlot(tail_);
+ auto tail = resources->getVariant(tail_);
tail->setNext(slot.id());
tail_ = slot.id();
} else {
head_ = slot.id();
tail_ = slot.id();
}
- return iterator(slot, slot.id());
}
-inline void CollectionData::addSlot(SlotWithId slot,
- ResourceManager* resources) {
+inline void CollectionData::appendPair(Slot key,
+ Slot value,
+ const ResourceManager* resources) {
+ key->setNext(value.id());
+
if (tail_ != NULL_SLOT) {
- auto tail = resources->getSlot(tail_);
- tail->setNext(slot.id());
- tail_ = slot.id();
+ auto tail = resources->getVariant(tail_);
+ tail->setNext(key.id());
+ tail_ = value.id();
} else {
- head_ = slot.id();
- tail_ = slot.id();
+ head_ = key.id();
+ tail_ = value.id();
}
}
@@ -79,30 +61,30 @@ inline void CollectionData::clear(ResourceManager* resources) {
auto next = head_;
while (next != NULL_SLOT) {
auto currId = next;
- auto slot = resources->getSlot(next);
+ auto slot = resources->getVariant(next);
next = slot->next();
- resources->freeSlot(SlotWithId(slot, currId));
+ resources->freeVariant({slot, currId});
}
head_ = NULL_SLOT;
tail_ = NULL_SLOT;
}
-inline SlotWithId CollectionData::getPreviousSlot(
- VariantSlot* target, const ResourceManager* resources) const {
- auto prev = SlotWithId();
+inline Slot CollectionData::getPreviousSlot(
+ VariantData* target, const ResourceManager* resources) const {
+ auto prev = Slot();
auto currentId = head_;
while (currentId != NULL_SLOT) {
- auto currentSlot = resources->getSlot(currentId);
+ auto currentSlot = resources->getVariant(currentId);
if (currentSlot == target)
- return prev;
- prev = SlotWithId(currentSlot, currentId);
+ break;
+ prev = Slot(currentSlot, currentId);
currentId = currentSlot->next();
}
- return SlotWithId();
+ return prev;
}
-inline void CollectionData::remove(iterator it, ResourceManager* resources) {
+inline void CollectionData::removeOne(iterator it, ResourceManager* resources) {
if (it.done())
return;
auto curr = it.slot_;
@@ -114,7 +96,25 @@ inline void CollectionData::remove(iterator it, ResourceManager* resources) {
head_ = next;
if (next == NULL_SLOT)
tail_ = prev.id();
- resources->freeSlot({it.slot_, it.currentId_});
+ resources->freeVariant({it.slot_, it.currentId_});
+}
+
+inline void CollectionData::removePair(ObjectData::iterator it,
+ ResourceManager* resources) {
+ if (it.done())
+ return;
+
+ auto keySlot = it.slot_;
+
+ auto valueId = it.nextId_;
+ auto valueSlot = resources->getVariant(valueId);
+
+ // remove value slot
+ keySlot->setNext(valueSlot->next());
+ resources->freeVariant({valueSlot, valueId});
+
+ // remove key slot
+ removeOne(it, resources);
}
inline size_t CollectionData::nesting(const ResourceManager* resources) const {
diff --git a/lib/ArduinoJson/src/ArduinoJson/Configuration.hpp b/lib/ArduinoJson/src/ArduinoJson/Configuration.hpp
index ae60890..cf6fb38 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Configuration.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Configuration.hpp
@@ -56,12 +56,6 @@
# endif
#endif
-// Store floating-point values with float (0) or double (1)
-// https://arduinojson.org/v7/config/use_double/
-#ifndef ARDUINOJSON_USE_DOUBLE
-# define ARDUINOJSON_USE_DOUBLE 1
-#endif
-
// Pointer size: a heuristic to set sensible defaults
#ifndef ARDUINOJSON_SIZEOF_POINTER
# if defined(__SIZEOF_POINTER__)
@@ -73,6 +67,16 @@
# endif
#endif
+// Store floating-point values with float (0) or double (1)
+// https://arduinojson.org/v7/config/use_double/
+#ifndef ARDUINOJSON_USE_DOUBLE
+# if ARDUINOJSON_SIZEOF_POINTER >= 4 // 32 & 64 bits systems
+# define ARDUINOJSON_USE_DOUBLE 1
+# else
+# define ARDUINOJSON_USE_DOUBLE 0
+# endif
+#endif
+
// Store integral values with long (0) or long long (1)
// https://arduinojson.org/v7/config/use_long_long/
#ifndef ARDUINOJSON_USE_LONG_LONG
@@ -106,12 +110,12 @@
// Capacity of each variant pool (in slots)
#ifndef ARDUINOJSON_POOL_CAPACITY
-# if ARDUINOJSON_SIZEOF_POINTER <= 2
-# define ARDUINOJSON_POOL_CAPACITY 16 // 128 bytes
-# elif ARDUINOJSON_SIZEOF_POINTER == 4
-# define ARDUINOJSON_POOL_CAPACITY 64 // 1024 bytes
+# if ARDUINOJSON_SLOT_ID_SIZE == 1
+# define ARDUINOJSON_POOL_CAPACITY 16 // 96 bytes
+# elif ARDUINOJSON_SLOT_ID_SIZE == 2
+# define ARDUINOJSON_POOL_CAPACITY 128 // 1024 bytes
# else
-# define ARDUINOJSON_POOL_CAPACITY 128 // 3072 bytes
+# define ARDUINOJSON_POOL_CAPACITY 256 // 4096 bytes
# endif
#endif
@@ -269,6 +273,12 @@
# endif
#endif
+#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_DOUBLE
+# define ARDUINOJSON_USE_EXTENSIONS 1
+#else
+# define ARDUINOJSON_USE_EXTENSIONS 0
+#endif
+
#if defined(nullptr)
# error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
// See https://github.com/bblanchon/ArduinoJson/issues/1355
diff --git a/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp b/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp
index acad2b2..5ba62f4 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp
@@ -150,24 +150,27 @@ class JsonDocument : public detail::VariantOperators {
return getVariant().template to();
}
- // Returns true if the root object contains the specified key.
+ // DEPRECATED: use obj["key"].is() instead
// https://arduinojson.org/v7/api/jsondocument/containskey/
template
+ ARDUINOJSON_DEPRECATED("use doc[\"key\"].is() instead")
bool containsKey(TChar* key) const {
return data_.getMember(detail::adaptString(key), &resources_) != 0;
}
- // Returns true if the root object contains the specified key.
+ // DEPRECATED: use obj[key].is() instead
// https://arduinojson.org/v7/api/jsondocument/containskey/
template
+ ARDUINOJSON_DEPRECATED("use doc[key].is() instead")
detail::enable_if_t::value, bool> containsKey(
const TString& key) const {
return data_.getMember(detail::adaptString(key), &resources_) != 0;
}
- // Returns true if the root object contains the specified key.
+ // DEPRECATED: use obj[key].is() instead
// https://arduinojson.org/v7/api/jsondocument/containskey/
template
+ ARDUINOJSON_DEPRECATED("use doc[key].is() instead")
detail::enable_if_t::value, bool> containsKey(
const TVariant& key) const {
return containsKey(key.template as());
diff --git a/lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp
index e1b7199..35a99d6 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Json/EscapeSequence.hpp
@@ -32,8 +32,8 @@ class EscapeSequence {
}
private:
- static const char* escapeTable(bool excludeSolidus) {
- return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
+ static const char* escapeTable(bool isSerializing) {
+ return &"//''\"\"\\\\b\bf\fn\nr\rt\t"[isSerializing ? 4 : 0];
}
};
diff --git a/lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp
index 33de891..459f78a 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Json/JsonDeserializer.hpp
@@ -283,7 +283,7 @@ class JsonDeserializer {
if (!member)
return DeserializationError::NoMemory;
} else {
- member->setNull(resources_);
+ member->clear(resources_);
}
// Parse value
@@ -517,10 +517,37 @@ class JsonDeserializer {
}
buffer_[n] = 0;
- if (!parseNumber(buffer_, result))
- return DeserializationError::InvalidInput;
+ auto number = parseNumber(buffer_);
+ switch (number.type()) {
+ case NumberType::UnsignedInteger:
+ if (result.setInteger(number.asUnsignedInteger(), resources_))
+ return DeserializationError::Ok;
+ else
+ return DeserializationError::NoMemory;
- return DeserializationError::Ok;
+ case NumberType::SignedInteger:
+ if (result.setInteger(number.asSignedInteger(), resources_))
+ return DeserializationError::Ok;
+ else
+ return DeserializationError::NoMemory;
+
+ case NumberType::Float:
+ if (result.setFloat(number.asFloat(), resources_))
+ return DeserializationError::Ok;
+ else
+ return DeserializationError::NoMemory;
+
+#if ARDUINOJSON_USE_DOUBLE
+ case NumberType::Double:
+ if (result.setFloat(number.asDouble(), resources_))
+ return DeserializationError::Ok;
+ else
+ return DeserializationError::NoMemory;
+#endif
+
+ default:
+ return DeserializationError::InvalidInput;
+ }
}
DeserializationError::Code skipNumericValue() {
diff --git a/lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp
index 189ae33..f9cfa59 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Json/JsonSerializer.hpp
@@ -25,9 +25,9 @@ class JsonSerializer : public VariantDataVisitor {
auto slotId = array.head();
while (slotId != NULL_SLOT) {
- auto slot = resources_->getSlot(slotId);
+ auto slot = resources_->getVariant(slotId);
- slot->data()->accept(*this);
+ slot->accept(*this, resources_);
slotId = slot->next();
@@ -44,24 +44,26 @@ class JsonSerializer : public VariantDataVisitor {
auto slotId = object.head();
- while (slotId != NULL_SLOT) {
- auto slot = resources_->getSlot(slotId);
+ bool isKey = true;
- formatter_.writeString(slot->key());
- write(':');
- slot->data()->accept(*this);
+ while (slotId != NULL_SLOT) {
+ auto slot = resources_->getVariant(slotId);
+ slot->accept(*this, resources_);
slotId = slot->next();
if (slotId != NULL_SLOT)
- write(',');
+ write(isKey ? ':' : ',');
+
+ isKey = !isKey;
}
write('}');
return bytesWritten();
}
- size_t visit(JsonFloat value) {
+ template
+ enable_if_t::value, size_t> visit(T value) {
formatter_.writeFloat(value);
return bytesWritten();
}
@@ -128,7 +130,8 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces a minified JSON document.
// https://arduinojson.org/v7/api/json/serializejson/
template
-size_t serializeJson(JsonVariantConst source, TDestination& destination) {
+detail::enable_if_t::value, size_t>
+serializeJson(JsonVariantConst source, TDestination& destination) {
using namespace detail;
return serialize(source, destination);
}
diff --git a/lib/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp
index ab049ad..9ae0367 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Json/PrettyJsonSerializer.hpp
@@ -26,7 +26,7 @@ class PrettyJsonSerializer : public JsonSerializer {
nesting_++;
while (!it.done()) {
indent();
- it->accept(*this);
+ it->accept(*this, base::resources_);
it.next(base::resources_);
base::write(it.done() ? "\r\n" : ",\r\n");
@@ -45,14 +45,17 @@ class PrettyJsonSerializer : public JsonSerializer {
if (!it.done()) {
base::write("{\r\n");
nesting_++;
+ bool isKey = true;
while (!it.done()) {
- indent();
- base::visit(it.key());
- base::write(": ");
- it->accept(*this);
-
+ if (isKey)
+ indent();
+ it->accept(*this, base::resources_);
it.next(base::resources_);
- base::write(it.done() ? "\r\n" : ",\r\n");
+ if (isKey)
+ base::write(": ");
+ else
+ base::write(it.done() ? "\r\n" : ",\r\n");
+ isKey = !isKey;
}
nesting_--;
indent();
@@ -81,7 +84,8 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
// Produces JsonDocument to create a prettified JSON document.
// https://arduinojson.org/v7/api/json/serializejsonpretty/
template
-size_t serializeJsonPretty(JsonVariantConst source, TDestination& destination) {
+detail::enable_if_t::value, size_t>
+serializeJsonPretty(JsonVariantConst source, TDestination& destination) {
using namespace ArduinoJson::detail;
return serialize(source, destination);
}
diff --git a/lib/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp b/lib/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp
index 5b13222..5b94b5e 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Json/TextFormatter.hpp
@@ -66,6 +66,10 @@ class TextFormatter {
template
void writeFloat(T value) {
+ writeFloat(JsonFloat(value), sizeof(T) >= 8 ? 9 : 6);
+ }
+
+ void writeFloat(JsonFloat value, int8_t decimalPlaces) {
if (isnan(value))
return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
@@ -87,7 +91,7 @@ class TextFormatter {
}
#endif
- FloatParts parts(value);
+ auto parts = decomposeFloat(value, decimalPlaces);
writeInteger(parts.integral);
if (parts.decimalPlaces)
diff --git a/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp b/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp
new file mode 100644
index 0000000..baa988f
--- /dev/null
+++ b/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPool.hpp
@@ -0,0 +1,110 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright © 2014-2024, Benoit BLANCHON
+// MIT License
+
+#pragma once
+
+#include
+#include
+#include
+
+ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
+
+using SlotId = uint_t;
+using SlotCount = SlotId;
+const SlotId NULL_SLOT = SlotId(-1);
+
+template
+class Slot {
+ public:
+ Slot() : ptr_(nullptr), id_(NULL_SLOT) {}
+ Slot(T* p, SlotId id) : ptr_(p), id_(id) {
+ ARDUINOJSON_ASSERT((p == nullptr) == (id == NULL_SLOT));
+ }
+
+ explicit operator bool() const {
+ return ptr_ != nullptr;
+ }
+
+ SlotId id() const {
+ return id_;
+ }
+
+ T* ptr() const {
+ return ptr_;
+ }
+
+ T* operator->() const {
+ ARDUINOJSON_ASSERT(ptr_ != nullptr);
+ return ptr_;
+ }
+
+ private:
+ T* ptr_;
+ SlotId id_;
+};
+
+template
+class MemoryPool {
+ public:
+ void create(SlotCount cap, Allocator* allocator) {
+ ARDUINOJSON_ASSERT(cap > 0);
+ slots_ = reinterpret_cast(allocator->allocate(slotsToBytes(cap)));
+ capacity_ = slots_ ? cap : 0;
+ usage_ = 0;
+ }
+
+ void destroy(Allocator* allocator) {
+ if (slots_)
+ allocator->deallocate(slots_);
+ slots_ = nullptr;
+ capacity_ = 0;
+ usage_ = 0;
+ }
+
+ Slot allocSlot() {
+ if (!slots_)
+ return {};
+ if (usage_ >= capacity_)
+ return {};
+ auto index = usage_++;
+ return {slots_ + index, SlotId(index)};
+ }
+
+ T* getSlot(SlotId id) const {
+ ARDUINOJSON_ASSERT(id < usage_);
+ return slots_ + id;
+ }
+
+ void clear() {
+ usage_ = 0;
+ }
+
+ void shrinkToFit(Allocator* allocator) {
+ auto newSlots = reinterpret_cast(
+ allocator->reallocate(slots_, slotsToBytes(usage_)));
+ if (newSlots) {
+ slots_ = newSlots;
+ capacity_ = usage_;
+ }
+ }
+
+ SlotCount usage() const {
+ return usage_;
+ }
+
+ static SlotCount bytesToSlots(size_t n) {
+ return static_cast(n / sizeof(T));
+ }
+
+ static size_t slotsToBytes(SlotCount n) {
+ return n * sizeof(T);
+ }
+
+ private:
+ SlotCount capacity_;
+ SlotCount usage_;
+ T* slots_;
+};
+
+ARDUINOJSON_END_PRIVATE_NAMESPACE
diff --git a/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPoolList.hpp b/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPoolList.hpp
new file mode 100644
index 0000000..dc6503c
--- /dev/null
+++ b/lib/ArduinoJson/src/ArduinoJson/Memory/MemoryPoolList.hpp
@@ -0,0 +1,214 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright © 2014-2024, Benoit BLANCHON
+// MIT License
+
+#pragma once
+
+#include
+#include
+#include
+
+#include // memcpy
+
+ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
+
+using PoolCount = SlotId;
+
+template
+class MemoryPoolList {
+ struct FreeSlot {
+ SlotId next;
+ };
+
+ static_assert(sizeof(FreeSlot) <= sizeof(T), "T is too small");
+
+ public:
+ using Pool = MemoryPool;
+
+ MemoryPoolList() = default;
+
+ ~MemoryPoolList() {
+ ARDUINOJSON_ASSERT(count_ == 0);
+ }
+
+ friend void swap(MemoryPoolList& a, MemoryPoolList& b) {
+ bool aUsedPreallocated = a.pools_ == a.preallocatedPools_;
+ bool bUsedPreallocated = b.pools_ == b.preallocatedPools_;
+
+ // Who is using preallocated pools?
+ if (aUsedPreallocated && bUsedPreallocated) {
+ // both of us => swap preallocated pools
+ for (PoolCount i = 0; i < ARDUINOJSON_INITIAL_POOL_COUNT; i++)
+ swap_(a.preallocatedPools_[i], b.preallocatedPools_[i]);
+ } else if (bUsedPreallocated) {
+ // only b => copy b's preallocated pools and give him a's pointer
+ for (PoolCount i = 0; i < b.count_; i++)
+ a.preallocatedPools_[i] = b.preallocatedPools_[i];
+ b.pools_ = a.pools_;
+ a.pools_ = a.preallocatedPools_;
+ } else if (aUsedPreallocated) {
+ // only a => copy a's preallocated pools and give him b's pointer
+ for (PoolCount i = 0; i < a.count_; i++)
+ b.preallocatedPools_[i] = a.preallocatedPools_[i];
+ a.pools_ = b.pools_;
+ b.pools_ = b.preallocatedPools_;
+ } else {
+ // neither => swap pointers
+ swap_(a.pools_, b.pools_);
+ }
+
+ swap_(a.count_, b.count_);
+ swap_(a.capacity_, b.capacity_);
+ swap_(a.freeList_, b.freeList_);
+ }
+
+ MemoryPoolList& operator=(MemoryPoolList&& src) {
+ ARDUINOJSON_ASSERT(count_ == 0);
+ if (src.pools_ == src.preallocatedPools_) {
+ memcpy(preallocatedPools_, src.preallocatedPools_,
+ sizeof(preallocatedPools_));
+ pools_ = preallocatedPools_;
+ } else {
+ pools_ = src.pools_;
+ src.pools_ = nullptr;
+ }
+ count_ = src.count_;
+ capacity_ = src.capacity_;
+ src.count_ = 0;
+ src.capacity_ = 0;
+ return *this;
+ }
+
+ Slot allocSlot(Allocator* allocator) {
+ // try to allocate from free list
+ if (freeList_ != NULL_SLOT) {
+ return allocFromFreeList();
+ }
+
+ // try to allocate from last pool (other pools are full)
+ if (count_) {
+ auto slot = allocFromLastPool();
+ if (slot)
+ return slot;
+ }
+
+ // create a new pool and try again
+ auto pool = addPool(allocator);
+ if (!pool)
+ return {};
+
+ return allocFromLastPool();
+ }
+
+ void freeSlot(Slot slot) {
+ reinterpret_cast(slot.ptr())->next = freeList_;
+ freeList_ = slot.id();
+ }
+
+ T* getSlot(SlotId id) const {
+ if (id == NULL_SLOT)
+ return nullptr;
+ auto poolIndex = SlotId(id / ARDUINOJSON_POOL_CAPACITY);
+ auto indexInPool = SlotId(id % ARDUINOJSON_POOL_CAPACITY);
+ ARDUINOJSON_ASSERT(poolIndex < count_);
+ return pools_[poolIndex].getSlot(indexInPool);
+ }
+
+ void clear(Allocator* allocator) {
+ for (PoolCount i = 0; i < count_; i++)
+ pools_[i].destroy(allocator);
+ count_ = 0;
+ freeList_ = NULL_SLOT;
+ if (pools_ != preallocatedPools_) {
+ allocator->deallocate(pools_);
+ pools_ = preallocatedPools_;
+ capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
+ }
+ }
+
+ SlotCount usage() const {
+ SlotCount total = 0;
+ for (PoolCount i = 0; i < count_; i++)
+ total = SlotCount(total + pools_[i].usage());
+ return total;
+ }
+
+ size_t size() const {
+ return Pool::slotsToBytes(usage());
+ }
+
+ void shrinkToFit(Allocator* allocator) {
+ if (count_ > 0)
+ pools_[count_ - 1].shrinkToFit(allocator);
+ if (pools_ != preallocatedPools_ && count_ != capacity_) {
+ pools_ = static_cast(
+ allocator->reallocate(pools_, count_ * sizeof(Pool)));
+ ARDUINOJSON_ASSERT(pools_ != nullptr); // realloc to smaller can't fail
+ capacity_ = count_;
+ }
+ }
+
+ private:
+ Slot allocFromFreeList() {
+ ARDUINOJSON_ASSERT(freeList_ != NULL_SLOT);
+ auto id = freeList_;
+ auto slot = getSlot(freeList_);
+ freeList_ = reinterpret_cast(slot)->next;
+ return {slot, id};
+ }
+
+ Slot allocFromLastPool() {
+ ARDUINOJSON_ASSERT(count_ > 0);
+ auto poolIndex = SlotId(count_ - 1);
+ auto slot = pools_[poolIndex].allocSlot();
+ if (!slot)
+ return {};
+ return {slot.ptr(),
+ SlotId(poolIndex * ARDUINOJSON_POOL_CAPACITY + slot.id())};
+ }
+
+ Pool* addPool(Allocator* allocator) {
+ if (count_ == capacity_ && !increaseCapacity(allocator))
+ return nullptr;
+ auto pool = &pools_[count_++];
+ SlotCount poolCapacity = ARDUINOJSON_POOL_CAPACITY;
+ if (count_ == maxPools) // last pool is smaller because of NULL_SLOT
+ poolCapacity--;
+ pool->create(poolCapacity, allocator);
+ return pool;
+ }
+
+ bool increaseCapacity(Allocator* allocator) {
+ if (capacity_ == maxPools)
+ return false;
+ void* newPools;
+ auto newCapacity = PoolCount(capacity_ * 2);
+
+ if (pools_ == preallocatedPools_) {
+ newPools = allocator->allocate(newCapacity * sizeof(Pool));
+ if (!newPools)
+ return false;
+ memcpy(newPools, preallocatedPools_, sizeof(preallocatedPools_));
+ } else {
+ newPools = allocator->reallocate(pools_, newCapacity * sizeof(Pool));
+ if (!newPools)
+ return false;
+ }
+
+ pools_ = static_cast(newPools);
+ capacity_ = newCapacity;
+ return true;
+ }
+
+ Pool preallocatedPools_[ARDUINOJSON_INITIAL_POOL_COUNT];
+ Pool* pools_ = preallocatedPools_;
+ PoolCount count_ = 0;
+ PoolCount capacity_ = ARDUINOJSON_INITIAL_POOL_COUNT;
+ SlotId freeList_ = NULL_SLOT;
+
+ public:
+ static const PoolCount maxPools =
+ PoolCount(NULL_SLOT / ARDUINOJSON_POOL_CAPACITY + 1);
+};
+
+ARDUINOJSON_END_PRIVATE_NAMESPACE
diff --git a/lib/ArduinoJson/src/ArduinoJson/Memory/ResourceManager.hpp b/lib/ArduinoJson/src/ArduinoJson/Memory/ResourceManager.hpp
index 2270e4f..c8e0d5b 100644
--- a/lib/ArduinoJson/src/ArduinoJson/Memory/ResourceManager.hpp
+++ b/lib/ArduinoJson/src/ArduinoJson/Memory/ResourceManager.hpp
@@ -5,19 +5,29 @@
#pragma once
#include
+#include
#include
-#include
#include
#include
#include
+#include