summaryrefslogtreecommitdiff
path: root/include/lib
diff options
context:
space:
mode:
authorDaniel Friesel <daniel.friesel@uos.de>2021-05-12 09:12:09 +0200
committerDaniel Friesel <daniel.friesel@uos.de>2021-05-12 09:12:09 +0200
commit39895a677e5d370824e702cfe90ebc67737b8482 (patch)
treeff5b4cc9e373d33a795d50d9333e05549bd9f2b8 /include/lib
parent42e7fdf01c3a5701bb51e93ad6c650c3dbbc5450 (diff)
import ArduinoJson 6.18.0
Diffstat (limited to 'include/lib')
-rw-r--r--include/lib/ArduinoJson.h73
-rw-r--r--include/lib/ArduinoJson/Array/ArrayFunctions.hpp31
-rw-r--r--include/lib/ArduinoJson/Array/ArrayImpl.hpp28
-rw-r--r--include/lib/ArduinoJson/Array/ArrayIterator.hpp121
-rw-r--r--include/lib/ArduinoJson/Array/ArrayRef.hpp205
-rw-r--r--include/lib/ArduinoJson/Array/ArrayShortcuts.hpp49
-rw-r--r--include/lib/ArduinoJson/Array/ElementProxy.hpp193
-rw-r--r--include/lib/ArduinoJson/Array/Utilities.hpp133
-rw-r--r--include/lib/ArduinoJson/Collection/CollectionData.hpp88
-rw-r--r--include/lib/ArduinoJson/Collection/CollectionImpl.hpp234
-rw-r--r--include/lib/ArduinoJson/Configuration.hpp255
-rw-r--r--include/lib/ArduinoJson/Deserialization/DeserializationError.hpp122
-rw-r--r--include/lib/ArduinoJson/Deserialization/Filter.hpp66
-rw-r--r--include/lib/ArduinoJson/Deserialization/NestingLimit.hpp29
-rw-r--r--include/lib/ArduinoJson/Deserialization/Reader.hpp56
-rw-r--r--include/lib/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp31
-rw-r--r--include/lib/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp17
-rw-r--r--include/lib/ArduinoJson/Deserialization/Readers/FlashReader.hpp53
-rw-r--r--include/lib/ArduinoJson/Deserialization/Readers/IteratorReader.hpp43
-rw-r--r--include/lib/ArduinoJson/Deserialization/Readers/RamReader.hpp50
-rw-r--r--include/lib/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp29
-rw-r--r--include/lib/ArduinoJson/Deserialization/Readers/VariantReader.hpp34
-rw-r--r--include/lib/ArduinoJson/Deserialization/deserialize.hpp71
-rw-r--r--include/lib/ArduinoJson/Document/BasicJsonDocument.hpp164
-rw-r--r--include/lib/ArduinoJson/Document/DynamicJsonDocument.hpp29
-rw-r--r--include/lib/ArduinoJson/Document/JsonDocument.hpp344
-rw-r--r--include/lib/ArduinoJson/Document/StaticJsonDocument.hpp56
-rw-r--r--include/lib/ArduinoJson/Json/EscapeSequence.hpp39
-rw-r--r--include/lib/ArduinoJson/Json/JsonDeserializer.hpp740
-rw-r--r--include/lib/ArduinoJson/Json/JsonSerializer.hpp137
-rw-r--r--include/lib/ArduinoJson/Json/Latch.hpp55
-rw-r--r--include/lib/ArduinoJson/Json/PrettyJsonSerializer.hpp89
-rw-r--r--include/lib/ArduinoJson/Json/TextFormatter.hpp163
-rw-r--r--include/lib/ArduinoJson/Json/Utf16.hpp67
-rw-r--r--include/lib/ArduinoJson/Json/Utf8.hpp46
-rw-r--r--include/lib/ArduinoJson/Memory/Alignment.hpp60
-rw-r--r--include/lib/ArduinoJson/Memory/MemoryPool.hpp212
-rw-r--r--include/lib/ArduinoJson/Misc/SerializedValue.hpp68
-rw-r--r--include/lib/ArduinoJson/Misc/Visitable.hpp21
-rw-r--r--include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp599
-rw-r--r--include/lib/ArduinoJson/MsgPack/MsgPackSerializer.hpp212
-rw-r--r--include/lib/ArduinoJson/MsgPack/endianess.hpp41
-rw-r--r--include/lib/ArduinoJson/MsgPack/ieee754.hpp18
-rw-r--r--include/lib/ArduinoJson/Namespace.hpp26
-rw-r--r--include/lib/ArduinoJson/Numbers/Float.hpp17
-rw-r--r--include/lib/ArduinoJson/Numbers/FloatParts.hpp87
-rw-r--r--include/lib/ArduinoJson/Numbers/FloatTraits.hpp201
-rw-r--r--include/lib/ArduinoJson/Numbers/Integer.hpp32
-rw-r--r--include/lib/ArduinoJson/Numbers/arithmeticCompare.hpp121
-rw-r--r--include/lib/ArduinoJson/Numbers/convertNumber.hpp107
-rw-r--r--include/lib/ArduinoJson/Numbers/parseNumber.hpp153
-rw-r--r--include/lib/ArduinoJson/Object/MemberProxy.hpp202
-rw-r--r--include/lib/ArduinoJson/Object/ObjectFunctions.hpp51
-rw-r--r--include/lib/ArduinoJson/Object/ObjectImpl.hpp69
-rw-r--r--include/lib/ArduinoJson/Object/ObjectIterator.hpp123
-rw-r--r--include/lib/ArduinoJson/Object/ObjectRef.hpp277
-rw-r--r--include/lib/ArduinoJson/Object/ObjectShortcuts.hpp73
-rw-r--r--include/lib/ArduinoJson/Object/Pair.hpp55
-rw-r--r--include/lib/ArduinoJson/Polyfills/alias_cast.hpp29
-rw-r--r--include/lib/ArduinoJson/Polyfills/assert.hpp14
-rw-r--r--include/lib/ArduinoJson/Polyfills/attributes.hpp54
-rw-r--r--include/lib/ArduinoJson/Polyfills/ctype.hpp20
-rw-r--r--include/lib/ArduinoJson/Polyfills/integer.hpp30
-rw-r--r--include/lib/ArduinoJson/Polyfills/limits.hpp45
-rw-r--r--include/lib/ArduinoJson/Polyfills/math.hpp27
-rw-r--r--include/lib/ArduinoJson/Polyfills/mpl/max.hpp26
-rw-r--r--include/lib/ArduinoJson/Polyfills/pgmspace.hpp79
-rw-r--r--include/lib/ArduinoJson/Polyfills/pgmspace_generic.hpp32
-rw-r--r--include/lib/ArduinoJson/Polyfills/preprocessor.hpp35
-rw-r--r--include/lib/ArduinoJson/Polyfills/safe_strcmp.hpp32
-rw-r--r--include/lib/ArduinoJson/Polyfills/static_array.hpp34
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits.hpp24
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/conditional.hpp20
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/declval.hpp14
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/enable_if.hpp19
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/integral_constant.hpp19
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_array.hpp21
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_base_of.hpp26
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_class.hpp26
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_const.hpp17
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_convertible.hpp47
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_enum.hpp22
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp19
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_integral.hpp33
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_pointer.hpp16
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_same.hpp17
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_signed.hpp43
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp37
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp49
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/remove_const.hpp20
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/remove_reference.hpp20
-rw-r--r--include/lib/ArduinoJson/Polyfills/type_traits/type_identity.hpp15
-rw-r--r--include/lib/ArduinoJson/Polyfills/utility.hpp28
-rw-r--r--include/lib/ArduinoJson/Serialization/CountingDecorator.hpp33
-rw-r--r--include/lib/ArduinoJson/Serialization/Writer.hpp47
-rw-r--r--include/lib/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp52
-rw-r--r--include/lib/ArduinoJson/Serialization/Writers/DummyWriter.hpp21
-rw-r--r--include/lib/ArduinoJson/Serialization/Writers/PrintWriter.hpp28
-rw-r--r--include/lib/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp35
-rw-r--r--include/lib/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp32
-rw-r--r--include/lib/ArduinoJson/Serialization/Writers/StdStringWriter.hpp40
-rw-r--r--include/lib/ArduinoJson/Serialization/measure.hpp18
-rw-r--r--include/lib/ArduinoJson/Serialization/serialize.hpp54
-rw-r--r--include/lib/ArduinoJson/StringStorage/StringCopier.hpp62
-rw-r--r--include/lib/ArduinoJson/StringStorage/StringMover.hpp42
-rw-r--r--include/lib/ArduinoJson/StringStorage/StringStorage.hpp23
-rw-r--r--include/lib/ArduinoJson/Strings/ArduinoStringAdapter.hpp62
-rw-r--r--include/lib/ArduinoJson/Strings/ConstRamStringAdapter.hpp62
-rw-r--r--include/lib/ArduinoJson/Strings/FlashStringAdapter.hpp62
-rw-r--r--include/lib/ArduinoJson/Strings/FlashStringIterator.hpp44
-rw-r--r--include/lib/ArduinoJson/Strings/IsString.hpp18
-rw-r--r--include/lib/ArduinoJson/Strings/IsWriteableString.hpp37
-rw-r--r--include/lib/ArduinoJson/Strings/RamStringAdapter.hpp43
-rw-r--r--include/lib/ArduinoJson/Strings/SizedFlashStringAdapter.hpp60
-rw-r--r--include/lib/ArduinoJson/Strings/SizedRamStringAdapter.hpp55
-rw-r--r--include/lib/ArduinoJson/Strings/StdStringAdapter.hpp65
-rw-r--r--include/lib/ArduinoJson/Strings/StoragePolicy.hpp15
-rw-r--r--include/lib/ArduinoJson/Strings/String.hpp77
-rw-r--r--include/lib/ArduinoJson/Strings/StringAdapters.hpp22
-rw-r--r--include/lib/ArduinoJson/Variant/Converter.hpp12
-rw-r--r--include/lib/ArduinoJson/Variant/ConverterImpl.hpp268
-rw-r--r--include/lib/ArduinoJson/Variant/SlotFunctions.hpp60
-rw-r--r--include/lib/ArduinoJson/Variant/VariantCompare.hpp208
-rw-r--r--include/lib/ArduinoJson/Variant/VariantContent.hpp59
-rw-r--r--include/lib/ArduinoJson/Variant/VariantData.hpp368
-rw-r--r--include/lib/ArduinoJson/Variant/VariantFunctions.hpp104
-rw-r--r--include/lib/ArduinoJson/Variant/VariantImpl.hpp143
-rw-r--r--include/lib/ArduinoJson/Variant/VariantOperators.hpp180
-rw-r--r--include/lib/ArduinoJson/Variant/VariantRef.hpp375
-rw-r--r--include/lib/ArduinoJson/Variant/VariantShortcuts.hpp23
-rw-r--r--include/lib/ArduinoJson/Variant/VariantSlot.hpp116
-rw-r--r--include/lib/ArduinoJson/Variant/VariantTag.hpp16
-rw-r--r--include/lib/ArduinoJson/Variant/VariantTo.hpp32
-rw-r--r--include/lib/ArduinoJson/Variant/Visitor.hpp54
-rw-r--r--include/lib/ArduinoJson/compatibility.hpp23
-rw-r--r--include/lib/ArduinoJson/version.hpp10
136 files changed, 10934 insertions, 0 deletions
diff --git a/include/lib/ArduinoJson.h b/include/lib/ArduinoJson.h
new file mode 100644
index 0000000..28d42ee
--- /dev/null
+++ b/include/lib/ArduinoJson.h
@@ -0,0 +1,73 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "ArduinoJson/Configuration.hpp"
+
+#if !ARDUINOJSON_DEBUG
+#ifdef __clang__
+#pragma clang system_header
+#elif defined __GNUC__
+#pragma GCC system_header
+#endif
+#endif
+
+#include "ArduinoJson/Array/ArrayRef.hpp"
+#include "ArduinoJson/Object/ObjectRef.hpp"
+#include "ArduinoJson/Variant/VariantRef.hpp"
+
+#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
+#include "ArduinoJson/Document/StaticJsonDocument.hpp"
+
+#include "ArduinoJson/Array/ArrayImpl.hpp"
+#include "ArduinoJson/Array/ElementProxy.hpp"
+#include "ArduinoJson/Array/Utilities.hpp"
+#include "ArduinoJson/Collection/CollectionImpl.hpp"
+#include "ArduinoJson/Object/MemberProxy.hpp"
+#include "ArduinoJson/Object/ObjectImpl.hpp"
+#include "ArduinoJson/Variant/ConverterImpl.hpp"
+#include "ArduinoJson/Variant/VariantCompare.hpp"
+#include "ArduinoJson/Variant/VariantImpl.hpp"
+
+#include "ArduinoJson/Json/JsonDeserializer.hpp"
+#include "ArduinoJson/Json/JsonSerializer.hpp"
+#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
+#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
+#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
+
+#include "ArduinoJson/compatibility.hpp"
+
+namespace ArduinoJson {
+typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
+typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
+typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
+typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
+typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
+typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
+typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
+typedef ARDUINOJSON_NAMESPACE::PairConst JsonPairConst;
+typedef ARDUINOJSON_NAMESPACE::String JsonString;
+typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
+typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
+typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
+using ARDUINOJSON_NAMESPACE::BasicJsonDocument;
+using ARDUINOJSON_NAMESPACE::copyArray;
+using ARDUINOJSON_NAMESPACE::DeserializationError;
+using ARDUINOJSON_NAMESPACE::deserializeJson;
+using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
+using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
+using ARDUINOJSON_NAMESPACE::JsonDocument;
+using ARDUINOJSON_NAMESPACE::measureJson;
+using ARDUINOJSON_NAMESPACE::serialized;
+using ARDUINOJSON_NAMESPACE::serializeJson;
+using ARDUINOJSON_NAMESPACE::serializeJsonPretty;
+using ARDUINOJSON_NAMESPACE::serializeMsgPack;
+using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
+
+namespace DeserializationOption {
+using ARDUINOJSON_NAMESPACE::Filter;
+using ARDUINOJSON_NAMESPACE::NestingLimit;
+} // namespace DeserializationOption
+} // namespace ArduinoJson
diff --git a/include/lib/ArduinoJson/Array/ArrayFunctions.hpp b/include/lib/ArduinoJson/Array/ArrayFunctions.hpp
new file mode 100644
index 0000000..e7cdc4c
--- /dev/null
+++ b/include/lib/ArduinoJson/Array/ArrayFunctions.hpp
@@ -0,0 +1,31 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
+ return arr ? arr->addElement(pool) : 0;
+}
+
+template <typename TVisitor>
+inline typename TVisitor::result_type arrayAccept(const CollectionData *arr,
+ TVisitor &visitor) {
+ if (arr)
+ return visitor.visitArray(*arr);
+ else
+ return visitor.visitNull();
+}
+
+inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
+ if (lhs == rhs)
+ return true;
+ if (!lhs || !rhs)
+ return false;
+ return lhs->equalsArray(*rhs);
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Array/ArrayImpl.hpp b/include/lib/ArduinoJson/Array/ArrayImpl.hpp
new file mode 100644
index 0000000..ae06b20
--- /dev/null
+++ b/include/lib/ArduinoJson/Array/ArrayImpl.hpp
@@ -0,0 +1,28 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TArray>
+inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
+ return impl()->addElement().template to<ArrayRef>();
+}
+
+template <typename TArray>
+inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
+ return impl()->addElement().template to<ObjectRef>();
+}
+
+template <typename TArray>
+inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[](
+ size_t index) const {
+ return ElementProxy<TArray>(*impl(), index);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Array/ArrayIterator.hpp b/include/lib/ArduinoJson/Array/ArrayIterator.hpp
new file mode 100644
index 0000000..fcacc6b
--- /dev/null
+++ b/include/lib/ArduinoJson/Array/ArrayIterator.hpp
@@ -0,0 +1,121 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Variant/SlotFunctions.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class VariantPtr {
+ public:
+ VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {}
+
+ VariantRef *operator->() {
+ return &_variant;
+ }
+
+ VariantRef &operator*() {
+ return _variant;
+ }
+
+ private:
+ VariantRef _variant;
+};
+
+class ArrayIterator {
+ public:
+ ArrayIterator() : _slot(0) {}
+ explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot)
+ : _pool(pool), _slot(slot) {}
+
+ VariantRef operator*() const {
+ return VariantRef(_pool, _slot->data());
+ }
+ VariantPtr operator->() {
+ return VariantPtr(_pool, _slot->data());
+ }
+
+ bool operator==(const ArrayIterator &other) const {
+ return _slot == other._slot;
+ }
+
+ bool operator!=(const ArrayIterator &other) const {
+ return _slot != other._slot;
+ }
+
+ ArrayIterator &operator++() {
+ _slot = _slot->next();
+ return *this;
+ }
+
+ ArrayIterator &operator+=(size_t distance) {
+ _slot = _slot->next(distance);
+ return *this;
+ }
+
+ VariantSlot *internal() {
+ return _slot;
+ }
+
+ private:
+ MemoryPool *_pool;
+ VariantSlot *_slot;
+};
+
+class VariantConstPtr {
+ public:
+ VariantConstPtr(const VariantData *data) : _variant(data) {}
+
+ VariantConstRef *operator->() {
+ return &_variant;
+ }
+
+ VariantConstRef &operator*() {
+ return _variant;
+ }
+
+ private:
+ VariantConstRef _variant;
+};
+
+class ArrayConstRefIterator {
+ public:
+ ArrayConstRefIterator() : _slot(0) {}
+ explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {}
+
+ VariantConstRef operator*() const {
+ return VariantConstRef(_slot->data());
+ }
+ VariantConstPtr operator->() {
+ return VariantConstPtr(_slot->data());
+ }
+
+ bool operator==(const ArrayConstRefIterator &other) const {
+ return _slot == other._slot;
+ }
+
+ bool operator!=(const ArrayConstRefIterator &other) const {
+ return _slot != other._slot;
+ }
+
+ ArrayConstRefIterator &operator++() {
+ _slot = _slot->next();
+ return *this;
+ }
+
+ ArrayConstRefIterator &operator+=(size_t distance) {
+ _slot = _slot->next(distance);
+ return *this;
+ }
+
+ const VariantSlot *internal() {
+ return _slot;
+ }
+
+ private:
+ const VariantSlot *_slot;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Array/ArrayRef.hpp b/include/lib/ArduinoJson/Array/ArrayRef.hpp
new file mode 100644
index 0000000..a991db0
--- /dev/null
+++ b/include/lib/ArduinoJson/Array/ArrayRef.hpp
@@ -0,0 +1,205 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayFunctions.hpp>
+#include <ArduinoJson/Array/ArrayIterator.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+// Returns the size (in bytes) of an array with n elements.
+// Can be very handy to determine the size of a StaticMemoryPool.
+#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
+ ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class ObjectRef;
+template <typename>
+class ElementProxy;
+
+template <typename TData>
+class ArrayRefBase {
+ public:
+ operator VariantConstRef() const {
+ const void* data = _data; // prevent warning cast-align
+ return VariantConstRef(reinterpret_cast<const VariantData*>(data));
+ }
+
+ template <typename TVisitor>
+ FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const {
+ return arrayAccept(_data, visitor);
+ }
+
+ FORCE_INLINE bool isNull() const {
+ return _data == 0;
+ }
+
+ FORCE_INLINE operator bool() const {
+ return _data != 0;
+ }
+
+ FORCE_INLINE size_t memoryUsage() const {
+ return _data ? _data->memoryUsage() : 0;
+ }
+
+ FORCE_INLINE size_t nesting() const {
+ return _data ? _data->nesting() : 0;
+ }
+
+ FORCE_INLINE size_t size() const {
+ return _data ? _data->size() : 0;
+ }
+
+ protected:
+ ArrayRefBase(TData* data) : _data(data) {}
+ TData* _data;
+};
+
+class ArrayConstRef : public ArrayRefBase<const CollectionData>,
+ public Visitable {
+ friend class ArrayRef;
+ typedef ArrayRefBase<const CollectionData> base_type;
+
+ public:
+ typedef ArrayConstRefIterator iterator;
+
+ FORCE_INLINE iterator begin() const {
+ if (!_data)
+ return iterator();
+ return iterator(_data->head());
+ }
+
+ FORCE_INLINE iterator end() const {
+ return iterator();
+ }
+
+ FORCE_INLINE ArrayConstRef() : base_type(0) {}
+ FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
+
+ FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
+ return arrayEquals(_data, rhs._data);
+ }
+
+ FORCE_INLINE VariantConstRef operator[](size_t index) const {
+ return getElement(index);
+ }
+
+ FORCE_INLINE VariantConstRef getElement(size_t index) const {
+ return VariantConstRef(_data ? _data->getElement(index) : 0);
+ }
+};
+
+class ArrayRef : public ArrayRefBase<CollectionData>,
+ public ArrayShortcuts<ArrayRef>,
+ public Visitable {
+ typedef ArrayRefBase<CollectionData> base_type;
+
+ public:
+ typedef ArrayIterator iterator;
+
+ FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
+ FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
+ : base_type(data), _pool(pool) {}
+
+ operator VariantRef() {
+ void* data = _data; // prevent warning cast-align
+ return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
+ }
+
+ operator ArrayConstRef() const {
+ return ArrayConstRef(_data);
+ }
+
+ VariantRef addElement() const {
+ return VariantRef(_pool, arrayAdd(_data, _pool));
+ }
+
+ FORCE_INLINE iterator begin() const {
+ if (!_data)
+ return iterator();
+ return iterator(_pool, _data->head());
+ }
+
+ FORCE_INLINE iterator end() const {
+ return iterator();
+ }
+
+ // Copy a ArrayRef
+ FORCE_INLINE bool set(ArrayConstRef src) const {
+ if (!_data || !src._data)
+ return false;
+ return _data->copyFrom(*src._data, _pool);
+ }
+
+ FORCE_INLINE bool operator==(ArrayRef rhs) const {
+ return arrayEquals(_data, rhs._data);
+ }
+
+ // Internal use
+ FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
+ return VariantRef(_pool, _data ? _data->getOrAddElement(index, _pool) : 0);
+ }
+
+ // Gets the value at the specified index.
+ FORCE_INLINE VariantRef getElement(size_t index) const {
+ return VariantRef(_pool, _data ? _data->getElement(index) : 0);
+ }
+
+ // Removes element at specified position.
+ FORCE_INLINE void remove(iterator it) const {
+ if (!_data)
+ return;
+ _data->removeSlot(it.internal());
+ }
+
+ // Removes element at specified index.
+ FORCE_INLINE void remove(size_t index) const {
+ if (!_data)
+ return;
+ _data->removeElement(index);
+ }
+
+ private:
+ MemoryPool* _pool;
+};
+
+template <>
+struct Converter<ArrayConstRef> {
+ static bool toJson(VariantConstRef src, VariantRef dst) {
+ return variantCopyFrom(getData(dst), getData(src), getPool(dst));
+ }
+
+ static ArrayConstRef fromJson(VariantConstRef src) {
+ return ArrayConstRef(variantAsArray(getData(src)));
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data && data->isArray();
+ }
+};
+
+template <>
+struct Converter<ArrayRef> {
+ static bool toJson(VariantConstRef src, VariantRef dst) {
+ return variantCopyFrom(getData(dst), getData(src), getPool(dst));
+ }
+
+ static ArrayRef fromJson(VariantRef src) {
+ VariantData* data = getData(src);
+ MemoryPool* pool = getPool(src);
+ return ArrayRef(pool, data != 0 ? data->asArray() : 0);
+ }
+
+ static bool checkJson(VariantConstRef) {
+ return false;
+ }
+
+ static bool checkJson(VariantRef src) {
+ VariantData* data = getData(src);
+ return data && data->isArray();
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Array/ArrayShortcuts.hpp b/include/lib/ArduinoJson/Array/ArrayShortcuts.hpp
new file mode 100644
index 0000000..fd26d04
--- /dev/null
+++ b/include/lib/ArduinoJson/Array/ArrayShortcuts.hpp
@@ -0,0 +1,49 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+// Forward declarations.
+class ArrayRef;
+class ObjectRef;
+template <typename>
+class ElementProxy;
+
+template <typename TArray>
+class ArrayShortcuts {
+ public:
+ // Returns the element at specified index if the variant is an array.
+ FORCE_INLINE ElementProxy<TArray> operator[](size_t index) const;
+
+ FORCE_INLINE ObjectRef createNestedObject() const;
+
+ FORCE_INLINE ArrayRef createNestedArray() const;
+
+ // Adds the specified value at the end of the array.
+ //
+ // bool add(TValue);
+ // TValue = bool, long, int, short, float, double, serialized, VariantRef,
+ // std::string, String, ObjectRef
+ template <typename T>
+ FORCE_INLINE bool add(const T &value) const {
+ return impl()->addElement().set(value);
+ }
+ //
+ // bool add(TValue);
+ // TValue = char*, const char*, const __FlashStringHelper*
+ template <typename T>
+ FORCE_INLINE bool add(T *value) const {
+ return impl()->addElement().set(value);
+ }
+
+ private:
+ const TArray *impl() const {
+ return static_cast<const TArray *>(this);
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Array/ElementProxy.hpp b/include/lib/ArduinoJson/Array/ElementProxy.hpp
new file mode 100644
index 0000000..c6062e4
--- /dev/null
+++ b/include/lib/ArduinoJson/Array/ElementProxy.hpp
@@ -0,0 +1,193 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Variant/VariantOperators.hpp>
+#include <ArduinoJson/Variant/VariantShortcuts.hpp>
+#include <ArduinoJson/Variant/VariantTo.hpp>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4522)
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TArray>
+class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
+ public VariantShortcuts<ElementProxy<TArray> >,
+ public Visitable,
+ public VariantTag {
+ typedef ElementProxy<TArray> this_type;
+
+ public:
+ typedef VariantRef variant_type;
+
+ FORCE_INLINE ElementProxy(TArray array, size_t index)
+ : _array(array), _index(index) {}
+
+ FORCE_INLINE ElementProxy(const ElementProxy& src)
+ : _array(src._array), _index(src._index) {}
+
+ FORCE_INLINE this_type& operator=(const this_type& src) {
+ getOrAddUpstreamElement().set(src.as<VariantConstRef>());
+ return *this;
+ }
+
+ // Replaces the value
+ //
+ // operator=(const TValue&)
+ // TValue = bool, long, int, short, float, double, serialized, VariantRef,
+ // std::string, String, ArrayRef, ObjectRef
+ template <typename T>
+ FORCE_INLINE this_type& operator=(const T& src) {
+ getOrAddUpstreamElement().set(src);
+ return *this;
+ }
+ //
+ // operator=(TValue)
+ // TValue = char*, const char*, const __FlashStringHelper*
+ template <typename T>
+ FORCE_INLINE this_type& operator=(T* src) {
+ getOrAddUpstreamElement().set(src);
+ return *this;
+ }
+
+ FORCE_INLINE void clear() const {
+ getUpstreamElement().clear();
+ }
+
+ FORCE_INLINE bool isNull() const {
+ return getUpstreamElement().isNull();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<!is_same<T, char*>::value, T>::type as()
+ const {
+ return getUpstreamElement().template as<T>();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char*>::value, const char*>::type
+ ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
+ as() const {
+ return as<const char*>();
+ }
+
+ template <typename T>
+ FORCE_INLINE operator T() const {
+ return getUpstreamElement();
+ }
+
+ template <typename T>
+ FORCE_INLINE bool is() const {
+ return getUpstreamElement().template is<T>();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename VariantTo<T>::type to() const {
+ return getOrAddUpstreamElement().template to<T>();
+ }
+
+ // Replaces the value
+ //
+ // bool set(const TValue&)
+ // TValue = bool, long, int, short, float, double, serialized, VariantRef,
+ // std::string, String, ArrayRef, ObjectRef
+ template <typename TValue>
+ FORCE_INLINE bool set(const TValue& value) const {
+ return getOrAddUpstreamElement().set(value);
+ }
+ //
+ // bool set(TValue)
+ // TValue = char*, const char*, const __FlashStringHelper*
+ template <typename TValue>
+ FORCE_INLINE bool set(TValue* value) const {
+ return getOrAddUpstreamElement().set(value);
+ }
+
+ template <typename TVisitor>
+ typename TVisitor::result_type accept(TVisitor& visitor) const {
+ return getUpstreamElement().accept(visitor);
+ }
+
+ FORCE_INLINE size_t size() const {
+ return getUpstreamElement().size();
+ }
+
+ template <typename TNestedKey>
+ VariantRef getMember(TNestedKey* key) const {
+ return getUpstreamElement().getMember(key);
+ }
+
+ template <typename TNestedKey>
+ VariantRef getMember(const TNestedKey& key) const {
+ return getUpstreamElement().getMember(key);
+ }
+
+ template <typename TNestedKey>
+ VariantRef getOrAddMember(TNestedKey* key) const {
+ return getOrAddUpstreamElement().getOrAddMember(key);
+ }
+
+ template <typename TNestedKey>
+ VariantRef getOrAddMember(const TNestedKey& key) const {
+ return getOrAddUpstreamElement().getOrAddMember(key);
+ }
+
+ VariantRef addElement() const {
+ return getOrAddUpstreamElement().addElement();
+ }
+
+ VariantRef getElement(size_t index) const {
+ return getOrAddUpstreamElement().getElement(index);
+ }
+
+ VariantRef getOrAddElement(size_t index) const {
+ return getOrAddUpstreamElement().getOrAddElement(index);
+ }
+
+ FORCE_INLINE void remove(size_t index) const {
+ getUpstreamElement().remove(index);
+ }
+ // remove(char*) const
+ // remove(const char*) const
+ // remove(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
+ TChar* key) const {
+ getUpstreamElement().remove(key);
+ }
+ // remove(const std::string&) const
+ // remove(const String&) const
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+ const TString& key) const {
+ getUpstreamElement().remove(key);
+ }
+
+ private:
+ FORCE_INLINE VariantRef getUpstreamElement() const {
+ return _array.getElement(_index);
+ }
+
+ FORCE_INLINE VariantRef getOrAddUpstreamElement() const {
+ return _array.getOrAddElement(_index);
+ }
+
+ friend bool convertToJson(const this_type& src, VariantRef dst) {
+ return dst.set(src.getUpstreamElement());
+ }
+
+ TArray _array;
+ const size_t _index;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
diff --git a/include/lib/ArduinoJson/Array/Utilities.hpp b/include/lib/ArduinoJson/Array/Utilities.hpp
new file mode 100644
index 0000000..619b91d
--- /dev/null
+++ b/include/lib/ArduinoJson/Array/Utilities.hpp
@@ -0,0 +1,133 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Document/JsonDocument.hpp>
+#include <ArduinoJson/Variant/Visitor.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Copy a 1D array to a JsonArray
+template <typename T, size_t N, typename TDestination>
+inline typename enable_if<!is_array<T>::value &&
+ !is_base_of<JsonDocument, TDestination>::value,
+ bool>::type
+copyArray(T (&src)[N], const TDestination& dst) {
+ return copyArray(src, N, dst);
+}
+
+// Copy a 1D array to a JsonDocument
+template <typename T, size_t N>
+inline bool copyArray(T (&src)[N], JsonDocument& dst) {
+ return copyArray(src, dst.to<ArrayRef>());
+}
+
+// Copy a 1D array to a JsonArray
+template <typename T, typename TDestination>
+inline typename enable_if<!is_array<T>::value &&
+ !is_base_of<JsonDocument, TDestination>::value,
+ bool>::type
+copyArray(T* src, size_t len, const TDestination& dst) {
+ bool ok = true;
+ for (size_t i = 0; i < len; i++) {
+ ok &= dst.add(src[i]);
+ }
+ return ok;
+}
+
+// Copy a 1D array to a JsonDocument
+template <typename T>
+inline bool copyArray(T* src, size_t len, JsonDocument& dst) {
+ return copyArray(src, len, dst.to<ArrayRef>());
+}
+
+// Copy a 2D array to a JsonArray
+template <typename T, size_t N1, size_t N2, typename TDestination>
+inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value,
+ bool>::type
+copyArray(T (&src)[N1][N2], const TDestination& dst) {
+ bool ok = true;
+ for (size_t i = 0; i < N1; i++) {
+ ArrayRef nestedArray = dst.createNestedArray();
+ for (size_t j = 0; j < N2; j++) {
+ ok &= nestedArray.add(src[i][j]);
+ }
+ }
+ return ok;
+}
+
+// Copy a 2D array to a JsonDocument
+template <typename T, size_t N1, size_t N2>
+inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) {
+ return copyArray(src, dst.to<ArrayRef>());
+}
+
+template <typename T>
+class ArrayCopier1D : public Visitor<size_t> {
+ public:
+ ArrayCopier1D(T* destination, size_t capacity)
+ : _destination(destination), _capacity(capacity) {}
+
+ size_t visitArray(const CollectionData& array) {
+ size_t size = 0;
+ VariantSlot* slot = array.head();
+
+ while (slot != 0 && size < _capacity) {
+ _destination[size++] =
+ Converter<T>::fromJson(VariantConstRef(slot->data()));
+ slot = slot->next();
+ }
+ return size;
+ }
+
+ private:
+ T* _destination;
+ size_t _capacity;
+};
+
+template <typename T, size_t N1, size_t N2>
+class ArrayCopier2D : public Visitor<void> {
+ public:
+ ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {}
+
+ void visitArray(const CollectionData& array) {
+ VariantSlot* slot = array.head();
+ size_t n = 0;
+ while (slot != 0 && n < N1) {
+ ArrayCopier1D<T> copier((*_destination)[n++], N2);
+ variantAccept(slot->data(), copier);
+ slot = slot->next();
+ }
+ }
+
+ private:
+ T (*_destination)[N1][N2];
+ size_t _capacity1, _capacity2;
+};
+
+// Copy a JsonArray to a 1D array
+template <typename TSource, typename T, size_t N>
+inline typename enable_if<!is_array<T>::value, size_t>::type copyArray(
+ const TSource& src, T (&dst)[N]) {
+ return copyArray(src, dst, N);
+}
+
+// Copy a JsonArray to a 1D array
+template <typename TSource, typename T>
+inline size_t copyArray(const TSource& src, T* dst, size_t len) {
+ ArrayCopier1D<T> copier(dst, len);
+
+ return src.accept(copier);
+}
+
+// Copy a JsonArray to a 2D array
+template <typename TSource, typename T, size_t N1, size_t N2>
+inline void copyArray(const TSource& src, T (&dst)[N1][N2]) {
+ ArrayCopier2D<T, N1, N2> copier(&dst);
+ src.accept(copier);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Collection/CollectionData.hpp b/include/lib/ArduinoJson/Collection/CollectionData.hpp
new file mode 100644
index 0000000..d2bca45
--- /dev/null
+++ b/include/lib/ArduinoJson/Collection/CollectionData.hpp
@@ -0,0 +1,88 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+#include <stddef.h> // size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class MemoryPool;
+class VariantData;
+class VariantSlot;
+
+class CollectionData {
+ VariantSlot *_head;
+ VariantSlot *_tail;
+
+ public:
+ // Must be a POD!
+ // - no constructor
+ // - no destructor
+ // - no virtual
+ // - no inheritance
+
+ // Array only
+
+ VariantData *addElement(MemoryPool *pool);
+
+ VariantData *getElement(size_t index) const;
+
+ VariantData *getOrAddElement(size_t index, MemoryPool *pool);
+
+ void removeElement(size_t index);
+
+ bool equalsArray(const CollectionData &other) const;
+
+ // Object only
+
+ template <typename TAdaptedString>
+ VariantData *addMember(TAdaptedString key, MemoryPool *pool);
+
+ template <typename TAdaptedString>
+ VariantData *getMember(TAdaptedString key) const;
+
+ template <typename TAdaptedString>
+ VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool);
+
+ template <typename TAdaptedString>
+ void removeMember(TAdaptedString key) {
+ removeSlot(getSlot(key));
+ }
+
+ template <typename TAdaptedString>
+ bool containsKey(const TAdaptedString &key) const;
+
+ bool equalsObject(const CollectionData &other) const;
+
+ // Generic
+
+ void clear();
+ size_t memoryUsage() const;
+ size_t nesting() const;
+ size_t size() const;
+
+ VariantSlot *addSlot(MemoryPool *);
+ void removeSlot(VariantSlot *slot);
+
+ bool copyFrom(const CollectionData &src, MemoryPool *pool);
+
+ VariantSlot *head() const {
+ return _head;
+ }
+
+ void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
+
+ private:
+ VariantSlot *getSlot(size_t index) const;
+
+ template <typename TAdaptedString>
+ VariantSlot *getSlot(TAdaptedString key) const;
+
+ VariantSlot *getPreviousSlot(VariantSlot *) const;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Collection/CollectionImpl.hpp b/include/lib/ArduinoJson/Collection/CollectionImpl.hpp
new file mode 100644
index 0000000..49a24be
--- /dev/null
+++ b/include/lib/ArduinoJson/Collection/CollectionImpl.hpp
@@ -0,0 +1,234 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline bool variantEquals(const VariantData* a, const VariantData* b) {
+ return variantCompare(a, b) == COMPARE_RESULT_EQUAL;
+}
+
+inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
+ VariantSlot* slot = pool->allocVariant();
+ if (!slot)
+ return 0;
+
+ if (_tail) {
+ _tail->setNextNotNull(slot);
+ _tail = slot;
+ } else {
+ _head = slot;
+ _tail = slot;
+ }
+
+ slot->clear();
+ return slot;
+}
+
+inline VariantData* CollectionData::addElement(MemoryPool* pool) {
+ return slotData(addSlot(pool));
+}
+
+template <typename TAdaptedString>
+inline VariantData* CollectionData::addMember(TAdaptedString key,
+ MemoryPool* pool) {
+ VariantSlot* slot = addSlot(pool);
+ if (!slotSetKey(slot, key, pool)) {
+ removeSlot(slot);
+ return 0;
+ }
+ return slot->data();
+}
+
+inline void CollectionData::clear() {
+ _head = 0;
+ _tail = 0;
+}
+
+template <typename TAdaptedString>
+inline bool CollectionData::containsKey(const TAdaptedString& key) const {
+ return getSlot(key) != 0;
+}
+
+inline bool CollectionData::copyFrom(const CollectionData& src,
+ MemoryPool* pool) {
+ clear();
+ for (VariantSlot* s = src._head; s; s = s->next()) {
+ VariantData* var;
+ if (s->key() != 0) {
+ if (s->ownsKey())
+ var = addMember(RamStringAdapter(s->key()), pool);
+ else
+ var = addMember(ConstRamStringAdapter(s->key()), pool);
+ } else {
+ var = addElement(pool);
+ }
+ if (!var)
+ return false;
+ if (!var->copyFrom(*s->data(), pool))
+ return false;
+ }
+ return true;
+}
+
+inline bool CollectionData::equalsObject(const CollectionData& other) const {
+ size_t count = 0;
+ for (VariantSlot* slot = _head; slot; slot = slot->next()) {
+ VariantData* v1 = slot->data();
+ VariantData* v2 = other.getMember(adaptString(slot->key()));
+ if (!variantEquals(v1, v2))
+ return false;
+ count++;
+ }
+ return count == other.size();
+}
+
+inline bool CollectionData::equalsArray(const CollectionData& other) const {
+ VariantSlot* s1 = _head;
+ VariantSlot* s2 = other._head;
+ for (;;) {
+ if (s1 == s2)
+ return true;
+ if (!s1 || !s2)
+ return false;
+ if (!variantEquals(s1->data(), s2->data()))
+ return false;
+ s1 = s1->next();
+ s2 = s2->next();
+ }
+}
+
+template <typename TAdaptedString>
+inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
+ VariantSlot* slot = _head;
+ while (slot) {
+ if (key.equals(slot->key()))
+ break;
+ slot = slot->next();
+ }
+ return slot;
+}
+
+inline VariantSlot* CollectionData::getSlot(size_t index) const {
+ if (!_head)
+ return 0;
+ return _head->next(index);
+}
+
+inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
+ VariantSlot* current = _head;
+ while (current) {
+ VariantSlot* next = current->next();
+ if (next == target)
+ return current;
+ current = next;
+ }
+ return 0;
+}
+
+template <typename TAdaptedString>
+inline VariantData* CollectionData::getMember(TAdaptedString key) const {
+ VariantSlot* slot = getSlot(key);
+ return slot ? slot->data() : 0;
+}
+
+template <typename TAdaptedString>
+inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
+ MemoryPool* pool) {
+ // ignore null key
+ if (key.isNull())
+ return 0;
+
+ // search a matching key
+ VariantSlot* slot = getSlot(key);
+ if (slot)
+ return slot->data();
+
+ return addMember(key, pool);
+}
+
+inline VariantData* CollectionData::getElement(size_t index) const {
+ VariantSlot* slot = getSlot(index);
+ return slot ? slot->data() : 0;
+}
+
+inline VariantData* CollectionData::getOrAddElement(size_t index,
+ MemoryPool* pool) {
+ VariantSlot* slot = _head;
+ while (slot && index > 0) {
+ slot = slot->next();
+ index--;
+ }
+ if (!slot)
+ index++;
+ while (index > 0) {
+ slot = addSlot(pool);
+ index--;
+ }
+ return slotData(slot);
+}
+
+inline void CollectionData::removeSlot(VariantSlot* slot) {
+ if (!slot)
+ return;
+ VariantSlot* prev = getPreviousSlot(slot);
+ VariantSlot* next = slot->next();
+ if (prev)
+ prev->setNext(next);
+ else
+ _head = next;
+ if (!next)
+ _tail = prev;
+}
+
+inline void CollectionData::removeElement(size_t index) {
+ removeSlot(getSlot(index));
+}
+
+inline size_t CollectionData::memoryUsage() const {
+ size_t total = 0;
+ for (VariantSlot* s = _head; s; s = s->next()) {
+ total += sizeof(VariantSlot) + s->data()->memoryUsage();
+ if (s->ownsKey())
+ total += strlen(s->key()) + 1;
+ }
+ return total;
+}
+
+inline size_t CollectionData::nesting() const {
+ size_t maxChildNesting = 0;
+ for (VariantSlot* s = _head; s; s = s->next()) {
+ size_t childNesting = s->data()->nesting();
+ if (childNesting > maxChildNesting)
+ maxChildNesting = childNesting;
+ }
+ return maxChildNesting + 1;
+}
+
+inline size_t CollectionData::size() const {
+ return slotSize(_head);
+}
+
+template <typename T>
+inline void movePointer(T*& p, ptrdiff_t offset) {
+ if (!p)
+ return;
+ p = reinterpret_cast<T*>(
+ reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset));
+ ARDUINOJSON_ASSERT(isAligned(p));
+}
+
+inline void CollectionData::movePointers(ptrdiff_t stringDistance,
+ ptrdiff_t variantDistance) {
+ movePointer(_head, variantDistance);
+ movePointer(_tail, variantDistance);
+ for (VariantSlot* slot = _head; slot; slot = slot->next())
+ slot->movePointers(stringDistance, variantDistance);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Configuration.hpp b/include/lib/ArduinoJson/Configuration.hpp
new file mode 100644
index 0000000..0c0d4c4
--- /dev/null
+++ b/include/lib/ArduinoJson/Configuration.hpp
@@ -0,0 +1,255 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#if __cplusplus >= 201103L
+#define ARDUINOJSON_HAS_LONG_LONG 1
+#define ARDUINOJSON_HAS_NULLPTR 1
+#define ARDUINOJSON_HAS_RVALUE_REFERENCES 1
+#else
+#define ARDUINOJSON_HAS_LONG_LONG 0
+#define ARDUINOJSON_HAS_NULLPTR 0
+#define ARDUINOJSON_HAS_RVALUE_REFERENCES 0
+#endif
+
+#if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG
+#define ARDUINOJSON_HAS_INT64 1
+#else
+#define ARDUINOJSON_HAS_INT64 0
+#endif
+
+// Small or big machine?
+#ifndef ARDUINOJSON_EMBEDDED_MODE
+#if defined(ARDUINO) /* Arduino*/ \
+ || defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \
+ || defined(__XC) /* MPLAB XC compiler */ \
+ || defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \
+ || defined(__AVR) /* Atmel AVR8/GNU C Compiler */
+#define ARDUINOJSON_EMBEDDED_MODE 1
+#else
+#define ARDUINOJSON_EMBEDDED_MODE 0
+#endif
+#endif
+
+// Auto enable std::stream if the right headers are here and no conflicting
+// macro is defined
+#if !defined(ARDUINOJSON_ENABLE_STD_STREAM) && defined(__has_include)
+#if __has_include(<istream>) && \
+ __has_include(<ostream>) && \
+ !defined(min) && \
+ !defined(max)
+#define ARDUINOJSON_ENABLE_STD_STREAM 1
+#else
+#define ARDUINOJSON_ENABLE_STD_STREAM 0
+#endif
+#endif
+
+// Auto enable std::string if the right header is here and no conflicting
+// macro is defined
+#if !defined(ARDUINOJSON_ENABLE_STD_STRING) && defined(__has_include)
+#if __has_include(<string>) && !defined(min) && !defined(max)
+#define ARDUINOJSON_ENABLE_STD_STRING 1
+#else
+#define ARDUINOJSON_ENABLE_STD_STRING 0
+#endif
+#endif
+
+#if ARDUINOJSON_EMBEDDED_MODE
+
+// Store floats by default to reduce the memory usage (issue #134)
+#ifndef ARDUINOJSON_USE_DOUBLE
+#define ARDUINOJSON_USE_DOUBLE 0
+#endif
+
+// Store longs by default, because they usually match the size of a float.
+#ifndef ARDUINOJSON_USE_LONG_LONG
+#define ARDUINOJSON_USE_LONG_LONG 0
+#endif
+
+// Embedded systems usually don't have std::string
+#ifndef ARDUINOJSON_ENABLE_STD_STRING
+#define ARDUINOJSON_ENABLE_STD_STRING 0
+#endif
+
+// Embedded systems usually don't have std::stream
+#ifndef ARDUINOJSON_ENABLE_STD_STREAM
+#define ARDUINOJSON_ENABLE_STD_STREAM 0
+#endif
+
+// Limit nesting as the stack is likely to be small
+#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
+#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
+#endif
+
+// Number of bits to store the pointer to next node
+// (saves RAM but limits the number of values in a document)
+#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
+#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 2
+// Address space == 16-bit => max 127 values
+#define ARDUINOJSON_SLOT_OFFSET_SIZE 1
+#else
+// Address space > 16-bit => max 32767 values
+#define ARDUINOJSON_SLOT_OFFSET_SIZE 2
+#endif
+#endif
+
+#else // ARDUINOJSON_EMBEDDED_MODE
+
+// On a computer we have plenty of memory so we can use doubles
+#ifndef ARDUINOJSON_USE_DOUBLE
+#define ARDUINOJSON_USE_DOUBLE 1
+#endif
+
+// Use long long when available
+#ifndef ARDUINOJSON_USE_LONG_LONG
+#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
+#define ARDUINOJSON_USE_LONG_LONG 1
+#else
+#define ARDUINOJSON_USE_LONG_LONG 0
+#endif
+#endif
+
+// On a computer, we can use std::string
+#ifndef ARDUINOJSON_ENABLE_STD_STRING
+#define ARDUINOJSON_ENABLE_STD_STRING 1
+#endif
+
+// On a computer, we can assume std::stream
+#ifndef ARDUINOJSON_ENABLE_STD_STREAM
+#define ARDUINOJSON_ENABLE_STD_STREAM 1
+#endif
+
+// On a computer, the stack is large so we can increase nesting limit
+#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
+#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
+#endif
+
+// Number of bits to store the pointer to next node
+#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE
+#define ARDUINOJSON_SLOT_OFFSET_SIZE 4
+#endif
+
+#endif // ARDUINOJSON_EMBEDDED_MODE
+
+#ifdef ARDUINO
+
+#include <Arduino.h>
+
+// Enable support for Arduino's String class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
+#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
+#endif
+
+// Enable support for Arduino's Stream class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
+#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
+#endif
+
+// Enable support for Arduino's Print class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
+#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
+#endif
+
+#else // ARDUINO
+
+// Disable support for Arduino's String class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
+#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
+#endif
+
+// Disable support for Arduino's Stream class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
+#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
+#endif
+
+// Disable support for Arduino's Print class
+#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
+#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
+#endif
+
+#endif // ARDUINO
+
+#ifndef ARDUINOJSON_ENABLE_PROGMEM
+#if defined(PROGMEM) && defined(pgm_read_byte) && defined(pgm_read_dword) && \
+ defined(pgm_read_ptr) && defined(pgm_read_float)
+#define ARDUINOJSON_ENABLE_PROGMEM 1
+#else
+#define ARDUINOJSON_ENABLE_PROGMEM 0
+#endif
+#endif
+
+// Convert unicode escape sequence (\u0123) to UTF-8
+#ifndef ARDUINOJSON_DECODE_UNICODE
+#define ARDUINOJSON_DECODE_UNICODE 1
+#endif
+
+// Ignore comments in input
+#ifndef ARDUINOJSON_ENABLE_COMMENTS
+#define ARDUINOJSON_ENABLE_COMMENTS 0
+#endif
+
+// Support NaN in JSON
+#ifndef ARDUINOJSON_ENABLE_NAN
+#define ARDUINOJSON_ENABLE_NAN 0
+#endif
+
+// Support Infinity in JSON
+#ifndef ARDUINOJSON_ENABLE_INFINITY
+#define ARDUINOJSON_ENABLE_INFINITY 0
+#endif
+
+// Control the exponentiation threshold for big numbers
+// CAUTION: cannot be more that 1e9 !!!!
+#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
+#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
+#endif
+
+// Control the exponentiation threshold for small numbers
+#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
+#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
+#endif
+
+#ifndef ARDUINOJSON_LITTLE_ENDIAN
+#if defined(_MSC_VER) || \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
+ defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64)
+#define ARDUINOJSON_LITTLE_ENDIAN 1
+#else
+#define ARDUINOJSON_LITTLE_ENDIAN 0
+#endif
+#endif
+
+#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
+#if defined(__AVR)
+#define ARDUINOJSON_ENABLE_ALIGNMENT 0
+#else
+#define ARDUINOJSON_ENABLE_ALIGNMENT 1
+#endif
+#endif
+
+#ifndef ARDUINOJSON_TAB
+#define ARDUINOJSON_TAB " "
+#endif
+
+#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
+#endif
+
+#ifndef ARDUINOJSON_STRING_BUFFER_SIZE
+#define ARDUINOJSON_STRING_BUFFER_SIZE 32
+#endif
+
+#ifndef ARDUINOJSON_DEBUG
+#ifdef __PLATFORMIO_BUILD_DEBUG__
+#define ARDUINOJSON_DEBUG 1
+#else
+#define ARDUINOJSON_DEBUG 0
+#endif
+#endif
+
+#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr)
+#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
+// See https://github.com/bblanchon/ArduinoJson/issues/1355
+#endif
diff --git a/include/lib/ArduinoJson/Deserialization/DeserializationError.hpp b/include/lib/ArduinoJson/Deserialization/DeserializationError.hpp
new file mode 100644
index 0000000..7b61711
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/DeserializationError.hpp
@@ -0,0 +1,122 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/preprocessor.hpp>
+#include <ArduinoJson/Polyfills/static_array.hpp>
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+#include <ostream>
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class DeserializationError {
+ // safe bool idiom
+ typedef void (DeserializationError::*bool_type)() const;
+ void safeBoolHelper() const {}
+
+ public:
+ enum Code {
+ Ok,
+ EmptyInput,
+ IncompleteInput,
+ InvalidInput,
+ NoMemory,
+ TooDeep
+ };
+
+ DeserializationError() {}
+ DeserializationError(Code c) : _code(c) {}
+
+ // Compare with DeserializationError
+ friend bool operator==(const DeserializationError& lhs,
+ const DeserializationError& rhs) {
+ return lhs._code == rhs._code;
+ }
+ friend bool operator!=(const DeserializationError& lhs,
+ const DeserializationError& rhs) {
+ return lhs._code != rhs._code;
+ }
+
+ // Compare with Code
+ friend bool operator==(const DeserializationError& lhs, Code rhs) {
+ return lhs._code == rhs;
+ }
+ friend bool operator==(Code lhs, const DeserializationError& rhs) {
+ return lhs == rhs._code;
+ }
+ friend bool operator!=(const DeserializationError& lhs, Code rhs) {
+ return lhs._code != rhs;
+ }
+ friend bool operator!=(Code lhs, const DeserializationError& rhs) {
+ return lhs != rhs._code;
+ }
+
+ // Behaves like a bool
+ operator bool_type() const {
+ return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
+ }
+ friend bool operator==(bool value, const DeserializationError& err) {
+ return static_cast<bool>(err) == value;
+ }
+ friend bool operator==(const DeserializationError& err, bool value) {
+ return static_cast<bool>(err) == value;
+ }
+ friend bool operator!=(bool value, const DeserializationError& err) {
+ return static_cast<bool>(err) != value;
+ }
+ friend bool operator!=(const DeserializationError& err, bool value) {
+ return static_cast<bool>(err) != value;
+ }
+
+ // Returns internal enum, useful for switch statement
+ Code code() const {
+ return _code;
+ }
+
+ const char* c_str() const {
+ static const char* messages[] = {
+ "Ok", "EmptyInput", "IncompleteInput",
+ "InvalidInput", "NoMemory", "TooDeep"};
+ ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
+ sizeof(messages) / sizeof(messages[0]));
+ return messages[_code];
+ }
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+ const __FlashStringHelper* f_str() const {
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok");
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s1, "EmptyInput");
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s2, "IncompleteInput");
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s3, "InvalidInput");
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s4, "NoMemory");
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "TooDeep");
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(
+ const char*, messages, ARDUINOJSON_EXPAND6({s0, s1, s2, s3, s4, s5}));
+ return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages,
+ _code);
+ }
+#endif
+
+ private:
+ Code _code;
+};
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+inline std::ostream& operator<<(std::ostream& s,
+ const DeserializationError& e) {
+ s << e.c_str();
+ return s;
+}
+
+inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
+ s << DeserializationError(c).c_str();
+ return s;
+}
+#endif
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Filter.hpp b/include/lib/ArduinoJson/Deserialization/Filter.hpp
new file mode 100644
index 0000000..7ea3078
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Filter.hpp
@@ -0,0 +1,66 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class Filter {
+ public:
+ explicit Filter(VariantConstRef v) : _variant(v) {}
+
+ bool allow() const {
+ return _variant;
+ }
+
+ bool allowArray() const {
+ return _variant == true || _variant.is<ArrayConstRef>();
+ }
+
+ bool allowObject() const {
+ return _variant == true || _variant.is<ObjectConstRef>();
+ }
+
+ bool allowValue() const {
+ return _variant == true;
+ }
+
+ template <typename TKey>
+ Filter operator[](const TKey& key) const {
+ if (_variant == true) // "true" means "allow recursively"
+ return *this;
+ else
+ return Filter(_variant[key] | _variant["*"]);
+ }
+
+ private:
+ VariantConstRef _variant;
+};
+
+struct AllowAllFilter {
+ bool allow() const {
+ return true;
+ }
+
+ bool allowArray() const {
+ return true;
+ }
+
+ bool allowObject() const {
+ return true;
+ }
+
+ bool allowValue() const {
+ return true;
+ }
+
+ template <typename TKey>
+ AllowAllFilter operator[](const TKey&) const {
+ return AllowAllFilter();
+ }
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/NestingLimit.hpp b/include/lib/ArduinoJson/Deserialization/NestingLimit.hpp
new file mode 100644
index 0000000..06964b4
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/NestingLimit.hpp
@@ -0,0 +1,29 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class NestingLimit {
+ public:
+ NestingLimit() : _value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
+ explicit NestingLimit(uint8_t n) : _value(n) {}
+
+ NestingLimit decrement() const {
+ ARDUINOJSON_ASSERT(_value > 0);
+ return NestingLimit(static_cast<uint8_t>(_value - 1));
+ }
+
+ bool reached() const {
+ return _value == 0;
+ }
+
+ private:
+ uint8_t _value;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Reader.hpp b/include/lib/ArduinoJson/Deserialization/Reader.hpp
new file mode 100644
index 0000000..e965c82
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Reader.hpp
@@ -0,0 +1,56 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdlib.h> // for size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// The default reader is a simple wrapper for Readers that are not copiable
+template <typename TSource, typename Enable = void>
+struct Reader {
+ public:
+ Reader(TSource& source) : _source(&source) {}
+
+ int read() {
+ return _source->read();
+ }
+
+ size_t readBytes(char* buffer, size_t length) {
+ return _source->readBytes(buffer, length);
+ }
+
+ private:
+ TSource* _source;
+};
+
+template <typename TSource, typename Enable = void>
+struct BoundedReader {
+ // no default implementation because we need to pass the size to the
+ // constructor
+};
+} // namespace ARDUINOJSON_NAMESPACE
+
+#include <ArduinoJson/Deserialization/Readers/IteratorReader.hpp>
+#include <ArduinoJson/Deserialization/Readers/RamReader.hpp>
+#include <ArduinoJson/Deserialization/Readers/VariantReader.hpp>
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
+#include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+#include <ArduinoJson/Deserialization/Readers/FlashReader.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+#include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp>
+#endif
diff --git a/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp
new file mode 100644
index 0000000..724638f
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp
@@ -0,0 +1,31 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <Arduino.h>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TSource>
+struct Reader<TSource,
+ typename enable_if<is_base_of<Stream, TSource>::value>::type> {
+ public:
+ explicit Reader(Stream& stream) : _stream(&stream) {}
+
+ int read() {
+ // don't use _stream.read() as it ignores the timeout
+ char c;
+ return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
+ }
+
+ size_t readBytes(char* buffer, size_t length) {
+ return _stream->readBytes(buffer, length);
+ }
+
+ private:
+ Stream* _stream;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp
new file mode 100644
index 0000000..71571d4
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp
@@ -0,0 +1,17 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TSource>
+struct Reader<TSource,
+ typename enable_if<is_base_of< ::String, TSource>::value>::type>
+ : BoundedReader<const char*> {
+ explicit Reader(const ::String& s)
+ : BoundedReader<const char*>(s.c_str(), s.length()) {}
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Readers/FlashReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/FlashReader.hpp
new file mode 100644
index 0000000..7eca134
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Readers/FlashReader.hpp
@@ -0,0 +1,53 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <>
+struct Reader<const __FlashStringHelper*, void> {
+ const char* _ptr;
+
+ public:
+ explicit Reader(const __FlashStringHelper* ptr)
+ : _ptr(reinterpret_cast<const char*>(ptr)) {}
+
+ int read() {
+ return pgm_read_byte(_ptr++);
+ }
+
+ size_t readBytes(char* buffer, size_t length) {
+ memcpy_P(buffer, _ptr, length);
+ _ptr += length;
+ return length;
+ }
+};
+
+template <>
+struct BoundedReader<const __FlashStringHelper*, void> {
+ const char* _ptr;
+ const char* _end;
+
+ public:
+ explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
+ : _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
+
+ int read() {
+ if (_ptr < _end)
+ return pgm_read_byte(_ptr++);
+ else
+ return -1;
+ }
+
+ size_t readBytes(char* buffer, size_t length) {
+ size_t available = static_cast<size_t>(_end - _ptr);
+ if (available < length)
+ length = available;
+ memcpy_P(buffer, _ptr, length);
+ _ptr += length;
+ return length;
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Readers/IteratorReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/IteratorReader.hpp
new file mode 100644
index 0000000..37c3c31
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Readers/IteratorReader.hpp
@@ -0,0 +1,43 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TIterator>
+class IteratorReader {
+ TIterator _ptr, _end;
+
+ public:
+ explicit IteratorReader(TIterator begin, TIterator end)
+ : _ptr(begin), _end(end) {}
+
+ int read() {
+ if (_ptr < _end)
+ return static_cast<unsigned char>(*_ptr++);
+ else
+ return -1;
+ }
+
+ size_t readBytes(char* buffer, size_t length) {
+ size_t i = 0;
+ while (i < length && _ptr < _end) buffer[i++] = *_ptr++;
+ return i;
+ }
+};
+
+template <typename T>
+struct void_ {
+ typedef void type;
+};
+
+template <typename TSource>
+struct Reader<TSource, typename void_<typename TSource::const_iterator>::type>
+ : IteratorReader<typename TSource::const_iterator> {
+ explicit Reader(const TSource& source)
+ : IteratorReader<typename TSource::const_iterator>(source.begin(),
+ source.end()) {}
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Readers/RamReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/RamReader.hpp
new file mode 100644
index 0000000..67cf682
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Readers/RamReader.hpp
@@ -0,0 +1,50 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct IsCharOrVoid {
+ static const bool value =
+ is_same<T, void>::value || is_same<T, char>::value ||
+ is_same<T, unsigned char>::value || is_same<T, signed char>::value;
+};
+
+template <typename T>
+struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
+
+template <typename TSource>
+struct Reader<TSource*,
+ typename enable_if<IsCharOrVoid<TSource>::value>::type> {
+ const char* _ptr;
+
+ public:
+ explicit Reader(const void* ptr)
+ : _ptr(ptr ? reinterpret_cast<const char*>(ptr) : "") {}
+
+ int read() {
+ return static_cast<unsigned char>(*_ptr++);
+ }
+
+ size_t readBytes(char* buffer, size_t length) {
+ for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++;
+ return length;
+ }
+};
+
+template <typename TSource>
+struct BoundedReader<TSource*,
+ typename enable_if<IsCharOrVoid<TSource>::value>::type>
+ : public IteratorReader<const char*> {
+ public:
+ explicit BoundedReader(const void* ptr, size_t len)
+ : IteratorReader<const char*>(reinterpret_cast<const char*>(ptr),
+ reinterpret_cast<const char*>(ptr) + len) {}
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp
new file mode 100644
index 0000000..eebaa2c
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp
@@ -0,0 +1,29 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <istream>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TSource>
+struct Reader<TSource, typename enable_if<
+ is_base_of<std::istream, TSource>::value>::type> {
+ public:
+ explicit Reader(std::istream& stream) : _stream(&stream) {}
+
+ int read() {
+ return _stream->get();
+ }
+
+ size_t readBytes(char* buffer, size_t length) {
+ _stream->read(buffer, static_cast<std::streamsize>(length));
+ return static_cast<size_t>(_stream->gcount());
+ }
+
+ private:
+ std::istream* _stream;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/Readers/VariantReader.hpp b/include/lib/ArduinoJson/Deserialization/Readers/VariantReader.hpp
new file mode 100644
index 0000000..e56e262
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/Readers/VariantReader.hpp
@@ -0,0 +1,34 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Object/MemberProxy.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TArray>
+struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> {
+ explicit Reader(const ElementProxy<TArray>& x)
+ : Reader<char*, void>(x.template as<const char*>()) {}
+};
+
+template <typename TObject, typename TStringRef>
+struct Reader<MemberProxy<TObject, TStringRef>, void> : Reader<char*, void> {
+ explicit Reader(const MemberProxy<TObject, TStringRef>& x)
+ : Reader<char*, void>(x.template as<const char*>()) {}
+};
+
+template <>
+struct Reader<VariantRef, void> : Reader<char*, void> {
+ explicit Reader(VariantRef x) : Reader<char*, void>(x.as<const char*>()) {}
+};
+
+template <>
+struct Reader<VariantConstRef, void> : Reader<char*, void> {
+ explicit Reader(VariantConstRef x)
+ : Reader<char*, void>(x.as<const char*>()) {}
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Deserialization/deserialize.hpp b/include/lib/ArduinoJson/Deserialization/deserialize.hpp
new file mode 100644
index 0000000..2329542
--- /dev/null
+++ b/include/lib/ArduinoJson/Deserialization/deserialize.hpp
@@ -0,0 +1,71 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Deserialization/DeserializationError.hpp>
+#include <ArduinoJson/Deserialization/Filter.hpp>
+#include <ArduinoJson/Deserialization/NestingLimit.hpp>
+#include <ArduinoJson/Deserialization/Reader.hpp>
+#include <ArduinoJson/StringStorage/StringStorage.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <template <typename, typename> class TDeserializer, typename TReader,
+ typename TWriter>
+TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
+ TReader reader,
+ TWriter writer) {
+ return TDeserializer<TReader, TWriter>(pool, reader, writer);
+}
+
+// deserialize(JsonDocument&, const std::string&, NestingLimit, Filter);
+// deserialize(JsonDocument&, const String&, NestingLimit, Filter);
+// deserialize(JsonDocument&, char*, NestingLimit, Filter);
+// deserialize(JsonDocument&, const char*, NestingLimit, Filter);
+// deserialize(JsonDocument&, const __FlashStringHelper*, NestingLimit, Filter);
+template <template <typename, typename> class TDeserializer, typename TString,
+ typename TFilter>
+typename enable_if<!is_array<TString>::value, DeserializationError>::type
+deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
+ TFilter filter) {
+ Reader<TString> reader(input);
+ doc.clear();
+ return makeDeserializer<TDeserializer>(
+ doc.memoryPool(), reader,
+ makeStringStorage(input, doc.memoryPool()))
+ .parse(doc.data(), filter, nestingLimit);
+}
+//
+// deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter);
+// deserialize(JsonDocument&, const char*, size_t, NestingLimit, Filter);
+// deserialize(JsonDocument&, const __FlashStringHelper*, size_t, NL, Filter);
+template <template <typename, typename> class TDeserializer, typename TChar,
+ typename TFilter>
+DeserializationError deserialize(JsonDocument &doc, TChar *input,
+ size_t inputSize, NestingLimit nestingLimit,
+ TFilter filter) {
+ BoundedReader<TChar *> reader(input, inputSize);
+ doc.clear();
+ return makeDeserializer<TDeserializer>(
+ doc.memoryPool(), reader,
+ makeStringStorage(input, doc.memoryPool()))
+ .parse(doc.data(), filter, nestingLimit);
+}
+//
+// deserialize(JsonDocument&, std::istream&, NestingLimit, Filter);
+// deserialize(JsonDocument&, Stream&, NestingLimit, Filter);
+template <template <typename, typename> class TDeserializer, typename TStream,
+ typename TFilter>
+DeserializationError deserialize(JsonDocument &doc, TStream &input,
+ NestingLimit nestingLimit, TFilter filter) {
+ Reader<TStream> reader(input);
+ doc.clear();
+ return makeDeserializer<TDeserializer>(
+ doc.memoryPool(), reader,
+ makeStringStorage(input, doc.memoryPool()))
+ .parse(doc.data(), filter, nestingLimit);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Document/BasicJsonDocument.hpp b/include/lib/ArduinoJson/Document/BasicJsonDocument.hpp
new file mode 100644
index 0000000..5c85d8a
--- /dev/null
+++ b/include/lib/ArduinoJson/Document/BasicJsonDocument.hpp
@@ -0,0 +1,164 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Document/JsonDocument.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Helper to implement the "base-from-member" idiom
+// (we need to store the allocator before constructing JsonDocument)
+template <typename TAllocator>
+class AllocatorOwner {
+ public:
+ AllocatorOwner() {}
+ AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {}
+ AllocatorOwner(TAllocator a) : _allocator(a) {}
+
+ void* allocate(size_t size) {
+ return _allocator.allocate(size);
+ }
+
+ void deallocate(void* ptr) {
+ if (ptr)
+ _allocator.deallocate(ptr);
+ }
+
+ void* reallocate(void* ptr, size_t new_size) {
+ return _allocator.reallocate(ptr, new_size);
+ }
+
+ TAllocator& allocator() {
+ return _allocator;
+ }
+
+ private:
+ TAllocator _allocator;
+};
+
+template <typename TAllocator>
+class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
+ public:
+ explicit BasicJsonDocument(size_t capa, TAllocator alloc = TAllocator())
+ : AllocatorOwner<TAllocator>(alloc), JsonDocument(allocPool(capa)) {}
+
+ // Copy-constructor
+ BasicJsonDocument(const BasicJsonDocument& src)
+ : AllocatorOwner<TAllocator>(src), JsonDocument() {
+ copyAssignFrom(src);
+ }
+
+ // Move-constructor
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+ BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner<TAllocator>(src) {
+ moveAssignFrom(src);
+ }
+#endif
+
+ BasicJsonDocument(const JsonDocument& src) {
+ copyAssignFrom(src);
+ }
+
+ // Construct from variant, array, or object
+ template <typename T>
+ BasicJsonDocument(
+ const T& src,
+ typename enable_if<
+ is_same<T, VariantRef>::value || is_same<T, VariantConstRef>::value ||
+ is_same<T, ArrayRef>::value || is_same<T, ArrayConstRef>::value ||
+ is_same<T, ObjectRef>::value ||
+ is_same<T, ObjectConstRef>::value>::type* = 0)
+ : JsonDocument(allocPool(src.memoryUsage())) {
+ set(src);
+ }
+
+ // disambiguate
+ BasicJsonDocument(VariantRef src)
+ : JsonDocument(allocPool(src.memoryUsage())) {
+ set(src);
+ }
+
+ ~BasicJsonDocument() {
+ freePool();
+ }
+
+ BasicJsonDocument& operator=(const BasicJsonDocument& src) {
+ copyAssignFrom(src);
+ return *this;
+ }
+
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+ BasicJsonDocument& operator=(BasicJsonDocument&& src) {
+ moveAssignFrom(src);
+ return *this;
+ }
+#endif
+
+ template <typename T>
+ BasicJsonDocument& operator=(const T& src) {
+ reallocPoolIfTooSmall(src.memoryUsage());
+ set(src);
+ return *this;
+ }
+
+ void shrinkToFit() {
+ ptrdiff_t bytes_reclaimed = _pool.squash();
+ if (bytes_reclaimed == 0)
+ return;
+
+ void* old_ptr = _pool.buffer();
+ void* new_ptr = this->reallocate(old_ptr, _pool.capacity());
+
+ ptrdiff_t ptr_offset =
+ static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
+
+ _pool.movePointers(ptr_offset);
+ _data.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
+ }
+
+ bool garbageCollect() {
+ // make a temporary clone and move assign
+ BasicJsonDocument tmp(*this);
+ if (!tmp.capacity())
+ return false;
+ tmp.set(*this);
+ moveAssignFrom(tmp);
+ return true;
+ }
+
+ using AllocatorOwner<TAllocator>::allocator;
+
+ private:
+ MemoryPool allocPool(size_t requiredSize) {
+ size_t capa = addPadding(requiredSize);
+ return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa);
+ }
+
+ void reallocPoolIfTooSmall(size_t requiredSize) {
+ if (requiredSize <= capacity())
+ return;
+ freePool();
+ replacePool(allocPool(addPadding(requiredSize)));
+ }
+
+ void freePool() {
+ this->deallocate(memoryPool().buffer());
+ }
+
+ void copyAssignFrom(const JsonDocument& src) {
+ reallocPoolIfTooSmall(src.capacity());
+ set(src);
+ }
+
+ void moveAssignFrom(BasicJsonDocument& src) {
+ freePool();
+ _data = src._data;
+ _pool = src._pool;
+ src._data.setNull();
+ src._pool = MemoryPool(0, 0);
+ }
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Document/DynamicJsonDocument.hpp b/include/lib/ArduinoJson/Document/DynamicJsonDocument.hpp
new file mode 100644
index 0000000..de6f411
--- /dev/null
+++ b/include/lib/ArduinoJson/Document/DynamicJsonDocument.hpp
@@ -0,0 +1,29 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Document/BasicJsonDocument.hpp>
+
+#include <stdlib.h> // malloc, free
+
+namespace ARDUINOJSON_NAMESPACE {
+
+struct DefaultAllocator {
+ void* allocate(size_t size) {
+ return malloc(size);
+ }
+
+ void deallocate(void* ptr) {
+ free(ptr);
+ }
+
+ void* reallocate(void* ptr, size_t new_size) {
+ return realloc(ptr, new_size);
+ }
+};
+
+typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Document/JsonDocument.hpp b/include/lib/ArduinoJson/Document/JsonDocument.hpp
new file mode 100644
index 0000000..d67d934
--- /dev/null
+++ b/include/lib/ArduinoJson/Document/JsonDocument.hpp
@@ -0,0 +1,344 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ElementProxy.hpp>
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Object/MemberProxy.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+#include <ArduinoJson/Variant/VariantTo.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class JsonDocument : public Visitable {
+ public:
+ template <typename TVisitor>
+ typename TVisitor::result_type accept(TVisitor& visitor) const {
+ return getVariant().accept(visitor);
+ }
+
+ template <typename T>
+ T as() {
+ return getVariant().template as<T>();
+ }
+
+ template <typename T>
+ T as() const {
+ return getVariant().template as<T>();
+ }
+
+ void clear() {
+ _pool.clear();
+ _data.setNull();
+ }
+
+ template <typename T>
+ bool is() {
+ return getVariant().template is<T>();
+ }
+
+ template <typename T>
+ bool is() const {
+ return getVariant().template is<T>();
+ }
+
+ bool isNull() const {
+ return getVariant().isNull();
+ }
+
+ size_t memoryUsage() const {
+ return _pool.size();
+ }
+
+ bool overflowed() const {
+ return _pool.overflowed();
+ }
+
+ size_t nesting() const {
+ return _data.nesting();
+ }
+
+ size_t capacity() const {
+ return _pool.capacity();
+ }
+
+ size_t size() const {
+ return _data.size();
+ }
+
+ bool set(const JsonDocument& src) {
+ return to<VariantRef>().set(src.as<VariantConstRef>());
+ }
+
+ template <typename T>
+ typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
+ const T& src) {
+ return to<VariantRef>().set(src);
+ }
+
+ template <typename T>
+ typename VariantTo<T>::type to() {
+ clear();
+ return getVariant().template to<T>();
+ }
+
+ // for internal use only
+ MemoryPool& memoryPool() {
+ return _pool;
+ }
+
+ // for internal use only
+ VariantData& data() {
+ return _data;
+ }
+
+ ArrayRef createNestedArray() {
+ return addElement().to<ArrayRef>();
+ }
+
+ // createNestedArray(char*)
+ // createNestedArray(const char*)
+ // createNestedArray(const __FlashStringHelper*)
+ template <typename TChar>
+ ArrayRef createNestedArray(TChar* key) {
+ return getOrAddMember(key).template to<ArrayRef>();
+ }
+
+ // createNestedArray(const std::string&)
+ // createNestedArray(const String&)
+ template <typename TString>
+ ArrayRef createNestedArray(const TString& key) {
+ return getOrAddMember(key).template to<ArrayRef>();
+ }
+
+ ObjectRef createNestedObject() {
+ return addElement().to<ObjectRef>();
+ }
+
+ // createNestedObject(char*)
+ // createNestedObject(const char*)
+ // createNestedObject(const __FlashStringHelper*)
+ template <typename TChar>
+ ObjectRef createNestedObject(TChar* key) {
+ return getOrAddMember(key).template to<ObjectRef>();
+ }
+
+ // createNestedObject(const std::string&)
+ // createNestedObject(const String&)
+ template <typename TString>
+ ObjectRef createNestedObject(const TString& key) {
+ return getOrAddMember(key).template to<ObjectRef>();
+ }
+
+ // containsKey(char*) const
+ // containsKey(const char*) const
+ // containsKey(const __FlashStringHelper*) const
+ template <typename TChar>
+ bool containsKey(TChar* key) const {
+ return !getMember(key).isUndefined();
+ }
+
+ // containsKey(const std::string&) const
+ // containsKey(const String&) const
+ template <typename TString>
+ bool containsKey(const TString& key) const {
+ return !getMember(key).isUndefined();
+ }
+
+ // operator[](const std::string&)
+ // operator[](const String&)
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value,
+ MemberProxy<JsonDocument&, TString> >::type
+ operator[](const TString& key) {
+ return MemberProxy<JsonDocument&, TString>(*this, key);
+ }
+
+ // operator[](char*)
+ // operator[](const char*)
+ // operator[](const __FlashStringHelper*)
+ template <typename TChar>
+ FORCE_INLINE typename enable_if<IsString<TChar*>::value,
+ MemberProxy<JsonDocument&, TChar*> >::type
+ operator[](TChar* key) {
+ return MemberProxy<JsonDocument&, TChar*>(*this, key);
+ }
+
+ // operator[](const std::string&) const
+ // operator[](const String&) const
+ template <typename TString>
+ FORCE_INLINE
+ typename enable_if<IsString<TString>::value, VariantConstRef>::type
+ operator[](const TString& key) const {
+ return getMember(key);
+ }
+
+ // operator[](char*) const
+ // operator[](const char*) const
+ // operator[](const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE
+ typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
+ operator[](TChar* key) const {
+ return getMember(key);
+ }
+
+ FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
+ return ElementProxy<JsonDocument&>(*this, index);
+ }
+
+ FORCE_INLINE VariantConstRef operator[](size_t index) const {
+ return getElement(index);
+ }
+
+ FORCE_INLINE VariantRef getElement(size_t index) {
+ return VariantRef(&_pool, _data.getElement(index));
+ }
+
+ FORCE_INLINE VariantConstRef getElement(size_t index) const {
+ return VariantConstRef(_data.getElement(index));
+ }
+
+ FORCE_INLINE VariantRef getOrAddElement(size_t index) {
+ return VariantRef(&_pool, _data.getOrAddElement(index, &_pool));
+ }
+
+ // JsonVariantConst getMember(char*) const
+ // JsonVariantConst getMember(const char*) const
+ // JsonVariantConst getMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantConstRef getMember(TChar* key) const {
+ return VariantConstRef(_data.getMember(adaptString(key)));
+ }
+
+ // JsonVariantConst getMember(const std::string&) const
+ // JsonVariantConst getMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE
+ typename enable_if<IsString<TString>::value, VariantConstRef>::type
+ getMember(const TString& key) const {
+ return VariantConstRef(_data.getMember(adaptString(key)));
+ }
+
+ // JsonVariant getMember(char*)
+ // JsonVariant getMember(const char*)
+ // JsonVariant getMember(const __FlashStringHelper*)
+ template <typename TChar>
+ FORCE_INLINE VariantRef getMember(TChar* key) {
+ return VariantRef(&_pool, _data.getMember(adaptString(key)));
+ }
+
+ // JsonVariant getMember(const std::string&)
+ // JsonVariant getMember(const String&)
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
+ getMember(const TString& key) {
+ return VariantRef(&_pool, _data.getMember(adaptString(key)));
+ }
+
+ // getOrAddMember(char*)
+ // getOrAddMember(const char*)
+ // getOrAddMember(const __FlashStringHelper*)
+ template <typename TChar>
+ FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
+ return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
+ }
+
+ // getOrAddMember(const std::string&)
+ // getOrAddMember(const String&)
+ template <typename TString>
+ FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
+ return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
+ }
+
+ FORCE_INLINE VariantRef addElement() {
+ return VariantRef(&_pool, _data.addElement(&_pool));
+ }
+
+ template <typename TValue>
+ FORCE_INLINE bool add(const TValue& value) {
+ return addElement().set(value);
+ }
+
+ // add(char*) const
+ // add(const char*) const
+ // add(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE bool add(TChar* value) {
+ return addElement().set(value);
+ }
+
+ FORCE_INLINE void remove(size_t index) {
+ _data.remove(index);
+ }
+ // remove(char*)
+ // remove(const char*)
+ // remove(const __FlashStringHelper*)
+ template <typename TChar>
+ FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
+ TChar* key) {
+ _data.remove(adaptString(key));
+ }
+ // remove(const std::string&)
+ // remove(const String&)
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+ const TString& key) {
+ _data.remove(adaptString(key));
+ }
+
+ FORCE_INLINE operator VariantConstRef() const {
+ return VariantConstRef(&_data);
+ }
+
+ bool operator==(VariantConstRef rhs) const {
+ return getVariant() == rhs;
+ }
+
+ bool operator!=(VariantConstRef rhs) const {
+ return getVariant() != rhs;
+ }
+
+ protected:
+ JsonDocument() : _pool(0, 0) {
+ _data.setNull();
+ }
+
+ JsonDocument(MemoryPool pool) : _pool(pool) {
+ _data.setNull();
+ }
+
+ JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
+ _data.setNull();
+ }
+
+ ~JsonDocument() {}
+
+ void replacePool(MemoryPool pool) {
+ _pool = pool;
+ }
+
+ VariantRef getVariant() {
+ return VariantRef(&_pool, &_data);
+ }
+
+ VariantConstRef getVariant() const {
+ return VariantConstRef(&_data);
+ }
+
+ MemoryPool _pool;
+ VariantData _data;
+
+ private:
+ JsonDocument(const JsonDocument&);
+ JsonDocument& operator=(const JsonDocument&);
+};
+
+inline bool convertToJson(const JsonDocument& src, VariantRef dst) {
+ return dst.set(src.as<VariantConstRef>());
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Document/StaticJsonDocument.hpp b/include/lib/ArduinoJson/Document/StaticJsonDocument.hpp
new file mode 100644
index 0000000..fbbadd4
--- /dev/null
+++ b/include/lib/ArduinoJson/Document/StaticJsonDocument.hpp
@@ -0,0 +1,56 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Document/JsonDocument.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <size_t desiredCapacity>
+class StaticJsonDocument : public JsonDocument {
+ static const size_t _capacity =
+ AddPadding<Max<1, desiredCapacity>::value>::value;
+
+ public:
+ StaticJsonDocument() : JsonDocument(_buffer, _capacity) {}
+
+ StaticJsonDocument(const StaticJsonDocument& src)
+ : JsonDocument(_buffer, _capacity) {
+ set(src);
+ }
+
+ template <typename T>
+ StaticJsonDocument(const T& src,
+ typename enable_if<IsVisitable<T>::value>::type* = 0)
+ : JsonDocument(_buffer, _capacity) {
+ set(src);
+ }
+
+ // disambiguate
+ StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) {
+ set(src);
+ }
+
+ StaticJsonDocument operator=(const StaticJsonDocument& src) {
+ set(src);
+ return *this;
+ }
+
+ template <typename T>
+ StaticJsonDocument operator=(const T& src) {
+ set(src);
+ return *this;
+ }
+
+ void garbageCollect() {
+ StaticJsonDocument tmp(*this);
+ set(tmp);
+ }
+
+ private:
+ char _buffer[_capacity];
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Json/EscapeSequence.hpp b/include/lib/ArduinoJson/Json/EscapeSequence.hpp
new file mode 100644
index 0000000..811e825
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/EscapeSequence.hpp
@@ -0,0 +1,39 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class EscapeSequence {
+ public:
+ // Optimized for code size on a 8-bit AVR
+ static char escapeChar(char c) {
+ const char *p = escapeTable(true);
+ while (p[0] && p[1] != c) {
+ p += 2;
+ }
+ return p[0];
+ }
+
+ // Optimized for code size on a 8-bit AVR
+ static char unescapeChar(char c) {
+ const char *p = escapeTable(false);
+ for (;;) {
+ if (p[0] == '\0')
+ return 0;
+ if (p[0] == c)
+ return p[1];
+ p += 2;
+ }
+ }
+
+ private:
+ static const char *escapeTable(bool excludeSolidus) {
+ return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Json/JsonDeserializer.hpp b/include/lib/ArduinoJson/Json/JsonDeserializer.hpp
new file mode 100644
index 0000000..1a07be8
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/JsonDeserializer.hpp
@@ -0,0 +1,740 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Deserialization/deserialize.hpp>
+#include <ArduinoJson/Json/EscapeSequence.hpp>
+#include <ArduinoJson/Json/Latch.hpp>
+#include <ArduinoJson/Json/Utf16.hpp>
+#include <ArduinoJson/Json/Utf8.hpp>
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Numbers/parseNumber.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TReader, typename TStringStorage>
+class JsonDeserializer {
+ public:
+ JsonDeserializer(MemoryPool &pool, TReader reader,
+ TStringStorage stringStorage)
+ : _stringStorage(stringStorage),
+ _foundSomething(false),
+ _latch(reader),
+ _pool(&pool),
+ _error(DeserializationError::Ok) {}
+
+ template <typename TFilter>
+ DeserializationError parse(VariantData &variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ parseVariant(variant, filter, nestingLimit);
+
+ if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
+ // We don't detect trailing characters earlier, so we need to check now
+ return DeserializationError::InvalidInput;
+ }
+
+ return _error;
+ }
+
+ private:
+ char current() {
+ return _latch.current();
+ }
+
+ void move() {
+ _latch.clear();
+ }
+
+ bool eat(char charToSkip) {
+ if (current() != charToSkip)
+ return false;
+ move();
+ return true;
+ }
+
+ template <typename TFilter>
+ bool parseVariant(VariantData &variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ if (!skipSpacesAndComments())
+ return false;
+
+ switch (current()) {
+ case '[':
+ if (filter.allowArray())
+ return parseArray(variant.toArray(), filter, nestingLimit);
+ else
+ return skipArray(nestingLimit);
+
+ case '{':
+ if (filter.allowObject())
+ return parseObject(variant.toObject(), filter, nestingLimit);
+ else
+ return skipObject(nestingLimit);
+
+ case '\"':
+ case '\'':
+ if (filter.allowValue())
+ return parseStringValue(variant);
+ else
+ return skipString();
+
+ default:
+ if (filter.allowValue())
+ return parseNumericValue(variant);
+ else
+ return skipNumericValue();
+ }
+ }
+
+ bool skipVariant(NestingLimit nestingLimit) {
+ if (!skipSpacesAndComments())
+ return false;
+
+ switch (current()) {
+ case '[':
+ return skipArray(nestingLimit);
+
+ case '{':
+ return skipObject(nestingLimit);
+
+ case '\"':
+ case '\'':
+ return skipString();
+
+ default:
+ return skipNumericValue();
+ }
+ }
+
+ template <typename TFilter>
+ bool parseArray(CollectionData &array, TFilter filter,
+ NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ // Skip opening braket
+ ARDUINOJSON_ASSERT(current() == '[');
+ move();
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // Empty array?
+ if (eat(']'))
+ return true;
+
+ TFilter memberFilter = filter[0UL];
+
+ // Read each value
+ for (;;) {
+ if (memberFilter.allow()) {
+ // Allocate slot in array
+ VariantData *value = array.addElement(_pool);
+ if (!value) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ // 1 - Parse value
+ if (!parseVariant(*value, memberFilter, nestingLimit.decrement()))
+ return false;
+ } else {
+ if (!skipVariant(nestingLimit.decrement()))
+ return false;
+ }
+
+ // 2 - Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // 3 - More values?
+ if (eat(']'))
+ return true;
+ if (!eat(',')) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+ }
+ }
+
+ bool skipArray(NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ // Skip opening braket
+ ARDUINOJSON_ASSERT(current() == '[');
+ move();
+
+ // Read each value
+ for (;;) {
+ // 1 - Skip value
+ if (!skipVariant(nestingLimit.decrement()))
+ return false;
+
+ // 2 - Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // 3 - More values?
+ if (eat(']'))
+ return true;
+ if (!eat(',')) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+ }
+ }
+
+ template <typename TFilter>
+ bool parseObject(CollectionData &object, TFilter filter,
+ NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ // Skip opening brace
+ ARDUINOJSON_ASSERT(current() == '{');
+ move();
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // Empty object?
+ if (eat('}'))
+ return true;
+
+ // Read each key value pair
+ for (;;) {
+ // Parse key
+ if (!parseKey())
+ return false;
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // Colon
+ if (!eat(':')) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+
+ const char *key = _stringStorage.c_str();
+
+ TFilter memberFilter = filter[key];
+
+ if (memberFilter.allow()) {
+ VariantData *variant = object.getMember(adaptString(key));
+ if (!variant) {
+ // Save key in memory pool.
+ // This MUST be done before adding the slot.
+ key = _stringStorage.save();
+
+ // Allocate slot in object
+ VariantSlot *slot = object.addSlot(_pool);
+ if (!slot) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ slot->setKey(key, typename TStringStorage::storage_policy());
+
+ variant = slot->data();
+ }
+
+ // Parse value
+ if (!parseVariant(*variant, memberFilter, nestingLimit.decrement()))
+ return false;
+ } else {
+ if (!skipVariant(nestingLimit.decrement()))
+ return false;
+ }
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // More keys/values?
+ if (eat('}'))
+ return true;
+ if (!eat(',')) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+ }
+ }
+
+ bool skipObject(NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ // Skip opening brace
+ ARDUINOJSON_ASSERT(current() == '{');
+ move();
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // Empty object?
+ if (eat('}'))
+ return true;
+
+ // Read each key value pair
+ for (;;) {
+ // Skip key
+ if (!skipVariant(nestingLimit.decrement()))
+ return false;
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // Colon
+ if (!eat(':')) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+
+ // Skip value
+ if (!skipVariant(nestingLimit.decrement()))
+ return false;
+
+ // Skip spaces
+ if (!skipSpacesAndComments())
+ return false;
+
+ // More keys/values?
+ if (eat('}'))
+ return true;
+ if (!eat(',')) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+ }
+ }
+
+ bool parseKey() {
+ _stringStorage.startString();
+ if (isQuote(current())) {
+ return parseQuotedString();
+ } else {
+ return parseNonQuotedString();
+ }
+ }
+
+ bool parseStringValue(VariantData &variant) {
+ _stringStorage.startString();
+ if (!parseQuotedString())
+ return false;
+ const char *value = _stringStorage.save();
+ variant.setStringPointer(value, typename TStringStorage::storage_policy());
+ return true;
+ }
+
+ bool parseQuotedString() {
+#if ARDUINOJSON_DECODE_UNICODE
+ Utf16::Codepoint codepoint;
+#endif
+ const char stopChar = current();
+
+ move();
+ for (;;) {
+ char c = current();
+ move();
+ if (c == stopChar)
+ break;
+
+ if (c == '\0') {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+
+ if (c == '\\') {
+ c = current();
+
+ if (c == '\0') {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+
+ if (c == 'u') {
+#if ARDUINOJSON_DECODE_UNICODE
+ move();
+ uint16_t codeunit;
+ if (!parseHex4(codeunit))
+ return false;
+ if (codepoint.append(codeunit))
+ Utf8::encodeCodepoint(codepoint.value(), _stringStorage);
+#else
+ _stringStorage.append('\\');
+#endif
+ continue;
+ }
+
+ // replace char
+ c = EscapeSequence::unescapeChar(c);
+ if (c == '\0') {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+ move();
+ }
+
+ _stringStorage.append(c);
+ }
+
+ _stringStorage.append('\0');
+
+ if (!_stringStorage.isValid()) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool parseNonQuotedString() {
+ char c = current();
+ ARDUINOJSON_ASSERT(c);
+
+ if (canBeInNonQuotedString(c)) { // no quotes
+ do {
+ move();
+ _stringStorage.append(c);
+ c = current();
+ } while (canBeInNonQuotedString(c));
+ } else {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+
+ _stringStorage.append('\0');
+
+ if (!_stringStorage.isValid()) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool skipString() {
+ const char stopChar = current();
+
+ move();
+ for (;;) {
+ char c = current();
+ move();
+ if (c == stopChar)
+ break;
+ if (c == '\0') {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ if (c == '\\') {
+ if (current() != '\0')
+ move();
+ }
+ }
+
+ return true;
+ }
+
+ bool parseNumericValue(VariantData &result) {
+ uint8_t n = 0;
+
+ char c = current();
+ while (canBeInNonQuotedString(c) && n < 63) {
+ move();
+ _buffer[n++] = c;
+ c = current();
+ }
+ _buffer[n] = 0;
+
+ c = _buffer[0];
+ if (c == 't') { // true
+ result.setBoolean(true);
+ if (n != 4) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ return true;
+ }
+ if (c == 'f') { // false
+ result.setBoolean(false);
+ if (n != 5) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ return true;
+ }
+ if (c == 'n') { // null
+ // the variant is already null
+ if (n != 4) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ return true;
+ }
+
+ if (!parseNumber(_buffer, result)) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+
+ return true;
+ }
+
+ bool skipNumericValue() {
+ char c = current();
+ while (canBeInNonQuotedString(c)) {
+ move();
+ c = current();
+ }
+ return true;
+ }
+
+ bool parseHex4(uint16_t &result) {
+ result = 0;
+ for (uint8_t i = 0; i < 4; ++i) {
+ char digit = current();
+ if (!digit) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ uint8_t value = decodeHex(digit);
+ if (value > 0x0F) {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+ result = uint16_t((result << 4) | value);
+ move();
+ }
+ return true;
+ }
+
+ static inline bool isBetween(char c, char min, char max) {
+ return min <= c && c <= max;
+ }
+
+ static inline bool canBeInNonQuotedString(char c) {
+ return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
+ isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
+ }
+
+ static inline bool isQuote(char c) {
+ return c == '\'' || c == '\"';
+ }
+
+ static inline uint8_t decodeHex(char c) {
+ if (c < 'A')
+ return uint8_t(c - '0');
+ c = char(c & ~0x20); // uppercase
+ return uint8_t(c - 'A' + 10);
+ }
+
+ bool skipSpacesAndComments() {
+ for (;;) {
+ switch (current()) {
+ // end of string
+ case '\0':
+ _error = _foundSomething ? DeserializationError::IncompleteInput
+ : DeserializationError::EmptyInput;
+ return false;
+
+ // spaces
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ move();
+ continue;
+
+#if ARDUINOJSON_ENABLE_COMMENTS
+ // comments
+ case '/':
+ move(); // skip '/'
+ switch (current()) {
+ // block comment
+ case '*': {
+ move(); // skip '*'
+ bool wasStar = false;
+ for (;;) {
+ char c = current();
+ if (c == '\0') {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ if (c == '/' && wasStar) {
+ move();
+ break;
+ }
+ wasStar = c == '*';
+ move();
+ }
+ break;
+ }
+
+ // trailing comment
+ case '/':
+ // no need to skip "//"
+ for (;;) {
+ move();
+ char c = current();
+ if (c == '\0') {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ if (c == '\n')
+ break;
+ }
+ break;
+
+ // not a comment, just a '/'
+ default:
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+ break;
+#endif
+
+ default:
+ _foundSomething = true;
+ return true;
+ }
+ }
+ }
+
+ TStringStorage _stringStorage;
+ bool _foundSomething;
+ Latch<TReader> _latch;
+ MemoryPool *_pool;
+ char _buffer[64]; // using a member instead of a local variable because it
+ // ended in the recursive path after compiler inlined the
+ // code
+ DeserializationError _error;
+};
+
+//
+// deserializeJson(JsonDocument&, const std::string&, ...)
+//
+// ... = NestingLimit
+template <typename TString>
+DeserializationError deserializeJson(
+ JsonDocument &doc, const TString &input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TString>
+DeserializationError deserializeJson(
+ JsonDocument &doc, const TString &input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TString>
+DeserializationError deserializeJson(JsonDocument &doc, const TString &input,
+ NestingLimit nestingLimit, Filter filter) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeJson(JsonDocument&, std::istream&, ...)
+//
+// ... = NestingLimit
+template <typename TStream>
+DeserializationError deserializeJson(
+ JsonDocument &doc, TStream &input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TStream>
+DeserializationError deserializeJson(
+ JsonDocument &doc, TStream &input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TStream>
+DeserializationError deserializeJson(JsonDocument &doc, TStream &input,
+ NestingLimit nestingLimit, Filter filter) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeJson(JsonDocument&, char*, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+ JsonDocument &doc, TChar *input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+ JsonDocument &doc, TChar *input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
+ NestingLimit nestingLimit, Filter filter) {
+ return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeJson(JsonDocument&, char*, size_t, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+ JsonDocument &doc, TChar *input, size_t inputSize,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeJson(
+ JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
+ filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
+ size_t inputSize,
+ NestingLimit nestingLimit, Filter filter) {
+ return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
+ filter);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Json/JsonSerializer.hpp b/include/lib/ArduinoJson/Json/JsonSerializer.hpp
new file mode 100644
index 0000000..5cb9aa2
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/JsonSerializer.hpp
@@ -0,0 +1,137 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Json/TextFormatter.hpp>
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Serialization/measure.hpp>
+#include <ArduinoJson/Serialization/serialize.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class JsonSerializer : public Visitor<size_t> {
+ public:
+ static const bool producesText = true;
+
+ JsonSerializer(TWriter writer) : _formatter(writer) {}
+
+ FORCE_INLINE size_t visitArray(const CollectionData &array) {
+ write('[');
+
+ VariantSlot *slot = array.head();
+
+ while (slot != 0) {
+ slot->data()->accept(*this);
+
+ slot = slot->next();
+ if (slot == 0)
+ break;
+
+ write(',');
+ }
+
+ write(']');
+ return bytesWritten();
+ }
+
+ size_t visitObject(const CollectionData &object) {
+ write('{');
+
+ VariantSlot *slot = object.head();
+
+ while (slot != 0) {
+ _formatter.writeString(slot->key());
+ write(':');
+ slot->data()->accept(*this);
+
+ slot = slot->next();
+ if (slot == 0)
+ break;
+
+ write(',');
+ }
+
+ write('}');
+ return bytesWritten();
+ }
+
+ size_t visitFloat(Float value) {
+ _formatter.writeFloat(value);
+ return bytesWritten();
+ }
+
+ size_t visitString(const char *value) {
+ _formatter.writeString(value);
+ return bytesWritten();
+ }
+
+ size_t visitRawJson(const char *data, size_t n) {
+ _formatter.writeRaw(data, n);
+ return bytesWritten();
+ }
+
+ size_t visitSignedInteger(Integer value) {
+ _formatter.writeInteger(value);
+ return bytesWritten();
+ }
+
+ size_t visitUnsignedInteger(UInt value) {
+ _formatter.writeInteger(value);
+ return bytesWritten();
+ }
+
+ size_t visitBoolean(bool value) {
+ _formatter.writeBoolean(value);
+ return bytesWritten();
+ }
+
+ size_t visitNull() {
+ _formatter.writeRaw("null");
+ return bytesWritten();
+ }
+
+ protected:
+ size_t bytesWritten() const {
+ return _formatter.bytesWritten();
+ }
+
+ void write(char c) {
+ _formatter.writeRaw(c);
+ }
+
+ void write(const char *s) {
+ _formatter.writeRaw(s);
+ }
+
+ private:
+ TextFormatter<TWriter> _formatter;
+};
+
+template <typename TSource, typename TDestination>
+size_t serializeJson(const TSource &source, TDestination &destination) {
+ return serialize<JsonSerializer>(source, destination);
+}
+
+template <typename TSource>
+size_t serializeJson(const TSource &source, void *buffer, size_t bufferSize) {
+ return serialize<JsonSerializer>(source, buffer, bufferSize);
+}
+
+template <typename TSource>
+size_t measureJson(const TSource &source) {
+ return measure<JsonSerializer>(source);
+}
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+template <typename T>
+inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
+operator<<(std::ostream &os, const T &source) {
+ serializeJson(source, os);
+ return os;
+}
+#endif
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Json/Latch.hpp b/include/lib/ArduinoJson/Json/Latch.hpp
new file mode 100644
index 0000000..aef1fe3
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/Latch.hpp
@@ -0,0 +1,55 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TReader>
+class Latch {
+ public:
+ Latch(TReader reader) : _reader(reader), _loaded(false) {
+#if ARDUINOJSON_DEBUG
+ _ended = false;
+#endif
+ }
+
+ void clear() {
+ _loaded = false;
+ }
+
+ int last() const {
+ return _current;
+ }
+
+ FORCE_INLINE char current() {
+ if (!_loaded) {
+ load();
+ }
+ return _current;
+ }
+
+ private:
+ void load() {
+ ARDUINOJSON_ASSERT(!_ended);
+ int c = _reader.read();
+#if ARDUINOJSON_DEBUG
+ if (c <= 0)
+ _ended = true;
+#endif
+ _current = static_cast<char>(c > 0 ? c : 0);
+ _loaded = true;
+ }
+
+ TReader _reader;
+ char _current;
+ bool _loaded;
+#if ARDUINOJSON_DEBUG
+ bool _ended;
+#endif
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Json/PrettyJsonSerializer.hpp b/include/lib/ArduinoJson/Json/PrettyJsonSerializer.hpp
new file mode 100644
index 0000000..dbb0c17
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/PrettyJsonSerializer.hpp
@@ -0,0 +1,89 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Json/JsonSerializer.hpp>
+#include <ArduinoJson/Serialization/measure.hpp>
+#include <ArduinoJson/Serialization/serialize.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class PrettyJsonSerializer : public JsonSerializer<TWriter> {
+ typedef JsonSerializer<TWriter> base;
+
+ public:
+ PrettyJsonSerializer(TWriter writer) : base(writer), _nesting(0) {}
+
+ size_t visitArray(const CollectionData &array) {
+ VariantSlot *slot = array.head();
+ if (slot) {
+ base::write("[\r\n");
+ _nesting++;
+ while (slot != 0) {
+ indent();
+ slot->data()->accept(*this);
+
+ slot = slot->next();
+ base::write(slot ? ",\r\n" : "\r\n");
+ }
+ _nesting--;
+ indent();
+ base::write("]");
+ } else {
+ base::write("[]");
+ }
+ return this->bytesWritten();
+ }
+
+ size_t visitObject(const CollectionData &object) {
+ VariantSlot *slot = object.head();
+ if (slot) {
+ base::write("{\r\n");
+ _nesting++;
+ while (slot != 0) {
+ indent();
+ base::visitString(slot->key());
+ base::write(": ");
+ slot->data()->accept(*this);
+
+ slot = slot->next();
+ base::write(slot ? ",\r\n" : "\r\n");
+ }
+ _nesting--;
+ indent();
+ base::write("}");
+ } else {
+ base::write("{}");
+ }
+ return this->bytesWritten();
+ }
+
+ private:
+ void indent() {
+ for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
+ }
+
+ uint8_t _nesting;
+};
+
+template <typename TSource, typename TDestination>
+size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
+ return serialize<PrettyJsonSerializer>(source, destination);
+}
+
+template <typename TSource>
+size_t serializeJsonPretty(const TSource &source, void *buffer,
+ size_t bufferSize) {
+ return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
+}
+
+template <typename TSource>
+size_t measureJsonPretty(const TSource &source) {
+ return measure<PrettyJsonSerializer>(source);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Json/TextFormatter.hpp b/include/lib/ArduinoJson/Json/TextFormatter.hpp
new file mode 100644
index 0000000..18694f1
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/TextFormatter.hpp
@@ -0,0 +1,163 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stdint.h>
+#include <string.h> // for strlen
+
+#include <ArduinoJson/Json/EscapeSequence.hpp>
+#include <ArduinoJson/Numbers/FloatParts.hpp>
+#include <ArduinoJson/Numbers/Integer.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Serialization/CountingDecorator.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class TextFormatter {
+ public:
+ explicit TextFormatter(TWriter writer) : _writer(writer) {}
+
+ // Returns the number of bytes sent to the TWriter implementation.
+ size_t bytesWritten() const {
+ return _writer.count();
+ }
+
+ void writeBoolean(bool value) {
+ if (value)
+ writeRaw("true");
+ else
+ writeRaw("false");
+ }
+
+ void writeString(const char *value) {
+ ARDUINOJSON_ASSERT(value != NULL);
+ writeRaw('\"');
+ while (*value) writeChar(*value++);
+ writeRaw('\"');
+ }
+
+ void writeChar(char c) {
+ char specialChar = EscapeSequence::escapeChar(c);
+ if (specialChar) {
+ writeRaw('\\');
+ writeRaw(specialChar);
+ } else {
+ writeRaw(c);
+ }
+ }
+
+ template <typename T>
+ void writeFloat(T value) {
+ if (isnan(value))
+ return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
+
+#if ARDUINOJSON_ENABLE_INFINITY
+ if (value < 0.0) {
+ writeRaw('-');
+ value = -value;
+ }
+
+ if (isinf(value))
+ return writeRaw("Infinity");
+#else
+ if (isinf(value))
+ return writeRaw("null");
+
+ if (value < 0.0) {
+ writeRaw('-');
+ value = -value;
+ }
+#endif
+
+ FloatParts<T> parts(value);
+
+ writeInteger(parts.integral);
+ if (parts.decimalPlaces)
+ writeDecimals(parts.decimal, parts.decimalPlaces);
+
+ if (parts.exponent) {
+ writeRaw('e');
+ writeInteger(parts.exponent);
+ }
+ }
+
+ template <typename T>
+ typename enable_if<is_signed<T>::value>::type writeInteger(T value) {
+ typedef typename make_unsigned<T>::type unsigned_type;
+ unsigned_type unsigned_value;
+ if (value < 0) {
+ writeRaw('-');
+ unsigned_value = unsigned_type(unsigned_type(~value) + 1);
+ } else {
+ unsigned_value = unsigned_type(value);
+ }
+ writeInteger(unsigned_value);
+ }
+
+ template <typename T>
+ typename enable_if<is_unsigned<T>::value>::type writeInteger(T value) {
+ char buffer[22];
+ char *end = buffer + sizeof(buffer);
+ char *begin = end;
+
+ // write the string in reverse order
+ do {
+ *--begin = char(value % 10 + '0');
+ value = T(value / 10);
+ } while (value);
+
+ // and dump it in the right order
+ writeRaw(begin, end);
+ }
+
+ void writeDecimals(uint32_t value, int8_t width) {
+ // buffer should be big enough for all digits and the dot
+ char buffer[16];
+ char *end = buffer + sizeof(buffer);
+ char *begin = end;
+
+ // write the string in reverse order
+ while (width--) {
+ *--begin = char(value % 10 + '0');
+ value /= 10;
+ }
+ *--begin = '.';
+
+ // and dump it in the right order
+ writeRaw(begin, end);
+ }
+
+ void writeRaw(const char *s) {
+ _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
+ }
+
+ void writeRaw(const char *s, size_t n) {
+ _writer.write(reinterpret_cast<const uint8_t *>(s), n);
+ }
+
+ void writeRaw(const char *begin, const char *end) {
+ _writer.write(reinterpret_cast<const uint8_t *>(begin),
+ static_cast<size_t>(end - begin));
+ }
+
+ template <size_t N>
+ void writeRaw(const char (&s)[N]) {
+ _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
+ }
+ void writeRaw(char c) {
+ _writer.write(static_cast<uint8_t>(c));
+ }
+
+ protected:
+ CountingDecorator<TWriter> _writer;
+ size_t _length;
+
+ private:
+ TextFormatter &operator=(const TextFormatter &); // cannot be assigned
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Json/Utf16.hpp b/include/lib/ArduinoJson/Json/Utf16.hpp
new file mode 100644
index 0000000..4e2750f
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/Utf16.hpp
@@ -0,0 +1,67 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdint.h> // uint16_t, uint32_t
+
+// The high surrogate may be uninitialized if the pair is invalid,
+// we choose to ignore the problem to reduce the size of the code
+// Garbage in => Garbage out
+#if defined(__GNUC__)
+#if __GNUC__ >= 7
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+namespace Utf16 {
+inline bool isHighSurrogate(uint16_t codeunit) {
+ return codeunit >= 0xD800 && codeunit < 0xDC00;
+}
+
+inline bool isLowSurrogate(uint16_t codeunit) {
+ return codeunit >= 0xDC00 && codeunit < 0xE000;
+}
+
+class Codepoint {
+ public:
+ Codepoint() : _highSurrogate(0) {}
+
+ bool append(uint16_t codeunit) {
+ if (isHighSurrogate(codeunit)) {
+ _highSurrogate = codeunit & 0x3FF;
+ return false;
+ }
+
+ if (isLowSurrogate(codeunit)) {
+ _codepoint =
+ uint32_t(0x10000 + ((_highSurrogate << 10) | (codeunit & 0x3FF)));
+ return true;
+ }
+
+ _codepoint = codeunit;
+ return true;
+ }
+
+ uint32_t value() const {
+ return _codepoint;
+ }
+
+ private:
+ uint16_t _highSurrogate;
+ uint32_t _codepoint;
+};
+} // namespace Utf16
+} // namespace ARDUINOJSON_NAMESPACE
+
+#if defined(__GNUC__)
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+#endif
diff --git a/include/lib/ArduinoJson/Json/Utf8.hpp b/include/lib/ArduinoJson/Json/Utf8.hpp
new file mode 100644
index 0000000..a30f77a
--- /dev/null
+++ b/include/lib/ArduinoJson/Json/Utf8.hpp
@@ -0,0 +1,46 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+namespace Utf8 {
+template <typename TStringBuilder>
+inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
+ // this function was optimize for code size on AVR
+
+ // a buffer to store the string in reverse
+ char buf[5];
+ char* p = buf;
+
+ *(p++) = 0;
+ if (codepoint32 < 0x80) {
+ *(p++) = char((codepoint32));
+ } else {
+ *(p++) = char((codepoint32 | 0x80) & 0xBF);
+ uint16_t codepoint16 = uint16_t(codepoint32 >> 6);
+ if (codepoint16 < 0x20) { // 0x800
+ *(p++) = char(codepoint16 | 0xC0);
+ } else {
+ *(p++) = char((codepoint16 | 0x80) & 0xBF);
+ codepoint16 = uint16_t(codepoint16 >> 6);
+ if (codepoint16 < 0x10) { // 0x10000
+ *(p++) = char(codepoint16 | 0xE0);
+ } else {
+ *(p++) = char((codepoint16 | 0x80) & 0xBF);
+ codepoint16 = uint16_t(codepoint16 >> 6);
+ *(p++) = char(codepoint16 | 0xF0);
+ }
+ }
+ }
+
+ while (*(--p)) {
+ str.append(*p);
+ }
+}
+} // namespace Utf8
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Memory/Alignment.hpp b/include/lib/ArduinoJson/Memory/Alignment.hpp
new file mode 100644
index 0000000..bf16798
--- /dev/null
+++ b/include/lib/ArduinoJson/Memory/Alignment.hpp
@@ -0,0 +1,60 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stddef.h> // size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_ENABLE_ALIGNMENT
+
+inline bool isAligned(size_t value) {
+ const size_t mask = sizeof(void *) - 1;
+ size_t addr = value;
+ return (addr & mask) == 0;
+}
+
+inline size_t addPadding(size_t bytes) {
+ const size_t mask = sizeof(void *) - 1;
+ return (bytes + mask) & ~mask;
+}
+
+template <size_t bytes>
+struct AddPadding {
+ static const size_t mask = sizeof(void *) - 1;
+ static const size_t value = (bytes + mask) & ~mask;
+};
+
+#else
+
+inline bool isAligned(size_t) {
+ return true;
+}
+
+inline size_t addPadding(size_t bytes) {
+ return bytes;
+}
+
+template <size_t bytes>
+struct AddPadding {
+ static const size_t value = bytes;
+};
+
+#endif
+
+template <typename T>
+inline bool isAligned(T *ptr) {
+ return isAligned(reinterpret_cast<size_t>(ptr));
+}
+
+template <typename T>
+inline T *addPadding(T *p) {
+ size_t address = addPadding(reinterpret_cast<size_t>(p));
+ return reinterpret_cast<T *>(address);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Memory/MemoryPool.hpp b/include/lib/ArduinoJson/Memory/MemoryPool.hpp
new file mode 100644
index 0000000..49debf8
--- /dev/null
+++ b/include/lib/ArduinoJson/Memory/MemoryPool.hpp
@@ -0,0 +1,212 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Memory/Alignment.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/mpl/max.hpp>
+#include <ArduinoJson/Variant/VariantSlot.hpp>
+
+#include <string.h> // memmove
+
+#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// _begin _end
+// v v
+// +-------------+--------------+--------------+
+// | strings... | (free) | ...variants |
+// +-------------+--------------+--------------+
+// ^ ^
+// _left _right
+
+class MemoryPool {
+ public:
+ MemoryPool(char* buf, size_t capa)
+ : _begin(buf),
+ _left(buf),
+ _right(buf ? buf + capa : 0),
+ _end(buf ? buf + capa : 0),
+ _overflowed(false) {
+ ARDUINOJSON_ASSERT(isAligned(_begin));
+ ARDUINOJSON_ASSERT(isAligned(_right));
+ ARDUINOJSON_ASSERT(isAligned(_end));
+ }
+
+ void* buffer() {
+ return _begin;
+ }
+
+ // Gets the capacity of the memoryPool in bytes
+ size_t capacity() const {
+ return size_t(_end - _begin);
+ }
+
+ size_t size() const {
+ return size_t(_left - _begin + _end - _right);
+ }
+
+ bool overflowed() const {
+ return _overflowed;
+ }
+
+ VariantSlot* allocVariant() {
+ return allocRight<VariantSlot>();
+ }
+
+ template <typename TAdaptedString>
+ const char* saveString(const TAdaptedString& str) {
+ if (str.isNull())
+ return 0;
+
+#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+ const char* existingCopy = findString(str.begin());
+ if (existingCopy)
+ return existingCopy;
+#endif
+
+ size_t n = str.size();
+
+ char* newCopy = allocString(n + 1);
+ if (newCopy) {
+ str.copyTo(newCopy, n);
+ newCopy[n] = 0; // force null-terminator
+ }
+ return newCopy;
+ }
+
+ void getFreeZone(char** zoneStart, size_t* zoneSize) const {
+ *zoneStart = _left;
+ *zoneSize = size_t(_right - _left);
+ }
+
+ const char* saveStringFromFreeZone(size_t len) {
+#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+ const char* dup = findString(_left);
+ if (dup)
+ return dup;
+#endif
+
+ const char* str = _left;
+ _left += len;
+ checkInvariants();
+ return str;
+ }
+
+ void markAsOverflowed() {
+ _overflowed = true;
+ }
+
+ void clear() {
+ _left = _begin;
+ _right = _end;
+ _overflowed = false;
+ }
+
+ bool canAlloc(size_t bytes) const {
+ return _left + bytes <= _right;
+ }
+
+ bool owns(void* p) const {
+ return _begin <= p && p < _end;
+ }
+
+ // Workaround for missing placement new
+ void* operator new(size_t, void* p) {
+ return p;
+ }
+
+ // Squash the free space between strings and variants
+ //
+ // _begin _end
+ // v v
+ // +-------------+--------------+
+ // | strings... | ...variants |
+ // +-------------+--------------+
+ // ^
+ // _left _right
+ //
+ // This funcion is called before a realloc.
+ ptrdiff_t squash() {
+ char* new_right = addPadding(_left);
+ if (new_right >= _right)
+ return 0;
+
+ size_t right_size = static_cast<size_t>(_end - _right);
+ memmove(new_right, _right, right_size);
+
+ ptrdiff_t bytes_reclaimed = _right - new_right;
+ _right = new_right;
+ _end = new_right + right_size;
+ return bytes_reclaimed;
+ }
+
+ // Move all pointers together
+ // This funcion is called after a realloc.
+ void movePointers(ptrdiff_t offset) {
+ _begin += offset;
+ _left += offset;
+ _right += offset;
+ _end += offset;
+ }
+
+ private:
+ void checkInvariants() {
+ ARDUINOJSON_ASSERT(_begin <= _left);
+ ARDUINOJSON_ASSERT(_left <= _right);
+ ARDUINOJSON_ASSERT(_right <= _end);
+ ARDUINOJSON_ASSERT(isAligned(_right));
+ }
+
+#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
+ template <typename TIterator>
+ const char* findString(TIterator str) {
+ for (char* next = _begin; next < _left; ++next) {
+ char* begin = next;
+
+ // try to match
+ for (TIterator it = str; *it == *next; ++it) {
+ if (*next++ == 0)
+ return begin;
+ }
+
+ // jump to next terminator
+ while (*next) ++next;
+ }
+ return 0;
+ }
+#endif
+
+ char* allocString(size_t n) {
+ if (!canAlloc(n)) {
+ _overflowed = true;
+ return 0;
+ }
+ char* s = _left;
+ _left += n;
+ checkInvariants();
+ return s;
+ }
+
+ template <typename T>
+ T* allocRight() {
+ return reinterpret_cast<T*>(allocRight(sizeof(T)));
+ }
+
+ void* allocRight(size_t bytes) {
+ if (!canAlloc(bytes)) {
+ _overflowed = true;
+ return 0;
+ }
+ _right -= bytes;
+ return _right;
+ }
+
+ char *_begin, *_left, *_right, *_end;
+ bool _overflowed;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Misc/SerializedValue.hpp b/include/lib/ArduinoJson/Misc/SerializedValue.hpp
new file mode 100644
index 0000000..30173bf
--- /dev/null
+++ b/include/lib/ArduinoJson/Misc/SerializedValue.hpp
@@ -0,0 +1,68 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/StringAdapters.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A special type of data that can be used to insert pregenerated JSON portions.
+template <typename T>
+class SerializedValue {
+ public:
+ explicit SerializedValue(T str) : _str(str) {}
+ operator T() const {
+ return _str;
+ }
+
+ const char* data() const {
+ return _str.c_str();
+ }
+
+ size_t size() const {
+ // CAUTION: the old Arduino String doesn't have size()
+ return _str.length();
+ }
+
+ private:
+ T _str;
+};
+
+template <typename TChar>
+class SerializedValue<TChar*> {
+ public:
+ explicit SerializedValue(TChar* p, size_t n) : _data(p), _size(n) {}
+ operator TChar*() const {
+ return _data;
+ }
+
+ TChar* data() const {
+ return _data;
+ }
+
+ size_t size() const {
+ return _size;
+ }
+
+ private:
+ TChar* _data;
+ size_t _size;
+};
+
+template <typename T>
+inline SerializedValue<T> serialized(T str) {
+ return SerializedValue<T>(str);
+}
+
+template <typename TChar>
+inline SerializedValue<TChar*> serialized(TChar* p) {
+ return SerializedValue<TChar*>(p, adaptString(p).size());
+}
+
+template <typename TChar>
+inline SerializedValue<TChar*> serialized(TChar* p, size_t n) {
+ return SerializedValue<TChar*>(p, n);
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Misc/Visitable.hpp b/include/lib/ArduinoJson/Misc/Visitable.hpp
new file mode 100644
index 0000000..f25d12f
--- /dev/null
+++ b/include/lib/ArduinoJson/Misc/Visitable.hpp
@@ -0,0 +1,21 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+struct Visitable {
+ // template<Visitor>
+ // void accept(Visitor&) const;
+};
+
+template <typename T>
+struct IsVisitable : is_base_of<Visitable, T> {};
+
+template <typename T>
+struct IsVisitable<T &> : IsVisitable<T> {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
new file mode 100644
index 0000000..49c6fd4
--- /dev/null
+++ b/include/lib/ArduinoJson/MsgPack/MsgPackDeserializer.hpp
@@ -0,0 +1,599 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Deserialization/deserialize.hpp>
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/MsgPack/endianess.hpp>
+#include <ArduinoJson/MsgPack/ieee754.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TReader, typename TStringStorage>
+class MsgPackDeserializer {
+ public:
+ MsgPackDeserializer(MemoryPool &pool, TReader reader,
+ TStringStorage stringStorage)
+ : _pool(&pool),
+ _reader(reader),
+ _stringStorage(stringStorage),
+ _error(DeserializationError::Ok),
+ _foundSomething(false) {}
+
+ template <typename TFilter>
+ DeserializationError parse(VariantData &variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ parseVariant(&variant, filter, nestingLimit);
+ return _foundSomething ? _error : DeserializationError::EmptyInput;
+ }
+
+ private:
+ // Prevent VS warning "assignment operator could not be generated"
+ MsgPackDeserializer &operator=(const MsgPackDeserializer &);
+
+ bool invalidInput() {
+ _error = DeserializationError::InvalidInput;
+ return false;
+ }
+
+ template <typename TFilter>
+ bool parseVariant(VariantData *variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ uint8_t code = 0; // TODO: why do we need to initialize this variable?
+ if (!readByte(code))
+ return false;
+
+ _foundSomething = true;
+
+ bool allowValue = filter.allowValue();
+
+ switch (code) {
+ case 0xc0:
+ // already null
+ return true;
+
+ case 0xc1:
+ return invalidInput();
+
+ case 0xc2:
+ if (allowValue)
+ variant->setBoolean(false);
+ return true;
+
+ case 0xc3:
+ if (allowValue)
+ variant->setBoolean(true);
+ return true;
+
+ case 0xc4: // bin 8 (not supported)
+ return skipString<uint8_t>();
+
+ case 0xc5: // bin 16 (not supported)
+ return skipString<uint16_t>();
+
+ case 0xc6: // bin 32 (not supported)
+ return skipString<uint32_t>();
+
+ case 0xc7: // ext 8 (not supported)
+ return skipExt<uint8_t>();
+
+ case 0xc8: // ext 16 (not supported)
+ return skipExt<uint16_t>();
+
+ case 0xc9: // ext 32 (not supported)
+ return skipExt<uint32_t>();
+
+ case 0xca:
+ if (allowValue)
+ return readFloat<float>(variant);
+ else
+ return skipBytes(4);
+
+ case 0xcb:
+ if (allowValue)
+ return readDouble<double>(variant);
+ else
+ return skipBytes(8);
+
+ case 0xcc:
+ if (allowValue)
+ return readInteger<uint8_t>(variant);
+ else
+ return skipBytes(1);
+
+ case 0xcd:
+ if (allowValue)
+ return readInteger<uint16_t>(variant);
+ else
+ return skipBytes(2);
+
+ case 0xce:
+ if (allowValue)
+ return readInteger<uint32_t>(variant);
+ else
+ return skipBytes(4);
+
+ case 0xcf:
+#if ARDUINOJSON_USE_LONG_LONG
+ if (allowValue)
+ return readInteger<uint64_t>(variant);
+ else
+ return skipBytes(8);
+#else
+ return skipBytes(8); // not supported
+#endif
+
+ case 0xd0:
+ if (allowValue)
+ return readInteger<int8_t>(variant);
+ else
+ return skipBytes(1);
+
+ case 0xd1:
+ if (allowValue)
+ return readInteger<int16_t>(variant);
+ else
+ return skipBytes(2);
+
+ case 0xd2:
+ if (allowValue)
+ return readInteger<int32_t>(variant);
+ else
+ return skipBytes(4);
+
+ case 0xd3:
+#if ARDUINOJSON_USE_LONG_LONG
+ if (allowValue)
+ return readInteger<int64_t>(variant);
+ else
+ return skipBytes(8); // not supported
+#else
+ return skipBytes(8);
+#endif
+
+ case 0xd4: // fixext 1 (not supported)
+ return skipBytes(2);
+
+ case 0xd5: // fixext 2 (not supported)
+ return skipBytes(3);
+
+ case 0xd6: // fixext 4 (not supported)
+ return skipBytes(5);
+
+ case 0xd7: // fixext 8 (not supported)
+ return skipBytes(9);
+
+ case 0xd8: // fixext 16 (not supported)
+ return skipBytes(17);
+
+ case 0xd9:
+ if (allowValue)
+ return readString<uint8_t>(variant);
+ else
+ return skipString<uint8_t>();
+
+ case 0xda:
+ if (allowValue)
+ return readString<uint16_t>(variant);
+ else
+ return skipString<uint16_t>();
+
+ case 0xdb:
+ if (allowValue)
+ return readString<uint32_t>(variant);
+ else
+ return skipString<uint32_t>();
+
+ case 0xdc:
+ return readArray<uint16_t>(variant, filter, nestingLimit);
+
+ case 0xdd:
+ return readArray<uint32_t>(variant, filter, nestingLimit);
+
+ case 0xde:
+ return readObject<uint16_t>(variant, filter, nestingLimit);
+
+ case 0xdf:
+ return readObject<uint32_t>(variant, filter, nestingLimit);
+ }
+
+ switch (code & 0xf0) {
+ case 0x80:
+ return readObject(variant, code & 0x0F, filter, nestingLimit);
+
+ case 0x90:
+ return readArray(variant, code & 0x0F, filter, nestingLimit);
+ }
+
+ if ((code & 0xe0) == 0xa0) {
+ if (allowValue)
+ return readString(variant, code & 0x1f);
+ else
+ return skipBytes(code & 0x1f);
+ }
+
+ if (allowValue)
+ variant->setInteger(static_cast<int8_t>(code));
+
+ return true;
+ }
+
+ bool readByte(uint8_t &value) {
+ int c = _reader.read();
+ if (c < 0) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ value = static_cast<uint8_t>(c);
+ return true;
+ }
+
+ bool readBytes(uint8_t *p, size_t n) {
+ if (_reader.readBytes(reinterpret_cast<char *>(p), n) == n)
+ return true;
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+
+ template <typename T>
+ bool readBytes(T &value) {
+ return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
+ }
+
+ bool skipBytes(size_t n) {
+ for (; n; --n) {
+ if (_reader.read() < 0) {
+ _error = DeserializationError::IncompleteInput;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template <typename T>
+ bool readInteger(T &value) {
+ if (!readBytes(value))
+ return false;
+ fixEndianess(value);
+ return true;
+ }
+
+ template <typename T>
+ bool readInteger(VariantData *variant) {
+ T value;
+ if (!readInteger(value))
+ return false;
+ variant->setInteger(value);
+ return true;
+ }
+
+ template <typename T>
+ typename enable_if<sizeof(T) == 4, bool>::type readFloat(
+ VariantData *variant) {
+ T value;
+ if (!readBytes(value))
+ return false;
+ fixEndianess(value);
+ variant->setFloat(value);
+ return true;
+ }
+
+ template <typename T>
+ typename enable_if<sizeof(T) == 8, bool>::type readDouble(
+ VariantData *variant) {
+ T value;
+ if (!readBytes(value))
+ return false;
+ fixEndianess(value);
+ variant->setFloat(value);
+ return true;
+ }
+
+ template <typename T>
+ typename enable_if<sizeof(T) == 4, bool>::type readDouble(
+ VariantData *variant) {
+ uint8_t i[8]; // input is 8 bytes
+ T value; // output is 4 bytes
+ uint8_t *o = reinterpret_cast<uint8_t *>(&value);
+ if (!readBytes(i, 8))
+ return false;
+ doubleToFloat(i, o);
+ fixEndianess(value);
+ variant->setFloat(value);
+ return true;
+ }
+
+ template <typename T>
+ bool readString(VariantData *variant) {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return readString(variant, size);
+ }
+
+ template <typename T>
+ bool readString() {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return readString(size);
+ }
+
+ template <typename T>
+ bool skipString() {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return skipBytes(size);
+ }
+
+ bool readString(VariantData *variant, size_t n) {
+ if (!readString(n))
+ return false;
+ variant->setStringPointer(_stringStorage.save(),
+ typename TStringStorage::storage_policy());
+ return true;
+ }
+
+ bool readString(size_t n) {
+ _stringStorage.startString();
+ for (; n; --n) {
+ uint8_t c;
+ if (!readBytes(c))
+ return false;
+ _stringStorage.append(static_cast<char>(c));
+ }
+ _stringStorage.append('\0');
+ if (!_stringStorage.isValid()) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ return true;
+ }
+
+ template <typename TSize, typename TFilter>
+ bool readArray(VariantData *variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ TSize size;
+ if (!readInteger(size))
+ return false;
+ return readArray(variant, size, filter, nestingLimit);
+ }
+
+ template <typename TFilter>
+ bool readArray(VariantData *variant, size_t n, TFilter filter,
+ NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ bool allowArray = filter.allowArray();
+
+ CollectionData *array = allowArray ? &variant->toArray() : 0;
+
+ TFilter memberFilter = filter[0U];
+
+ for (; n; --n) {
+ VariantData *value;
+
+ if (memberFilter.allow()) {
+ value = array->addElement(_pool);
+ if (!value) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+ } else {
+ value = 0;
+ }
+
+ if (!parseVariant(value, memberFilter, nestingLimit.decrement()))
+ return false;
+ }
+
+ return true;
+ }
+
+ template <typename TSize, typename TFilter>
+ bool readObject(VariantData *variant, TFilter filter,
+ NestingLimit nestingLimit) {
+ TSize size;
+ if (!readInteger(size))
+ return false;
+ return readObject(variant, size, filter, nestingLimit);
+ }
+
+ template <typename TFilter>
+ bool readObject(VariantData *variant, size_t n, TFilter filter,
+ NestingLimit nestingLimit) {
+ if (nestingLimit.reached()) {
+ _error = DeserializationError::TooDeep;
+ return false;
+ }
+
+ CollectionData *object = filter.allowObject() ? &variant->toObject() : 0;
+
+ for (; n; --n) {
+ if (!readKey())
+ return false;
+
+ const char *key = _stringStorage.c_str();
+ TFilter memberFilter = filter[key];
+ VariantData *member;
+
+ if (memberFilter.allow()) {
+ // Save key in memory pool.
+ // This MUST be done before adding the slot.
+ key = _stringStorage.save();
+
+ VariantSlot *slot = object->addSlot(_pool);
+ if (!slot) {
+ _error = DeserializationError::NoMemory;
+ return false;
+ }
+
+ slot->setKey(key, typename TStringStorage::storage_policy());
+
+ member = slot->data();
+ } else {
+ member = 0;
+ }
+
+ if (!parseVariant(member, memberFilter, nestingLimit.decrement()))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool readKey() {
+ uint8_t code;
+ if (!readByte(code))
+ return false;
+
+ if ((code & 0xe0) == 0xa0)
+ return readString(code & 0x1f);
+
+ switch (code) {
+ case 0xd9:
+ return readString<uint8_t>();
+
+ case 0xda:
+ return readString<uint16_t>();
+
+ case 0xdb:
+ return readString<uint32_t>();
+
+ default:
+ return invalidInput();
+ }
+ }
+
+ template <typename T>
+ bool skipExt() {
+ T size;
+ if (!readInteger(size))
+ return false;
+ return skipBytes(size + 1);
+ }
+
+ MemoryPool *_pool;
+ TReader _reader;
+ TStringStorage _stringStorage;
+ DeserializationError _error;
+ bool _foundSomething;
+};
+
+//
+// deserializeMsgPack(JsonDocument&, const std::string&, ...)
+//
+// ... = NestingLimit
+template <typename TString>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, const TString &input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TString>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, const TString &input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TString>
+DeserializationError deserializeMsgPack(JsonDocument &doc, const TString &input,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeMsgPack(JsonDocument&, std::istream&, ...)
+//
+// ... = NestingLimit
+template <typename TStream>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TStream &input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TStream>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TStream &input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TStream>
+DeserializationError deserializeMsgPack(JsonDocument &doc, TStream &input,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeMsgPack(JsonDocument&, char*, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
+}
+
+//
+// deserializeMsgPack(JsonDocument&, char*, size_t, ...)
+//
+// ... = NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input, size_t inputSize,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
+ AllowAllFilter());
+}
+// ... = Filter, NestingLimit
+template <typename TChar>
+DeserializationError deserializeMsgPack(
+ JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
+ NestingLimit nestingLimit = NestingLimit()) {
+ return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
+ filter);
+}
+// ... = NestingLimit, Filter
+template <typename TChar>
+DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
+ size_t inputSize,
+ NestingLimit nestingLimit,
+ Filter filter) {
+ return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
+ filter);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/MsgPack/MsgPackSerializer.hpp b/include/lib/ArduinoJson/MsgPack/MsgPackSerializer.hpp
new file mode 100644
index 0000000..b1cd872
--- /dev/null
+++ b/include/lib/ArduinoJson/MsgPack/MsgPackSerializer.hpp
@@ -0,0 +1,212 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/MsgPack/endianess.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Serialization/CountingDecorator.hpp>
+#include <ArduinoJson/Serialization/measure.hpp>
+#include <ArduinoJson/Serialization/serialize.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class MsgPackSerializer : public Visitor<size_t> {
+ public:
+ static const bool producesText = false;
+
+ MsgPackSerializer(TWriter writer) : _writer(writer) {}
+
+ template <typename T>
+ typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
+ writeByte(0xCA);
+ writeInteger(value32);
+ return bytesWritten();
+ }
+
+ template <typename T>
+ ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
+ typename enable_if<sizeof(T) == 8, size_t>::type visitFloat(T value64) {
+ float value32 = float(value64);
+ if (value32 == value64) {
+ writeByte(0xCA);
+ writeInteger(value32);
+ } else {
+ writeByte(0xCB);
+ writeInteger(value64);
+ }
+ return bytesWritten();
+ }
+
+ size_t visitArray(const CollectionData& array) {
+ size_t n = array.size();
+ if (n < 0x10) {
+ writeByte(uint8_t(0x90 + array.size()));
+ } else if (n < 0x10000) {
+ writeByte(0xDC);
+ writeInteger(uint16_t(n));
+ } else {
+ writeByte(0xDD);
+ writeInteger(uint32_t(n));
+ }
+ for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
+ slot->data()->accept(*this);
+ }
+ return bytesWritten();
+ }
+
+ size_t visitObject(const CollectionData& object) {
+ size_t n = object.size();
+ if (n < 0x10) {
+ writeByte(uint8_t(0x80 + n));
+ } else if (n < 0x10000) {
+ writeByte(0xDE);
+ writeInteger(uint16_t(n));
+ } else {
+ writeByte(0xDF);
+ writeInteger(uint32_t(n));
+ }
+ for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
+ visitString(slot->key());
+ slot->data()->accept(*this);
+ }
+ return bytesWritten();
+ }
+
+ size_t visitString(const char* value) {
+ ARDUINOJSON_ASSERT(value != NULL);
+
+ size_t n = strlen(value);
+
+ if (n < 0x20) {
+ writeByte(uint8_t(0xA0 + n));
+ } else if (n < 0x100) {
+ writeByte(0xD9);
+ writeInteger(uint8_t(n));
+ } else if (n < 0x10000) {
+ writeByte(0xDA);
+ writeInteger(uint16_t(n));
+ } else {
+ writeByte(0xDB);
+ writeInteger(uint32_t(n));
+ }
+ writeBytes(reinterpret_cast<const uint8_t*>(value), n);
+ return bytesWritten();
+ }
+
+ size_t visitRawJson(const char* data, size_t size) {
+ writeBytes(reinterpret_cast<const uint8_t*>(data), size);
+ return bytesWritten();
+ }
+
+ size_t visitSignedInteger(Integer value) {
+ if (value > 0) {
+ visitUnsignedInteger(static_cast<UInt>(value));
+ } else if (value >= -0x20) {
+ writeInteger(int8_t(value));
+ } else if (value >= -0x80) {
+ writeByte(0xD0);
+ writeInteger(int8_t(value));
+ } else if (value >= -0x8000) {
+ writeByte(0xD1);
+ writeInteger(int16_t(value));
+ }
+#if ARDUINOJSON_USE_LONG_LONG
+ else if (value >= -0x80000000LL)
+#else
+ else
+#endif
+ {
+ writeByte(0xD2);
+ writeInteger(int32_t(value));
+ }
+#if ARDUINOJSON_USE_LONG_LONG
+ else {
+ writeByte(0xD3);
+ writeInteger(int64_t(value));
+ }
+#endif
+ return bytesWritten();
+ }
+
+ size_t visitUnsignedInteger(UInt value) {
+ if (value <= 0x7F) {
+ writeInteger(uint8_t(value));
+ } else if (value <= 0xFF) {
+ writeByte(0xCC);
+ writeInteger(uint8_t(value));
+ } else if (value <= 0xFFFF) {
+ writeByte(0xCD);
+ writeInteger(uint16_t(value));
+ }
+#if ARDUINOJSON_USE_LONG_LONG
+ else if (value <= 0xFFFFFFFF)
+#else
+ else
+#endif
+ {
+ writeByte(0xCE);
+ writeInteger(uint32_t(value));
+ }
+#if ARDUINOJSON_USE_LONG_LONG
+ else {
+ writeByte(0xCF);
+ writeInteger(uint64_t(value));
+ }
+#endif
+ return bytesWritten();
+ }
+
+ size_t visitBoolean(bool value) {
+ writeByte(value ? 0xC3 : 0xC2);
+ return bytesWritten();
+ }
+
+ size_t visitNull() {
+ writeByte(0xC0);
+ return bytesWritten();
+ }
+
+ private:
+ size_t bytesWritten() const {
+ return _writer.count();
+ }
+
+ void writeByte(uint8_t c) {
+ _writer.write(c);
+ }
+
+ void writeBytes(const uint8_t* p, size_t n) {
+ _writer.write(p, n);
+ }
+
+ template <typename T>
+ void writeInteger(T value) {
+ fixEndianess(value);
+ writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+ }
+
+ CountingDecorator<TWriter> _writer;
+};
+
+template <typename TSource, typename TDestination>
+inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
+ return serialize<MsgPackSerializer>(source, output);
+}
+
+template <typename TSource>
+inline size_t serializeMsgPack(const TSource& source, void* output,
+ size_t size) {
+ return serialize<MsgPackSerializer>(source, output, size);
+}
+
+template <typename TSource>
+inline size_t measureMsgPack(const TSource& source) {
+ return measure<MsgPackSerializer>(source);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/MsgPack/endianess.hpp b/include/lib/ArduinoJson/MsgPack/endianess.hpp
new file mode 100644
index 0000000..74f7e9d
--- /dev/null
+++ b/include/lib/ArduinoJson/MsgPack/endianess.hpp
@@ -0,0 +1,41 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Polyfills/utility.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_LITTLE_ENDIAN
+inline void fixEndianess(uint8_t *p, integral_constant<size_t, 8>) {
+ swap(p[0], p[7]);
+ swap(p[1], p[6]);
+ swap(p[2], p[5]);
+ swap(p[3], p[4]);
+}
+
+inline void fixEndianess(uint8_t *p, integral_constant<size_t, 4>) {
+ swap(p[0], p[3]);
+ swap(p[1], p[2]);
+}
+
+inline void fixEndianess(uint8_t *p, integral_constant<size_t, 2>) {
+ swap(p[0], p[1]);
+}
+
+inline void fixEndianess(uint8_t *, integral_constant<size_t, 1>) {}
+
+template <typename T>
+inline void fixEndianess(T &value) {
+ fixEndianess(reinterpret_cast<uint8_t *>(&value),
+ integral_constant<size_t, sizeof(T)>());
+}
+#else
+template <typename T>
+inline void fixEndianess(T &) {}
+#endif
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/MsgPack/ieee754.hpp b/include/lib/ArduinoJson/MsgPack/ieee754.hpp
new file mode 100644
index 0000000..016d533
--- /dev/null
+++ b/include/lib/ArduinoJson/MsgPack/ieee754.hpp
@@ -0,0 +1,18 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
+ f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5));
+ f[1] = uint8_t((d[1] << 3) | (d[2] >> 5));
+ f[2] = uint8_t((d[2] << 3) | (d[3] >> 5));
+ f[3] = uint8_t((d[3] << 3) | (d[4] >> 5));
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Namespace.hpp b/include/lib/ArduinoJson/Namespace.hpp
new file mode 100644
index 0000000..2d85440
--- /dev/null
+++ b/include/lib/ArduinoJson/Namespace.hpp
@@ -0,0 +1,26 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/preprocessor.hpp>
+#include <ArduinoJson/version.hpp>
+
+#ifndef ARDUINOJSON_NAMESPACE
+
+#define ARDUINOJSON_NAMESPACE \
+ ARDUINOJSON_CONCAT4( \
+ ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
+ ARDUINOJSON_VERSION_MINOR, \
+ ARDUINOJSON_VERSION_REVISION), \
+ _, \
+ ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \
+ ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \
+ ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \
+ ARDUINOJSON_HEX_DIGIT( \
+ ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
+ ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE))
+
+#endif
diff --git a/include/lib/ArduinoJson/Numbers/Float.hpp b/include/lib/ArduinoJson/Numbers/Float.hpp
new file mode 100644
index 0000000..bbaca04
--- /dev/null
+++ b/include/lib/ArduinoJson/Numbers/Float.hpp
@@ -0,0 +1,17 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_USE_DOUBLE
+typedef double Float;
+#else
+typedef float Float;
+#endif
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Numbers/FloatParts.hpp b/include/lib/ArduinoJson/Numbers/FloatParts.hpp
new file mode 100644
index 0000000..4e53add
--- /dev/null
+++ b/include/lib/ArduinoJson/Numbers/FloatParts.hpp
@@ -0,0 +1,87 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Numbers/FloatTraits.hpp>
+#include <ArduinoJson/Polyfills/math.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TFloat>
+struct FloatParts {
+ uint32_t integral;
+ uint32_t decimal;
+ int16_t exponent;
+ int8_t decimalPlaces;
+
+ FloatParts(TFloat value) {
+ uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000;
+ decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6;
+
+ exponent = normalize(value);
+
+ integral = uint32_t(value);
+ // reduce number of decimal places by the number of integral places
+ for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
+ maxDecimalPart /= 10;
+ decimalPlaces--;
+ }
+
+ TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart);
+
+ decimal = uint32_t(remainder);
+ remainder = remainder - TFloat(decimal);
+
+ // rounding:
+ // increment by 1 if remainder >= 0.5
+ decimal += uint32_t(remainder * 2);
+ if (decimal >= maxDecimalPart) {
+ decimal = 0;
+ integral++;
+ if (exponent && integral >= 10) {
+ exponent++;
+ integral = 1;
+ }
+ }
+
+ // remove trailing zeros
+ while (decimal % 10 == 0 && decimalPlaces > 0) {
+ decimal /= 10;
+ decimalPlaces--;
+ }
+ }
+
+ static int16_t normalize(TFloat& value) {
+ typedef FloatTraits<TFloat> traits;
+ int16_t powersOf10 = 0;
+
+ int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
+ int bit = 1 << index;
+
+ if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
+ for (; index >= 0; index--) {
+ if (value >= traits::positiveBinaryPowerOfTen(index)) {
+ value *= traits::negativeBinaryPowerOfTen(index);
+ powersOf10 = int16_t(powersOf10 + bit);
+ }
+ bit >>= 1;
+ }
+ }
+
+ if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
+ for (; index >= 0; index--) {
+ if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
+ value *= traits::positiveBinaryPowerOfTen(index);
+ powersOf10 = int16_t(powersOf10 - bit);
+ }
+ bit >>= 1;
+ }
+ }
+
+ return powersOf10;
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Numbers/FloatTraits.hpp b/include/lib/ArduinoJson/Numbers/FloatTraits.hpp
new file mode 100644
index 0000000..60b1dfd
--- /dev/null
+++ b/include/lib/ArduinoJson/Numbers/FloatTraits.hpp
@@ -0,0 +1,201 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h> // for size_t
+#include <stdint.h>
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/alias_cast.hpp>
+#include <ArduinoJson/Polyfills/math.hpp>
+#include <ArduinoJson/Polyfills/preprocessor.hpp>
+#include <ArduinoJson/Polyfills/static_array.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, size_t = sizeof(T)>
+struct FloatTraits {};
+
+template <typename T>
+struct FloatTraits<T, 8 /*64bits*/> {
+ typedef uint64_t mantissa_type;
+ static const short mantissa_bits = 52;
+ static const mantissa_type mantissa_max =
+ (mantissa_type(1) << mantissa_bits) - 1;
+
+ typedef int16_t exponent_type;
+ static const exponent_type exponent_max = 308;
+
+ template <typename TExponent>
+ static T make_float(T m, TExponent e) {
+ if (e > 0) {
+ for (uint8_t index = 0; e != 0; index++) {
+ if (e & 1)
+ m *= positiveBinaryPowerOfTen(index);
+ e >>= 1;
+ }
+ } else {
+ e = TExponent(-e);
+ for (uint8_t index = 0; e != 0; index++) {
+ if (e & 1)
+ m *= negativeBinaryPowerOfTen(index);
+ e >>= 1;
+ }
+ }
+ return m;
+ }
+
+ static T positiveBinaryPowerOfTen(int index) {
+ ARDUINOJSON_DEFINE_STATIC_ARRAY( //
+ uint32_t, factors,
+ ARDUINOJSON_EXPAND18({
+ 0x40240000, 0x00000000, // 1e1
+ 0x40590000, 0x00000000, // 1e2
+ 0x40C38800, 0x00000000, // 1e4
+ 0x4197D784, 0x00000000, // 1e8
+ 0x4341C379, 0x37E08000, // 1e16
+ 0x4693B8B5, 0xB5056E17, // 1e32
+ 0x4D384F03, 0xE93FF9F5, // 1e64
+ 0x5A827748, 0xF9301D32, // 1e128
+ 0x75154FDD, 0x7F73BF3C // 1e256
+ }));
+ return forge(
+ ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
+ ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
+ }
+
+ static T negativeBinaryPowerOfTen(int index) {
+ ARDUINOJSON_DEFINE_STATIC_ARRAY( //
+ uint32_t, factors,
+ ARDUINOJSON_EXPAND18({
+ 0x3FB99999, 0x9999999A, // 1e-1
+ 0x3F847AE1, 0x47AE147B, // 1e-2
+ 0x3F1A36E2, 0xEB1C432D, // 1e-4
+ 0x3E45798E, 0xE2308C3A, // 1e-8
+ 0x3C9CD2B2, 0x97D889BC, // 1e-16
+ 0x3949F623, 0xD5A8A733, // 1e-32
+ 0x32A50FFD, 0x44F4A73D, // 1e-64
+ 0x255BBA08, 0xCF8C979D, // 1e-128
+ 0x0AC80628, 0x64AC6F43 // 1e-256
+ }));
+ return forge(
+ ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
+ ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
+ }
+
+ static T negativeBinaryPowerOfTenPlusOne(int index) {
+ ARDUINOJSON_DEFINE_STATIC_ARRAY( //
+ uint32_t, factors,
+ ARDUINOJSON_EXPAND18({
+ 0x3FF00000, 0x00000000, // 1e0
+ 0x3FB99999, 0x9999999A, // 1e-1
+ 0x3F50624D, 0xD2F1A9FC, // 1e-3
+ 0x3E7AD7F2, 0x9ABCAF48, // 1e-7
+ 0x3CD203AF, 0x9EE75616, // 1e-15
+ 0x398039D6, 0x65896880, // 1e-31
+ 0x32DA53FC, 0x9631D10D, // 1e-63
+ 0x25915445, 0x81B7DEC2, // 1e-127
+ 0x0AFE07B2, 0x7DD78B14 // 1e-255
+ }));
+ return forge(
+ ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
+ ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
+ }
+
+ static T nan() {
+ return forge(0x7ff80000, 0x00000000);
+ }
+
+ static T inf() {
+ return forge(0x7ff00000, 0x00000000);
+ }
+
+ static T highest() {
+ return forge(0x7FEFFFFF, 0xFFFFFFFF);
+ }
+
+ static T lowest() {
+ return forge(0xFFEFFFFF, 0xFFFFFFFF);
+ }
+
+ // constructs a double floating point values from its binary representation
+ // we use this function to workaround platforms with single precision literals
+ // (for example, when -fsingle-precision-constant is passed to GCC)
+ static T forge(uint32_t msb, uint32_t lsb) {
+ return alias_cast<T>((uint64_t(msb) << 32) | lsb);
+ }
+};
+
+template <typename T>
+struct FloatTraits<T, 4 /*32bits*/> {
+ typedef uint32_t mantissa_type;
+ static const short mantissa_bits = 23;
+ static const mantissa_type mantissa_max =
+ (mantissa_type(1) << mantissa_bits) - 1;
+
+ typedef int8_t exponent_type;
+ static const exponent_type exponent_max = 38;
+
+ template <typename TExponent>
+ static T make_float(T m, TExponent e) {
+ if (e > 0) {
+ for (uint8_t index = 0; e != 0; index++) {
+ if (e & 1)
+ m *= positiveBinaryPowerOfTen(index);
+ e >>= 1;
+ }
+ } else {
+ e = -e;
+ for (uint8_t index = 0; e != 0; index++) {
+ if (e & 1)
+ m *= negativeBinaryPowerOfTen(index);
+ e >>= 1;
+ }
+ }
+ return m;
+ }
+
+ static T positiveBinaryPowerOfTen(int index) {
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(
+ T, factors,
+ ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}));
+ return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
+ }
+
+ static T negativeBinaryPowerOfTen(int index) {
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(
+ T, factors,
+ ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}));
+ return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
+ }
+
+ static T negativeBinaryPowerOfTenPlusOne(int index) {
+ ARDUINOJSON_DEFINE_STATIC_ARRAY(
+ T, factors,
+ ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}));
+ return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
+ }
+
+ static T forge(uint32_t bits) {
+ return alias_cast<T>(bits);
+ }
+
+ static T nan() {
+ return forge(0x7fc00000);
+ }
+
+ static T inf() {
+ return forge(0x7f800000);
+ }
+
+ static T highest() {
+ return forge(0x7f7fffff);
+ }
+
+ static T lowest() {
+ return forge(0xFf7fffff);
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Numbers/Integer.hpp b/include/lib/ArduinoJson/Numbers/Integer.hpp
new file mode 100644
index 0000000..fb656a7
--- /dev/null
+++ b/include/lib/ArduinoJson/Numbers/Integer.hpp
@@ -0,0 +1,32 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdint.h> // int64_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#if ARDUINOJSON_USE_LONG_LONG
+typedef int64_t Integer;
+typedef uint64_t UInt;
+#else
+typedef long Integer;
+typedef unsigned long UInt;
+#endif
+
+} // namespace ARDUINOJSON_NAMESPACE
+
+#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG
+#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \
+ static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \
+ "To use 64-bit integers with ArduinoJson, you must set " \
+ "ARDUINOJSON_USE_LONG_LONG to 1. See " \
+ "https://arduinojson.org/v6/api/config/use_long_long/");
+#else
+#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)
+#endif
diff --git a/include/lib/ArduinoJson/Numbers/arithmeticCompare.hpp b/include/lib/ArduinoJson/Numbers/arithmeticCompare.hpp
new file mode 100644
index 0000000..bfd41d5
--- /dev/null
+++ b/include/lib/ArduinoJson/Numbers/arithmeticCompare.hpp
@@ -0,0 +1,121 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Numbers/Integer.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+enum CompareResult {
+ COMPARE_RESULT_DIFFER = 0,
+ COMPARE_RESULT_EQUAL = 1,
+ COMPARE_RESULT_GREATER = 2,
+ COMPARE_RESULT_LESS = 4,
+
+ COMPARE_RESULT_GREATER_OR_EQUAL = 3,
+ COMPARE_RESULT_LESS_OR_EQUAL = 5
+};
+
+template <typename T>
+CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
+ if (lhs < rhs)
+ return COMPARE_RESULT_LESS;
+ else if (lhs > rhs)
+ return COMPARE_RESULT_GREATER;
+ else
+ return COMPARE_RESULT_EQUAL;
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+ const T1 &lhs, const T2 &rhs,
+ typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+ sizeof(T1) < sizeof(T2),
+ int // Using int instead of void to avoid C2572 on
+ // Visual Studio 2012, 2013, and 2015
+ >::type * = 0) {
+ return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+ const T1 &lhs, const T2 &rhs,
+ typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+ sizeof(T2) < sizeof(T1)>::type * = 0) {
+ return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+ const T1 &lhs, const T2 &rhs,
+ typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+ is_signed<T1>::value == is_signed<T2>::value &&
+ sizeof(T2) == sizeof(T1)>::type * = 0) {
+ return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+ const T1 &lhs, const T2 &rhs,
+ typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+ is_unsigned<T1>::value && is_signed<T2>::value &&
+ sizeof(T2) == sizeof(T1)>::type * = 0) {
+ if (rhs < 0)
+ return COMPARE_RESULT_GREATER;
+ return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+ const T1 &lhs, const T2 &rhs,
+ typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
+ is_signed<T1>::value && is_unsigned<T2>::value &&
+ sizeof(T2) == sizeof(T1)>::type * = 0) {
+ if (lhs < 0)
+ return COMPARE_RESULT_LESS;
+ return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
+}
+
+template <typename T1, typename T2>
+CompareResult arithmeticCompare(
+ const T1 &lhs, const T2 &rhs,
+ typename enable_if<is_floating_point<T1>::value ||
+ is_floating_point<T2>::value>::type * = 0) {
+ return arithmeticCompare<double>(static_cast<double>(lhs),
+ static_cast<double>(rhs));
+}
+
+template <typename T2>
+CompareResult arithmeticCompareNegateLeft(
+ UInt, const T2 &, typename enable_if<is_unsigned<T2>::value>::type * = 0) {
+ return COMPARE_RESULT_LESS;
+}
+
+template <typename T2>
+CompareResult arithmeticCompareNegateLeft(
+ UInt lhs, const T2 &rhs,
+ typename enable_if<is_signed<T2>::value>::type * = 0) {
+ if (rhs > 0)
+ return COMPARE_RESULT_LESS;
+ return arithmeticCompare(-rhs, static_cast<T2>(lhs));
+}
+
+template <typename T1>
+CompareResult arithmeticCompareNegateRight(
+ const T1 &, UInt, typename enable_if<is_unsigned<T1>::value>::type * = 0) {
+ return COMPARE_RESULT_GREATER;
+}
+
+template <typename T1>
+CompareResult arithmeticCompareNegateRight(
+ const T1 &lhs, UInt rhs,
+ typename enable_if<is_signed<T1>::value>::type * = 0) {
+ if (lhs > 0)
+ return COMPARE_RESULT_GREATER;
+ return arithmeticCompare(static_cast<T1>(rhs), -lhs);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Numbers/convertNumber.hpp b/include/lib/ArduinoJson/Numbers/convertNumber.hpp
new file mode 100644
index 0000000..02bbefa
--- /dev/null
+++ b/include/lib/ArduinoJson/Numbers/convertNumber.hpp
@@ -0,0 +1,107 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic push
+#endif
+#pragma GCC diagnostic ignored "-Wconversion"
+#endif
+
+#include <ArduinoJson/Numbers/Float.hpp>
+#include <ArduinoJson/Polyfills/limits.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// uint32 -> int32
+// uint64 -> int32
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TIn>::value && is_unsigned<TIn>::value &&
+ is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn),
+ bool>::type
+canConvertNumber(TIn value) {
+ return value <= TIn(numeric_limits<TOut>::highest());
+}
+
+// uint32 -> int64
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TIn>::value && is_unsigned<TIn>::value &&
+ is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut),
+ bool>::type
+canConvertNumber(TIn) {
+ return true;
+}
+
+// uint32 -> float
+// int32 -> float
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TIn>::value && is_floating_point<TOut>::value,
+ bool>::type
+canConvertNumber(TIn) {
+ return true;
+}
+
+// int64 -> int32
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
+ is_integral<TOut>::value && is_signed<TOut>::value &&
+ sizeof(TOut) < sizeof(TIn),
+ bool>::type
+canConvertNumber(TIn value) {
+ return value >= TIn(numeric_limits<TOut>::lowest()) &&
+ value <= TIn(numeric_limits<TOut>::highest());
+}
+
+// int32 -> int32
+// int32 -> int64
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
+ is_integral<TOut>::value && is_signed<TOut>::value &&
+ sizeof(TIn) <= sizeof(TOut),
+ bool>::type
+canConvertNumber(TIn) {
+ return true;
+}
+
+// int32 -> uint32
+template <typename TOut, typename TIn>
+typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
+ is_integral<TOut>::value && is_unsigned<TOut>::value,
+ bool>::type
+canConvertNumber(TIn value) {
+ if (value < 0)
+ return false;
+ return value <= TIn(numeric_limits<TOut>::highest());
+}
+
+// float -> int32
+// float -> int64
+template <typename TOut, typename TIn>
+typename enable_if<is_floating_point<TIn>::value &&
+ !is_floating_point<TOut>::value,
+ bool>::type
+canConvertNumber(TIn value) {
+ return value >= numeric_limits<TOut>::lowest() &&
+ value <= numeric_limits<TOut>::highest();
+}
+
+template <typename TOut, typename TIn>
+TOut convertNumber(TIn value) {
+ return canConvertNumber<TOut>(value) ? TOut(value) : 0;
+}
+} // namespace ARDUINOJSON_NAMESPACE
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(__GNUC__)
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic pop
+#endif
+#endif
diff --git a/include/lib/ArduinoJson/Numbers/parseNumber.hpp b/include/lib/ArduinoJson/Numbers/parseNumber.hpp
new file mode 100644
index 0000000..cf050c7
--- /dev/null
+++ b/include/lib/ArduinoJson/Numbers/parseNumber.hpp
@@ -0,0 +1,153 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Numbers/FloatTraits.hpp>
+#include <ArduinoJson/Numbers/convertNumber.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Polyfills/ctype.hpp>
+#include <ArduinoJson/Polyfills/math.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/Converter.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename A, typename B>
+struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
+
+inline bool parseNumber(const char* s, VariantData& result) {
+ typedef FloatTraits<Float> traits;
+ typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t;
+ typedef traits::exponent_type exponent_t;
+
+ ARDUINOJSON_ASSERT(s != 0);
+
+ bool is_negative = false;
+ switch (*s) {
+ case '-':
+ is_negative = true;
+ s++;
+ break;
+ case '+':
+ s++;
+ break;
+ }
+
+#if ARDUINOJSON_ENABLE_NAN
+ if (*s == 'n' || *s == 'N') {
+ result.setFloat(traits::nan());
+ return true;
+ }
+#endif
+
+#if ARDUINOJSON_ENABLE_INFINITY
+ if (*s == 'i' || *s == 'I') {
+ result.setFloat(is_negative ? -traits::inf() : traits::inf());
+ return true;
+ }
+#endif
+
+ if (!isdigit(*s) && *s != '.')
+ return false;
+
+ mantissa_t mantissa = 0;
+ exponent_t exponent_offset = 0;
+ const mantissa_t maxUint = UInt(-1);
+
+ while (isdigit(*s)) {
+ uint8_t digit = uint8_t(*s - '0');
+ if (mantissa > maxUint / 10)
+ break;
+ mantissa *= 10;
+ if (mantissa > maxUint - digit)
+ break;
+ mantissa += digit;
+ s++;
+ }
+
+ if (*s == '\0') {
+ if (is_negative) {
+ const mantissa_t sintMantissaMax = mantissa_t(1)
+ << (sizeof(Integer) * 8 - 1);
+ if (mantissa <= sintMantissaMax) {
+ result.setInteger(Integer(~mantissa + 1));
+ return true;
+ }
+ } else {
+ result.setInteger(UInt(mantissa));
+ return true;
+ }
+ }
+
+ // avoid mantissa overflow
+ while (mantissa > traits::mantissa_max) {
+ mantissa /= 10;
+ exponent_offset++;
+ }
+
+ // remaing digits can't fit in the mantissa
+ while (isdigit(*s)) {
+ exponent_offset++;
+ s++;
+ }
+
+ if (*s == '.') {
+ s++;
+ while (isdigit(*s)) {
+ if (mantissa < traits::mantissa_max / 10) {
+ mantissa = mantissa * 10 + uint8_t(*s - '0');
+ exponent_offset--;
+ }
+ s++;
+ }
+ }
+
+ int exponent = 0;
+ if (*s == 'e' || *s == 'E') {
+ s++;
+ bool negative_exponent = false;
+ if (*s == '-') {
+ negative_exponent = true;
+ s++;
+ } else if (*s == '+') {
+ s++;
+ }
+
+ while (isdigit(*s)) {
+ exponent = exponent * 10 + (*s - '0');
+ if (exponent + exponent_offset > traits::exponent_max) {
+ if (negative_exponent)
+ result.setFloat(is_negative ? -0.0f : 0.0f);
+ else
+ result.setFloat(is_negative ? -traits::inf() : traits::inf());
+ return true;
+ }
+ s++;
+ }
+ if (negative_exponent)
+ exponent = -exponent;
+ }
+ exponent += exponent_offset;
+
+ // we should be at the end of the string, otherwise it's an error
+ if (*s != '\0')
+ return false;
+
+ Float final_result =
+ traits::make_float(static_cast<Float>(mantissa), exponent);
+
+ result.setFloat(is_negative ? -final_result : final_result);
+ return true;
+}
+
+template <typename T>
+inline T parseNumber(const char* s) {
+ VariantData value;
+ value.init(); // VariantData is a POD, so it has no constructor
+ parseNumber(s, value);
+ return Converter<T>::fromJson(VariantConstRef(&value));
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Object/MemberProxy.hpp b/include/lib/ArduinoJson/Object/MemberProxy.hpp
new file mode 100644
index 0000000..0bee84b
--- /dev/null
+++ b/include/lib/ArduinoJson/Object/MemberProxy.hpp
@@ -0,0 +1,202 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantOperators.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+#include <ArduinoJson/Variant/VariantShortcuts.hpp>
+#include <ArduinoJson/Variant/VariantTo.hpp>
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4522)
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TObject, typename TStringRef>
+class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
+ public VariantShortcuts<MemberProxy<TObject, TStringRef> >,
+ public Visitable,
+ public VariantTag {
+ typedef MemberProxy<TObject, TStringRef> this_type;
+
+ public:
+ typedef VariantRef variant_type;
+
+ FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
+ : _object(variant), _key(key) {}
+
+ FORCE_INLINE MemberProxy(const MemberProxy &src)
+ : _object(src._object), _key(src._key) {}
+
+ FORCE_INLINE operator VariantConstRef() const {
+ return getUpstreamMember();
+ }
+
+ FORCE_INLINE this_type &operator=(const this_type &src) {
+ getOrAddUpstreamMember().set(src);
+ return *this;
+ }
+
+ template <typename TValue>
+ FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
+ operator=(const TValue &src) {
+ getOrAddUpstreamMember().set(src);
+ return *this;
+ }
+
+ // operator=(char*)
+ // operator=(const char*)
+ // operator=(const __FlashStringHelper*)
+ template <typename TChar>
+ FORCE_INLINE this_type &operator=(TChar *src) {
+ getOrAddUpstreamMember().set(src);
+ return *this;
+ }
+
+ FORCE_INLINE void clear() const {
+ getUpstreamMember().clear();
+ }
+
+ FORCE_INLINE bool isNull() const {
+ return getUpstreamMember().isNull();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<!is_same<T, char *>::value, T>::type as()
+ const {
+ return getUpstreamMember().template as<T>();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char *>::value, const char *>::type
+ ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
+ as() const {
+ return as<const char *>();
+ }
+
+ template <typename T>
+ FORCE_INLINE operator T() const {
+ return getUpstreamMember();
+ }
+
+ template <typename TValue>
+ FORCE_INLINE bool is() const {
+ return getUpstreamMember().template is<TValue>();
+ }
+
+ FORCE_INLINE size_t size() const {
+ return getUpstreamMember().size();
+ }
+
+ FORCE_INLINE void remove(size_t index) const {
+ getUpstreamMember().remove(index);
+ }
+ // remove(char*) const
+ // remove(const char*) const
+ // remove(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
+ TChar *key) const {
+ getUpstreamMember().remove(key);
+ }
+ // remove(const std::string&) const
+ // remove(const String&) const
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+ const TString &key) const {
+ getUpstreamMember().remove(key);
+ }
+
+ template <typename TValue>
+ FORCE_INLINE typename VariantTo<TValue>::type to() {
+ return getOrAddUpstreamMember().template to<TValue>();
+ }
+
+ template <typename TValue>
+ FORCE_INLINE bool set(const TValue &value) {
+ return getOrAddUpstreamMember().set(value);
+ }
+
+ // set(char*) const
+ // set(const char*) const
+ // set(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE bool set(TChar *value) {
+ return getOrAddUpstreamMember().set(value);
+ }
+
+ template <typename TVisitor>
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
+ return getUpstreamMember().accept(visitor);
+ }
+
+ FORCE_INLINE VariantRef addElement() const {
+ return getOrAddUpstreamMember().addElement();
+ }
+
+ FORCE_INLINE VariantRef getElement(size_t index) const {
+ return getUpstreamMember().getElement(index);
+ }
+
+ FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
+ return getOrAddUpstreamMember().getOrAddElement(index);
+ }
+
+ // getMember(char*) const
+ // getMember(const char*) const
+ // getMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantRef getMember(TChar *key) const {
+ return getUpstreamMember().getMember(key);
+ }
+
+ // getMember(const std::string&) const
+ // getMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE VariantRef getMember(const TString &key) const {
+ return getUpstreamMember().getMember(key);
+ }
+
+ // getOrAddMember(char*) const
+ // getOrAddMember(const char*) const
+ // getOrAddMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantRef getOrAddMember(TChar *key) const {
+ return getOrAddUpstreamMember().getOrAddMember(key);
+ }
+
+ // getOrAddMember(const std::string&) const
+ // getOrAddMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE VariantRef getOrAddMember(const TString &key) const {
+ return getOrAddUpstreamMember().getOrAddMember(key);
+ }
+
+ private:
+ FORCE_INLINE VariantRef getUpstreamMember() const {
+ return _object.getMember(_key);
+ }
+
+ FORCE_INLINE VariantRef getOrAddUpstreamMember() const {
+ return _object.getOrAddMember(_key);
+ }
+
+ friend bool convertToJson(const this_type &src, VariantRef dst) {
+ return dst.set(src.getUpstreamMember());
+ }
+
+ TObject _object;
+ TStringRef _key;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
diff --git a/include/lib/ArduinoJson/Object/ObjectFunctions.hpp b/include/lib/ArduinoJson/Object/ObjectFunctions.hpp
new file mode 100644
index 0000000..1b46e84
--- /dev/null
+++ b/include/lib/ArduinoJson/Object/ObjectFunctions.hpp
@@ -0,0 +1,51 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TVisitor>
+typename TVisitor::result_type objectAccept(const CollectionData *obj,
+ TVisitor &visitor) {
+ if (obj)
+ return visitor.visitObject(*obj);
+ else
+ return visitor.visitNull();
+}
+
+inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
+ if (lhs == rhs)
+ return true;
+ if (!lhs || !rhs)
+ return false;
+ return lhs->equalsObject(*rhs);
+}
+
+template <typename TAdaptedString>
+inline VariantData *objectGetMember(const CollectionData *obj,
+ TAdaptedString key) {
+ if (!obj)
+ return 0;
+ return obj->getMember(key);
+}
+
+template <typename TAdaptedString>
+void objectRemove(CollectionData *obj, TAdaptedString key) {
+ if (!obj)
+ return;
+ obj->removeMember(key);
+}
+
+template <typename TAdaptedString>
+inline VariantData *objectGetOrAddMember(CollectionData *obj,
+ TAdaptedString key, MemoryPool *pool) {
+ if (!obj)
+ return 0;
+
+ return obj->getOrAddMember(key, pool);
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Object/ObjectImpl.hpp b/include/lib/ArduinoJson/Object/ObjectImpl.hpp
new file mode 100644
index 0000000..d66b61c
--- /dev/null
+++ b/include/lib/ArduinoJson/Object/ObjectImpl.hpp
@@ -0,0 +1,69 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TObject>
+template <typename TString>
+inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
+ const TString& key) const {
+ return impl()->getOrAddMember(key).template to<ArrayRef>();
+}
+
+template <typename TObject>
+template <typename TChar>
+inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const {
+ return impl()->getOrAddMember(key).template to<ArrayRef>();
+}
+
+template <typename TObject>
+template <typename TString>
+inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
+ const TString& key) const {
+ return impl()->getOrAddMember(key).template to<ObjectRef>();
+}
+
+template <typename TObject>
+template <typename TChar>
+inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
+ TChar* key) const {
+ return impl()->getOrAddMember(key).template to<ObjectRef>();
+}
+
+template <typename TObject>
+template <typename TString>
+inline typename enable_if<IsString<TString>::value, bool>::type
+ObjectShortcuts<TObject>::containsKey(const TString& key) const {
+ return !impl()->getMember(key).isUndefined();
+}
+
+template <typename TObject>
+template <typename TChar>
+inline typename enable_if<IsString<TChar*>::value, bool>::type
+ObjectShortcuts<TObject>::containsKey(TChar* key) const {
+ return !impl()->getMember(key).isUndefined();
+}
+
+template <typename TObject>
+template <typename TString>
+inline typename enable_if<IsString<TString*>::value,
+ MemberProxy<TObject, TString*> >::type
+ObjectShortcuts<TObject>::operator[](TString* key) const {
+ return MemberProxy<TObject, TString*>(*impl(), key);
+}
+
+template <typename TObject>
+template <typename TString>
+inline typename enable_if<IsString<TString>::value,
+ MemberProxy<TObject, TString> >::type
+ObjectShortcuts<TObject>::operator[](const TString& key) const {
+ return MemberProxy<TObject, TString>(*impl(), key);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Object/ObjectIterator.hpp b/include/lib/ArduinoJson/Object/ObjectIterator.hpp
new file mode 100644
index 0000000..d729459
--- /dev/null
+++ b/include/lib/ArduinoJson/Object/ObjectIterator.hpp
@@ -0,0 +1,123 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Object/Pair.hpp>
+#include <ArduinoJson/Variant/SlotFunctions.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class PairPtr {
+ public:
+ PairPtr(MemoryPool *pool, VariantSlot *slot) : _pair(pool, slot) {}
+
+ const Pair *operator->() const {
+ return &_pair;
+ }
+
+ const Pair &operator*() const {
+ return _pair;
+ }
+
+ private:
+ Pair _pair;
+};
+
+class ObjectIterator {
+ public:
+ ObjectIterator() : _slot(0) {}
+
+ explicit ObjectIterator(MemoryPool *pool, VariantSlot *slot)
+ : _pool(pool), _slot(slot) {}
+
+ Pair operator*() const {
+ return Pair(_pool, _slot);
+ }
+ PairPtr operator->() {
+ return PairPtr(_pool, _slot);
+ }
+
+ bool operator==(const ObjectIterator &other) const {
+ return _slot == other._slot;
+ }
+
+ bool operator!=(const ObjectIterator &other) const {
+ return _slot != other._slot;
+ }
+
+ ObjectIterator &operator++() {
+ _slot = _slot->next();
+ return *this;
+ }
+
+ ObjectIterator &operator+=(size_t distance) {
+ _slot = _slot->next(distance);
+ return *this;
+ }
+
+ VariantSlot *internal() {
+ return _slot;
+ }
+
+ private:
+ MemoryPool *_pool;
+ VariantSlot *_slot;
+};
+
+class PairConstPtr {
+ public:
+ PairConstPtr(const VariantSlot *slot) : _pair(slot) {}
+
+ const PairConst *operator->() const {
+ return &_pair;
+ }
+
+ const PairConst &operator*() const {
+ return _pair;
+ }
+
+ private:
+ PairConst _pair;
+};
+
+class ObjectConstIterator {
+ public:
+ ObjectConstIterator() : _slot(0) {}
+
+ explicit ObjectConstIterator(const VariantSlot *slot) : _slot(slot) {}
+
+ PairConst operator*() const {
+ return PairConst(_slot);
+ }
+ PairConstPtr operator->() {
+ return PairConstPtr(_slot);
+ }
+
+ bool operator==(const ObjectConstIterator &other) const {
+ return _slot == other._slot;
+ }
+
+ bool operator!=(const ObjectConstIterator &other) const {
+ return _slot != other._slot;
+ }
+
+ ObjectConstIterator &operator++() {
+ _slot = _slot->next();
+ return *this;
+ }
+
+ ObjectConstIterator &operator+=(size_t distance) {
+ _slot = _slot->next(distance);
+ return *this;
+ }
+
+ const VariantSlot *internal() {
+ return _slot;
+ }
+
+ private:
+ const VariantSlot *_slot;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Object/ObjectRef.hpp b/include/lib/ArduinoJson/Object/ObjectRef.hpp
new file mode 100644
index 0000000..c945fb6
--- /dev/null
+++ b/include/lib/ArduinoJson/Object/ObjectRef.hpp
@@ -0,0 +1,277 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Object/ObjectFunctions.hpp>
+#include <ArduinoJson/Object/ObjectIterator.hpp>
+
+// Returns the size (in bytes) of an object with n elements.
+// Can be very handy to determine the size of a StaticMemoryPool.
+#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
+ ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TData>
+class ObjectRefBase {
+ public:
+ operator VariantConstRef() const {
+ const void* data = _data; // prevent warning cast-align
+ return VariantConstRef(reinterpret_cast<const VariantData*>(data));
+ }
+
+ template <typename TVisitor>
+ typename TVisitor::result_type accept(TVisitor& visitor) const {
+ return objectAccept(_data, visitor);
+ }
+
+ FORCE_INLINE bool isNull() const {
+ return _data == 0;
+ }
+
+ FORCE_INLINE operator bool() const {
+ return _data != 0;
+ }
+
+ FORCE_INLINE size_t memoryUsage() const {
+ return _data ? _data->memoryUsage() : 0;
+ }
+
+ FORCE_INLINE size_t nesting() const {
+ return _data ? _data->nesting() : 0;
+ }
+
+ FORCE_INLINE size_t size() const {
+ return _data ? _data->size() : 0;
+ }
+
+ protected:
+ ObjectRefBase(TData* data) : _data(data) {}
+ TData* _data;
+};
+
+class ObjectConstRef : public ObjectRefBase<const CollectionData>,
+ public Visitable {
+ friend class ObjectRef;
+ typedef ObjectRefBase<const CollectionData> base_type;
+
+ public:
+ typedef ObjectConstIterator iterator;
+
+ ObjectConstRef() : base_type(0) {}
+ ObjectConstRef(const CollectionData* data) : base_type(data) {}
+
+ FORCE_INLINE iterator begin() const {
+ if (!_data)
+ return iterator();
+ return iterator(_data->head());
+ }
+
+ FORCE_INLINE iterator end() const {
+ return iterator();
+ }
+
+ // containsKey(const std::string&) const
+ // containsKey(const String&) const
+ template <typename TString>
+ FORCE_INLINE bool containsKey(const TString& key) const {
+ return !getMember(key).isUndefined();
+ }
+
+ // containsKey(char*) const
+ // containsKey(const char*) const
+ // containsKey(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE bool containsKey(TChar* key) const {
+ return !getMember(key).isUndefined();
+ }
+
+ // getMember(const std::string&) const
+ // getMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE VariantConstRef getMember(const TString& key) const {
+ return get_impl(adaptString(key));
+ }
+
+ // getMember(char*) const
+ // getMember(const char*) const
+ // getMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantConstRef getMember(TChar* key) const {
+ return get_impl(adaptString(key));
+ }
+
+ // operator[](const std::string&) const
+ // operator[](const String&) const
+ template <typename TString>
+ FORCE_INLINE
+ typename enable_if<IsString<TString>::value, VariantConstRef>::type
+ operator[](const TString& key) const {
+ return get_impl(adaptString(key));
+ }
+
+ // operator[](char*) const
+ // operator[](const char*) const
+ // operator[](const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE
+ typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
+ operator[](TChar* key) const {
+ return get_impl(adaptString(key));
+ }
+
+ FORCE_INLINE bool operator==(ObjectConstRef rhs) const {
+ return objectEquals(_data, rhs._data);
+ }
+
+ private:
+ template <typename TAdaptedString>
+ FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
+ return VariantConstRef(objectGetMember(_data, key));
+ }
+};
+
+class ObjectRef : public ObjectRefBase<CollectionData>,
+ public ObjectShortcuts<ObjectRef>,
+ public Visitable {
+ typedef ObjectRefBase<CollectionData> base_type;
+
+ public:
+ typedef ObjectIterator iterator;
+
+ FORCE_INLINE ObjectRef() : base_type(0), _pool(0) {}
+ FORCE_INLINE ObjectRef(MemoryPool* buf, CollectionData* data)
+ : base_type(data), _pool(buf) {}
+
+ operator VariantRef() const {
+ void* data = _data; // prevent warning cast-align
+ return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
+ }
+
+ operator ObjectConstRef() const {
+ return ObjectConstRef(_data);
+ }
+
+ FORCE_INLINE iterator begin() const {
+ if (!_data)
+ return iterator();
+ return iterator(_pool, _data->head());
+ }
+
+ FORCE_INLINE iterator end() const {
+ return iterator();
+ }
+
+ void clear() const {
+ if (!_data)
+ return;
+ _data->clear();
+ }
+
+ FORCE_INLINE bool set(ObjectConstRef src) {
+ if (!_data || !src._data)
+ return false;
+ return _data->copyFrom(*src._data, _pool);
+ }
+
+ // getMember(const std::string&) const
+ // getMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE VariantRef getMember(const TString& key) const {
+ return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
+ }
+
+ // getMember(char*) const
+ // getMember(const char*) const
+ // getMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantRef getMember(TChar* key) const {
+ return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
+ }
+
+ // getOrAddMember(const std::string&) const
+ // getOrAddMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE VariantRef getOrAddMember(const TString& key) const {
+ return VariantRef(_pool,
+ objectGetOrAddMember(_data, adaptString(key), _pool));
+ }
+
+ // getOrAddMember(char*) const
+ // getOrAddMember(const char*) const
+ // getOrAddMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantRef getOrAddMember(TChar* key) const {
+ return VariantRef(_pool,
+ objectGetOrAddMember(_data, adaptString(key), _pool));
+ }
+
+ FORCE_INLINE bool operator==(ObjectRef rhs) const {
+ return objectEquals(_data, rhs._data);
+ }
+
+ FORCE_INLINE void remove(iterator it) const {
+ if (!_data)
+ return;
+ _data->removeSlot(it.internal());
+ }
+
+ // remove(const std::string&) const
+ // remove(const String&) const
+ template <typename TString>
+ FORCE_INLINE void remove(const TString& key) const {
+ objectRemove(_data, adaptString(key));
+ }
+
+ // remove(char*) const
+ // remove(const char*) const
+ // remove(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE void remove(TChar* key) const {
+ objectRemove(_data, adaptString(key));
+ }
+
+ private:
+ MemoryPool* _pool;
+};
+
+template <>
+struct Converter<ObjectConstRef> {
+ static bool toJson(VariantConstRef src, VariantRef dst) {
+ return variantCopyFrom(getData(dst), getData(src), getPool(dst));
+ }
+
+ static ObjectConstRef fromJson(VariantConstRef src) {
+ return ObjectConstRef(variantAsObject(getData(src)));
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data && data->isObject();
+ }
+};
+
+template <>
+struct Converter<ObjectRef> {
+ static bool toJson(VariantConstRef src, VariantRef dst) {
+ return variantCopyFrom(getData(dst), getData(src), getPool(dst));
+ }
+
+ static ObjectRef fromJson(VariantRef src) {
+ VariantData* data = getData(src);
+ MemoryPool* pool = getPool(src);
+ return ObjectRef(pool, data != 0 ? data->asObject() : 0);
+ }
+
+ static bool checkJson(VariantConstRef) {
+ return false;
+ }
+
+ static bool checkJson(VariantRef src) {
+ VariantData* data = getData(src);
+ return data && data->isObject();
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Object/ObjectShortcuts.hpp b/include/lib/ArduinoJson/Object/ObjectShortcuts.hpp
new file mode 100644
index 0000000..0f3409f
--- /dev/null
+++ b/include/lib/ArduinoJson/Object/ObjectShortcuts.hpp
@@ -0,0 +1,73 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/StringAdapters.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+template <typename TParent, typename TStringRef>
+class MemberProxy;
+
+template <typename TObject>
+class ObjectShortcuts {
+ public:
+ // containsKey(const std::string&) const
+ // containsKey(const String&) const
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
+ containsKey(const TString &key) const;
+
+ // containsKey(char*) const
+ // containsKey(const char*) const
+ // containsKey(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE typename enable_if<IsString<TChar *>::value, bool>::type
+ containsKey(TChar *key) const;
+
+ // operator[](const std::string&) const
+ // operator[](const String&) const
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value,
+ MemberProxy<TObject, TString> >::type
+ operator[](const TString &key) const;
+
+ // operator[](char*) const
+ // operator[](const char*) const
+ // operator[](const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE typename enable_if<IsString<TChar *>::value,
+ MemberProxy<TObject, TChar *> >::type
+ operator[](TChar *key) const;
+
+ // createNestedArray(const std::string&) const
+ // createNestedArray(const String&) const
+ template <typename TString>
+ FORCE_INLINE ArrayRef createNestedArray(const TString &key) const;
+
+ // createNestedArray(char*) const
+ // createNestedArray(const char*) const
+ // createNestedArray(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE ArrayRef createNestedArray(TChar *key) const;
+
+ // createNestedObject(const std::string&) const
+ // createNestedObject(const String&) const
+ template <typename TString>
+ ObjectRef createNestedObject(const TString &key) const;
+
+ // createNestedObject(char*) const
+ // createNestedObject(const char*) const
+ // createNestedObject(const __FlashStringHelper*) const
+ template <typename TChar>
+ ObjectRef createNestedObject(TChar *key) const;
+
+ private:
+ const TObject *impl() const {
+ return static_cast<const TObject *>(this);
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Object/Pair.hpp b/include/lib/ArduinoJson/Object/Pair.hpp
new file mode 100644
index 0000000..44fce75
--- /dev/null
+++ b/include/lib/ArduinoJson/Object/Pair.hpp
@@ -0,0 +1,55 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/String.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+// A key value pair for CollectionData.
+class Pair {
+ public:
+ Pair(MemoryPool* pool, VariantSlot* slot) {
+ if (slot) {
+ _key = String(slot->key(), !slot->ownsKey());
+ _value = VariantRef(pool, slot->data());
+ }
+ }
+
+ String key() const {
+ return _key;
+ }
+
+ VariantRef value() const {
+ return _value;
+ }
+
+ private:
+ String _key;
+ VariantRef _value;
+};
+
+class PairConst {
+ public:
+ PairConst(const VariantSlot* slot) {
+ if (slot) {
+ _key = String(slot->key(), !slot->ownsKey());
+ _value = VariantConstRef(slot->data());
+ }
+ }
+
+ String key() const {
+ return _key;
+ }
+
+ VariantConstRef value() const {
+ return _value;
+ }
+
+ private:
+ String _key;
+ VariantConstRef _value;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/alias_cast.hpp b/include/lib/ArduinoJson/Polyfills/alias_cast.hpp
new file mode 100644
index 0000000..8f8e277
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/alias_cast.hpp
@@ -0,0 +1,29 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stdint.h>
+#include <stdlib.h> // for size_t
+
+#include <ArduinoJson/Configuration.hpp>
+#include "math.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, typename F>
+struct alias_cast_t {
+ union {
+ F raw;
+ T data;
+ };
+};
+
+template <typename T, typename F>
+T alias_cast(F raw_data) {
+ alias_cast_t<T, F> ac;
+ ac.raw = raw_data;
+ return ac.data;
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/assert.hpp b/include/lib/ArduinoJson/Polyfills/assert.hpp
new file mode 100644
index 0000000..1030ec6
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/assert.hpp
@@ -0,0 +1,14 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+
+#if ARDUINOJSON_DEBUG
+#include <assert.h>
+#define ARDUINOJSON_ASSERT(X) assert(X)
+#else
+#define ARDUINOJSON_ASSERT(X) ((void)0)
+#endif
diff --git a/include/lib/ArduinoJson/Polyfills/attributes.hpp b/include/lib/ArduinoJson/Polyfills/attributes.hpp
new file mode 100644
index 0000000..f04c9ac
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/attributes.hpp
@@ -0,0 +1,54 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#ifdef _MSC_VER // Visual Studio
+
+#define FORCE_INLINE // __forceinline causes C4714 when returning std::string
+#define NO_INLINE __declspec(noinline)
+
+#ifndef ARDUINOJSON_DEPRECATED
+#define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg))
+#endif
+
+#elif defined(__GNUC__) // GCC or Clang
+
+#define FORCE_INLINE __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+
+#ifndef ARDUINOJSON_DEPRECATED
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated(msg)))
+#else
+#define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated))
+#endif
+#endif
+
+#else // Other compilers
+
+#define FORCE_INLINE
+#define NO_INLINE
+
+#ifndef ARDUINOJSON_DEPRECATED
+#define ARDUINOJSON_DEPRECATED(msg)
+#endif
+
+#endif
+
+#if __cplusplus >= 201103L
+#define NOEXCEPT noexcept
+#else
+#define NOEXCEPT throw()
+#endif
+
+#if defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+#define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
+#else
+#define ARDUINOJSON_NO_SANITIZE(check)
+#endif
+#else
+#define ARDUINOJSON_NO_SANITIZE(check)
+#endif
diff --git a/include/lib/ArduinoJson/Polyfills/ctype.hpp b/include/lib/ArduinoJson/Polyfills/ctype.hpp
new file mode 100644
index 0000000..bd7a8cc
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/ctype.hpp
@@ -0,0 +1,20 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+#ifndef isdigit
+inline bool isdigit(char c) {
+ return '0' <= c && c <= '9';
+}
+#endif
+
+inline bool issign(char c) {
+ return '-' == c || c == '+';
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/integer.hpp b/include/lib/ArduinoJson/Polyfills/integer.hpp
new file mode 100644
index 0000000..066c7b8
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/integer.hpp
@@ -0,0 +1,30 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stdint.h> // int8_t, int16_t
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <int Bits>
+struct int_t;
+
+template <>
+struct int_t<8> {
+ typedef int8_t type;
+};
+
+template <>
+struct int_t<16> {
+ typedef int16_t type;
+};
+
+template <>
+struct int_t<32> {
+ typedef int32_t type;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/limits.hpp b/include/lib/ArduinoJson/Polyfills/limits.hpp
new file mode 100644
index 0000000..8004828
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/limits.hpp
@@ -0,0 +1,45 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_traits.hpp"
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4310)
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Differs from standard because we can't use the symbols "min" and "max"
+template <typename T, typename Enable = void>
+struct numeric_limits;
+
+template <typename T>
+struct numeric_limits<T, typename enable_if<is_unsigned<T>::value>::type> {
+ static T lowest() {
+ return 0;
+ }
+ static T highest() {
+ return T(-1);
+ }
+};
+
+template <typename T>
+struct numeric_limits<
+ T, typename enable_if<is_integral<T>::value && is_signed<T>::value>::type> {
+ static T lowest() {
+ return T(T(1) << (sizeof(T) * 8 - 1));
+ }
+ static T highest() {
+ return T(~lowest());
+ }
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
diff --git a/include/lib/ArduinoJson/Polyfills/math.hpp b/include/lib/ArduinoJson/Polyfills/math.hpp
new file mode 100644
index 0000000..eff272a
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/math.hpp
@@ -0,0 +1,27 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Some libraries #define isnan() and isinf() so we need to check before
+// using this name
+
+#ifndef isnan
+template <typename T>
+bool isnan(T x) {
+ return x != x;
+}
+#endif
+
+#ifndef isinf
+template <typename T>
+bool isinf(T x) {
+ return x != 0.0 && x * 2 == x;
+}
+#endif
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/mpl/max.hpp b/include/lib/ArduinoJson/Polyfills/mpl/max.hpp
new file mode 100644
index 0000000..9ac47a5
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/mpl/max.hpp
@@ -0,0 +1,26 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stddef.h> // for size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns the highest value
+template <size_t X, size_t Y, bool MaxIsX = (X > Y)>
+struct Max {};
+
+template <size_t X, size_t Y>
+struct Max<X, Y, true> {
+ static const size_t value = X;
+};
+
+template <size_t X, size_t Y>
+struct Max<X, Y, false> {
+ static const size_t value = Y;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/pgmspace.hpp b/include/lib/ArduinoJson/Polyfills/pgmspace.hpp
new file mode 100644
index 0000000..f253818
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/pgmspace.hpp
@@ -0,0 +1,79 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/assert.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+// Wraps a const char* so that the our functions are picked only if the
+// originals are missing
+struct pgm_p {
+ pgm_p(const char* p) : address(p) {}
+ const char* address;
+};
+} // namespace ARDUINOJSON_NAMESPACE
+
+#ifndef strlen_P
+inline size_t strlen_P(ARDUINOJSON_NAMESPACE::pgm_p s) {
+ const char* p = s.address;
+ ARDUINOJSON_ASSERT(p != NULL);
+ while (pgm_read_byte(p)) p++;
+ return size_t(p - s.address);
+}
+#endif
+
+#ifndef strncmp_P
+inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) {
+ const char* s1 = a;
+ const char* s2 = b.address;
+ ARDUINOJSON_ASSERT(s1 != NULL);
+ ARDUINOJSON_ASSERT(s2 != NULL);
+ while (n-- > 0) {
+ char c1 = *s1++;
+ char c2 = static_cast<char>(pgm_read_byte(s2++));
+ if (c1 < c2)
+ return -1;
+ if (c1 > c2)
+ return 1;
+ if (c1 == 0 /* and c2 as well */)
+ return 0;
+ }
+ return 0;
+}
+#endif
+
+#ifndef strcmp_P
+inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) {
+ const char* s1 = a;
+ const char* s2 = b.address;
+ ARDUINOJSON_ASSERT(s1 != NULL);
+ ARDUINOJSON_ASSERT(s2 != NULL);
+ for (;;) {
+ char c1 = *s1++;
+ char c2 = static_cast<char>(pgm_read_byte(s2++));
+ if (c1 < c2)
+ return -1;
+ if (c1 > c2)
+ return 1;
+ if (c1 == 0 /* and c2 as well */)
+ return 0;
+ }
+}
+#endif
+
+#ifndef memcpy_P
+inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) {
+ uint8_t* d = reinterpret_cast<uint8_t*>(dst);
+ const char* s = src.address;
+ ARDUINOJSON_ASSERT(d != NULL);
+ ARDUINOJSON_ASSERT(s != NULL);
+ while (n-- > 0) {
+ *d++ = pgm_read_byte(s++);
+ }
+ return dst;
+}
+#endif
diff --git a/include/lib/ArduinoJson/Polyfills/pgmspace_generic.hpp b/include/lib/ArduinoJson/Polyfills/pgmspace_generic.hpp
new file mode 100644
index 0000000..f5bbd85
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/pgmspace_generic.hpp
@@ -0,0 +1,32 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+typename enable_if<is_pointer<T>::value, T>::type pgm_read(const void* p) {
+ return reinterpret_cast<T>(pgm_read_ptr(p));
+}
+
+template <typename T>
+typename enable_if<is_floating_point<T>::value &&
+ sizeof(T) == sizeof(float), // on AVR sizeof(double) ==
+ // sizeof(float)
+ T>::type
+pgm_read(const void* p) {
+ return pgm_read_float(p);
+}
+
+template <typename T>
+typename enable_if<is_same<T, uint32_t>::value, T>::type pgm_read(
+ const void* p) {
+ return pgm_read_dword(p);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/preprocessor.hpp b/include/lib/ArduinoJson/Polyfills/preprocessor.hpp
new file mode 100644
index 0000000..488654b
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/preprocessor.hpp
@@ -0,0 +1,35 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#define ARDUINOJSON_EXPAND6(a, b, c, d, e, f) a, b, c, d, e, f
+#define ARDUINOJSON_EXPAND9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i
+#define ARDUINOJSON_EXPAND18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, \
+ q, r) \
+ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r
+
+#define ARDUINOJSON_CONCAT_(A, B) A##B
+#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B)
+#define ARDUINOJSON_CONCAT4(A, B, C, D) \
+ ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
+
+#define ARDUINOJSON_HEX_DIGIT_0000() 0
+#define ARDUINOJSON_HEX_DIGIT_0001() 1
+#define ARDUINOJSON_HEX_DIGIT_0010() 2
+#define ARDUINOJSON_HEX_DIGIT_0011() 3
+#define ARDUINOJSON_HEX_DIGIT_0100() 4
+#define ARDUINOJSON_HEX_DIGIT_0101() 5
+#define ARDUINOJSON_HEX_DIGIT_0110() 6
+#define ARDUINOJSON_HEX_DIGIT_0111() 7
+#define ARDUINOJSON_HEX_DIGIT_1000() 8
+#define ARDUINOJSON_HEX_DIGIT_1001() 9
+#define ARDUINOJSON_HEX_DIGIT_1010() A
+#define ARDUINOJSON_HEX_DIGIT_1011() B
+#define ARDUINOJSON_HEX_DIGIT_1100() C
+#define ARDUINOJSON_HEX_DIGIT_1101() D
+#define ARDUINOJSON_HEX_DIGIT_1110() E
+#define ARDUINOJSON_HEX_DIGIT_1111() F
+#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D()
+#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D)
diff --git a/include/lib/ArduinoJson/Polyfills/safe_strcmp.hpp b/include/lib/ArduinoJson/Polyfills/safe_strcmp.hpp
new file mode 100644
index 0000000..e017b5d
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/safe_strcmp.hpp
@@ -0,0 +1,32 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stdint.h> // int8_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+inline int safe_strcmp(const char* a, const char* b) {
+ if (a == b)
+ return 0;
+ if (!a)
+ return -1;
+ if (!b)
+ return 1;
+ return strcmp(a, b);
+}
+
+inline int safe_strncmp(const char* a, const char* b, size_t n) {
+ if (a == b)
+ return 0;
+ if (!a)
+ return -1;
+ if (!b)
+ return 1;
+ return strncmp(a, b, n);
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/static_array.hpp b/include/lib/ArduinoJson/Polyfills/static_array.hpp
new file mode 100644
index 0000000..a877b4c
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/static_array.hpp
@@ -0,0 +1,34 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+
+#include <ArduinoJson/Polyfills/pgmspace_generic.hpp>
+
+#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
+#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
+ static type const name[] PROGMEM = value;
+#endif
+
+#ifndef ARDUINOJSON_READ_STATIC_ARRAY
+#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \
+ pgm_read<type>(name + index)
+#endif
+
+#else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0
+
+#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY
+#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \
+ static type const name[] = value;
+#endif
+
+#ifndef ARDUINOJSON_READ_STATIC_ARRAY
+#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index]
+#endif
+
+#endif
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits.hpp b/include/lib/ArduinoJson/Polyfills/type_traits.hpp
new file mode 100644
index 0000000..4a8ff4b
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits.hpp
@@ -0,0 +1,24 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_traits/conditional.hpp"
+#include "type_traits/enable_if.hpp"
+#include "type_traits/integral_constant.hpp"
+#include "type_traits/is_array.hpp"
+#include "type_traits/is_base_of.hpp"
+#include "type_traits/is_class.hpp"
+#include "type_traits/is_const.hpp"
+#include "type_traits/is_convertible.hpp"
+#include "type_traits/is_enum.hpp"
+#include "type_traits/is_floating_point.hpp"
+#include "type_traits/is_integral.hpp"
+#include "type_traits/is_pointer.hpp"
+#include "type_traits/is_same.hpp"
+#include "type_traits/is_signed.hpp"
+#include "type_traits/is_unsigned.hpp"
+#include "type_traits/make_unsigned.hpp"
+#include "type_traits/remove_const.hpp"
+#include "type_traits/remove_reference.hpp"
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/conditional.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/conditional.hpp
new file mode 100644
index 0000000..e42d1bb
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/conditional.hpp
@@ -0,0 +1,20 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <bool Condition, class TrueType, class FalseType>
+struct conditional {
+ typedef TrueType type;
+};
+
+template <class TrueType, class FalseType>
+struct conditional<false, TrueType, FalseType> {
+ typedef FalseType type;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/declval.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/declval.hpp
new file mode 100644
index 0000000..8708112
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/declval.hpp
@@ -0,0 +1,14 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+T declval();
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/enable_if.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/enable_if.hpp
new file mode 100644
index 0000000..cc29b33
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/enable_if.hpp
@@ -0,0 +1,19 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T if Condition is true.
+template <bool Condition, typename T = void>
+struct enable_if {};
+
+template <typename T>
+struct enable_if<true, T> {
+ typedef T type;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/integral_constant.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/integral_constant.hpp
new file mode 100644
index 0000000..b53d711
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/integral_constant.hpp
@@ -0,0 +1,19 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, T v>
+struct integral_constant {
+ static const T value = v;
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_array.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_array.hpp
new file mode 100644
index 0000000..ee739a7
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_array.hpp
@@ -0,0 +1,21 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+#include <stddef.h> // size_t
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_array : false_type {};
+
+template <typename T>
+struct is_array<T[]> : true_type {};
+
+template <typename T, size_t N>
+struct is_array<T[N]> : true_type {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_base_of.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_base_of.hpp
new file mode 100644
index 0000000..32b41cd
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_base_of.hpp
@@ -0,0 +1,26 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns true if Derived inherits from TBase is an
+// integral type.
+template <typename TBase, typename TDerived>
+class is_base_of {
+ protected: // <- to avoid GCC's "all member functions in class are private"
+ typedef char Yes[1];
+ typedef char No[2];
+
+ static Yes &probe(const TBase *);
+ static No &probe(...);
+
+ public:
+ static const bool value =
+ sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes);
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_class.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_class.hpp
new file mode 100644
index 0000000..a3808f3
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_class.hpp
@@ -0,0 +1,26 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "declval.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_class {
+ protected: // <- to avoid GCC's "all member functions in class are private"
+ typedef char Yes[1];
+ typedef char No[2];
+
+ template <typename U>
+ static Yes &probe(void (U::*)(void));
+ template <typename>
+ static No &probe(...);
+
+ public:
+ static const bool value = sizeof(probe<T>(0)) == sizeof(Yes);
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_const.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_const.hpp
new file mode 100644
index 0000000..32e758c
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_const.hpp
@@ -0,0 +1,17 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T without the const modifier
+template <typename T>
+struct is_const : false_type {};
+
+template <typename T>
+struct is_const<const T> : true_type {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_convertible.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_convertible.hpp
new file mode 100644
index 0000000..847525a
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_convertible.hpp
@@ -0,0 +1,47 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "declval.hpp"
+
+#ifdef _MSC_VER
+#pragma warning(push)
+// conversion from 'T' to 'To', possible loss of data
+#pragma warning(disable : 4244)
+#endif
+
+// clang-format off
+#ifdef __ICCARM__
+// Suppress IAR Compiler Warning[Pa093]: implicit conversion from floating point to integer
+#pragma diag_suppress=Pa093
+#endif
+// clang-format on
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename From, typename To>
+struct is_convertible {
+ protected: // <- to avoid GCC's "all member functions in class are private"
+ typedef char Yes[1];
+ typedef char No[2];
+
+ static Yes &probe(To);
+ static No &probe(...);
+
+ public:
+ static const bool value = sizeof(probe(declval<From>())) == sizeof(Yes);
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// clang-format off
+#ifdef __ICCARM__
+#pragma diag_default=Pa093
+#endif
+// clang-format on
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_enum.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_enum.hpp
new file mode 100644
index 0000000..26aec1d
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_enum.hpp
@@ -0,0 +1,22 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "is_class.hpp"
+#include "is_convertible.hpp"
+#include "is_floating_point.hpp"
+#include "is_integral.hpp"
+#include "is_same.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_enum {
+ static const bool value = is_convertible<T, int>::value &&
+ !is_class<T>::value && !is_integral<T>::value &&
+ !is_floating_point<T>::value;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp
new file mode 100644
index 0000000..b7e9d3d
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_floating_point.hpp
@@ -0,0 +1,19 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct is_floating_point : false_type {};
+
+template <>
+struct is_floating_point<float> : true_type {};
+
+template <>
+struct is_floating_point<double> : true_type {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_integral.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_integral.hpp
new file mode 100644
index 0000000..26e895c
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_integral.hpp
@@ -0,0 +1,33 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include "is_same.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns true if T is an integral type.
+template <typename T>
+struct is_integral {
+ static const bool value =
+ is_same<T, signed char>::value || is_same<T, unsigned char>::value ||
+ is_same<T, signed short>::value || is_same<T, unsigned short>::value ||
+ is_same<T, signed int>::value || is_same<T, unsigned int>::value ||
+ is_same<T, signed long>::value || is_same<T, unsigned long>::value ||
+#if ARDUINOJSON_HAS_LONG_LONG
+ is_same<T, signed long long>::value ||
+ is_same<T, unsigned long long>::value ||
+#endif
+#if ARDUINOJSON_HAS_INT64
+ is_same<T, signed __int64>::value ||
+ is_same<T, unsigned __int64>::value ||
+#endif
+ is_same<T, char>::value || is_same<T, bool>::value;
+};
+
+template <typename T>
+struct is_integral<const T> : is_integral<T> {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_pointer.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_pointer.hpp
new file mode 100644
index 0000000..a249539
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_pointer.hpp
@@ -0,0 +1,16 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct is_pointer : false_type {};
+
+template <typename T>
+struct is_pointer<T*> : true_type {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_same.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_same.hpp
new file mode 100644
index 0000000..db5da9b
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_same.hpp
@@ -0,0 +1,17 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that returns true if types T and U are the same.
+template <typename T, typename U>
+struct is_same : false_type {};
+
+template <typename T>
+struct is_same<T, T> : true_type {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_signed.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_signed.hpp
new file mode 100644
index 0000000..fbb701c
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_signed.hpp
@@ -0,0 +1,43 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct is_signed : false_type {};
+
+template <>
+struct is_signed<char> : true_type {};
+
+template <>
+struct is_signed<signed char> : true_type {};
+
+template <>
+struct is_signed<signed short> : true_type {};
+
+template <>
+struct is_signed<signed int> : true_type {};
+
+template <>
+struct is_signed<signed long> : true_type {};
+
+template <>
+struct is_signed<float> : true_type {};
+
+template <>
+struct is_signed<double> : true_type {};
+
+#if ARDUINOJSON_HAS_LONG_LONG
+template <>
+struct is_signed<signed long long> : true_type {};
+#endif
+
+#if ARDUINOJSON_HAS_INT64
+template <>
+struct is_signed<signed __int64> : true_type {};
+#endif
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp
new file mode 100644
index 0000000..be26498
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/is_unsigned.hpp
@@ -0,0 +1,37 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct is_unsigned : false_type {};
+
+template <>
+struct is_unsigned<bool> : true_type {};
+
+template <>
+struct is_unsigned<unsigned char> : true_type {};
+
+template <>
+struct is_unsigned<unsigned short> : true_type {};
+
+template <>
+struct is_unsigned<unsigned int> : true_type {};
+
+template <>
+struct is_unsigned<unsigned long> : true_type {};
+
+#if ARDUINOJSON_HAS_INT64
+template <>
+struct is_unsigned<unsigned __int64> : true_type {};
+#endif
+
+#if ARDUINOJSON_HAS_LONG_LONG
+template <>
+struct is_unsigned<unsigned long long> : true_type {};
+#endif
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp
new file mode 100644
index 0000000..4cf2d08
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/make_unsigned.hpp
@@ -0,0 +1,49 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_identity.hpp"
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct make_unsigned;
+
+template <>
+struct make_unsigned<char> : type_identity<unsigned char> {};
+
+template <>
+struct make_unsigned<signed char> : type_identity<unsigned char> {};
+template <>
+struct make_unsigned<unsigned char> : type_identity<unsigned char> {};
+
+template <>
+struct make_unsigned<signed short> : type_identity<unsigned short> {};
+template <>
+struct make_unsigned<unsigned short> : type_identity<unsigned short> {};
+
+template <>
+struct make_unsigned<signed int> : type_identity<unsigned int> {};
+template <>
+struct make_unsigned<unsigned int> : type_identity<unsigned int> {};
+
+template <>
+struct make_unsigned<signed long> : type_identity<unsigned long> {};
+template <>
+struct make_unsigned<unsigned long> : type_identity<unsigned long> {};
+
+#if ARDUINOJSON_HAS_LONG_LONG
+template <>
+struct make_unsigned<signed long long> : type_identity<unsigned long long> {};
+template <>
+struct make_unsigned<unsigned long long> : type_identity<unsigned long long> {};
+#endif
+
+#if ARDUINOJSON_HAS_INT64
+template <>
+struct make_unsigned<signed __int64> : type_identity<unsigned __int64> {};
+template <>
+struct make_unsigned<unsigned __int64> : type_identity<unsigned __int64> {};
+#endif
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/remove_const.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/remove_const.hpp
new file mode 100644
index 0000000..5a19eb1
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/remove_const.hpp
@@ -0,0 +1,20 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T without the const modifier
+template <typename T>
+struct remove_const {
+ typedef T type;
+};
+template <typename T>
+struct remove_const<const T> {
+ typedef T type;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/remove_reference.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/remove_reference.hpp
new file mode 100644
index 0000000..1812850
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/remove_reference.hpp
@@ -0,0 +1,20 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// A meta-function that return the type T without the reference modifier.
+template <typename T>
+struct remove_reference {
+ typedef T type;
+};
+template <typename T>
+struct remove_reference<T&> {
+ typedef T type;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/type_traits/type_identity.hpp b/include/lib/ArduinoJson/Polyfills/type_traits/type_identity.hpp
new file mode 100644
index 0000000..c464a47
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/type_traits/type_identity.hpp
@@ -0,0 +1,15 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "integral_constant.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+struct type_identity {
+ typedef T type;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Polyfills/utility.hpp b/include/lib/ArduinoJson/Polyfills/utility.hpp
new file mode 100644
index 0000000..c99bc99
--- /dev/null
+++ b/include/lib/ArduinoJson/Polyfills/utility.hpp
@@ -0,0 +1,28 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include "type_traits.hpp"
+
+namespace ARDUINOJSON_NAMESPACE {
+template <typename T>
+inline void swap(T& a, T& b) {
+ T t(a);
+ a = b;
+ b = t;
+}
+
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+template <typename T>
+typename remove_reference<T>::type&& move(T&& t) {
+ return static_cast<typename remove_reference<T>::type&&>(t);
+}
+#else
+template <typename T>
+T& move(T& t) {
+ return t;
+}
+#endif
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/CountingDecorator.hpp b/include/lib/ArduinoJson/Serialization/CountingDecorator.hpp
new file mode 100644
index 0000000..3d89fb1
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/CountingDecorator.hpp
@@ -0,0 +1,33 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TWriter>
+class CountingDecorator {
+ public:
+ explicit CountingDecorator(TWriter& writer) : _writer(writer), _count(0) {}
+
+ void write(uint8_t c) {
+ _count += _writer.write(c);
+ }
+
+ void write(const uint8_t* s, size_t n) {
+ _count += _writer.write(s, n);
+ }
+
+ size_t count() const {
+ return _count;
+ }
+
+ private:
+ TWriter _writer;
+ size_t _count;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/Writer.hpp b/include/lib/ArduinoJson/Serialization/Writer.hpp
new file mode 100644
index 0000000..52bd117
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/Writer.hpp
@@ -0,0 +1,47 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// The default writer is a simple wrapper for Writers that are not copiable
+template <typename TDestination, typename Enable = void>
+class Writer {
+ public:
+ explicit Writer(TDestination& dest) : _dest(&dest) {}
+
+ size_t write(uint8_t c) {
+ return _dest->write(c);
+ }
+
+ size_t write(const uint8_t* s, size_t n) {
+ return _dest->write(s, n);
+ }
+
+ private:
+ TDestination* _dest;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
+
+#include <ArduinoJson/Serialization/Writers/StaticStringWriter.hpp>
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+#include <ArduinoJson/Serialization/Writers/StdStringWriter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STREAM
+#include <ArduinoJson/Serialization/Writers/StdStreamWriter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
+#include <ArduinoJson/Serialization/Writers/PrintWriter.hpp>
+#endif
diff --git a/include/lib/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp b/include/lib/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp
new file mode 100644
index 0000000..5efa6e4
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/Writers/ArduinoStringWriter.hpp
@@ -0,0 +1,52 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <Arduino.h>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <>
+class Writer< ::String, void> {
+ static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
+
+ public:
+ explicit Writer(::String &str) : _destination(&str) {
+ _size = 0;
+ }
+
+ ~Writer() {
+ flush();
+ }
+
+ size_t write(uint8_t c) {
+ ARDUINOJSON_ASSERT(_size < bufferCapacity);
+ _buffer[_size++] = static_cast<char>(c);
+ if (_size + 1 >= bufferCapacity)
+ flush();
+ return 1;
+ }
+
+ size_t write(const uint8_t *s, size_t n) {
+ for (size_t i = 0; i < n; i++) {
+ write(s[i]);
+ }
+ return n;
+ }
+
+ private:
+ void flush() {
+ ARDUINOJSON_ASSERT(_size < bufferCapacity);
+ _buffer[_size] = 0;
+ *_destination += _buffer;
+ _size = 0;
+ }
+
+ ::String *_destination;
+ char _buffer[bufferCapacity];
+ size_t _size;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/Writers/DummyWriter.hpp b/include/lib/ArduinoJson/Serialization/Writers/DummyWriter.hpp
new file mode 100644
index 0000000..a26a1f1
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/Writers/DummyWriter.hpp
@@ -0,0 +1,21 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class DummyWriter {
+ public:
+ size_t write(uint8_t) {
+ return 1;
+ }
+
+ size_t write(const uint8_t*, size_t n) {
+ return n;
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/Writers/PrintWriter.hpp b/include/lib/ArduinoJson/Serialization/Writers/PrintWriter.hpp
new file mode 100644
index 0000000..13a6491
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/Writers/PrintWriter.hpp
@@ -0,0 +1,28 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TDestination>
+class Writer<
+ TDestination,
+ typename enable_if<is_base_of< ::Print, TDestination>::value>::type> {
+ public:
+ explicit Writer(::Print& print) : _print(&print) {}
+
+ size_t write(uint8_t c) {
+ return _print->write(c);
+ }
+
+ size_t write(const uint8_t* s, size_t n) {
+ return _print->write(s, n);
+ }
+
+ private:
+ ::Print* _print;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp b/include/lib/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp
new file mode 100644
index 0000000..1a4213b
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/Writers/StaticStringWriter.hpp
@@ -0,0 +1,35 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class StaticStringWriter {
+ public:
+ StaticStringWriter(char *buf, size_t size) : end(buf + size), p(buf) {}
+
+ size_t write(uint8_t c) {
+ if (p >= end)
+ return 0;
+ *p++ = static_cast<char>(c);
+ return 1;
+ }
+
+ size_t write(const uint8_t *s, size_t n) {
+ char *begin = p;
+ while (p < end && n > 0) {
+ *p++ = static_cast<char>(*s++);
+ n--;
+ }
+ return size_t(p - begin);
+ }
+
+ private:
+ char *end;
+ char *p;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp b/include/lib/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp
new file mode 100644
index 0000000..e08ba4d
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/Writers/StdStreamWriter.hpp
@@ -0,0 +1,32 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ostream>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TDestination>
+class Writer<
+ TDestination,
+ typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
+ public:
+ explicit Writer(std::ostream& os) : _os(&os) {}
+
+ size_t write(uint8_t c) {
+ _os->put(static_cast<char>(c));
+ return 1;
+ }
+
+ size_t write(const uint8_t* s, size_t n) {
+ _os->write(reinterpret_cast<const char*>(s),
+ static_cast<std::streamsize>(n));
+ return n;
+ }
+
+ private:
+ std::ostream* _os;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/Writers/StdStringWriter.hpp b/include/lib/ArduinoJson/Serialization/Writers/StdStringWriter.hpp
new file mode 100644
index 0000000..c1f7cc0
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/Writers/StdStringWriter.hpp
@@ -0,0 +1,40 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+#include <string>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <class T>
+struct is_std_string : false_type {};
+
+template <class TCharTraits, class TAllocator>
+struct is_std_string<std::basic_string<char, TCharTraits, TAllocator> >
+ : true_type {};
+
+template <typename TDestination>
+class Writer<TDestination,
+ typename enable_if<is_std_string<TDestination>::value>::type> {
+ public:
+ Writer(TDestination &str) : _str(&str) {}
+
+ size_t write(uint8_t c) {
+ _str->operator+=(static_cast<char>(c));
+ return 1;
+ }
+
+ size_t write(const uint8_t *s, size_t n) {
+ _str->append(reinterpret_cast<const char *>(s), n);
+ return n;
+ }
+
+ private:
+ TDestination *_str;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/measure.hpp b/include/lib/ArduinoJson/Serialization/measure.hpp
new file mode 100644
index 0000000..6d19994
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/measure.hpp
@@ -0,0 +1,18 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Serialization/Writers/DummyWriter.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <template <typename> class TSerializer, typename TSource>
+size_t measure(const TSource &source) {
+ DummyWriter dp;
+ TSerializer<DummyWriter> serializer(dp);
+ return source.accept(serializer);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Serialization/serialize.hpp b/include/lib/ArduinoJson/Serialization/serialize.hpp
new file mode 100644
index 0000000..16d2e4e
--- /dev/null
+++ b/include/lib/ArduinoJson/Serialization/serialize.hpp
@@ -0,0 +1,54 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Serialization/Writer.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <template <typename> class TSerializer, typename TSource,
+ typename TWriter>
+size_t doSerialize(const TSource &source, TWriter writer) {
+ TSerializer<TWriter> serializer(writer);
+ return source.accept(serializer);
+}
+
+template <template <typename> class TSerializer, typename TSource,
+ typename TDestination>
+size_t serialize(const TSource &source, TDestination &destination) {
+ Writer<TDestination> writer(destination);
+ return doSerialize<TSerializer>(source, writer);
+}
+
+template <template <typename> class TSerializer, typename TSource>
+typename enable_if<!TSerializer<StaticStringWriter>::producesText, size_t>::type
+serialize(const TSource &source, void *buffer, size_t bufferSize) {
+ StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize);
+ return doSerialize<TSerializer>(source, writer);
+}
+
+template <template <typename> class TSerializer, typename TSource>
+typename enable_if<TSerializer<StaticStringWriter>::producesText, size_t>::type
+serialize(const TSource &source, void *buffer, size_t bufferSize) {
+ StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize);
+ size_t n = doSerialize<TSerializer>(source, writer);
+ // add null-terminator for text output (not counted in the size)
+ if (n < bufferSize)
+ reinterpret_cast<char *>(buffer)[n] = 0;
+ return n;
+}
+
+template <template <typename> class TSerializer, typename TSource,
+ typename TChar, size_t N>
+#if defined _MSC_VER && _MSC_VER < 1900
+typename enable_if<sizeof(remove_reference<TChar>::type) == 1, size_t>::type
+#else
+typename enable_if<sizeof(TChar) == 1, size_t>::type
+#endif
+serialize(const TSource &source, TChar (&buffer)[N]) {
+ return serialize<TSerializer>(source, buffer, N);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/StringStorage/StringCopier.hpp b/include/lib/ArduinoJson/StringStorage/StringCopier.hpp
new file mode 100644
index 0000000..8b1104b
--- /dev/null
+++ b/include/lib/ArduinoJson/StringStorage/StringCopier.hpp
@@ -0,0 +1,62 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class StringCopier {
+ public:
+ StringCopier(MemoryPool& pool) : _pool(&pool) {}
+
+ void startString() {
+ _pool->getFreeZone(&_ptr, &_capacity);
+ _size = 0;
+ }
+
+ const char* save() {
+ ARDUINOJSON_ASSERT(_ptr);
+ return _pool->saveStringFromFreeZone(_size);
+ }
+
+ void append(const char* s) {
+ while (*s) append(*s++);
+ }
+
+ void append(const char* s, size_t n) {
+ while (n-- > 0) append(*s++);
+ }
+
+ void append(char c) {
+ if (!_ptr)
+ return;
+
+ if (_size >= _capacity) {
+ _ptr = 0;
+ _pool->markAsOverflowed();
+ return;
+ }
+
+ _ptr[_size++] = c;
+ }
+
+ bool isValid() {
+ return _ptr != 0;
+ }
+
+ const char* c_str() {
+ return _ptr;
+ }
+
+ typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+ MemoryPool* _pool;
+ char* _ptr;
+ size_t _size;
+ size_t _capacity;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/StringStorage/StringMover.hpp b/include/lib/ArduinoJson/StringStorage/StringMover.hpp
new file mode 100644
index 0000000..f727a7d
--- /dev/null
+++ b/include/lib/ArduinoJson/StringStorage/StringMover.hpp
@@ -0,0 +1,42 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class StringMover {
+ public:
+ StringMover(char* ptr) : _writePtr(ptr) {}
+
+ void startString() {
+ _startPtr = _writePtr;
+ }
+
+ const char* save() const {
+ return _startPtr;
+ }
+
+ void append(char c) {
+ *_writePtr++ = c;
+ }
+
+ bool isValid() const {
+ return true;
+ }
+
+ const char* c_str() const {
+ return _startPtr;
+ }
+
+ typedef storage_policies::store_by_address storage_policy;
+
+ private:
+ char* _writePtr;
+ char* _startPtr;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/StringStorage/StringStorage.hpp b/include/lib/ArduinoJson/StringStorage/StringStorage.hpp
new file mode 100644
index 0000000..36e6326
--- /dev/null
+++ b/include/lib/ArduinoJson/StringStorage/StringStorage.hpp
@@ -0,0 +1,23 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/StringStorage/StringCopier.hpp>
+#include <ArduinoJson/StringStorage/StringMover.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TInput>
+StringCopier makeStringStorage(TInput&, MemoryPool& pool) {
+ return StringCopier(pool);
+}
+
+template <typename TChar>
+StringMover makeStringStorage(
+ TChar* input, MemoryPool&,
+ typename enable_if<!is_const<TChar>::value>::type* = 0) {
+ return StringMover(reinterpret_cast<char*>(input));
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/ArduinoStringAdapter.hpp b/include/lib/ArduinoJson/Strings/ArduinoStringAdapter.hpp
new file mode 100644
index 0000000..24646cc
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/ArduinoStringAdapter.hpp
@@ -0,0 +1,62 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <Arduino.h>
+
+#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class ArduinoStringAdapter {
+ public:
+ ArduinoStringAdapter(const ::String& str) : _str(&str) {}
+
+ void copyTo(char* p, size_t n) const {
+ memcpy(p, _str->c_str(), n);
+ }
+
+ bool isNull() const {
+ // Arduino's String::c_str() can return NULL
+ return !_str->c_str();
+ }
+
+ int compare(const char* other) const {
+ // Arduino's String::c_str() can return NULL
+ const char* me = _str->c_str();
+ return safe_strcmp(me, other);
+ }
+
+ bool equals(const char* expected) const {
+ return compare(expected) == 0;
+ }
+
+ size_t size() const {
+ return _str->length();
+ }
+
+ const char* begin() const {
+ return _str->c_str();
+ }
+
+ typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+ const ::String* _str;
+};
+
+template <>
+struct IsString< ::String> : true_type {};
+
+template <>
+struct IsString< ::StringSumHelper> : true_type {};
+
+inline ArduinoStringAdapter adaptString(const ::String& str) {
+ return ArduinoStringAdapter(str);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/ConstRamStringAdapter.hpp b/include/lib/ArduinoJson/Strings/ConstRamStringAdapter.hpp
new file mode 100644
index 0000000..ec7d53a
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/ConstRamStringAdapter.hpp
@@ -0,0 +1,62 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h> // size_t
+#include <string.h> // strcmp
+
+#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class ConstRamStringAdapter {
+ public:
+ ConstRamStringAdapter(const char* str = 0) : _str(str) {}
+
+ int compare(const char* other) const {
+ return safe_strcmp(_str, other);
+ }
+
+ bool equals(const char* expected) const {
+ return compare(expected) == 0;
+ }
+
+ bool isNull() const {
+ return !_str;
+ }
+
+ size_t size() const {
+ if (!_str)
+ return 0;
+ return strlen(_str);
+ }
+
+ const char* data() const {
+ return _str;
+ }
+
+ const char* begin() const {
+ return _str;
+ }
+
+ typedef storage_policies::store_by_address storage_policy;
+
+ protected:
+ const char* _str;
+};
+
+template <>
+struct IsString<const char*> : true_type {};
+
+template <int N>
+struct IsString<const char[N]> : true_type {};
+
+inline ConstRamStringAdapter adaptString(const char* str) {
+ return ConstRamStringAdapter(str);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/FlashStringAdapter.hpp b/include/lib/ArduinoJson/Strings/FlashStringAdapter.hpp
new file mode 100644
index 0000000..292e348
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/FlashStringAdapter.hpp
@@ -0,0 +1,62 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/pgmspace.hpp>
+#include <ArduinoJson/Strings/FlashStringIterator.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class FlashStringAdapter {
+ public:
+ FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {}
+
+ int compare(const char* other) const {
+ if (!other && !_str)
+ return 0;
+ if (!_str)
+ return -1;
+ if (!other)
+ return 1;
+ return -strcmp_P(other, reinterpret_cast<const char*>(_str));
+ }
+
+ bool equals(const char* expected) const {
+ return compare(expected) == 0;
+ }
+
+ bool isNull() const {
+ return !_str;
+ }
+
+ void copyTo(char* p, size_t n) const {
+ memcpy_P(p, reinterpret_cast<const char*>(_str), n);
+ }
+
+ size_t size() const {
+ if (!_str)
+ return 0;
+ return strlen_P(reinterpret_cast<const char*>(_str));
+ }
+
+ FlashStringIterator begin() const {
+ return FlashStringIterator(_str);
+ }
+
+ typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+ const __FlashStringHelper* _str;
+};
+
+inline FlashStringAdapter adaptString(const __FlashStringHelper* str) {
+ return FlashStringAdapter(str);
+}
+
+template <>
+struct IsString<const __FlashStringHelper*> : true_type {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/FlashStringIterator.hpp b/include/lib/ArduinoJson/Strings/FlashStringIterator.hpp
new file mode 100644
index 0000000..9a97f32
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/FlashStringIterator.hpp
@@ -0,0 +1,44 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class FlashStringIterator {
+ public:
+ explicit FlashStringIterator(const __FlashStringHelper* ptr)
+ : _ptr(reinterpret_cast<const char*>(ptr)) {}
+
+ explicit FlashStringIterator(const char* ptr) : _ptr(ptr) {}
+
+ FlashStringIterator operator+(ptrdiff_t d) const {
+ return FlashStringIterator(_ptr + d);
+ }
+
+ ptrdiff_t operator-(FlashStringIterator other) const {
+ return _ptr - other._ptr;
+ }
+
+ FlashStringIterator operator++(int) {
+ return FlashStringIterator(_ptr++);
+ }
+
+ FlashStringIterator operator++() {
+ return FlashStringIterator(++_ptr);
+ }
+
+ bool operator!=(FlashStringIterator other) const {
+ return _ptr != other._ptr;
+ }
+
+ char operator*() const {
+ return char(pgm_read_byte(_ptr));
+ }
+
+ private:
+ const char* _ptr;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/IsString.hpp b/include/lib/ArduinoJson/Strings/IsString.hpp
new file mode 100644
index 0000000..af5a91a
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/IsString.hpp
@@ -0,0 +1,18 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+template <typename>
+struct IsString : false_type {};
+
+template <typename T>
+struct IsString<const T> : IsString<T> {};
+
+template <typename T>
+struct IsString<T&> : IsString<T> {};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/IsWriteableString.hpp b/include/lib/ArduinoJson/Strings/IsWriteableString.hpp
new file mode 100644
index 0000000..32039e3
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/IsWriteableString.hpp
@@ -0,0 +1,37 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <Arduino.h>
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+#include <string>
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename>
+struct IsWriteableString : false_type {};
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+
+template <>
+struct IsWriteableString< ::String> : true_type {};
+
+#endif
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+
+template <typename TCharTraits, typename TAllocator>
+struct IsWriteableString<std::basic_string<char, TCharTraits, TAllocator> >
+ : true_type {};
+
+#endif
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/RamStringAdapter.hpp b/include/lib/ArduinoJson/Strings/RamStringAdapter.hpp
new file mode 100644
index 0000000..eded6c9
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/RamStringAdapter.hpp
@@ -0,0 +1,43 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class RamStringAdapter : public ConstRamStringAdapter {
+ public:
+ RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
+
+ void copyTo(char* p, size_t n) const {
+ memcpy(p, _str, n);
+ }
+
+ typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy;
+};
+
+template <typename TChar>
+inline RamStringAdapter adaptString(const TChar* str) {
+ return RamStringAdapter(reinterpret_cast<const char*>(str));
+}
+
+inline RamStringAdapter adaptString(char* str) {
+ return RamStringAdapter(str);
+}
+
+template <typename TChar>
+struct IsString<TChar*> {
+ static const bool value = sizeof(TChar) == 1;
+};
+
+template <>
+struct IsString<void*> {
+ static const bool value = false;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/SizedFlashStringAdapter.hpp b/include/lib/ArduinoJson/Strings/SizedFlashStringAdapter.hpp
new file mode 100644
index 0000000..b9cc0bf
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/SizedFlashStringAdapter.hpp
@@ -0,0 +1,60 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/FlashStringIterator.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class SizedFlashStringAdapter {
+ public:
+ SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz)
+ : _str(str), _size(sz) {}
+
+ int compare(const char* other) const {
+ if (!other && !_str)
+ return 0;
+ if (!_str)
+ return -1;
+ if (!other)
+ return 1;
+ return -strncmp_P(other, reinterpret_cast<const char*>(_str), _size);
+ }
+
+ bool equals(const char* expected) const {
+ return compare(expected) == 0;
+ }
+
+ bool isNull() const {
+ return !_str;
+ }
+
+ void copyTo(char* p, size_t n) const {
+ memcpy_P(p, reinterpret_cast<const char*>(_str), n);
+ }
+
+ size_t size() const {
+ return _size;
+ }
+
+ FlashStringIterator begin() const {
+ return FlashStringIterator(_str);
+ }
+
+ typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+ const __FlashStringHelper* _str;
+ size_t _size;
+};
+
+inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str,
+ size_t sz) {
+ return SizedFlashStringAdapter(str, sz);
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/SizedRamStringAdapter.hpp b/include/lib/ArduinoJson/Strings/SizedRamStringAdapter.hpp
new file mode 100644
index 0000000..fe23408
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/SizedRamStringAdapter.hpp
@@ -0,0 +1,55 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+#include <string.h> // strcmp
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class SizedRamStringAdapter {
+ public:
+ SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {}
+
+ int compare(const char* other) const {
+ return safe_strncmp(_str, other, _size);
+ }
+
+ bool equals(const char* expected) const {
+ return compare(expected) == 0;
+ }
+
+ bool isNull() const {
+ return !_str;
+ }
+
+ void copyTo(char* p, size_t n) const {
+ memcpy(p, _str, n);
+ }
+
+ size_t size() const {
+ return _size;
+ }
+
+ const char* begin() const {
+ return _str;
+ }
+
+ typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+ const char* _str;
+ size_t _size;
+};
+
+template <typename TChar>
+inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) {
+ return SizedRamStringAdapter(reinterpret_cast<const char*>(str), size);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/StdStringAdapter.hpp b/include/lib/ArduinoJson/Strings/StdStringAdapter.hpp
new file mode 100644
index 0000000..ebf4c39
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/StdStringAdapter.hpp
@@ -0,0 +1,65 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+#include <string>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TString>
+class StdStringAdapter {
+ public:
+ StdStringAdapter(const TString& str) : _str(&str) {}
+
+ void copyTo(char* p, size_t n) const {
+ memcpy(p, _str->c_str(), n);
+ }
+
+ bool isNull() const {
+ return false;
+ }
+
+ int compare(const char* other) const {
+ if (!other)
+ return 1;
+ return _str->compare(other);
+ }
+
+ bool equals(const char* expected) const {
+ if (!expected)
+ return false;
+ return *_str == expected;
+ }
+
+ size_t size() const {
+ return _str->size();
+ }
+
+ const char* begin() const {
+ return _str->c_str();
+ }
+
+ typedef storage_policies::store_by_copy storage_policy;
+
+ private:
+ const TString* _str;
+};
+
+template <typename TCharTraits, typename TAllocator>
+struct IsString<std::basic_string<char, TCharTraits, TAllocator> > : true_type {
+};
+
+template <typename TCharTraits, typename TAllocator>
+inline StdStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >
+adaptString(const std::basic_string<char, TCharTraits, TAllocator>& str) {
+ return StdStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >(
+ str);
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/StoragePolicy.hpp b/include/lib/ArduinoJson/Strings/StoragePolicy.hpp
new file mode 100644
index 0000000..df0d62b
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/StoragePolicy.hpp
@@ -0,0 +1,15 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+namespace storage_policies {
+struct store_by_address {};
+struct store_by_copy {};
+struct decide_at_runtime {};
+} // namespace storage_policies
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/String.hpp b/include/lib/ArduinoJson/Strings/String.hpp
new file mode 100644
index 0000000..4f2abde
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/String.hpp
@@ -0,0 +1,77 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class String {
+ public:
+ String() : _data(0), _isStatic(true) {}
+ String(const char* data, bool isStaticData = true)
+ : _data(data), _isStatic(isStaticData) {}
+
+ const char* c_str() const {
+ return _data;
+ }
+
+ bool isNull() const {
+ return !_data;
+ }
+
+ bool isStatic() const {
+ return _isStatic;
+ }
+
+ friend bool operator==(String lhs, String rhs) {
+ if (lhs._data == rhs._data)
+ return true;
+ if (!lhs._data)
+ return false;
+ if (!rhs._data)
+ return false;
+ return strcmp(lhs._data, rhs._data) == 0;
+ }
+
+ friend bool operator!=(String lhs, String rhs) {
+ if (lhs._data == rhs._data)
+ return false;
+ if (!lhs._data)
+ return true;
+ if (!rhs._data)
+ return true;
+ return strcmp(lhs._data, rhs._data) != 0;
+ }
+
+ private:
+ const char* _data;
+ bool _isStatic;
+};
+
+class StringAdapter : public RamStringAdapter {
+ public:
+ StringAdapter(const String& str)
+ : RamStringAdapter(str.c_str()), _isStatic(str.isStatic()) {}
+
+ bool isStatic() const {
+ return _isStatic;
+ }
+
+ typedef storage_policies::decide_at_runtime storage_policy;
+
+ private:
+ bool _isStatic;
+};
+
+template <>
+struct IsString<String> : true_type {};
+
+inline StringAdapter adaptString(const String& str) {
+ return StringAdapter(str);
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Strings/StringAdapters.hpp b/include/lib/ArduinoJson/Strings/StringAdapters.hpp
new file mode 100644
index 0000000..3d294d2
--- /dev/null
+++ b/include/lib/ArduinoJson/Strings/StringAdapters.hpp
@@ -0,0 +1,22 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
+#include <ArduinoJson/Strings/RamStringAdapter.hpp>
+#include <ArduinoJson/Strings/SizedRamStringAdapter.hpp>
+
+#if ARDUINOJSON_ENABLE_STD_STRING
+#include <ArduinoJson/Strings/StdStringAdapter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STRING
+#include <ArduinoJson/Strings/ArduinoStringAdapter.hpp>
+#endif
+
+#if ARDUINOJSON_ENABLE_PROGMEM
+#include <ArduinoJson/Strings/FlashStringAdapter.hpp>
+#include <ArduinoJson/Strings/SizedFlashStringAdapter.hpp>
+#endif
diff --git a/include/lib/ArduinoJson/Variant/Converter.hpp b/include/lib/ArduinoJson/Variant/Converter.hpp
new file mode 100644
index 0000000..476ca8f
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/Converter.hpp
@@ -0,0 +1,12 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, typename Enable = void>
+struct Converter;
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/ConverterImpl.hpp b/include/lib/ArduinoJson/Variant/ConverterImpl.hpp
new file mode 100644
index 0000000..34e12bb
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/ConverterImpl.hpp
@@ -0,0 +1,268 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Strings/IsWriteableString.hpp>
+#include <ArduinoJson/Variant/VariantFunctions.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T, typename Enable>
+struct Converter {
+ static bool toJson(const T& src, VariantRef dst) {
+ // clang-format off
+ return convertToJson(src, dst); // Error here? See https://arduinojson.org/v6/unsupported-set/
+ // clang-format on
+ }
+
+ static T fromJson(VariantConstRef src) {
+ // clang-format off
+ T result; // Error here? See https://arduinojson.org/v6/non-default-constructible/
+ convertFromJson(src, result); // Error here? See https://arduinojson.org/v6/unsupported-as/
+ // clang-format on
+ return result;
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ T dummy;
+ // clang-format off
+ return canConvertFromJson(src, dummy); // Error here? See https://arduinojson.org/v6/unsupported-is/
+ // clang-format on
+ }
+};
+
+template <typename T>
+struct Converter<
+ T, typename enable_if<is_integral<T>::value && !is_same<bool, T>::value &&
+ !is_same<char, T>::value>::type> {
+ static bool toJson(T src, VariantRef dst) {
+ VariantData* data = getData(dst);
+ ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
+ if (!data)
+ return false;
+ data->setInteger(src);
+ return true;
+ }
+
+ static T fromJson(VariantConstRef src) {
+ ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
+ const VariantData* data = getData(src);
+ return data ? data->asIntegral<T>() : T();
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data && data->isInteger<T>();
+ }
+};
+
+template <typename T>
+struct Converter<T, typename enable_if<is_enum<T>::value>::type> {
+ static bool toJson(T src, VariantRef dst) {
+ return dst.set(static_cast<Integer>(src));
+ }
+
+ static T fromJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data ? static_cast<T>(data->asIntegral<int>()) : T();
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data && data->isInteger<int>();
+ }
+};
+
+template <>
+struct Converter<bool> {
+ static bool toJson(bool src, VariantRef dst) {
+ VariantData* data = getData(dst);
+ if (!data)
+ return false;
+ data->setBoolean(src);
+ return true;
+ }
+
+ static bool fromJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data ? data->asBoolean() : false;
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data && data->isBoolean();
+ }
+};
+
+template <typename T>
+struct Converter<T, typename enable_if<is_floating_point<T>::value>::type> {
+ static bool toJson(T src, VariantRef dst) {
+ VariantData* data = getData(dst);
+ if (!data)
+ return false;
+ data->setFloat(static_cast<Float>(src));
+ return true;
+ }
+
+ static T fromJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data ? data->asFloat<T>() : false;
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data && data->isFloat();
+ }
+};
+
+template <>
+struct Converter<const char*> {
+ static bool toJson(const char* src, VariantRef dst) {
+ return variantSetString(getData(dst), adaptString(src), getPool(dst));
+ }
+
+ static const char* fromJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data ? data->asString() : 0;
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data && data->isString();
+ }
+};
+
+template <typename T>
+inline typename enable_if<IsString<T>::value, bool>::type convertToJson(
+ const T& src, VariantRef dst) {
+ VariantData* data = getData(dst);
+ MemoryPool* pool = getPool(dst);
+ return variantSetString(data, adaptString(src), pool);
+}
+
+template <typename T>
+inline typename enable_if<IsWriteableString<T>::value>::type convertFromJson(
+ VariantConstRef src, T& dst) {
+ const VariantData* data = getData(src);
+ const char* cstr = data != 0 ? data->asString() : 0;
+ if (cstr)
+ dst = cstr;
+ else
+ serializeJson(src, dst);
+}
+
+template <typename T>
+inline typename enable_if<IsWriteableString<T>::value, bool>::type
+canConvertFromJson(VariantConstRef src, const T&) {
+ const VariantData* data = getData(src);
+ return data && data->isString();
+}
+
+template <>
+struct Converter<SerializedValue<const char*> > {
+ static bool toJson(SerializedValue<const char*> src, VariantRef dst) {
+ VariantData* data = getData(dst);
+ if (!data)
+ return false;
+ data->setLinkedRaw(src);
+ return true;
+ }
+};
+
+// SerializedValue<std::string>
+// SerializedValue<String>
+// SerializedValue<const __FlashStringHelper*>
+template <typename T>
+struct Converter<SerializedValue<T>,
+ typename enable_if<!is_same<const char*, T>::value>::type> {
+ static bool toJson(SerializedValue<T> src, VariantRef dst) {
+ VariantData* data = getData(dst);
+ MemoryPool* pool = getPool(dst);
+ return data != 0 && data->setOwnedRaw(src, pool);
+ }
+};
+
+#if ARDUINOJSON_HAS_NULLPTR
+
+template <>
+struct Converter<decltype(nullptr)> {
+ static bool toJson(decltype(nullptr), VariantRef dst) {
+ variantSetNull(getData(dst));
+ return true;
+ }
+ static decltype(nullptr) fromJson(VariantConstRef) {
+ return nullptr;
+ }
+ static bool checkJson(VariantConstRef src) {
+ const VariantData* data = getData(src);
+ return data == 0 || data->isNull();
+ }
+};
+
+#endif
+
+#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
+
+class MemoryPoolPrint : public Print {
+ public:
+ MemoryPoolPrint(MemoryPool* pool) : _pool(pool), _size(0) {
+ pool->getFreeZone(&_string, &_capacity);
+ }
+
+ const char* c_str() {
+ _string[_size++] = 0;
+ ARDUINOJSON_ASSERT(_size <= _capacity);
+ return _pool->saveStringFromFreeZone(_size);
+ }
+
+ size_t write(uint8_t c) {
+ if (_size >= _capacity)
+ return 0;
+
+ _string[_size++] = char(c);
+ return 1;
+ }
+
+ size_t write(const uint8_t* buffer, size_t size) {
+ if (_size + size >= _capacity) {
+ _size = _capacity; // mark as overflowed
+ return 0;
+ }
+ memcpy(&_string[_size], buffer, size);
+ _size += size;
+ return size;
+ }
+
+ bool overflowed() const {
+ return _size >= _capacity;
+ }
+
+ private:
+ MemoryPool* _pool;
+ size_t _size;
+ char* _string;
+ size_t _capacity;
+};
+
+inline bool convertToJson(const ::Printable& src, VariantRef dst) {
+ MemoryPool* pool = getPool(dst);
+ VariantData* data = getData(dst);
+ if (!pool || !data)
+ return false;
+ MemoryPoolPrint print(pool);
+ src.printTo(print);
+ if (print.overflowed()) {
+ pool->markAsOverflowed();
+ data->setNull();
+ return false;
+ }
+ data->setStringPointer(print.c_str(), storage_policies::store_by_copy());
+ return true;
+}
+
+#endif
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/SlotFunctions.hpp b/include/lib/ArduinoJson/Variant/SlotFunctions.hpp
new file mode 100644
index 0000000..74ac5a7
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/SlotFunctions.hpp
@@ -0,0 +1,60 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/assert.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
+ if (!var)
+ return false;
+ return slotSetKey(var, key, pool, typename TAdaptedString::storage_policy());
+}
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
+ storage_policies::decide_at_runtime) {
+ if (key.isStatic()) {
+ return slotSetKey(var, key, pool, storage_policies::store_by_address());
+ } else {
+ return slotSetKey(var, key, pool, storage_policies::store_by_copy());
+ }
+}
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
+ storage_policies::store_by_address) {
+ ARDUINOJSON_ASSERT(var);
+ var->setKey(key.data(), storage_policies::store_by_address());
+ return true;
+}
+
+template <typename TAdaptedString>
+inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
+ storage_policies::store_by_copy) {
+ const char* dup = pool->saveString(key);
+ if (!dup)
+ return false;
+ ARDUINOJSON_ASSERT(var);
+ var->setKey(dup, storage_policies::store_by_copy());
+ return true;
+}
+
+inline size_t slotSize(const VariantSlot* var) {
+ size_t n = 0;
+ while (var) {
+ n++;
+ var = var->next();
+ }
+ return n;
+}
+
+inline VariantData* slotData(VariantSlot* slot) {
+ return reinterpret_cast<VariantData*>(slot);
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantCompare.hpp b/include/lib/ArduinoJson/Variant/VariantCompare.hpp
new file mode 100644
index 0000000..025ef90
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantCompare.hpp
@@ -0,0 +1,208 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/IsString.hpp>
+#include <ArduinoJson/Variant/Visitor.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class CollectionData;
+
+struct ComparerBase : Visitor<CompareResult> {};
+
+template <typename T, typename Enable = void>
+struct Comparer;
+
+template <typename T>
+struct Comparer<T, typename enable_if<IsString<T>::value>::type>
+ : ComparerBase {
+ T rhs;
+
+ explicit Comparer(T value) : rhs(value) {}
+
+ CompareResult visitString(const char *lhs) {
+ int i = adaptString(rhs).compare(lhs);
+ if (i < 0)
+ return COMPARE_RESULT_GREATER;
+ else if (i > 0)
+ return COMPARE_RESULT_LESS;
+ else
+ return COMPARE_RESULT_EQUAL;
+ }
+
+ CompareResult visitNull() {
+ if (adaptString(rhs).isNull())
+ return COMPARE_RESULT_EQUAL;
+ else
+ return COMPARE_RESULT_DIFFER;
+ }
+};
+
+template <typename T>
+struct Comparer<T, typename enable_if<is_integral<T>::value ||
+ is_floating_point<T>::value>::type>
+ : ComparerBase {
+ T rhs;
+
+ explicit Comparer(T value) : rhs(value) {}
+
+ CompareResult visitFloat(Float lhs) {
+ return arithmeticCompare(lhs, rhs);
+ }
+
+ CompareResult visitSignedInteger(Integer lhs) {
+ return arithmeticCompare(lhs, rhs);
+ }
+
+ CompareResult visitUnsignedInteger(UInt lhs) {
+ return arithmeticCompare(lhs, rhs);
+ }
+
+ CompareResult visitBoolean(bool lhs) {
+ return visitUnsignedInteger(static_cast<UInt>(lhs));
+ }
+};
+
+struct NullComparer : ComparerBase {
+ CompareResult visitNull() {
+ return COMPARE_RESULT_EQUAL;
+ }
+};
+
+#if ARDUINOJSON_HAS_NULLPTR
+template <>
+struct Comparer<decltype(nullptr), void> : NullComparer {
+ explicit Comparer(decltype(nullptr)) : NullComparer() {}
+};
+#endif
+
+struct ArrayComparer : ComparerBase {
+ const CollectionData *_rhs;
+
+ explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
+
+ CompareResult visitArray(const CollectionData &lhs) {
+ if (lhs.equalsArray(*_rhs))
+ return COMPARE_RESULT_EQUAL;
+ else
+ return COMPARE_RESULT_DIFFER;
+ }
+};
+
+struct ObjectComparer : ComparerBase {
+ const CollectionData *_rhs;
+
+ explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
+
+ CompareResult visitObject(const CollectionData &lhs) {
+ if (lhs.equalsObject(*_rhs))
+ return COMPARE_RESULT_EQUAL;
+ else
+ return COMPARE_RESULT_DIFFER;
+ }
+};
+
+struct RawComparer : ComparerBase {
+ const char *_rhsData;
+ size_t _rhsSize;
+
+ explicit RawComparer(const char *rhsData, size_t rhsSize)
+ : _rhsData(rhsData), _rhsSize(rhsSize) {}
+
+ CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
+ size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
+ int n = memcmp(lhsData, _rhsData, size);
+ if (n < 0)
+ return COMPARE_RESULT_LESS;
+ else if (n > 0)
+ return COMPARE_RESULT_GREATER;
+ else
+ return COMPARE_RESULT_EQUAL;
+ }
+};
+
+template <typename T>
+struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
+ : ComparerBase {
+ T rhs;
+
+ explicit Comparer(T value) : rhs(value) {}
+
+ CompareResult visitArray(const CollectionData &lhs) {
+ ArrayComparer comparer(lhs);
+ return accept(comparer);
+ }
+
+ CompareResult visitObject(const CollectionData &lhs) {
+ ObjectComparer comparer(lhs);
+ return accept(comparer);
+ }
+
+ CompareResult visitFloat(Float lhs) {
+ Comparer<Float> comparer(lhs);
+ return accept(comparer);
+ }
+
+ CompareResult visitString(const char *lhs) {
+ Comparer<const char *> comparer(lhs);
+ return accept(comparer);
+ }
+
+ CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
+ RawComparer comparer(lhsData, lhsSize);
+ return accept(comparer);
+ }
+
+ CompareResult visitSignedInteger(Integer lhs) {
+ Comparer<Integer> comparer(lhs);
+ return accept(comparer);
+ }
+
+ CompareResult visitUnsignedInteger(UInt lhs) {
+ Comparer<UInt> comparer(lhs);
+ return accept(comparer);
+ }
+
+ CompareResult visitBoolean(bool lhs) {
+ Comparer<bool> comparer(lhs);
+ return accept(comparer);
+ }
+
+ CompareResult visitNull() {
+ NullComparer comparer;
+ return accept(comparer);
+ }
+
+ private:
+ template <typename TComparer>
+ CompareResult accept(TComparer &comparer) {
+ CompareResult reversedResult = rhs.accept(comparer);
+ switch (reversedResult) {
+ case COMPARE_RESULT_GREATER:
+ return COMPARE_RESULT_LESS;
+ case COMPARE_RESULT_LESS:
+ return COMPARE_RESULT_GREATER;
+ default:
+ return reversedResult;
+ }
+ }
+};
+
+template <typename T1, typename T2>
+CompareResult compare(const T1 &lhs, const T2 &rhs) {
+ Comparer<T2> comparer(rhs);
+ return lhs.accept(comparer);
+}
+
+inline int variantCompare(const VariantData *a, const VariantData *b) {
+ return compare(VariantConstRef(a), VariantConstRef(b));
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantContent.hpp b/include/lib/ArduinoJson/Variant/VariantContent.hpp
new file mode 100644
index 0000000..47bf09c
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantContent.hpp
@@ -0,0 +1,59 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h> // size_t
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+#include <ArduinoJson/Numbers/Float.hpp>
+#include <ArduinoJson/Numbers/Integer.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+//
+enum {
+ VALUE_MASK = 0x7F,
+
+ OWNED_VALUE_BIT = 0x01,
+ VALUE_IS_NULL = 0,
+ VALUE_IS_LINKED_RAW = 0x02,
+ VALUE_IS_OWNED_RAW = 0x03,
+ VALUE_IS_LINKED_STRING = 0x04,
+ VALUE_IS_OWNED_STRING = 0x05,
+
+ // CAUTION: no OWNED_VALUE_BIT below
+
+ VALUE_IS_BOOLEAN = 0x06,
+
+ NUMBER_BIT = 0x08,
+ VALUE_IS_UNSIGNED_INTEGER = 0x08,
+ VALUE_IS_SIGNED_INTEGER = 0x0A,
+ VALUE_IS_FLOAT = 0x0C,
+
+ COLLECTION_MASK = 0x60,
+ VALUE_IS_OBJECT = 0x20,
+ VALUE_IS_ARRAY = 0x40,
+
+ OWNED_KEY_BIT = 0x80
+};
+
+struct RawData {
+ const char *data;
+ size_t size;
+};
+
+union VariantContent {
+ Float asFloat;
+ bool asBoolean;
+ UInt asUnsignedInteger;
+ Integer asSignedInteger;
+ CollectionData asCollection;
+ const char *asString;
+ struct {
+ const char *data;
+ size_t size;
+ } asRaw;
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantData.hpp b/include/lib/ArduinoJson/Variant/VariantData.hpp
new file mode 100644
index 0000000..82ae745
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantData.hpp
@@ -0,0 +1,368 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Misc/SerializedValue.hpp>
+#include <ArduinoJson/Numbers/convertNumber.hpp>
+#include <ArduinoJson/Strings/RamStringAdapter.hpp>
+#include <ArduinoJson/Variant/VariantContent.hpp>
+
+// VariantData can't have a constructor (to be a POD), so we have no way to fix
+// this warning
+#if defined(__GNUC__)
+#if __GNUC__ >= 7
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+#endif
+
+namespace ARDUINOJSON_NAMESPACE {
+
+class VariantData {
+ VariantContent _content; // must be first to allow cast from array to variant
+ uint8_t _flags;
+
+ public:
+ // Must be a POD!
+ // - no constructor
+ // - no destructor
+ // - no virtual
+ // - no inheritance
+ void init() {
+ _flags = 0;
+ }
+
+ template <typename TVisitor>
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
+ switch (type()) {
+ case VALUE_IS_FLOAT:
+ return visitor.visitFloat(_content.asFloat);
+
+ case VALUE_IS_ARRAY:
+ return visitor.visitArray(_content.asCollection);
+
+ case VALUE_IS_OBJECT:
+ return visitor.visitObject(_content.asCollection);
+
+ case VALUE_IS_LINKED_STRING:
+ case VALUE_IS_OWNED_STRING:
+ return visitor.visitString(_content.asString);
+
+ case VALUE_IS_OWNED_RAW:
+ case VALUE_IS_LINKED_RAW:
+ return visitor.visitRawJson(_content.asRaw.data, _content.asRaw.size);
+
+ case VALUE_IS_SIGNED_INTEGER:
+ return visitor.visitSignedInteger(_content.asSignedInteger);
+
+ case VALUE_IS_UNSIGNED_INTEGER:
+ return visitor.visitUnsignedInteger(_content.asUnsignedInteger);
+
+ case VALUE_IS_BOOLEAN:
+ return visitor.visitBoolean(_content.asBoolean != 0);
+
+ default:
+ return visitor.visitNull();
+ }
+ }
+
+ template <typename T>
+ T asIntegral() const;
+
+ template <typename T>
+ T asFloat() const;
+
+ const char *asString() const;
+
+ bool asBoolean() const;
+
+ CollectionData *asArray() {
+ return isArray() ? &_content.asCollection : 0;
+ }
+
+ const CollectionData *asArray() const {
+ return const_cast<VariantData *>(this)->asArray();
+ }
+
+ CollectionData *asObject() {
+ return isObject() ? &_content.asCollection : 0;
+ }
+
+ const CollectionData *asObject() const {
+ return const_cast<VariantData *>(this)->asObject();
+ }
+
+ bool copyFrom(const VariantData &src, MemoryPool *pool) {
+ switch (src.type()) {
+ case VALUE_IS_ARRAY:
+ return toArray().copyFrom(src._content.asCollection, pool);
+ case VALUE_IS_OBJECT:
+ return toObject().copyFrom(src._content.asCollection, pool);
+ case VALUE_IS_OWNED_STRING:
+ return setString(RamStringAdapter(src._content.asString), pool);
+ case VALUE_IS_OWNED_RAW:
+ return setOwnedRaw(
+ serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
+ default:
+ setType(src.type());
+ _content = src._content;
+ return true;
+ }
+ }
+
+ bool isArray() const {
+ return (_flags & VALUE_IS_ARRAY) != 0;
+ }
+
+ bool isBoolean() const {
+ return type() == VALUE_IS_BOOLEAN;
+ }
+
+ bool isCollection() const {
+ return (_flags & COLLECTION_MASK) != 0;
+ }
+
+ template <typename T>
+ bool isInteger() const {
+ switch (type()) {
+ case VALUE_IS_UNSIGNED_INTEGER:
+ return canConvertNumber<T>(_content.asUnsignedInteger);
+
+ case VALUE_IS_SIGNED_INTEGER:
+ return canConvertNumber<T>(_content.asSignedInteger);
+
+ default:
+ return false;
+ }
+ }
+
+ bool isFloat() const {
+ return (_flags & NUMBER_BIT) != 0;
+ }
+
+ bool isString() const {
+ return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
+ }
+
+ bool isObject() const {
+ return (_flags & VALUE_IS_OBJECT) != 0;
+ }
+
+ bool isNull() const {
+ return type() == VALUE_IS_NULL;
+ }
+
+ bool isEnclosed() const {
+ return !isFloat();
+ }
+
+ void remove(size_t index) {
+ if (isArray())
+ _content.asCollection.removeElement(index);
+ }
+
+ template <typename TAdaptedString>
+ void remove(TAdaptedString key) {
+ if (isObject())
+ _content.asCollection.removeMember(key);
+ }
+
+ void setBoolean(bool value) {
+ setType(VALUE_IS_BOOLEAN);
+ _content.asBoolean = value;
+ }
+
+ void setFloat(Float value) {
+ setType(VALUE_IS_FLOAT);
+ _content.asFloat = value;
+ }
+
+ void setLinkedRaw(SerializedValue<const char *> value) {
+ if (value.data()) {
+ setType(VALUE_IS_LINKED_RAW);
+ _content.asRaw.data = value.data();
+ _content.asRaw.size = value.size();
+ } else {
+ setType(VALUE_IS_NULL);
+ }
+ }
+
+ template <typename T>
+ bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
+ const char *dup = pool->saveString(adaptString(value.data(), value.size()));
+ if (dup) {
+ setType(VALUE_IS_OWNED_RAW);
+ _content.asRaw.data = dup;
+ _content.asRaw.size = value.size();
+ return true;
+ } else {
+ setType(VALUE_IS_NULL);
+ return false;
+ }
+ }
+
+ template <typename T>
+ typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
+ setType(VALUE_IS_UNSIGNED_INTEGER);
+ _content.asUnsignedInteger = static_cast<UInt>(value);
+ }
+
+ template <typename T>
+ typename enable_if<is_signed<T>::value>::type setInteger(T value) {
+ setType(VALUE_IS_SIGNED_INTEGER);
+ _content.asSignedInteger = value;
+ }
+
+ void setNull() {
+ setType(VALUE_IS_NULL);
+ }
+
+ void setStringPointer(const char *s, storage_policies::store_by_copy) {
+ ARDUINOJSON_ASSERT(s != 0);
+ setType(VALUE_IS_OWNED_STRING);
+ _content.asString = s;
+ }
+
+ void setStringPointer(const char *s, storage_policies::store_by_address) {
+ ARDUINOJSON_ASSERT(s != 0);
+ setType(VALUE_IS_LINKED_STRING);
+ _content.asString = s;
+ }
+
+ template <typename TAdaptedString>
+ bool setString(TAdaptedString value, MemoryPool *pool) {
+ return storeString(value, pool, typename TAdaptedString::storage_policy());
+ }
+
+ CollectionData &toArray() {
+ setType(VALUE_IS_ARRAY);
+ _content.asCollection.clear();
+ return _content.asCollection;
+ }
+
+ CollectionData &toObject() {
+ setType(VALUE_IS_OBJECT);
+ _content.asCollection.clear();
+ return _content.asCollection;
+ }
+
+ size_t memoryUsage() const {
+ switch (type()) {
+ case VALUE_IS_OWNED_STRING:
+ return strlen(_content.asString) + 1;
+ case VALUE_IS_OWNED_RAW:
+ return _content.asRaw.size;
+ case VALUE_IS_OBJECT:
+ case VALUE_IS_ARRAY:
+ return _content.asCollection.memoryUsage();
+ default:
+ return 0;
+ }
+ }
+
+ size_t nesting() const {
+ return isCollection() ? _content.asCollection.nesting() : 0;
+ }
+
+ size_t size() const {
+ return isCollection() ? _content.asCollection.size() : 0;
+ }
+
+ VariantData *addElement(MemoryPool *pool) {
+ if (isNull())
+ toArray();
+ if (!isArray())
+ return 0;
+ return _content.asCollection.addElement(pool);
+ }
+
+ VariantData *getElement(size_t index) const {
+ return isArray() ? _content.asCollection.getElement(index) : 0;
+ }
+
+ VariantData *getOrAddElement(size_t index, MemoryPool *pool) {
+ if (isNull())
+ toArray();
+ if (!isArray())
+ return 0;
+ return _content.asCollection.getOrAddElement(index, pool);
+ }
+
+ template <typename TAdaptedString>
+ VariantData *getMember(TAdaptedString key) const {
+ return isObject() ? _content.asCollection.getMember(key) : 0;
+ }
+
+ template <typename TAdaptedString>
+ VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) {
+ if (isNull())
+ toObject();
+ if (!isObject())
+ return 0;
+ return _content.asCollection.getOrAddMember(key, pool);
+ }
+
+ void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
+ if (_flags & OWNED_VALUE_BIT)
+ _content.asString += stringDistance;
+ if (_flags & COLLECTION_MASK)
+ _content.asCollection.movePointers(stringDistance, variantDistance);
+ }
+
+ uint8_t type() const {
+ return _flags & VALUE_MASK;
+ }
+
+ private:
+ void setType(uint8_t t) {
+ _flags &= OWNED_KEY_BIT;
+ _flags |= t;
+ }
+
+ template <typename TAdaptedString>
+ inline bool storeString(TAdaptedString value, MemoryPool *pool,
+ storage_policies::decide_at_runtime) {
+ if (value.isStatic())
+ return storeString(value, pool, storage_policies::store_by_address());
+ else
+ return storeString(value, pool, storage_policies::store_by_copy());
+ }
+
+ template <typename TAdaptedString>
+ inline bool storeString(TAdaptedString value, MemoryPool *,
+ storage_policies::store_by_address) {
+ if (value.isNull())
+ setNull();
+ else
+ setStringPointer(value.data(), storage_policies::store_by_address());
+ return true;
+ }
+
+ template <typename TAdaptedString>
+ inline bool storeString(TAdaptedString value, MemoryPool *pool,
+ storage_policies::store_by_copy) {
+ if (value.isNull()) {
+ setNull();
+ return true;
+ }
+ const char *copy = pool->saveString(value);
+ if (!copy) {
+ setNull();
+ return false;
+ }
+ setStringPointer(copy, storage_policies::store_by_copy());
+ return true;
+ }
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
+
+#if defined(__GNUC__)
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+#endif
diff --git a/include/lib/ArduinoJson/Variant/VariantFunctions.hpp b/include/lib/ArduinoJson/Variant/VariantFunctions.hpp
new file mode 100644
index 0000000..3fc9cbb
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantFunctions.hpp
@@ -0,0 +1,104 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Variant/VariantData.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TVisitor>
+inline typename TVisitor::result_type variantAccept(const VariantData *var,
+ TVisitor &visitor) {
+ if (var != 0)
+ return var->accept(visitor);
+ else
+ return visitor.visitNull();
+}
+
+inline const CollectionData *variantAsArray(const VariantData *var) {
+ return var != 0 ? var->asArray() : 0;
+}
+
+inline const CollectionData *variantAsObject(const VariantData *var) {
+ return var != 0 ? var->asObject() : 0;
+}
+
+inline CollectionData *variantAsObject(VariantData *var) {
+ return var != 0 ? var->asObject() : 0;
+}
+
+inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
+ MemoryPool *pool) {
+ if (!dst)
+ return false;
+ if (!src) {
+ dst->setNull();
+ return true;
+ }
+ return dst->copyFrom(*src, pool);
+}
+
+inline int variantCompare(const VariantData *a, const VariantData *b);
+
+inline void variantSetNull(VariantData *var) {
+ if (!var)
+ return;
+ var->setNull();
+}
+
+template <typename TAdaptedString>
+inline bool variantSetString(VariantData *var, TAdaptedString value,
+ MemoryPool *pool) {
+ if (!var)
+ return false;
+ return var->setString(value, pool);
+}
+
+inline size_t variantSize(const VariantData *var) {
+ return var != 0 ? var->size() : 0;
+}
+
+inline CollectionData *variantToArray(VariantData *var) {
+ if (!var)
+ return 0;
+ return &var->toArray();
+}
+
+inline CollectionData *variantToObject(VariantData *var) {
+ if (!var)
+ return 0;
+ return &var->toObject();
+}
+
+inline NO_INLINE VariantData *variantAddElement(VariantData *var,
+ MemoryPool *pool) {
+ return var != 0 ? var->addElement(pool) : 0;
+}
+
+inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var,
+ size_t index,
+ MemoryPool *pool) {
+ return var != 0 ? var->getOrAddElement(index, pool) : 0;
+}
+
+template <typename TChar>
+NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
+ MemoryPool *pool) {
+ return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
+}
+
+template <typename TString>
+NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
+ const TString &key,
+ MemoryPool *pool) {
+ return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
+}
+
+inline bool variantIsNull(const VariantData *var) {
+ return var == 0 || var->isNull();
+}
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantImpl.hpp b/include/lib/ArduinoJson/Variant/VariantImpl.hpp
new file mode 100644
index 0000000..b91e584
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantImpl.hpp
@@ -0,0 +1,143 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayRef.hpp>
+#include <ArduinoJson/Configuration.hpp>
+#include <ArduinoJson/Numbers/convertNumber.hpp>
+#include <ArduinoJson/Numbers/parseNumber.hpp>
+#include <ArduinoJson/Object/ObjectRef.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+
+#include <string.h> // for strcmp
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T>
+inline T VariantData::asIntegral() const {
+ switch (type()) {
+ case VALUE_IS_BOOLEAN:
+ return _content.asBoolean;
+ case VALUE_IS_UNSIGNED_INTEGER:
+ return convertNumber<T>(_content.asUnsignedInteger);
+ case VALUE_IS_SIGNED_INTEGER:
+ return convertNumber<T>(_content.asSignedInteger);
+ case VALUE_IS_LINKED_STRING:
+ case VALUE_IS_OWNED_STRING:
+ return parseNumber<T>(_content.asString);
+ case VALUE_IS_FLOAT:
+ return convertNumber<T>(_content.asFloat);
+ default:
+ return 0;
+ }
+}
+
+inline bool VariantData::asBoolean() const {
+ switch (type()) {
+ case VALUE_IS_BOOLEAN:
+ return _content.asBoolean;
+ case VALUE_IS_SIGNED_INTEGER:
+ case VALUE_IS_UNSIGNED_INTEGER:
+ return _content.asUnsignedInteger != 0;
+ case VALUE_IS_FLOAT:
+ return _content.asFloat != 0;
+ case VALUE_IS_NULL:
+ return false;
+ default:
+ return true;
+ }
+}
+
+// T = float/double
+template <typename T>
+inline T VariantData::asFloat() const {
+ switch (type()) {
+ case VALUE_IS_BOOLEAN:
+ return static_cast<T>(_content.asBoolean);
+ case VALUE_IS_UNSIGNED_INTEGER:
+ return static_cast<T>(_content.asUnsignedInteger);
+ case VALUE_IS_SIGNED_INTEGER:
+ return static_cast<T>(_content.asSignedInteger);
+ case VALUE_IS_LINKED_STRING:
+ case VALUE_IS_OWNED_STRING:
+ return parseNumber<T>(_content.asString);
+ case VALUE_IS_FLOAT:
+ return static_cast<T>(_content.asFloat);
+ default:
+ return 0;
+ }
+}
+
+inline const char *VariantData::asString() const {
+ switch (type()) {
+ case VALUE_IS_LINKED_STRING:
+ case VALUE_IS_OWNED_STRING:
+ return _content.asString;
+ default:
+ return 0;
+ }
+}
+
+template <typename T>
+inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
+VariantRef::to() const {
+ return ArrayRef(_pool, variantToArray(_data));
+}
+
+template <typename T>
+typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type
+VariantRef::to() const {
+ return ObjectRef(_pool, variantToObject(_data));
+}
+
+template <typename T>
+typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type
+VariantRef::to() const {
+ variantSetNull(_data);
+ return *this;
+}
+
+inline VariantConstRef VariantConstRef::getElement(size_t index) const {
+ return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
+}
+
+inline VariantRef VariantRef::addElement() const {
+ return VariantRef(_pool, variantAddElement(_data, _pool));
+}
+
+inline VariantRef VariantRef::getElement(size_t index) const {
+ return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0);
+}
+
+inline VariantRef VariantRef::getOrAddElement(size_t index) const {
+ return VariantRef(_pool, variantGetOrAddElement(_data, index, _pool));
+}
+
+template <typename TChar>
+inline VariantRef VariantRef::getMember(TChar *key) const {
+ return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
+}
+
+template <typename TString>
+inline typename enable_if<IsString<TString>::value, VariantRef>::type
+VariantRef::getMember(const TString &key) const {
+ return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
+}
+
+template <typename TChar>
+inline VariantRef VariantRef::getOrAddMember(TChar *key) const {
+ return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
+}
+
+template <typename TString>
+inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
+ return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
+}
+
+inline VariantConstRef operator|(VariantConstRef preferedValue,
+ VariantConstRef defaultValue) {
+ return preferedValue ? preferedValue : defaultValue;
+}
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantOperators.hpp b/include/lib/ArduinoJson/Variant/VariantOperators.hpp
new file mode 100644
index 0000000..54174a4
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantOperators.hpp
@@ -0,0 +1,180 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
+#include <ArduinoJson/Polyfills/attributes.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Variant/VariantTag.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename T1, typename T2>
+CompareResult compare(const T1 &lhs, const T2 &rhs); // VariantCompare.cpp
+
+template <typename TVariant>
+struct VariantOperators {
+ // Returns the default value if the VariantRef is undefined or incompatible
+ //
+ // int operator|(JsonVariant, int)
+ // float operator|(JsonVariant, float)
+ // bool operator|(JsonVariant, bool)
+ template <typename T>
+ friend
+ typename enable_if<!IsVariant<T>::value && !is_array<T>::value, T>::type
+ operator|(const TVariant &variant, const T &defaultValue) {
+ if (variant.template is<T>())
+ return variant.template as<T>();
+ else
+ return defaultValue;
+ }
+ //
+ // const char* operator|(JsonVariant, const char*)
+ friend const char *operator|(const TVariant &variant,
+ const char *defaultValue) {
+ if (variant.template is<const char *>())
+ return variant.template as<const char *>();
+ else
+ return defaultValue;
+ }
+ //
+ // JsonVariant operator|(JsonVariant, JsonVariant)
+ template <typename T>
+ friend typename enable_if<IsVariant<T>::value, typename T::variant_type>::type
+ operator|(const TVariant &variant, T defaultValue) {
+ if (variant)
+ return variant;
+ else
+ return defaultValue;
+ }
+
+ // value == TVariant
+ template <typename T>
+ friend bool operator==(T *lhs, TVariant rhs) {
+ return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
+ }
+ template <typename T>
+ friend bool operator==(const T &lhs, TVariant rhs) {
+ return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
+ }
+
+ // TVariant == value
+ template <typename T>
+ friend bool operator==(TVariant lhs, T *rhs) {
+ return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
+ }
+ template <typename T>
+ friend typename enable_if<!IsVisitable<T>::value, bool>::type operator==(
+ TVariant lhs, const T &rhs) {
+ return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
+ }
+
+ // value != TVariant
+ template <typename T>
+ friend bool operator!=(T *lhs, TVariant rhs) {
+ return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
+ }
+ template <typename T>
+ friend bool operator!=(const T &lhs, TVariant rhs) {
+ return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
+ }
+
+ // TVariant != value
+ template <typename T>
+ friend bool operator!=(TVariant lhs, T *rhs) {
+ return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
+ }
+ template <typename T>
+ friend typename enable_if<!IsVisitable<T>::value, bool>::type operator!=(
+ TVariant lhs, const T &rhs) {
+ return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
+ }
+
+ // value < TVariant
+ template <typename T>
+ friend bool operator<(T *lhs, TVariant rhs) {
+ return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
+ }
+ template <typename T>
+ friend bool operator<(const T &lhs, TVariant rhs) {
+ return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
+ }
+
+ // TVariant < value
+ template <typename T>
+ friend bool operator<(TVariant lhs, T *rhs) {
+ return compare(lhs, rhs) == COMPARE_RESULT_LESS;
+ }
+ template <typename T>
+ friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<(
+ TVariant lhs, const T &rhs) {
+ return compare(lhs, rhs) == COMPARE_RESULT_LESS;
+ }
+
+ // value <= TVariant
+ template <typename T>
+ friend bool operator<=(T *lhs, TVariant rhs) {
+ return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+ }
+ template <typename T>
+ friend bool operator<=(const T &lhs, TVariant rhs) {
+ return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+ }
+
+ // TVariant <= value
+ template <typename T>
+ friend bool operator<=(TVariant lhs, T *rhs) {
+ return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+ }
+ template <typename T>
+ friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<=(
+ TVariant lhs, const T &rhs) {
+ return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+ }
+
+ // value > TVariant
+ template <typename T>
+ friend bool operator>(T *lhs, TVariant rhs) {
+ return compare(rhs, lhs) == COMPARE_RESULT_LESS;
+ }
+ template <typename T>
+ friend bool operator>(const T &lhs, TVariant rhs) {
+ return compare(rhs, lhs) == COMPARE_RESULT_LESS;
+ }
+
+ // TVariant > value
+ template <typename T>
+ friend bool operator>(TVariant lhs, T *rhs) {
+ return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
+ }
+ template <typename T>
+ friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>(
+ TVariant lhs, const T &rhs) {
+ return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
+ }
+
+ // value >= TVariant
+ template <typename T>
+ friend bool operator>=(T *lhs, TVariant rhs) {
+ return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+ }
+ template <typename T>
+ friend bool operator>=(const T &lhs, TVariant rhs) {
+ return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
+ }
+
+ // TVariant >= value
+ template <typename T>
+ friend bool operator>=(TVariant lhs, T *rhs) {
+ return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+ }
+ template <typename T>
+ friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>=(
+ TVariant lhs, const T &rhs) {
+ return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
+ }
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantRef.hpp b/include/lib/ArduinoJson/Variant/VariantRef.hpp
new file mode 100644
index 0000000..8d4c410
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantRef.hpp
@@ -0,0 +1,375 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h> // for uint8_t
+
+#include <ArduinoJson/Memory/MemoryPool.hpp>
+#include <ArduinoJson/Misc/Visitable.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/StringAdapters.hpp>
+#include <ArduinoJson/Variant/Converter.hpp>
+#include <ArduinoJson/Variant/VariantFunctions.hpp>
+#include <ArduinoJson/Variant/VariantOperators.hpp>
+#include <ArduinoJson/Variant/VariantRef.hpp>
+#include <ArduinoJson/Variant/VariantShortcuts.hpp>
+#include <ArduinoJson/Variant/VariantTag.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+// Forward declarations.
+class ArrayRef;
+class ObjectRef;
+
+// Contains the methods shared by VariantRef and VariantConstRef
+template <typename TData>
+class VariantRefBase : public VariantTag {
+ public:
+ FORCE_INLINE bool isNull() const {
+ return variantIsNull(_data);
+ }
+
+ FORCE_INLINE bool isUndefined() const {
+ return !_data;
+ }
+
+ FORCE_INLINE size_t memoryUsage() const {
+ return _data ? _data->memoryUsage() : 0;
+ }
+
+ FORCE_INLINE size_t nesting() const {
+ return _data ? _data->nesting() : 0;
+ }
+
+ size_t size() const {
+ return variantSize(_data);
+ }
+
+ protected:
+ VariantRefBase(TData *data) : _data(data) {}
+ TData *_data;
+
+ friend TData *getData(const VariantRefBase &variant) {
+ return variant._data;
+ }
+};
+
+// A variant that can be a any value serializable to a JSON value.
+//
+// It can be set to:
+// - a boolean
+// - a char, short, int or a long (signed or unsigned)
+// - a string (const char*)
+// - a reference to a ArrayRef or ObjectRef
+class VariantRef : public VariantRefBase<VariantData>,
+ public VariantOperators<VariantRef>,
+ public VariantShortcuts<VariantRef>,
+ public Visitable {
+ typedef VariantRefBase<VariantData> base_type;
+ friend class VariantConstRef;
+
+ public:
+ // Intenal use only
+ FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data)
+ : base_type(data), _pool(pool) {}
+
+ // Creates an uninitialized VariantRef
+ FORCE_INLINE VariantRef() : base_type(0), _pool(0) {}
+
+ FORCE_INLINE void clear() const {
+ return variantSetNull(_data);
+ }
+
+ template <typename T>
+ FORCE_INLINE bool set(const T &value) const {
+ return Converter<T>::toJson(value, *this);
+ }
+
+ FORCE_INLINE bool ARDUINOJSON_DEPRECATED(
+ "Support for char is deprecated, use int8_t or uint8_t instead")
+ set(char value) const {
+ return set<signed char>(value);
+ }
+
+ template <typename T>
+ FORCE_INLINE bool set(T *value) const {
+ return Converter<T *>::toJson(value, *this);
+ }
+
+ template <typename T>
+ FORCE_INLINE
+ typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
+ T>::type
+ as() const {
+ return Converter<T>::fromJson(*this);
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char *>::value, const char *>::type
+ ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
+ as() const {
+ return as<const char *>();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char>::value, char>::type
+ ARDUINOJSON_DEPRECATED(
+ "Support for char is deprecated, use int8_t or uint8_t instead")
+ as() const {
+ return as<signed char>();
+ }
+
+ template <typename T>
+ FORCE_INLINE
+ typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
+ bool>::type
+ is() const {
+ return Converter<T>::checkJson(*this);
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char *>::value, bool>::type
+ ARDUINOJSON_DEPRECATED("Replace is<char*>() with is<const char*>()")
+ is() const {
+ return is<const char *>();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char>::value, bool>::type
+ ARDUINOJSON_DEPRECATED(
+ "Support for char is deprecated, use int8_t or uint8_t instead")
+ is() const {
+ return is<signed char>();
+ }
+
+ template <typename T>
+ FORCE_INLINE operator T() const {
+ return as<T>();
+ }
+
+ template <typename TVisitor>
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
+ return variantAccept(_data, visitor);
+ }
+
+ // Change the type of the variant
+ //
+ // ArrayRef to<ArrayRef>()
+ template <typename T>
+ typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type to() const;
+ //
+ // ObjectRef to<ObjectRef>()
+ template <typename T>
+ typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type to() const;
+ //
+ // ObjectRef to<VariantRef>()
+ template <typename T>
+ typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
+ const;
+
+ VariantRef addElement() const;
+
+ FORCE_INLINE VariantRef getElement(size_t) const;
+
+ FORCE_INLINE VariantRef getOrAddElement(size_t) const;
+
+ // getMember(const char*) const
+ // getMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantRef getMember(TChar *) const;
+
+ // getMember(const std::string&) const
+ // getMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
+ getMember(const TString &) const;
+
+ // getOrAddMember(char*) const
+ // getOrAddMember(const char*) const
+ // getOrAddMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantRef getOrAddMember(TChar *) const;
+
+ // getOrAddMember(const std::string&) const
+ // getOrAddMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE VariantRef getOrAddMember(const TString &) const;
+
+ FORCE_INLINE void remove(size_t index) const {
+ if (_data)
+ _data->remove(index);
+ }
+ // remove(char*) const
+ // remove(const char*) const
+ // remove(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
+ TChar *key) const {
+ if (_data)
+ _data->remove(adaptString(key));
+ }
+ // remove(const std::string&) const
+ // remove(const String&) const
+ template <typename TString>
+ FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
+ const TString &key) const {
+ if (_data)
+ _data->remove(adaptString(key));
+ }
+
+ private:
+ MemoryPool *_pool;
+
+ friend MemoryPool *getPool(const VariantRef &variant) {
+ return variant._pool;
+ }
+};
+
+class VariantConstRef : public VariantRefBase<const VariantData>,
+ public VariantOperators<VariantConstRef>,
+ public VariantShortcuts<VariantConstRef>,
+ public Visitable {
+ typedef VariantRefBase<const VariantData> base_type;
+ friend class VariantRef;
+
+ public:
+ VariantConstRef() : base_type(0) {}
+ VariantConstRef(const VariantData *data) : base_type(data) {}
+ VariantConstRef(VariantRef var) : base_type(var._data) {}
+
+ template <typename TVisitor>
+ typename TVisitor::result_type accept(TVisitor &visitor) const {
+ return variantAccept(_data, visitor);
+ }
+
+ template <typename T>
+ FORCE_INLINE
+ typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
+ T>::type
+ as() const {
+ return Converter<T>::fromJson(*this);
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char *>::value, const char *>::type
+ ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
+ as() const {
+ return as<const char *>();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char>::value, char>::type
+ ARDUINOJSON_DEPRECATED(
+ "Support for char is deprecated, use int8_t or uint8_t instead")
+ as() const {
+ return as<signed char>();
+ }
+
+ template <typename T>
+ FORCE_INLINE
+ typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
+ bool>::type
+ is() const {
+ return Converter<T>::checkJson(*this);
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char *>::value, bool>::type
+ ARDUINOJSON_DEPRECATED("Replace is<char*>() with is<const char*>()")
+ is() const {
+ return is<const char *>();
+ }
+
+ template <typename T>
+ FORCE_INLINE typename enable_if<is_same<T, char>::value, bool>::type
+ ARDUINOJSON_DEPRECATED(
+ "Support for char is deprecated, use int8_t or uint8_t instead")
+ is() const {
+ return is<signed char>();
+ }
+
+ template <typename T>
+ FORCE_INLINE operator T() const {
+ return as<T>();
+ }
+
+ FORCE_INLINE VariantConstRef getElement(size_t) const;
+
+ FORCE_INLINE VariantConstRef operator[](size_t index) const {
+ return getElement(index);
+ }
+
+ // getMember(const std::string&) const
+ // getMember(const String&) const
+ template <typename TString>
+ FORCE_INLINE VariantConstRef getMember(const TString &key) const {
+ return VariantConstRef(
+ objectGetMember(variantAsObject(_data), adaptString(key)));
+ }
+
+ // getMember(char*) const
+ // getMember(const char*) const
+ // getMember(const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE VariantConstRef getMember(TChar *key) const {
+ const CollectionData *obj = variantAsObject(_data);
+ return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0);
+ }
+
+ // operator[](const std::string&) const
+ // operator[](const String&) const
+ template <typename TString>
+ FORCE_INLINE
+ typename enable_if<IsString<TString>::value, VariantConstRef>::type
+ operator[](const TString &key) const {
+ return getMember(key);
+ }
+
+ // operator[](char*) const
+ // operator[](const char*) const
+ // operator[](const __FlashStringHelper*) const
+ template <typename TChar>
+ FORCE_INLINE
+ typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
+ operator[](TChar *key) const {
+ return getMember(key);
+ }
+};
+
+template <>
+struct Converter<VariantRef> {
+ static bool toJson(VariantRef src, VariantRef dst) {
+ return variantCopyFrom(getData(dst), getData(src), getPool(dst));
+ }
+ static VariantRef fromJson(VariantRef src) {
+ return src;
+ }
+ static bool checkJson(VariantRef src) {
+ VariantData *data = getData(src);
+ return !!data;
+ }
+ static bool checkJson(VariantConstRef) {
+ return false;
+ }
+};
+
+template <>
+struct Converter<VariantConstRef> {
+ static bool toJson(VariantConstRef src, VariantRef dst) {
+ return variantCopyFrom(getData(dst), getData(src), getPool(dst));
+ }
+
+ static VariantConstRef fromJson(VariantConstRef src) {
+ return VariantConstRef(getData(src));
+ }
+
+ static bool checkJson(VariantConstRef src) {
+ const VariantData *data = getData(src);
+ return !!data;
+ }
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantShortcuts.hpp b/include/lib/ArduinoJson/Variant/VariantShortcuts.hpp
new file mode 100644
index 0000000..e62847f
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantShortcuts.hpp
@@ -0,0 +1,23 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Array/ArrayShortcuts.hpp>
+#include <ArduinoJson/Object/ObjectShortcuts.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TVariant>
+class VariantShortcuts : public ObjectShortcuts<TVariant>,
+ public ArrayShortcuts<TVariant> {
+ public:
+ using ArrayShortcuts<TVariant>::createNestedArray;
+ using ArrayShortcuts<TVariant>::createNestedObject;
+ using ArrayShortcuts<TVariant>::operator[];
+ using ObjectShortcuts<TVariant>::createNestedArray;
+ using ObjectShortcuts<TVariant>::createNestedObject;
+ using ObjectShortcuts<TVariant>::operator[];
+};
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantSlot.hpp b/include/lib/ArduinoJson/Variant/VariantSlot.hpp
new file mode 100644
index 0000000..a271c1e
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantSlot.hpp
@@ -0,0 +1,116 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/integer.hpp>
+#include <ArduinoJson/Polyfills/limits.hpp>
+#include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+#include <ArduinoJson/Variant/VariantContent.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+typedef int_t<ARDUINOJSON_SLOT_OFFSET_SIZE * 8>::type VariantSlotDiff;
+
+class VariantSlot {
+ // CAUTION: same layout as VariantData
+ // we cannot use composition because it adds padding
+ // (+20% on ESP8266 for example)
+ VariantContent _content;
+ uint8_t _flags;
+ VariantSlotDiff _next;
+ const char* _key;
+
+ public:
+ // Must be a POD!
+ // - no constructor
+ // - no destructor
+ // - no virtual
+ // - no inheritance
+
+ VariantData* data() {
+ return reinterpret_cast<VariantData*>(&_content);
+ }
+
+ const VariantData* data() const {
+ return reinterpret_cast<const VariantData*>(&_content);
+ }
+
+ VariantSlot* next() {
+ return _next ? this + _next : 0;
+ }
+
+ const VariantSlot* next() const {
+ return const_cast<VariantSlot*>(this)->next();
+ }
+
+ VariantSlot* next(size_t distance) {
+ VariantSlot* slot = this;
+ while (distance--) {
+ if (!slot->_next)
+ return 0;
+ slot += slot->_next;
+ }
+ return slot;
+ }
+
+ const VariantSlot* next(size_t distance) const {
+ return const_cast<VariantSlot*>(this)->next(distance);
+ }
+
+ void setNext(VariantSlot* slot) {
+ ARDUINOJSON_ASSERT(!slot || slot - this >=
+ numeric_limits<VariantSlotDiff>::lowest());
+ ARDUINOJSON_ASSERT(!slot || slot - this <=
+ numeric_limits<VariantSlotDiff>::highest());
+ _next = VariantSlotDiff(slot ? slot - this : 0);
+ }
+
+ void setNextNotNull(VariantSlot* slot) {
+ ARDUINOJSON_ASSERT(slot != 0);
+ ARDUINOJSON_ASSERT(slot - this >=
+ numeric_limits<VariantSlotDiff>::lowest());
+ ARDUINOJSON_ASSERT(slot - this <=
+ numeric_limits<VariantSlotDiff>::highest());
+ _next = VariantSlotDiff(slot - this);
+ }
+
+ void setKey(const char* k, storage_policies::store_by_copy) {
+ ARDUINOJSON_ASSERT(k != NULL);
+ _flags |= OWNED_KEY_BIT;
+ _key = k;
+ }
+
+ void setKey(const char* k, storage_policies::store_by_address) {
+ ARDUINOJSON_ASSERT(k != NULL);
+ _flags &= VALUE_MASK;
+ _key = k;
+ }
+
+ const char* key() const {
+ return _key;
+ }
+
+ bool ownsKey() const {
+ return (_flags & OWNED_KEY_BIT) != 0;
+ }
+
+ void clear() {
+ _next = 0;
+ _flags = 0;
+ _key = 0;
+ }
+
+ void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
+ if (_flags & OWNED_KEY_BIT)
+ _key += stringDistance;
+ if (_flags & OWNED_VALUE_BIT)
+ _content.asString += stringDistance;
+ if (_flags & COLLECTION_MASK)
+ _content.asCollection.movePointers(stringDistance, variantDistance);
+ }
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantTag.hpp b/include/lib/ArduinoJson/Variant/VariantTag.hpp
new file mode 100644
index 0000000..7164164
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantTag.hpp
@@ -0,0 +1,16 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+struct VariantTag {};
+
+template <typename T>
+struct IsVariant : is_base_of<VariantTag, T> {};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/VariantTo.hpp b/include/lib/ArduinoJson/Variant/VariantTo.hpp
new file mode 100644
index 0000000..352ecba
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/VariantTo.hpp
@@ -0,0 +1,32 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Namespace.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+class ArrayRef;
+class ObjectRef;
+class VariantRef;
+
+// A metafunction that returns the type of the value returned by
+// VariantRef::to<T>()
+template <typename T>
+struct VariantTo {};
+
+template <>
+struct VariantTo<ArrayRef> {
+ typedef ArrayRef type;
+};
+template <>
+struct VariantTo<ObjectRef> {
+ typedef ObjectRef type;
+};
+template <>
+struct VariantTo<VariantRef> {
+ typedef VariantRef type;
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/Variant/Visitor.hpp b/include/lib/ArduinoJson/Variant/Visitor.hpp
new file mode 100644
index 0000000..33237dd
--- /dev/null
+++ b/include/lib/ArduinoJson/Variant/Visitor.hpp
@@ -0,0 +1,54 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Collection/CollectionData.hpp>
+#include <ArduinoJson/Numbers/Float.hpp>
+#include <ArduinoJson/Numbers/Integer.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TResult>
+struct Visitor {
+ typedef TResult result_type;
+
+ TResult visitArray(const CollectionData &) {
+ return TResult();
+ }
+
+ TResult visitBoolean(bool) {
+ return TResult();
+ }
+
+ TResult visitFloat(Float) {
+ return TResult();
+ }
+
+ TResult visitSignedInteger(Integer) {
+ return TResult();
+ }
+
+ TResult visitNull() {
+ return TResult();
+ }
+
+ TResult visitObject(const CollectionData &) {
+ return TResult();
+ }
+
+ TResult visitUnsignedInteger(UInt) {
+ return TResult();
+ }
+
+ TResult visitRawJson(const char *, size_t) {
+ return TResult();
+ }
+
+ TResult visitString(const char *) {
+ return TResult();
+ }
+};
+
+} // namespace ARDUINOJSON_NAMESPACE
diff --git a/include/lib/ArduinoJson/compatibility.hpp b/include/lib/ArduinoJson/compatibility.hpp
new file mode 100644
index 0000000..cca477e
--- /dev/null
+++ b/include/lib/ArduinoJson/compatibility.hpp
@@ -0,0 +1,23 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+//
+// clang-format off
+
+#ifdef __GNUC__
+
+#define ARDUINOJSON_PRAGMA(x) _Pragma(#x)
+
+#define ARDUINOJSON_COMPILE_ERROR(msg) ARDUINOJSON_PRAGMA(GCC error msg)
+
+#define ARDUINOJSON_STRINGIFY(S) #S
+
+#define ARDUINOJSON_DEPRECATION_ERROR(X, Y) \
+ ARDUINOJSON_COMPILE_ERROR(ARDUINOJSON_STRINGIFY(X is a Y from ArduinoJson 5. Please see https:/\/arduinojson.org/upgrade to learn how to upgrade your program to ArduinoJson version 6))
+
+#define StaticJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(StaticJsonBuffer, class)
+#define DynamicJsonBuffer ARDUINOJSON_DEPRECATION_ERROR(DynamicJsonBuffer, class)
+#define JsonBuffer ARDUINOJSON_DEPRECATION_ERROR(JsonBuffer, class)
+#define RawJson ARDUINOJSON_DEPRECATION_ERROR(RawJson, function)
+
+#endif
diff --git a/include/lib/ArduinoJson/version.hpp b/include/lib/ArduinoJson/version.hpp
new file mode 100644
index 0000000..d8aaf77
--- /dev/null
+++ b/include/lib/ArduinoJson/version.hpp
@@ -0,0 +1,10 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#define ARDUINOJSON_VERSION "6.18.0"
+#define ARDUINOJSON_VERSION_MAJOR 6
+#define ARDUINOJSON_VERSION_MINOR 18
+#define ARDUINOJSON_VERSION_REVISION 0