diff --git a/lib/ArduinoJson/ArduinoJson.h b/lib/ArduinoJson/ArduinoJson.h new file mode 100644 index 0000000..ecf94fb --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson.h @@ -0,0 +1,17 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#ifdef __cplusplus + +#include "ArduinoJson.hpp" + +using namespace ArduinoJson; + +#else + +#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp + +#endif diff --git a/lib/ArduinoJson/ArduinoJson.hpp b/lib/ArduinoJson/ArduinoJson.hpp new file mode 100644 index 0000000..fdaf786 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson.hpp @@ -0,0 +1,65 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_VER < 1910) +# error ArduinoJson requires C++11 or newer. Configure your compiler for C++11 or downgrade ArduinoJson to 6.20. +#endif + +#include "ArduinoJson/Configuration.hpp" + +// Include Arduino.h before stdlib.h to avoid conflict with atexit() +// https://github.com/bblanchon/ArduinoJson/pull/1693#issuecomment-1001060240 +#if ARDUINOJSON_ENABLE_ARDUINO_STRING || ARDUINOJSON_ENABLE_ARDUINO_STREAM || \ + ARDUINOJSON_ENABLE_ARDUINO_PRINT || \ + (ARDUINOJSON_ENABLE_PROGMEM && defined(ARDUINO)) +# include +#endif + +#if !ARDUINOJSON_DEBUG +# ifdef __clang__ +# pragma clang system_header +# elif defined __GNUC__ +# pragma GCC system_header +# endif +#endif + +// Remove true and false macros defined by some cores, such as Arduino Due's +// See issues #2181 and arduino/ArduinoCore-sam#50 +#ifdef true +# undef true +#endif +#ifdef false +# undef false +#endif + +#include "ArduinoJson/Array/JsonArray.hpp" +#include "ArduinoJson/Object/JsonObject.hpp" +#include "ArduinoJson/Variant/JsonVariantConst.hpp" + +#include "ArduinoJson/Document/JsonDocument.hpp" + +#include "ArduinoJson/Array/ArrayImpl.hpp" +#include "ArduinoJson/Array/ElementProxy.hpp" +#include "ArduinoJson/Array/Utilities.hpp" +#include "ArduinoJson/Collection/CollectionImpl.hpp" +#include "ArduinoJson/Memory/ResourceManagerImpl.hpp" +#include "ArduinoJson/Object/MemberProxy.hpp" +#include "ArduinoJson/Object/ObjectImpl.hpp" +#include "ArduinoJson/Variant/ConverterImpl.hpp" +#include "ArduinoJson/Variant/JsonVariantCopier.hpp" +#include "ArduinoJson/Variant/VariantCompare.hpp" +#include "ArduinoJson/Variant/VariantImpl.hpp" +#include "ArduinoJson/Variant/VariantRefBaseImpl.hpp" + +#include "ArduinoJson/Json/JsonDeserializer.hpp" +#include "ArduinoJson/Json/JsonSerializer.hpp" +#include "ArduinoJson/Json/PrettyJsonSerializer.hpp" +#include "ArduinoJson/MsgPack/MsgPackBinary.hpp" +#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp" +#include "ArduinoJson/MsgPack/MsgPackExtension.hpp" +#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp" + +#include "ArduinoJson/compatibility.hpp" diff --git a/lib/ArduinoJson/ArduinoJson/Array/ArrayData.hpp b/lib/ArduinoJson/ArduinoJson/Array/ArrayData.hpp new file mode 100644 index 0000000..c386950 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Array/ArrayData.hpp @@ -0,0 +1,66 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +class ArrayData : public CollectionData { + public: + VariantData* addElement(ResourceManager* resources); + + static VariantData* addElement(ArrayData* array, ResourceManager* resources) { + if (!array) + return nullptr; + return array->addElement(resources); + } + + template + bool addValue(const T& value, ResourceManager* resources); + + template + static bool addValue(ArrayData* array, const T& value, + ResourceManager* resources) { + if (!array) + return false; + return array->addValue(value, resources); + } + + VariantData* getOrAddElement(size_t index, ResourceManager* resources); + + VariantData* getElement(size_t index, const ResourceManager* resources) const; + + static VariantData* getElement(const ArrayData* array, size_t index, + const ResourceManager* resources) { + if (!array) + return nullptr; + return array->getElement(index, resources); + } + + void removeElement(size_t index, ResourceManager* resources); + + static void removeElement(ArrayData* array, size_t index, + ResourceManager* resources) { + if (!array) + return; + array->removeElement(index, resources); + } + + void remove(iterator it, ResourceManager* resources) { + CollectionData::removeOne(it, resources); + } + + static void remove(ArrayData* array, iterator it, + ResourceManager* resources) { + if (array) + return array->remove(it, resources); + } + + private: + iterator at(size_t index, const ResourceManager* resources) const; +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Array/ArrayImpl.hpp b/lib/ArduinoJson/ArduinoJson/Array/ArrayImpl.hpp new file mode 100644 index 0000000..044064f --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Array/ArrayImpl.hpp @@ -0,0 +1,79 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +inline ArrayData::iterator ArrayData::at( + size_t index, const ResourceManager* resources) const { + auto it = createIterator(resources); + while (!it.done() && index) { + it.next(resources); + --index; + } + return it; +} + +inline VariantData* ArrayData::addElement(ResourceManager* resources) { + auto slot = resources->allocVariant(); + if (!slot) + return nullptr; + CollectionData::appendOne(slot, resources); + return slot.ptr(); +} + +inline VariantData* ArrayData::getOrAddElement(size_t index, + ResourceManager* resources) { + auto it = createIterator(resources); + while (!it.done() && index > 0) { + it.next(resources); + index--; + } + if (it.done()) + index++; + VariantData* element = it.data(); + while (index > 0) { + element = addElement(resources); + if (!element) + return nullptr; + index--; + } + return element; +} + +inline VariantData* ArrayData::getElement( + size_t index, const ResourceManager* resources) const { + return at(index, resources).data(); +} + +inline void ArrayData::removeElement(size_t index, ResourceManager* resources) { + remove(at(index, resources), resources); +} + +template +inline bool ArrayData::addValue(const T& value, ResourceManager* resources) { + ARDUINOJSON_ASSERT(resources != nullptr); + auto slot = resources->allocVariant(); + if (!slot) + return false; + JsonVariant variant(slot.ptr(), resources); + if (!variant.set(value)) { + resources->freeVariant(slot); + return false; + } + CollectionData::appendOne(slot, resources); + return true; +} + +// Returns the size (in bytes) of an array with n elements. +constexpr size_t sizeofArray(size_t n) { + return n * ResourceManager::slotSize; +} + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Array/ElementProxy.hpp b/lib/ArduinoJson/ArduinoJson/Array/ElementProxy.hpp new file mode 100644 index 0000000..d0d8b41 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Array/ElementProxy.hpp @@ -0,0 +1,75 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +// A proxy class to get or set an element of an array. +// https://arduinojson.org/v7/api/jsonarray/subscript/ +template +class ElementProxy : public VariantRefBase>, + public VariantOperators> { + friend class VariantAttorney; + + friend class VariantRefBase>; + + template + friend class MemberProxy; + + template + friend class ElementProxy; + + public: + ElementProxy(TUpstream upstream, size_t index) + : upstream_(upstream), index_(index) {} + + ElementProxy& operator=(const ElementProxy& src) { + this->set(src); + return *this; + } + + template + ElementProxy& operator=(const T& src) { + this->set(src); + return *this; + } + + template + ElementProxy& operator=(T* src) { + this->set(src); + return *this; + } + + private: + // clang-format off + ElementProxy(const ElementProxy& src) // Error here? See https://arduinojson.org/v7/proxy-non-copyable/ + : upstream_(src.upstream_), index_(src.index_) {} + // clang-format on + + ResourceManager* getResourceManager() const { + return VariantAttorney::getResourceManager(upstream_); + } + + FORCE_INLINE VariantData* getData() const { + return VariantData::getElement( + VariantAttorney::getData(upstream_), index_, + VariantAttorney::getResourceManager(upstream_)); + } + + VariantData* getOrCreateData() const { + auto data = VariantAttorney::getOrCreateData(upstream_); + if (!data) + return nullptr; + return data->getOrAddElement( + index_, VariantAttorney::getResourceManager(upstream_)); + } + + TUpstream upstream_; + size_t index_; +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Array/JsonArray.hpp b/lib/ArduinoJson/ArduinoJson/Array/JsonArray.hpp new file mode 100644 index 0000000..0441bee --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Array/JsonArray.hpp @@ -0,0 +1,219 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE + +class JsonObject; + +// A reference to an array in a JsonDocument +// https://arduinojson.org/v7/api/jsonarray/ +class JsonArray : public detail::VariantOperators { + friend class detail::VariantAttorney; + + public: + using iterator = JsonArrayIterator; + + // Constructs an unbound reference. + JsonArray() : data_(0), resources_(0) {} + + // INTERNAL USE ONLY + JsonArray(detail::ArrayData* data, detail::ResourceManager* resources) + : data_(data), resources_(resources) {} + + // Returns a JsonVariant pointing to the array. + // https://arduinojson.org/v7/api/jsonvariant/ + operator JsonVariant() { + void* data = data_; // prevent warning cast-align + return JsonVariant(reinterpret_cast(data), + resources_); + } + + // Returns a read-only reference to the array. + // https://arduinojson.org/v7/api/jsonarrayconst/ + operator JsonArrayConst() const { + return JsonArrayConst(data_, resources_); + } + + // Appends a new (empty) element to the array. + // Returns a reference to the new element. + // https://arduinojson.org/v7/api/jsonarray/add/ + template ::value, int> = 0> + T add() const { + return add().to(); + } + + // Appends a new (null) element to the array. + // Returns a reference to the new element. + // https://arduinojson.org/v7/api/jsonarray/add/ + template ::value, int> = 0> + JsonVariant add() const { + return JsonVariant(detail::ArrayData::addElement(data_, resources_), + resources_); + } + + // Appends a value to the array. + // https://arduinojson.org/v7/api/jsonarray/add/ + template + bool add(const T& value) const { + return detail::ArrayData::addValue(data_, value, resources_); + } + + // Appends a value to the array. + // https://arduinojson.org/v7/api/jsonarray/add/ + template ::value, int> = 0> + bool add(T* value) const { + return detail::ArrayData::addValue(data_, value, resources_); + } + + // Returns an iterator to the first element of the array. + // https://arduinojson.org/v7/api/jsonarray/begin/ + iterator begin() const { + if (!data_) + return iterator(); + return iterator(data_->createIterator(resources_), resources_); + } + + // Returns an iterator following the last element of the array. + // https://arduinojson.org/v7/api/jsonarray/end/ + iterator end() const { + return iterator(); + } + + // Copies an array. + // https://arduinojson.org/v7/api/jsonarray/set/ + bool set(JsonArrayConst src) const { + if (!data_) + return false; + + clear(); + for (auto element : src) { + if (!add(element)) + return false; + } + + return true; + } + + // Removes the element at the specified iterator. + // https://arduinojson.org/v7/api/jsonarray/remove/ + void remove(iterator it) const { + detail::ArrayData::remove(data_, it.iterator_, resources_); + } + + // Removes the element at the specified index. + // https://arduinojson.org/v7/api/jsonarray/remove/ + void remove(size_t index) const { + detail::ArrayData::removeElement(data_, index, resources_); + } + + // Removes the element at the specified index. + // https://arduinojson.org/v7/api/jsonarray/remove/ + template ::value, int> = 0> + void remove(const TVariant& variant) const { + if (variant.template is()) + remove(variant.template as()); + } + + // Removes all the elements of the array. + // https://arduinojson.org/v7/api/jsonarray/clear/ + void clear() const { + detail::ArrayData::clear(data_, resources_); + } + + // Gets or sets the element at the specified index. + // https://arduinojson.org/v7/api/jsonarray/subscript/ + template ::value, int> = 0> + detail::ElementProxy operator[](T index) const { + return {*this, size_t(index)}; + } + + // Gets or sets the element at the specified index. + // https://arduinojson.org/v7/api/jsonarray/subscript/ + template ::value, int> = 0> + detail::ElementProxy operator[](const TVariant& variant) const { + if (variant.template is()) + return {*this, variant.template as()}; + else + return {*this, size_t(-1)}; + } + + operator JsonVariantConst() const { + return JsonVariantConst(collectionToVariant(data_), resources_); + } + + // Returns true if the reference is unbound. + // https://arduinojson.org/v7/api/jsonarray/isnull/ + bool isNull() const { + return data_ == 0; + } + + // Returns true if the reference is bound. + // https://arduinojson.org/v7/api/jsonarray/isnull/ + operator bool() const { + return data_ != 0; + } + + // Returns the depth (nesting level) of the array. + // https://arduinojson.org/v7/api/jsonarray/nesting/ + size_t nesting() const { + return detail::VariantData::nesting(collectionToVariant(data_), resources_); + } + + // Returns the number of elements in the array. + // https://arduinojson.org/v7/api/jsonarray/size/ + size_t size() const { + return data_ ? data_->size(resources_) : 0; + } + + // DEPRECATED: use add() instead + ARDUINOJSON_DEPRECATED("use add() instead") + JsonVariant add() const { + return add(); + } + + // DEPRECATED: use add() instead + ARDUINOJSON_DEPRECATED("use add() instead") + JsonArray createNestedArray() const { + return add(); + } + + // DEPRECATED: use add() instead + ARDUINOJSON_DEPRECATED("use add() instead") + JsonObject createNestedObject() const; + + // DEPRECATED: always returns zero + ARDUINOJSON_DEPRECATED("always returns zero") + size_t memoryUsage() const { + return 0; + } + + private: + detail::ResourceManager* getResourceManager() const { + return resources_; + } + + detail::VariantData* getData() const { + return collectionToVariant(data_); + } + + detail::VariantData* getOrCreateData() const { + return collectionToVariant(data_); + } + + detail::ArrayData* data_; + detail::ResourceManager* resources_; +}; + +ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Array/JsonArrayConst.hpp b/lib/ArduinoJson/ArduinoJson/Array/JsonArrayConst.hpp new file mode 100644 index 0000000..88762d3 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Array/JsonArrayConst.hpp @@ -0,0 +1,133 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include +#include + +ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE + +class JsonObject; + +// A read-only reference to an array in a JsonDocument +// https://arduinojson.org/v7/api/jsonarrayconst/ +class JsonArrayConst : public detail::VariantOperators { + friend class JsonArray; + friend class detail::VariantAttorney; + + public: + using iterator = JsonArrayConstIterator; + + // Returns an iterator to the first element of the array. + // https://arduinojson.org/v7/api/jsonarrayconst/begin/ + iterator begin() const { + if (!data_) + return iterator(); + return iterator(data_->createIterator(resources_), resources_); + } + + // Returns an iterator to the element following the last element of the array. + // https://arduinojson.org/v7/api/jsonarrayconst/end/ + iterator end() const { + return iterator(); + } + + // Creates an unbound reference. + JsonArrayConst() : data_(0), resources_(0) {} + + // INTERNAL USE ONLY + JsonArrayConst(const detail::ArrayData* data, + const detail::ResourceManager* resources) + : data_(data), resources_(resources) {} + + // Returns the element at the specified index. + // https://arduinojson.org/v7/api/jsonarrayconst/subscript/ + template ::value, int> = 0> + JsonVariantConst operator[](T index) const { + return JsonVariantConst( + detail::ArrayData::getElement(data_, size_t(index), resources_), + resources_); + } + + // Returns the element at the specified index. + // https://arduinojson.org/v7/api/jsonarrayconst/subscript/ + template ::value, int> = 0> + JsonVariantConst operator[](const TVariant& variant) const { + if (variant.template is()) + return operator[](variant.template as()); + else + return JsonVariantConst(); + } + + operator JsonVariantConst() const { + return JsonVariantConst(getData(), resources_); + } + + // Returns true if the reference is unbound. + // https://arduinojson.org/v7/api/jsonarrayconst/isnull/ + bool isNull() const { + return data_ == 0; + } + + // Returns true if the reference is bound. + // https://arduinojson.org/v7/api/jsonarrayconst/isnull/ + operator bool() const { + return data_ != 0; + } + + // Returns the depth (nesting level) of the array. + // https://arduinojson.org/v7/api/jsonarrayconst/nesting/ + size_t nesting() const { + return detail::VariantData::nesting(getData(), resources_); + } + + // Returns the number of elements in the array. + // https://arduinojson.org/v7/api/jsonarrayconst/size/ + size_t size() const { + return data_ ? data_->size(resources_) : 0; + } + + // DEPRECATED: always returns zero + ARDUINOJSON_DEPRECATED("always returns zero") + size_t memoryUsage() const { + return 0; + } + + private: + const detail::VariantData* getData() const { + return collectionToVariant(data_); + } + + const detail::ArrayData* data_; + const detail::ResourceManager* resources_; +}; + +// Compares the content of two arrays. +// Returns true if the two arrays are equal. +inline bool operator==(JsonArrayConst lhs, JsonArrayConst rhs) { + if (!lhs && !rhs) + return true; + if (!lhs || !rhs) + return false; + + auto a = lhs.begin(); + auto b = rhs.begin(); + + for (;;) { + if (a == b) // same pointer or both null + return true; + if (a == lhs.end() || b == rhs.end()) + return false; + if (*a != *b) + return false; + ++a; + ++b; + } +} + +ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Array/JsonArrayIterator.hpp b/lib/ArduinoJson/ArduinoJson/Array/JsonArrayIterator.hpp new file mode 100644 index 0000000..48daf8b --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Array/JsonArrayIterator.hpp @@ -0,0 +1,96 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE + +template +class Ptr { + public: + Ptr(T value) : value_(value) {} + + T* operator->() { + return &value_; + } + + T& operator*() { + return value_; + } + + private: + T value_; +}; + +class JsonArrayIterator { + friend class JsonArray; + + public: + JsonArrayIterator() {} + explicit JsonArrayIterator(detail::ArrayData::iterator iterator, + detail::ResourceManager* resources) + : iterator_(iterator), resources_(resources) {} + + JsonVariant operator*() { + return JsonVariant(iterator_.data(), resources_); + } + Ptr operator->() { + return operator*(); + } + + bool operator==(const JsonArrayIterator& other) const { + return iterator_ == other.iterator_; + } + + bool operator!=(const JsonArrayIterator& other) const { + return iterator_ != other.iterator_; + } + + JsonArrayIterator& operator++() { + iterator_.next(resources_); + return *this; + } + + private: + detail::ArrayData::iterator iterator_; + detail::ResourceManager* resources_; +}; + +class JsonArrayConstIterator { + friend class JsonArray; + + public: + JsonArrayConstIterator() {} + explicit JsonArrayConstIterator(detail::ArrayData::iterator iterator, + const detail::ResourceManager* resources) + : iterator_(iterator), resources_(resources) {} + + JsonVariantConst operator*() const { + return JsonVariantConst(iterator_.data(), resources_); + } + Ptr operator->() { + return operator*(); + } + + bool operator==(const JsonArrayConstIterator& other) const { + return iterator_ == other.iterator_; + } + + bool operator!=(const JsonArrayConstIterator& other) const { + return iterator_ != other.iterator_; + } + + JsonArrayConstIterator& operator++() { + iterator_.next(resources_); + return *this; + } + + private: + detail::ArrayData::iterator iterator_; + const detail::ResourceManager* resources_; +}; + +ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Array/Utilities.hpp b/lib/ArduinoJson/ArduinoJson/Array/Utilities.hpp new file mode 100644 index 0000000..9f404de --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Array/Utilities.hpp @@ -0,0 +1,112 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE + +// Copies a value to a JsonVariant. +// This is a degenerated form of copyArray() to stop the recursion. +template ::value, int> = 0> +inline bool copyArray(const T& src, JsonVariant dst) { + return dst.set(src); +} + +// Copies values from an array to a JsonArray or a JsonVariant. +// https://arduinojson.org/v7/api/misc/copyarray/ +template ::value, int> = 0> +inline bool copyArray(T (&src)[N], const TDestination& dst) { + return copyArray(src, N, dst); +} + +// Copies values from an array to a JsonArray or a JsonVariant. +// https://arduinojson.org/v7/api/misc/copyarray/ +template ::value, int> = 0> +inline bool copyArray(const T* src, size_t len, const TDestination& dst) { + bool ok = true; + for (size_t i = 0; i < len; i++) { + ok &= copyArray(src[i], dst.template add()); + } + return ok; +} + +// Copies a string to a JsonVariant. +// This is a degenerated form of copyArray() to handle strings. +template +inline bool copyArray(const char* src, size_t, const TDestination& dst) { + return dst.set(src); +} + +// Copies values from an array to a JsonDocument. +// https://arduinojson.org/v7/api/misc/copyarray/ +template +inline bool copyArray(const T& src, JsonDocument& dst) { + return copyArray(src, dst.to()); +} + +// Copies an array to a JsonDocument. +// https://arduinojson.org/v7/api/misc/copyarray/ +template +inline bool copyArray(const T* src, size_t len, JsonDocument& dst) { + return copyArray(src, len, dst.to()); +} + +// Copies a value from a JsonVariant. +// This is a degenerated form of copyArray() to stop the recursion. +template ::value, int> = 0> +inline size_t copyArray(JsonVariantConst src, T& dst) { + dst = src.as(); + return 1; +} + +// Copies values from a JsonArray or JsonVariant to an array. +// https://arduinojson.org/v7/api/misc/copyarray/ +template +inline size_t copyArray(JsonArrayConst src, T (&dst)[N]) { + return copyArray(src, dst, N); +} + +// Copies values from a JsonArray or JsonVariant to an array. +// https://arduinojson.org/v7/api/misc/copyarray/ +template +inline size_t copyArray(JsonArrayConst src, T* dst, size_t len) { + size_t i = 0; + for (JsonArrayConst::iterator it = src.begin(); it != src.end() && i < len; + ++it) + copyArray(*it, dst[i++]); + return i; +} + +// Copies a string from a JsonVariant. +// This is a degenerated form of copyArray() to handle strings. +template +inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) { + JsonString s = src; + size_t len = N - 1; + if (len > s.size()) + len = s.size(); + memcpy(dst, s.c_str(), len); + dst[len] = 0; + return 1; +} + +// Copies values from a JsonDocument to an array. +// https://arduinojson.org/v7/api/misc/copyarray/ +template < + typename TSource, typename T, + detail::enable_if_t::value && + detail::is_base_of::value, + int> = 0> +inline size_t copyArray(const TSource& src, T& dst) { + return copyArray(src.template as(), dst); +} + +ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Collection/CollectionData.hpp b/lib/ArduinoJson/ArduinoJson/Collection/CollectionData.hpp new file mode 100644 index 0000000..8821599 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Collection/CollectionData.hpp @@ -0,0 +1,122 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include +#include + +#include // size_t + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +class VariantData; +class ResourceManager; + +class CollectionIterator { + friend class CollectionData; + + public: + CollectionIterator() : slot_(nullptr), currentId_(NULL_SLOT) {} + + void next(const ResourceManager* resources); + + bool done() const { + return slot_ == nullptr; + } + + bool operator==(const CollectionIterator& other) const { + return slot_ == other.slot_; + } + + bool operator!=(const CollectionIterator& other) const { + return slot_ != other.slot_; + } + + VariantData* operator->() { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return data(); + } + + VariantData& operator*() { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return *data(); + } + + const VariantData& operator*() const { + ARDUINOJSON_ASSERT(slot_ != nullptr); + return *data(); + } + + VariantData* data() { + return reinterpret_cast(slot_); + } + + const VariantData* data() const { + return reinterpret_cast(slot_); + } + + private: + CollectionIterator(VariantData* slot, SlotId slotId); + + VariantData* slot_; + SlotId currentId_, nextId_; +}; + +class CollectionData { + SlotId head_ = NULL_SLOT; + SlotId tail_ = NULL_SLOT; + + public: + // Placement new + static void* operator new(size_t, void* p) noexcept { + return p; + } + + static void operator delete(void*, void*) noexcept {} + + using iterator = CollectionIterator; + + iterator createIterator(const ResourceManager* resources) const; + + size_t size(const ResourceManager*) const; + size_t nesting(const ResourceManager*) const; + + void clear(ResourceManager* resources); + + static void clear(CollectionData* collection, ResourceManager* resources) { + if (!collection) + return; + collection->clear(resources); + } + + SlotId head() const { + return head_; + } + + protected: + void appendOne(Slot slot, const ResourceManager* resources); + void appendPair(Slot key, Slot value, + const ResourceManager* resources); + + void removeOne(iterator it, ResourceManager* resources); + void removePair(iterator it, ResourceManager* resources); + + private: + Slot getPreviousSlot(VariantData*, const ResourceManager*) const; +}; + +inline const VariantData* collectionToVariant( + const CollectionData* collection) { + const void* data = collection; // prevent warning cast-align + return reinterpret_cast(data); +} + +inline VariantData* collectionToVariant(CollectionData* collection) { + void* data = collection; // prevent warning cast-align + return reinterpret_cast(data); +} + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Collection/CollectionImpl.hpp b/lib/ArduinoJson/ArduinoJson/Collection/CollectionImpl.hpp new file mode 100644 index 0000000..7b43053 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Collection/CollectionImpl.hpp @@ -0,0 +1,137 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include +#include +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +inline CollectionIterator::CollectionIterator(VariantData* slot, SlotId slotId) + : slot_(slot), currentId_(slotId) { + nextId_ = slot_ ? slot_->next() : NULL_SLOT; +} + +inline void CollectionIterator::next(const ResourceManager* resources) { + ARDUINOJSON_ASSERT(currentId_ != NULL_SLOT); + slot_ = resources->getVariant(nextId_); + currentId_ = nextId_; + if (slot_) + nextId_ = slot_->next(); +} + +inline CollectionData::iterator CollectionData::createIterator( + const ResourceManager* resources) const { + return iterator(resources->getVariant(head_), head_); +} + +inline void CollectionData::appendOne(Slot slot, + const ResourceManager* resources) { + if (tail_ != NULL_SLOT) { + auto tail = resources->getVariant(tail_); + tail->setNext(slot.id()); + tail_ = slot.id(); + } else { + head_ = slot.id(); + tail_ = slot.id(); + } +} + +inline void CollectionData::appendPair(Slot key, + Slot value, + const ResourceManager* resources) { + key->setNext(value.id()); + + if (tail_ != NULL_SLOT) { + auto tail = resources->getVariant(tail_); + tail->setNext(key.id()); + tail_ = value.id(); + } else { + head_ = key.id(); + tail_ = value.id(); + } +} + +inline void CollectionData::clear(ResourceManager* resources) { + auto next = head_; + while (next != NULL_SLOT) { + auto currId = next; + auto slot = resources->getVariant(next); + next = slot->next(); + resources->freeVariant({slot, currId}); + } + + head_ = NULL_SLOT; + tail_ = NULL_SLOT; +} + +inline Slot CollectionData::getPreviousSlot( + VariantData* target, const ResourceManager* resources) const { + auto prev = Slot(); + auto currentId = head_; + while (currentId != NULL_SLOT) { + auto currentSlot = resources->getVariant(currentId); + if (currentSlot == target) + break; + prev = Slot(currentSlot, currentId); + currentId = currentSlot->next(); + } + return prev; +} + +inline void CollectionData::removeOne(iterator it, ResourceManager* resources) { + if (it.done()) + return; + auto curr = it.slot_; + auto prev = getPreviousSlot(curr, resources); + auto next = curr->next(); + if (prev) + prev->setNext(next); + else + head_ = next; + if (next == NULL_SLOT) + tail_ = prev.id(); + resources->freeVariant({it.slot_, it.currentId_}); +} + +inline void CollectionData::removePair(ObjectData::iterator it, + ResourceManager* resources) { + if (it.done()) + return; + + auto keySlot = it.slot_; + + auto valueId = it.nextId_; + auto valueSlot = resources->getVariant(valueId); + + // remove value slot + keySlot->setNext(valueSlot->next()); + resources->freeVariant({valueSlot, valueId}); + + // remove key slot + removeOne(it, resources); +} + +inline size_t CollectionData::nesting(const ResourceManager* resources) const { + size_t maxChildNesting = 0; + for (auto it = createIterator(resources); !it.done(); it.next(resources)) { + size_t childNesting = it->nesting(resources); + if (childNesting > maxChildNesting) + maxChildNesting = childNesting; + } + return maxChildNesting + 1; +} + +inline size_t CollectionData::size(const ResourceManager* resources) const { + size_t count = 0; + for (auto it = createIterator(resources); !it.done(); it.next(resources)) + count++; + return count; +} + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Configuration.hpp b/lib/ArduinoJson/ArduinoJson/Configuration.hpp new file mode 100644 index 0000000..801202c --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Configuration.hpp @@ -0,0 +1,285 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +// Support std::istream and std::ostream +// https://arduinojson.org/v7/config/enable_std_stream/ +#ifndef ARDUINOJSON_ENABLE_STD_STREAM +# ifdef __has_include +# if __has_include() && \ + __has_include() && \ + !defined(min) && \ + !defined(max) +# define ARDUINOJSON_ENABLE_STD_STREAM 1 +# else +# define ARDUINOJSON_ENABLE_STD_STREAM 0 +# endif +# else +# ifdef ARDUINO +# define ARDUINOJSON_ENABLE_STD_STREAM 0 +# else +# define ARDUINOJSON_ENABLE_STD_STREAM 1 +# endif +# endif +#endif + +// Support std::string +// https://arduinojson.org/v7/config/enable_std_string/ +#ifndef ARDUINOJSON_ENABLE_STD_STRING +# ifdef __has_include +# if __has_include() && !defined(min) && !defined(max) +# define ARDUINOJSON_ENABLE_STD_STRING 1 +# else +# define ARDUINOJSON_ENABLE_STD_STRING 0 +# endif +# else +# ifdef ARDUINO +# define ARDUINOJSON_ENABLE_STD_STRING 0 +# else +# define ARDUINOJSON_ENABLE_STD_STRING 1 +# endif +# endif +#endif + +// Support for std::string_view +#ifndef ARDUINOJSON_ENABLE_STRING_VIEW +# ifdef __has_include +# if __has_include() && __cplusplus >= 201703L +# define ARDUINOJSON_ENABLE_STRING_VIEW 1 +# else +# define ARDUINOJSON_ENABLE_STRING_VIEW 0 +# endif +# else +# define ARDUINOJSON_ENABLE_STRING_VIEW 0 +# endif +#endif + +// Pointer size: a heuristic to set sensible defaults +#ifndef ARDUINOJSON_SIZEOF_POINTER +# if defined(__SIZEOF_POINTER__) +# define ARDUINOJSON_SIZEOF_POINTER __SIZEOF_POINTER__ +# elif defined(_WIN64) && _WIN64 +# define ARDUINOJSON_SIZEOF_POINTER 8 // 64 bits +# else +# define ARDUINOJSON_SIZEOF_POINTER 4 // assume 32 bits otherwise +# endif +#endif + +// Store floating-point values with float (0) or double (1) +// https://arduinojson.org/v7/config/use_double/ +#ifndef ARDUINOJSON_USE_DOUBLE +# if ARDUINOJSON_SIZEOF_POINTER >= 4 // 32 & 64 bits systems +# define ARDUINOJSON_USE_DOUBLE 1 +# else +# define ARDUINOJSON_USE_DOUBLE 0 +# endif +#endif + +// Store integral values with long (0) or long long (1) +// https://arduinojson.org/v7/config/use_long_long/ +#ifndef ARDUINOJSON_USE_LONG_LONG +# if ARDUINOJSON_SIZEOF_POINTER >= 4 // 32 & 64 bits systems +# define ARDUINOJSON_USE_LONG_LONG 1 +# else +# define ARDUINOJSON_USE_LONG_LONG 0 +# endif +#endif + +// Limit nesting as the stack is likely to be small +// https://arduinojson.org/v7/config/default_nesting_limit/ +#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT +# define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 +#endif + +// Number of bytes to store a slot id +// https://arduinojson.org/v7/config/slot_id_size/ +#ifndef ARDUINOJSON_SLOT_ID_SIZE +# if ARDUINOJSON_SIZEOF_POINTER <= 2 +// 8-bit and 16-bit archs => up to 255 slots +# define ARDUINOJSON_SLOT_ID_SIZE 1 +# elif ARDUINOJSON_SIZEOF_POINTER == 4 +// 32-bit arch => up to 65535 slots +# define ARDUINOJSON_SLOT_ID_SIZE 2 +# else +// 64-bit arch => up to 4294967295 slots +# define ARDUINOJSON_SLOT_ID_SIZE 4 +# endif +#endif + +// Capacity of each variant pool (in slots) +#ifndef ARDUINOJSON_POOL_CAPACITY +# if ARDUINOJSON_SLOT_ID_SIZE == 1 +# define ARDUINOJSON_POOL_CAPACITY 16 // 96 bytes +# elif ARDUINOJSON_SLOT_ID_SIZE == 2 +# define ARDUINOJSON_POOL_CAPACITY 128 // 1024 bytes +# else +# define ARDUINOJSON_POOL_CAPACITY 256 // 4096 bytes +# endif +#endif + +// Initial capacity of the pool list +#ifndef ARDUINOJSON_INITIAL_POOL_COUNT +# define ARDUINOJSON_INITIAL_POOL_COUNT 4 +#endif + +// Automatically call shrinkToFit() from deserializeXxx() +// Disabled by default on 8-bit platforms because it's not worth the increase in +// code size +#ifndef ARDUINOJSON_AUTO_SHRINK +# if ARDUINOJSON_SIZEOF_POINTER <= 2 +# define ARDUINOJSON_AUTO_SHRINK 0 +# else +# define ARDUINOJSON_AUTO_SHRINK 1 +# endif +#endif + +// Number of bytes to store the length of a string +// https://arduinojson.org/v7/config/string_length_size/ +#ifndef ARDUINOJSON_STRING_LENGTH_SIZE +# if ARDUINOJSON_SIZEOF_POINTER <= 2 +# define ARDUINOJSON_STRING_LENGTH_SIZE 1 // up to 255 characters +# else +# define ARDUINOJSON_STRING_LENGTH_SIZE 2 // up to 65535 characters +# endif +#endif + +#ifdef ARDUINO + +// Enable support for Arduino's String class +// https://arduinojson.org/v7/config/enable_arduino_string/ +# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +# define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 +# endif + +// Enable support for Arduino's Stream class +// https://arduinojson.org/v7/config/enable_arduino_stream/ +# 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 + +// Enable support for PROGMEM +// https://arduinojson.org/v7/config/enable_progmem/ +# ifndef ARDUINOJSON_ENABLE_PROGMEM +# define ARDUINOJSON_ENABLE_PROGMEM 1 +# endif + +#else // ARDUINO + +// Disable support for Arduino's String class +// https://arduinojson.org/v7/config/enable_arduino_string/ +# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +# define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 +# endif + +// Disable support for Arduino's Stream class +// https://arduinojson.org/v7/config/enable_arduino_stream/ +# 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 + +// Enable PROGMEM support on AVR only +// https://arduinojson.org/v7/config/enable_progmem/ +# ifndef ARDUINOJSON_ENABLE_PROGMEM +# ifdef __AVR__ +# define ARDUINOJSON_ENABLE_PROGMEM 1 +# else +# define ARDUINOJSON_ENABLE_PROGMEM 0 +# endif +# endif + +#endif // ARDUINO + +// Convert unicode escape sequence (\u0123) to UTF-8 +// https://arduinojson.org/v7/config/decode_unicode/ +#ifndef ARDUINOJSON_DECODE_UNICODE +# define ARDUINOJSON_DECODE_UNICODE 1 +#endif + +// Ignore comments in input +// https://arduinojson.org/v7/config/enable_comments/ +#ifndef ARDUINOJSON_ENABLE_COMMENTS +# define ARDUINOJSON_ENABLE_COMMENTS 0 +#endif + +// Support NaN in JSON +// https://arduinojson.org/v7/config/enable_nan/ +#ifndef ARDUINOJSON_ENABLE_NAN +# define ARDUINOJSON_ENABLE_NAN 0 +#endif + +// Support Infinity in JSON +// https://arduinojson.org/v7/config/enable_infinity/ +#ifndef ARDUINOJSON_ENABLE_INFINITY +# define ARDUINOJSON_ENABLE_INFINITY 0 +#endif + +// Control the exponentiation threshold for big numbers +// CAUTION: cannot be more that 1e9 !!!! +// https://arduinojson.org/v7/config/positive_exponentiation_threshold/ +#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD +# define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 +#endif + +// Control the exponentiation threshold for small numbers +// https://arduinojson.org/v7/config/negative_exponentiation_threshold/ +#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_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_USE_LONG_LONG || ARDUINOJSON_USE_DOUBLE +# define ARDUINOJSON_USE_EXTENSIONS 1 +#else +# define ARDUINOJSON_USE_EXTENSIONS 0 +#endif + +#if defined(nullptr) +# error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr +// See https://github.com/bblanchon/ArduinoJson/issues/1355 +#endif diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/DeserializationError.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/DeserializationError.hpp new file mode 100644 index 0000000..c498b07 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/DeserializationError.hpp @@ -0,0 +1,106 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include +#include + +#if ARDUINOJSON_ENABLE_STD_STREAM +# include +#endif + +ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE + +class DeserializationError { + 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_; + } + + // Returns true if there is an error + explicit operator bool() const { + return code_ != Ok; + } + + // 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(code_) < + sizeof(messages) / sizeof(messages[0])); + return messages[code_]; + } + +#if ARDUINOJSON_ENABLE_PROGMEM + const __FlashStringHelper* f_str() const { + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s0, "Ok"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s1, "EmptyInput"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s2, "IncompleteInput"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s3, "InvalidInput"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s4, "NoMemory"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(char, s5, "TooDeep"); + ARDUINOJSON_DEFINE_PROGMEM_ARRAY(const char*, messages, + {s0, s1, s2, s3, s4, s5}); + return reinterpret_cast( + detail::pgm_read(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 + +ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/DeserializationOptions.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/DeserializationOptions.hpp new file mode 100644 index 0000000..b711d71 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/DeserializationOptions.hpp @@ -0,0 +1,35 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +struct DeserializationOptions { + TFilter filter; + DeserializationOption::NestingLimit nestingLimit; +}; + +template +inline DeserializationOptions makeDeserializationOptions( + TFilter filter, DeserializationOption::NestingLimit nestingLimit = {}) { + return {filter, nestingLimit}; +} + +template +inline DeserializationOptions makeDeserializationOptions( + DeserializationOption::NestingLimit nestingLimit, TFilter filter) { + return {filter, nestingLimit}; +} + +inline DeserializationOptions makeDeserializationOptions( + DeserializationOption::NestingLimit nestingLimit = {}) { + return {{}, nestingLimit}; +} + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Filter.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Filter.hpp new file mode 100644 index 0000000..564893b --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Filter.hpp @@ -0,0 +1,77 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE + +namespace DeserializationOption { +class Filter { + public: +#if ARDUINOJSON_AUTO_SHRINK + explicit Filter(JsonDocument& doc) : variant_(doc) { + doc.shrinkToFit(); + } +#endif + + explicit Filter(JsonVariantConst variant) : variant_(variant) {} + + bool allow() const { + return variant_; + } + + bool allowArray() const { + return variant_ == true || variant_.is(); + } + + bool allowObject() const { + return variant_ == true || variant_.is(); + } + + bool allowValue() const { + return variant_ == true; + } + + template + Filter operator[](const TKey& key) const { + if (variant_ == true) // "true" means "allow recursively" + return *this; + JsonVariantConst member = variant_[key]; + return Filter(member.isNull() ? variant_["*"] : member); + } + + private: + JsonVariantConst variant_; +}; +} // namespace DeserializationOption + +namespace detail { +struct AllowAllFilter { + bool allow() const { + return true; + } + + bool allowArray() const { + return true; + } + + bool allowObject() const { + return true; + } + + bool allowValue() const { + return true; + } + + template + AllowAllFilter operator[](const TKey&) const { + return AllowAllFilter(); + } +}; +} // namespace detail + +ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/NestingLimit.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/NestingLimit.hpp new file mode 100644 index 0000000..11aba7e --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/NestingLimit.hpp @@ -0,0 +1,32 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE + +namespace DeserializationOption { +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(value_ - 1)); + } + + bool reached() const { + return value_ == 0; + } + + private: + uint8_t value_; +}; +} // namespace DeserializationOption + +ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Reader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Reader.hpp new file mode 100644 index 0000000..4610312 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Reader.hpp @@ -0,0 +1,74 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +#include // for size_t + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +// The default reader is a simple wrapper for Readers that are not copyable +template +struct Reader { + public: + Reader(TSource& source) : source_(&source) {} + + int read() { + // clang-format off + return source_->read(); // Error here? See https://arduinojson.org/v7/invalid-input/ + // clang-format on + } + + size_t readBytes(char* buffer, size_t length) { + return source_->readBytes(buffer, length); + } + + private: + TSource* source_; +}; + +template +struct BoundedReader { + // no default implementation because we need to pass the size to the + // constructor +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE + +#include +#include +#include + +#if ARDUINOJSON_ENABLE_ARDUINO_STREAM +# include +#endif + +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +# include +#endif + +#if ARDUINOJSON_ENABLE_PROGMEM +# include +#endif + +#if ARDUINOJSON_ENABLE_STD_STREAM +# include +#endif + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +Reader> makeReader(TInput&& input) { + return Reader>{detail::forward(input)}; +} + +template +BoundedReader makeReader(TChar* input, size_t inputSize) { + return BoundedReader{input, inputSize}; +} + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp new file mode 100644 index 0000000..7c4d6b8 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp @@ -0,0 +1,30 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +struct Reader::value>> { + 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(c) : -1; + } + + size_t readBytes(char* buffer, size_t length) { + return stream_->readBytes(buffer, length); + } + + private: + Stream* stream_; +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp new file mode 100644 index 0000000..ba3d7b7 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp @@ -0,0 +1,18 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +struct Reader::value>> + : BoundedReader { + explicit Reader(const ::String& s) + : BoundedReader(s.c_str(), s.length()) {} +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/FlashReader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/FlashReader.hpp new file mode 100644 index 0000000..80c0da8 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/FlashReader.hpp @@ -0,0 +1,56 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template <> +struct Reader { + const char* ptr_; + + public: + explicit Reader(const __FlashStringHelper* ptr) + : ptr_(reinterpret_cast(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 char* ptr_; + const char* end_; + + public: + explicit BoundedReader(const __FlashStringHelper* ptr, size_t size) + : ptr_(reinterpret_cast(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(end_ - ptr_); + if (available < length) + length = available; + memcpy_P(buffer, ptr_, length); + ptr_ += length; + return length; + } +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/IteratorReader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/IteratorReader.hpp new file mode 100644 index 0000000..428d3f5 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/IteratorReader.hpp @@ -0,0 +1,42 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +class IteratorReader { + TIterator ptr_, end_; + + public: + explicit IteratorReader(TIterator begin, TIterator end) + : ptr_(begin), end_(end) {} + + int read() { + if (ptr_ < end_) + return static_cast(*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 +struct Reader> + : IteratorReader { + explicit Reader(const TSource& source) + : IteratorReader(source.begin(), + source.end()) {} +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/RamReader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/RamReader.hpp new file mode 100644 index 0000000..30ddd8f --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/RamReader.hpp @@ -0,0 +1,49 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +struct IsCharOrVoid { + static const bool value = + is_same::value || is_same::value || + is_same::value || is_same::value; +}; + +template +struct IsCharOrVoid : IsCharOrVoid {}; + +template +struct Reader::value>> { + const char* ptr_; + + public: + explicit Reader(const void* ptr) + : ptr_(ptr ? reinterpret_cast(ptr) : "") {} + + int read() { + return static_cast(*ptr_++); + } + + size_t readBytes(char* buffer, size_t length) { + for (size_t i = 0; i < length; i++) + buffer[i] = *ptr_++; + return length; + } +}; + +template +struct BoundedReader::value>> + : public IteratorReader { + public: + explicit BoundedReader(const void* ptr, size_t len) + : IteratorReader(reinterpret_cast(ptr), + reinterpret_cast(ptr) + len) {} +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp new file mode 100644 index 0000000..5de22c0 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/StdStreamReader.hpp @@ -0,0 +1,29 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +struct Reader::value>> { + 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(length)); + return static_cast(stream_->gcount()); + } + + private: + std::istream* stream_; +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/VariantReader.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/VariantReader.hpp new file mode 100644 index 0000000..6b91517 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/Readers/VariantReader.hpp @@ -0,0 +1,19 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +template +struct Reader::value>> + : Reader { + explicit Reader(const TVariant& x) + : Reader(x.template as()) {} +}; + +ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/lib/ArduinoJson/ArduinoJson/Deserialization/deserialize.hpp b/lib/ArduinoJson/ArduinoJson/Deserialization/deserialize.hpp new file mode 100644 index 0000000..a23e093 --- /dev/null +++ b/lib/ArduinoJson/ArduinoJson/Deserialization/deserialize.hpp @@ -0,0 +1,79 @@ +// ArduinoJson - https://arduinojson.org +// Copyright © 2014-2026, Benoit BLANCHON +// MIT License + +#pragma once + +#include +#include +#include +#include + +ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE + +// A meta-function that returns the first type of the parameter pack +// or void if empty +template +struct first_or_void { + using type = void; +}; +template +struct first_or_void { + using type = T; +}; + +// A meta-function that returns true if T is a valid destination type for +// deserialize() +template +using is_deserialize_destination = + bool_constant>::value || + IsVariant::value>; + +template +inline void shrinkJsonDocument(TDestination&) { + // no-op by default +} + +#if ARDUINOJSON_AUTO_SHRINK +inline void shrinkJsonDocument(JsonDocument& doc) { + doc.shrinkToFit(); +} +#endif + +template