mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
update ArduinoJson to latest v6.20.0 (saves 1600 bytes in flash. whoot!)
This commit is contained in:
@@ -21,19 +21,19 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "ArduinoJson/Array/ArrayRef.hpp"
|
||||
#include "ArduinoJson/Object/ObjectRef.hpp"
|
||||
#include "ArduinoJson/Variant/VariantRef.hpp"
|
||||
#include "ArduinoJson/Array/JsonArray.hpp"
|
||||
#include "ArduinoJson/Object/JsonObject.hpp"
|
||||
#include "ArduinoJson/Variant/JsonVariantConst.hpp"
|
||||
|
||||
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
||||
|
||||
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
||||
#include "ArduinoJson/Array/ElementProxy.hpp"
|
||||
#include "ArduinoJson/Array/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/Array/Utilities.hpp"
|
||||
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
||||
#include "ArduinoJson/Object/JsonObjectImpl.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"
|
||||
@@ -47,25 +47,25 @@
|
||||
#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::JsonArray;
|
||||
using ARDUINOJSON_NAMESPACE::JsonArrayConst;
|
||||
using ARDUINOJSON_NAMESPACE::JsonDocument;
|
||||
using ARDUINOJSON_NAMESPACE::JsonFloat;
|
||||
using ARDUINOJSON_NAMESPACE::JsonInteger;
|
||||
using ARDUINOJSON_NAMESPACE::JsonObject;
|
||||
using ARDUINOJSON_NAMESPACE::JsonObjectConst;
|
||||
using ARDUINOJSON_NAMESPACE::JsonPair;
|
||||
using ARDUINOJSON_NAMESPACE::JsonPairConst;
|
||||
using ARDUINOJSON_NAMESPACE::JsonString;
|
||||
using ARDUINOJSON_NAMESPACE::JsonUInt;
|
||||
using ARDUINOJSON_NAMESPACE::JsonVariant;
|
||||
using ARDUINOJSON_NAMESPACE::JsonVariantConst;
|
||||
using ARDUINOJSON_NAMESPACE::measureJson;
|
||||
using ARDUINOJSON_NAMESPACE::serialized;
|
||||
using ARDUINOJSON_NAMESPACE::serializeJson;
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -1,28 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -1,121 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -1,213 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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);
|
||||
}
|
||||
|
||||
void clear() const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->clear();
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<ArrayConstRef> {
|
||||
static void toJson(VariantConstRef src, VariantRef dst) {
|
||||
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 void toJson(VariantConstRef src, VariantRef dst) {
|
||||
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 InvalidConversion<VariantConstRef, ArrayRef> fromJson(VariantConstRef);
|
||||
|
||||
static bool checkJson(VariantConstRef) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantRef src) {
|
||||
VariantData* data = getData(src);
|
||||
return data && data->isArray();
|
||||
}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -1,49 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -4,194 +4,57 @@
|
||||
|
||||
#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
|
||||
#include <ArduinoJson/Variant/VariantRefBase.hpp>
|
||||
|
||||
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;
|
||||
// A proxy class to get or set an element of an array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/subscript/
|
||||
template <typename TUpstream>
|
||||
class ElementProxy : public VariantRefBase<ElementProxy<TUpstream> >,
|
||||
public VariantOperators<ElementProxy<TUpstream> > {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
typedef VariantRef variant_type;
|
||||
ElementProxy(TUpstream upstream, size_t index)
|
||||
: _upstream(upstream), _index(index) {}
|
||||
|
||||
FORCE_INLINE ElementProxy(TArray array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
ElementProxy(const ElementProxy& src)
|
||||
: _upstream(src._upstream), _index(src._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>());
|
||||
FORCE_INLINE ElementProxy& operator=(const ElementProxy& src) {
|
||||
this->set(src);
|
||||
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);
|
||||
FORCE_INLINE ElementProxy& operator=(const T& src) {
|
||||
this->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();
|
||||
}
|
||||
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
return getUpstreamElement().memoryUsage();
|
||||
}
|
||||
|
||||
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);
|
||||
FORCE_INLINE ElementProxy& operator=(T* src) {
|
||||
this->set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
FORCE_INLINE VariantRef getUpstreamElement() const {
|
||||
return _array.getElement(_index);
|
||||
FORCE_INLINE MemoryPool* getPool() const {
|
||||
return VariantAttorney::getPool(_upstream);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef getOrAddUpstreamElement() const {
|
||||
return _array.getOrAddElement(_index);
|
||||
FORCE_INLINE VariantData* getData() const {
|
||||
return variantGetElement(VariantAttorney::getData(_upstream), _index);
|
||||
}
|
||||
|
||||
friend void convertToJson(const this_type& src, VariantRef dst) {
|
||||
dst.set(src.getUpstreamElement());
|
||||
FORCE_INLINE VariantData* getOrCreateData() const {
|
||||
return variantGetOrAddElement(VariantAttorney::getOrCreateData(_upstream),
|
||||
_index, VariantAttorney::getPool(_upstream));
|
||||
}
|
||||
|
||||
TArray _array;
|
||||
const size_t _index;
|
||||
TUpstream _upstream;
|
||||
size_t _index;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
210
lib/ArduinoJson/src/ArduinoJson/Array/JsonArray.hpp
Normal file
210
lib/ArduinoJson/src/ArduinoJson/Array/JsonArray.hpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/ElementProxy.hpp>
|
||||
#include <ArduinoJson/Array/JsonArrayConst.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonObject;
|
||||
|
||||
// A reference to an array in a JsonDocument
|
||||
// https://arduinojson.org/v6/api/jsonarray/
|
||||
class JsonArray : public VariantOperators<JsonArray> {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
typedef JsonArrayIterator iterator;
|
||||
|
||||
// Constructs an unbound reference.
|
||||
FORCE_INLINE JsonArray() : _data(0), _pool(0) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
FORCE_INLINE JsonArray(MemoryPool* pool, CollectionData* data)
|
||||
: _data(data), _pool(pool) {}
|
||||
|
||||
// Returns a JsonVariant pointing to the array.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/
|
||||
operator JsonVariant() {
|
||||
void* data = _data; // prevent warning cast-align
|
||||
return JsonVariant(_pool, reinterpret_cast<VariantData*>(data));
|
||||
}
|
||||
|
||||
// Returns a read-only reference to the array.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/
|
||||
operator JsonArrayConst() const {
|
||||
return JsonArrayConst(_data);
|
||||
}
|
||||
|
||||
// Appends a new (null) element to the array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v6/api/jsonarray/add/
|
||||
JsonVariant add() const {
|
||||
if (!_data)
|
||||
return JsonVariant();
|
||||
return JsonVariant(_pool, _data->addElement(_pool));
|
||||
}
|
||||
|
||||
// Appends a value to the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/add/
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(const T& value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
// Appends a value to the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/add/
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(T* value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
// Returns an iterator to the first element of the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/begin/
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data)
|
||||
return iterator();
|
||||
return iterator(_pool, _data->head());
|
||||
}
|
||||
|
||||
// Returns an iterator following the last element of the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/end/
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Copies an array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/set/
|
||||
FORCE_INLINE bool set(JsonArrayConst src) const {
|
||||
if (!_data || !src._data)
|
||||
return false;
|
||||
return _data->copyFrom(*src._data, _pool);
|
||||
}
|
||||
|
||||
// Compares the content of two arrays.
|
||||
FORCE_INLINE bool operator==(JsonArray rhs) const {
|
||||
return JsonArrayConst(_data) == JsonArrayConst(rhs._data);
|
||||
}
|
||||
|
||||
// Removes the element at the specified iterator.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsonarray/remove/
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->removeSlot(it._slot);
|
||||
}
|
||||
|
||||
// Removes the element at the specified index.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsonarray/remove/
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->removeElement(index);
|
||||
}
|
||||
|
||||
// Removes all the elements of the array.
|
||||
// ⚠️ Doesn't release the memory associated with the removed elements.
|
||||
// https://arduinojson.org/v6/api/jsonarray/clear/
|
||||
void clear() const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->clear();
|
||||
}
|
||||
|
||||
// Gets or sets the element at the specified index.
|
||||
// https://arduinojson.org/v6/api/jsonarray/subscript/
|
||||
FORCE_INLINE ElementProxy<JsonArray> operator[](size_t index) const {
|
||||
return ElementProxy<JsonArray>(*this, index);
|
||||
}
|
||||
|
||||
// Creates an object and appends it to the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/createnestedobject/
|
||||
FORCE_INLINE JsonObject createNestedObject() const;
|
||||
|
||||
// Creates an array and appends it to the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/createnestedarray/
|
||||
FORCE_INLINE JsonArray createNestedArray() const {
|
||||
return add().to<JsonArray>();
|
||||
}
|
||||
|
||||
operator JsonVariantConst() const {
|
||||
return JsonVariantConst(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns true if the reference is unbound.
|
||||
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
// Returns true if the reference is bound.
|
||||
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
||||
FORCE_INLINE operator bool() const {
|
||||
return _data != 0;
|
||||
}
|
||||
|
||||
// Returns the number of bytes occupied by the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/memoryusage/
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
return _data ? _data->memoryUsage() : 0;
|
||||
}
|
||||
|
||||
// Returns the depth (nesting level) of the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/nesting/
|
||||
FORCE_INLINE size_t nesting() const {
|
||||
return variantNesting(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns the number of elements in the array.
|
||||
// https://arduinojson.org/v6/api/jsonarray/size/
|
||||
FORCE_INLINE size_t size() const {
|
||||
return _data ? _data->size() : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* getPool() const {
|
||||
return _pool;
|
||||
}
|
||||
|
||||
VariantData* getData() const {
|
||||
return collectionToVariant(_data);
|
||||
}
|
||||
|
||||
VariantData* getOrCreateData() const {
|
||||
return collectionToVariant(_data);
|
||||
}
|
||||
|
||||
CollectionData* _data;
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<JsonArray> : private VariantAttorney {
|
||||
static void toJson(JsonVariantConst src, JsonVariant dst) {
|
||||
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||
}
|
||||
|
||||
static JsonArray fromJson(JsonVariant src) {
|
||||
VariantData* data = getData(src);
|
||||
MemoryPool* pool = getPool(src);
|
||||
return JsonArray(pool, data != 0 ? data->asArray() : 0);
|
||||
}
|
||||
|
||||
static InvalidConversion<JsonVariantConst, JsonArray> fromJson(
|
||||
JsonVariantConst);
|
||||
|
||||
static bool checkJson(JsonVariantConst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariant src) {
|
||||
VariantData* data = getData(src);
|
||||
return data && data->isArray();
|
||||
}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
134
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp
Normal file
134
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/JsonArrayIterator.hpp>
|
||||
#include <ArduinoJson/Variant/VariantAttorney.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonObject;
|
||||
|
||||
// A read-only reference to an array in a JsonDocument
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/
|
||||
class JsonArrayConst : public VariantOperators<JsonArrayConst> {
|
||||
friend class JsonArray;
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
typedef JsonArrayConstIterator iterator;
|
||||
|
||||
// Returns an iterator to the first element of the array.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/begin/
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data)
|
||||
return iterator();
|
||||
return iterator(_data->head());
|
||||
}
|
||||
|
||||
// Returns an iterator to the element following the last element of the array.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/end/
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Creates an unbound reference.
|
||||
FORCE_INLINE JsonArrayConst() : _data(0) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
FORCE_INLINE JsonArrayConst(const CollectionData* data) : _data(data) {}
|
||||
|
||||
// Compares the content of two arrays.
|
||||
// Returns true if the two arrays are equal.
|
||||
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
|
||||
if (_data == rhs._data)
|
||||
return true;
|
||||
if (!_data || !rhs._data)
|
||||
return false;
|
||||
|
||||
iterator it1 = begin();
|
||||
iterator it2 = rhs.begin();
|
||||
|
||||
for (;;) {
|
||||
bool end1 = it1 == end();
|
||||
bool end2 = it2 == rhs.end();
|
||||
if (end1 && end2)
|
||||
return true;
|
||||
if (end1 || end2)
|
||||
return false;
|
||||
if (*it1 != *it2)
|
||||
return false;
|
||||
++it1;
|
||||
++it2;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the element at the specified index.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/subscript/
|
||||
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||
return JsonVariantConst(_data ? _data->getElement(index) : 0);
|
||||
}
|
||||
|
||||
operator JsonVariantConst() const {
|
||||
return JsonVariantConst(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns true if the reference is unbound.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
// Returns true if the reference is bound.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
||||
FORCE_INLINE operator bool() const {
|
||||
return _data != 0;
|
||||
}
|
||||
|
||||
// Returns the number of bytes occupied by the array.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/memoryusage/
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
return _data ? _data->memoryUsage() : 0;
|
||||
}
|
||||
|
||||
// Returns the depth (nesting level) of the array.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/nesting/
|
||||
FORCE_INLINE size_t nesting() const {
|
||||
return variantNesting(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns the number of elements in the array.
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/size/
|
||||
FORCE_INLINE size_t size() const {
|
||||
return _data ? _data->size() : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantData* getData() const {
|
||||
return collectionToVariant(_data);
|
||||
}
|
||||
|
||||
const CollectionData* _data;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<JsonArrayConst> : private VariantAttorney {
|
||||
static void toJson(JsonVariantConst src, JsonVariant dst) {
|
||||
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||
}
|
||||
|
||||
static JsonArrayConst fromJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data ? data->asArray() : 0;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data && data->isArray();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
32
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayImpl.hpp
Normal file
32
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayImpl.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/JsonArray.hpp>
|
||||
#include <ArduinoJson/Object/JsonObject.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline JsonObject JsonArray::createNestedObject() const {
|
||||
return add().to<JsonObject>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
inline JsonArray VariantRefBase<TDerived>::createNestedArray() const {
|
||||
return add().template to<JsonArray>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
inline JsonObject VariantRefBase<TDerived>::createNestedObject() const {
|
||||
return add().template to<JsonObject>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
|
||||
size_t index) const {
|
||||
return ElementProxy<TDerived>(derived(), index);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
117
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayIterator.hpp
Normal file
117
lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayIterator.hpp
Normal file
@@ -0,0 +1,117 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
||||
#include <ArduinoJson/Variant/SlotFunctions.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class VariantPtr {
|
||||
public:
|
||||
VariantPtr(MemoryPool* pool, VariantData* data) : _variant(pool, data) {}
|
||||
|
||||
JsonVariant* operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
JsonVariant& operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariant _variant;
|
||||
};
|
||||
|
||||
class JsonArrayIterator {
|
||||
friend class JsonArray;
|
||||
|
||||
public:
|
||||
JsonArrayIterator() : _slot(0) {}
|
||||
explicit JsonArrayIterator(MemoryPool* pool, VariantSlot* slot)
|
||||
: _pool(pool), _slot(slot) {}
|
||||
|
||||
JsonVariant operator*() const {
|
||||
return JsonVariant(_pool, _slot->data());
|
||||
}
|
||||
VariantPtr operator->() {
|
||||
return VariantPtr(_pool, _slot->data());
|
||||
}
|
||||
|
||||
bool operator==(const JsonArrayIterator& other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonArrayIterator& other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonArrayIterator& operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonArrayIterator& operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* _pool;
|
||||
VariantSlot* _slot;
|
||||
};
|
||||
|
||||
class VariantConstPtr {
|
||||
public:
|
||||
VariantConstPtr(const VariantData* data) : _variant(data) {}
|
||||
|
||||
JsonVariantConst* operator->() {
|
||||
return &_variant;
|
||||
}
|
||||
|
||||
JsonVariantConst& operator*() {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariantConst _variant;
|
||||
};
|
||||
|
||||
class JsonArrayConstIterator {
|
||||
friend class JsonArray;
|
||||
|
||||
public:
|
||||
JsonArrayConstIterator() : _slot(0) {}
|
||||
explicit JsonArrayConstIterator(const VariantSlot* slot) : _slot(slot) {}
|
||||
|
||||
JsonVariantConst operator*() const {
|
||||
return JsonVariantConst(_slot->data());
|
||||
}
|
||||
VariantConstPtr operator->() {
|
||||
return VariantConstPtr(_slot->data());
|
||||
}
|
||||
|
||||
bool operator==(const JsonArrayConstIterator& other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonArrayConstIterator& other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonArrayConstIterator& operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonArrayConstIterator& operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantSlot* _slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -4,19 +4,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/ArrayRef.hpp>
|
||||
#include <ArduinoJson/Array/JsonArray.hpp>
|
||||
#include <ArduinoJson/Document/JsonDocument.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// Trivial form to stop the recursion
|
||||
// Copies a value to a JsonVariant.
|
||||
// This is a degenerated form of copyArray() to stop the recursion.
|
||||
template <typename T>
|
||||
inline typename enable_if<!is_array<T>::value, bool>::type copyArray(
|
||||
const T& src, VariantRef dst) {
|
||||
const T& src, JsonVariant dst) {
|
||||
return dst.set(src);
|
||||
}
|
||||
|
||||
// Copy array to a JsonArray/JsonVariant/MemberProxy/ElementProxy
|
||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||
template <typename T, size_t N, typename TDestination>
|
||||
inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value,
|
||||
bool>::type
|
||||
@@ -24,64 +26,72 @@ copyArray(T (&src)[N], const TDestination& dst) {
|
||||
return copyArray(src, N, dst);
|
||||
}
|
||||
|
||||
// Copy ptr+size to a JsonArray/JsonVariant/MemberProxy/ElementProxy
|
||||
// Copies values from an array to a JsonArray or a JsonVariant.
|
||||
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||
template <typename T, typename TDestination>
|
||||
inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value,
|
||||
bool>::type
|
||||
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.addElement());
|
||||
ok &= copyArray(src[i], dst.add());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Special case for char[] which much be treated as const char*
|
||||
// Copies a string to a JsonVariant.
|
||||
// This is a degenerated form of copyArray() to handle strings.
|
||||
template <typename TDestination>
|
||||
inline bool copyArray(const char* src, size_t, const TDestination& dst) {
|
||||
return dst.set(src);
|
||||
}
|
||||
|
||||
// Copy array to a JsonDocument
|
||||
// Copies values from an array to a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||
template <typename T>
|
||||
inline bool copyArray(const T& src, JsonDocument& dst) {
|
||||
return copyArray(src, dst.to<ArrayRef>());
|
||||
return copyArray(src, dst.to<JsonArray>());
|
||||
}
|
||||
|
||||
// Copy a ptr+size array to a JsonDocument
|
||||
// Copies an array to a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||
template <typename T>
|
||||
inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
|
||||
return copyArray(src, len, dst.to<ArrayRef>());
|
||||
return copyArray(src, len, dst.to<JsonArray>());
|
||||
}
|
||||
|
||||
// Trivial case form to stop the recursion
|
||||
// Copies a value from a JsonVariant.
|
||||
// This is a degenerated form of copyArray() to stop the recursion.
|
||||
template <typename T>
|
||||
inline typename enable_if<!is_array<T>::value, size_t>::type copyArray(
|
||||
VariantConstRef src, T& dst) {
|
||||
JsonVariantConst src, T& dst) {
|
||||
dst = src.as<T>();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Copy a JsonArray to array
|
||||
// Copies values from a JsonArray or JsonVariant to an array.
|
||||
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||
template <typename T, size_t N>
|
||||
inline size_t copyArray(ArrayConstRef src, T (&dst)[N]) {
|
||||
inline size_t copyArray(JsonArrayConst src, T (&dst)[N]) {
|
||||
return copyArray(src, dst, N);
|
||||
}
|
||||
|
||||
// Copy a JsonArray to ptr+size
|
||||
// Copies values from a JsonArray or JsonVariant to an array.
|
||||
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||
template <typename T>
|
||||
inline size_t copyArray(ArrayConstRef src, T* dst, size_t len) {
|
||||
inline size_t copyArray(JsonArrayConst src, T* dst, size_t len) {
|
||||
size_t i = 0;
|
||||
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < len;
|
||||
for (JsonArrayConst::iterator it = src.begin(); it != src.end() && i < len;
|
||||
++it)
|
||||
copyArray(*it, dst[i++]);
|
||||
return i;
|
||||
}
|
||||
|
||||
// Special case for char[] which must be treated as a string
|
||||
// Copies a string from a JsonVariant.
|
||||
// This is a degenerated form of copyArray() to handle strings.
|
||||
template <size_t N>
|
||||
inline size_t copyArray(VariantConstRef src, char (&dst)[N]) {
|
||||
String s = src;
|
||||
inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
|
||||
JsonString s = src;
|
||||
size_t len = N - 1;
|
||||
if (len > s.size())
|
||||
len = s.size();
|
||||
@@ -90,14 +100,14 @@ inline size_t copyArray(VariantConstRef src, char (&dst)[N]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Copy a JsonDocument to an array
|
||||
// (JsonDocument doesn't implicitly convert to JsonArrayConst)
|
||||
// Copies values from a JsonDocument to an array.
|
||||
// https://arduinojson.org/v6/api/misc/copyarray/
|
||||
template <typename TSource, typename T>
|
||||
inline typename enable_if<is_array<T>::value &&
|
||||
is_base_of<JsonDocument, TSource>::value,
|
||||
size_t>::type
|
||||
copyArray(const TSource& src, T& dst) {
|
||||
return copyArray(src.template as<ArrayConstRef>(), dst);
|
||||
return copyArray(src.template as<JsonArrayConst>(), dst);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -16,8 +16,8 @@ class VariantData;
|
||||
class VariantSlot;
|
||||
|
||||
class CollectionData {
|
||||
VariantSlot *_head;
|
||||
VariantSlot *_tail;
|
||||
VariantSlot* _head;
|
||||
VariantSlot* _tail;
|
||||
|
||||
public:
|
||||
// Must be a POD!
|
||||
@@ -28,27 +28,24 @@ class CollectionData {
|
||||
|
||||
// Array only
|
||||
|
||||
VariantData *addElement(MemoryPool *pool);
|
||||
VariantData* addElement(MemoryPool* pool);
|
||||
|
||||
VariantData *getElement(size_t index) const;
|
||||
VariantData* getElement(size_t index) const;
|
||||
|
||||
VariantData *getOrAddElement(size_t index, MemoryPool *pool);
|
||||
VariantData* getOrAddElement(size_t index, MemoryPool* pool);
|
||||
|
||||
void removeElement(size_t index);
|
||||
|
||||
bool equalsArray(const CollectionData &other) const;
|
||||
|
||||
// Object only
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
VariantData *addMember(TAdaptedString key, MemoryPool *pool, TStoragePolicy);
|
||||
template <typename TAdaptedString>
|
||||
VariantData* addMember(TAdaptedString key, MemoryPool* pool);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *getMember(TAdaptedString key) const;
|
||||
VariantData* getMember(TAdaptedString key) const;
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool,
|
||||
TStoragePolicy);
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void removeMember(TAdaptedString key) {
|
||||
@@ -56,34 +53,42 @@ class CollectionData {
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
bool containsKey(const TAdaptedString &key) const;
|
||||
|
||||
bool equalsObject(const CollectionData &other) const;
|
||||
bool containsKey(const TAdaptedString& key) const;
|
||||
|
||||
// Generic
|
||||
|
||||
void clear();
|
||||
size_t memoryUsage() const;
|
||||
size_t nesting() const;
|
||||
size_t size() const;
|
||||
|
||||
VariantSlot *addSlot(MemoryPool *);
|
||||
void removeSlot(VariantSlot *slot);
|
||||
VariantSlot* addSlot(MemoryPool*);
|
||||
void removeSlot(VariantSlot* slot);
|
||||
|
||||
bool copyFrom(const CollectionData &src, MemoryPool *pool);
|
||||
bool copyFrom(const CollectionData& src, MemoryPool* pool);
|
||||
|
||||
VariantSlot *head() const {
|
||||
VariantSlot* head() const {
|
||||
return _head;
|
||||
}
|
||||
|
||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
|
||||
|
||||
private:
|
||||
VariantSlot *getSlot(size_t index) const;
|
||||
VariantSlot* getSlot(size_t index) const;
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantSlot *getSlot(TAdaptedString key) const;
|
||||
VariantSlot* getSlot(TAdaptedString key) const;
|
||||
|
||||
VariantSlot *getPreviousSlot(VariantSlot *) const;
|
||||
VariantSlot* getPreviousSlot(VariantSlot*) const;
|
||||
};
|
||||
|
||||
inline const VariantData* collectionToVariant(
|
||||
const CollectionData* collection) {
|
||||
const void* data = collection; // prevent warning cast-align
|
||||
return reinterpret_cast<const VariantData*>(data);
|
||||
}
|
||||
|
||||
inline VariantData* collectionToVariant(CollectionData* collection) {
|
||||
void* data = collection; // prevent warning cast-align
|
||||
return reinterpret_cast<VariantData*>(data);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -11,16 +11,13 @@
|
||||
|
||||
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) {
|
||||
ARDUINOJSON_ASSERT(pool->owns(_tail)); // Can't alter a linked array/object
|
||||
_tail->setNextNotNull(slot);
|
||||
_tail = slot;
|
||||
} else {
|
||||
@@ -36,12 +33,11 @@ inline VariantData* CollectionData::addElement(MemoryPool* pool) {
|
||||
return slotData(addSlot(pool));
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* CollectionData::addMember(TAdaptedString key,
|
||||
MemoryPool* pool,
|
||||
TStoragePolicy storage) {
|
||||
MemoryPool* pool) {
|
||||
VariantSlot* slot = addSlot(pool);
|
||||
if (!slotSetKey(slot, key, pool, storage)) {
|
||||
if (!slotSetKey(slot, key, pool)) {
|
||||
removeSlot(slot);
|
||||
return 0;
|
||||
}
|
||||
@@ -64,8 +60,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
|
||||
for (VariantSlot* s = src._head; s; s = s->next()) {
|
||||
VariantData* var;
|
||||
if (s->key() != 0) {
|
||||
String key(s->key(), s->ownsKey() ? String::Copied : String::Linked);
|
||||
var = addMember(adaptString(key), pool, getStringStoragePolicy(key));
|
||||
JsonString key(s->key(),
|
||||
s->ownsKey() ? JsonString::Copied : JsonString::Linked);
|
||||
var = addMember(adaptString(key), pool);
|
||||
} else {
|
||||
var = addElement(pool);
|
||||
}
|
||||
@@ -77,33 +74,6 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
|
||||
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 {
|
||||
if (key.isNull())
|
||||
@@ -140,9 +110,9 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const {
|
||||
return slot ? slot->data() : 0;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
inline VariantData* CollectionData::getOrAddMember(
|
||||
TAdaptedString key, MemoryPool* pool, TStoragePolicy storage_policy) {
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
|
||||
MemoryPool* pool) {
|
||||
// ignore null key
|
||||
if (key.isNull())
|
||||
return 0;
|
||||
@@ -152,7 +122,7 @@ inline VariantData* CollectionData::getOrAddMember(
|
||||
if (slot)
|
||||
return slot->data();
|
||||
|
||||
return addMember(key, pool, storage_policy);
|
||||
return addMember(key, pool);
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::getElement(size_t index) const {
|
||||
@@ -203,16 +173,6 @@ inline size_t CollectionData::memoryUsage() const {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -10,18 +10,18 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class Filter {
|
||||
public:
|
||||
explicit Filter(VariantConstRef v) : _variant(v) {}
|
||||
explicit Filter(JsonVariantConst v) : _variant(v) {}
|
||||
|
||||
bool allow() const {
|
||||
return _variant;
|
||||
}
|
||||
|
||||
bool allowArray() const {
|
||||
return _variant == true || _variant.is<ArrayConstRef>();
|
||||
return _variant == true || _variant.is<JsonArrayConst>();
|
||||
}
|
||||
|
||||
bool allowObject() const {
|
||||
return _variant == true || _variant.is<ObjectConstRef>();
|
||||
return _variant == true || _variant.is<JsonObjectConst>();
|
||||
}
|
||||
|
||||
bool allowValue() const {
|
||||
@@ -32,12 +32,12 @@ class Filter {
|
||||
Filter operator[](const TKey& key) const {
|
||||
if (_variant == true) // "true" means "allow recursively"
|
||||
return *this;
|
||||
VariantConstRef member = _variant[key];
|
||||
JsonVariantConst member = _variant[key];
|
||||
return Filter(member.isNull() ? _variant["*"] : member);
|
||||
}
|
||||
|
||||
private:
|
||||
VariantConstRef _variant;
|
||||
JsonVariantConst _variant;
|
||||
};
|
||||
|
||||
struct AllowAllFilter {
|
||||
|
||||
@@ -23,7 +23,8 @@ class IteratorReader {
|
||||
|
||||
size_t readBytes(char* buffer, size_t length) {
|
||||
size_t i = 0;
|
||||
while (i < length && _ptr < _end) buffer[i++] = *_ptr++;
|
||||
while (i < length && _ptr < _end)
|
||||
buffer[i++] = *_ptr++;
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,7 +32,8 @@ struct Reader<TSource*,
|
||||
}
|
||||
|
||||
size_t readBytes(char* buffer, size_t length) {
|
||||
for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
buffer[i] = *_ptr++;
|
||||
return length;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,30 +5,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Object/MemberProxy.hpp>
|
||||
#include <ArduinoJson/Variant/VariantRef.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TArray>
|
||||
struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> {
|
||||
explicit Reader(const ElementProxy<TArray>& x)
|
||||
template <typename TVariant>
|
||||
struct Reader<TVariant, typename enable_if<IsVariant<TVariant>::value>::type>
|
||||
: Reader<char*, void> {
|
||||
explicit Reader(const TVariant& 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
|
||||
|
||||
@@ -14,9 +14,10 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <template <typename, typename> class TDeserializer, typename TReader,
|
||||
typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool* pool,
|
||||
TReader reader,
|
||||
TWriter writer) {
|
||||
ARDUINOJSON_ASSERT(pool != 0);
|
||||
return TDeserializer<TReader, TWriter>(pool, reader, writer);
|
||||
}
|
||||
|
||||
@@ -28,14 +29,15 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
|
||||
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,
|
||||
deserialize(JsonDocument& doc, const TString& input, NestingLimit nestingLimit,
|
||||
TFilter filter) {
|
||||
Reader<TString> reader(input);
|
||||
VariantData* data = VariantAttorney::getData(doc);
|
||||
MemoryPool* pool = VariantAttorney::getPool(doc);
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), reader,
|
||||
makeStringStorage(input, doc.memoryPool()))
|
||||
.parse(doc.data(), filter, nestingLimit);
|
||||
return makeDeserializer<TDeserializer>(pool, reader,
|
||||
makeStringStorage(input, pool))
|
||||
.parse(*data, filter, nestingLimit);
|
||||
}
|
||||
//
|
||||
// deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter);
|
||||
@@ -43,29 +45,31 @@ deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
|
||||
// deserialize(JsonDocument&, const __FlashStringHelper*, size_t, NL, Filter);
|
||||
template <template <typename, typename> class TDeserializer, typename TChar,
|
||||
typename TFilter>
|
||||
DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
||||
DeserializationError deserialize(JsonDocument& doc, TChar* input,
|
||||
size_t inputSize, NestingLimit nestingLimit,
|
||||
TFilter filter) {
|
||||
BoundedReader<TChar *> reader(input, inputSize);
|
||||
BoundedReader<TChar*> reader(input, inputSize);
|
||||
VariantData* data = VariantAttorney::getData(doc);
|
||||
MemoryPool* pool = VariantAttorney::getPool(doc);
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), reader,
|
||||
makeStringStorage(input, doc.memoryPool()))
|
||||
.parse(doc.data(), filter, nestingLimit);
|
||||
return makeDeserializer<TDeserializer>(pool, reader,
|
||||
makeStringStorage(input, pool))
|
||||
.parse(*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,
|
||||
DeserializationError deserialize(JsonDocument& doc, TStream& input,
|
||||
NestingLimit nestingLimit, TFilter filter) {
|
||||
Reader<TStream> reader(input);
|
||||
VariantData* data = VariantAttorney::getData(doc);
|
||||
MemoryPool* pool = VariantAttorney::getPool(doc);
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), reader,
|
||||
makeStringStorage(input, doc.memoryPool()))
|
||||
.parse(doc.data(), filter, nestingLimit);
|
||||
return makeDeserializer<TDeserializer>(pool, reader,
|
||||
makeStringStorage(input, pool))
|
||||
.parse(*data, filter, nestingLimit);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -37,6 +37,8 @@ class AllocatorOwner {
|
||||
TAllocator _allocator;
|
||||
};
|
||||
|
||||
// A JsonDocument that uses the provided allocator to allocate its memory pool.
|
||||
// https://arduinojson.org/v6/api/basicjsondocument/
|
||||
template <typename TAllocator>
|
||||
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||
public:
|
||||
@@ -65,16 +67,16 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||
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)
|
||||
is_same<T, JsonVariant>::value ||
|
||||
is_same<T, JsonVariantConst>::value || is_same<T, JsonArray>::value ||
|
||||
is_same<T, JsonArrayConst>::value || is_same<T, JsonObject>::value ||
|
||||
is_same<T, JsonObjectConst>::value>::type* = 0)
|
||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
// disambiguate
|
||||
BasicJsonDocument(VariantRef src)
|
||||
BasicJsonDocument(JsonVariant src)
|
||||
: JsonDocument(allocPool(src.memoryUsage())) {
|
||||
set(src);
|
||||
}
|
||||
@@ -104,6 +106,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reduces the capacity of the memory pool to match the current usage.
|
||||
// https://arduinojson.org/v6/api/basicjsondocument/shrinktofit/
|
||||
void shrinkToFit() {
|
||||
ptrdiff_t bytes_reclaimed = _pool.squash();
|
||||
if (bytes_reclaimed == 0)
|
||||
@@ -119,6 +123,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||
_data.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
|
||||
}
|
||||
|
||||
// Reclaims the memory leaked when removing and replacing values.
|
||||
// https://arduinojson.org/v6/api/jsondocument/garbagecollect/
|
||||
bool garbageCollect() {
|
||||
// make a temporary clone and move assign
|
||||
BasicJsonDocument tmp(*this);
|
||||
@@ -146,7 +152,7 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
||||
}
|
||||
|
||||
void freePool() {
|
||||
this->deallocate(memoryPool().buffer());
|
||||
this->deallocate(getPool()->buffer());
|
||||
}
|
||||
|
||||
void copyAssignFrom(const JsonDocument& src) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// The allocator of DynamicJsonDocument.
|
||||
struct DefaultAllocator {
|
||||
void* allocate(size_t size) {
|
||||
return malloc(size);
|
||||
@@ -24,6 +25,8 @@ struct DefaultAllocator {
|
||||
}
|
||||
};
|
||||
|
||||
// A JsonDocument with a memory pool in the heap.
|
||||
// https://arduinojson.org/v6/api/dynamicjsondocument/
|
||||
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -6,152 +6,169 @@
|
||||
|
||||
#include <ArduinoJson/Array/ElementProxy.hpp>
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Object/JsonObject.hpp>
|
||||
#include <ArduinoJson/Object/MemberProxy.hpp>
|
||||
#include <ArduinoJson/Object/ObjectRef.hpp>
|
||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||
#include <ArduinoJson/Variant/VariantRef.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
|
||||
#include <ArduinoJson/Variant/VariantTo.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonDocument : public Visitable,
|
||||
public VariantOperators<const JsonDocument&> {
|
||||
public:
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||
return getVariant().accept(visitor);
|
||||
}
|
||||
// A JSON document.
|
||||
// https://arduinojson.org/v6/api/jsondocument/
|
||||
class JsonDocument : public VariantOperators<const JsonDocument&> {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
// Casts the root to the specified type.
|
||||
// https://arduinojson.org/v6/api/jsondocument/as/
|
||||
template <typename T>
|
||||
T as() {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
// Casts the root to the specified type.
|
||||
// https://arduinojson.org/v6/api/jsondocument/as/
|
||||
template <typename T>
|
||||
T as() const {
|
||||
return getVariant().template as<T>();
|
||||
}
|
||||
|
||||
// Empties the document and resets the memory pool
|
||||
// https://arduinojson.org/v6/api/jsondocument/clear/
|
||||
void clear() {
|
||||
_pool.clear();
|
||||
_data.init();
|
||||
}
|
||||
|
||||
// Returns true if the root is of the specified type.
|
||||
// https://arduinojson.org/v6/api/jsondocument/is/
|
||||
template <typename T>
|
||||
bool is() {
|
||||
return getVariant().template is<T>();
|
||||
}
|
||||
|
||||
// Returns true if the root is of the specified type.
|
||||
// https://arduinojson.org/v6/api/jsondocument/is/
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return getVariant().template is<T>();
|
||||
}
|
||||
|
||||
// Returns true if the root is null.
|
||||
// https://arduinojson.org/v6/api/jsondocument/isnull/
|
||||
bool isNull() const {
|
||||
return getVariant().isNull();
|
||||
}
|
||||
|
||||
// Returns the number of used bytes in the memory pool.
|
||||
// https://arduinojson.org/v6/api/jsondocument/memoryusage/
|
||||
size_t memoryUsage() const {
|
||||
return _pool.size();
|
||||
}
|
||||
|
||||
// Returns trues if the memory pool was too small.
|
||||
// https://arduinojson.org/v6/api/jsondocument/overflowed/
|
||||
bool overflowed() const {
|
||||
return _pool.overflowed();
|
||||
}
|
||||
|
||||
// Returns the depth (nesting level) of the array.
|
||||
// https://arduinojson.org/v6/api/jsondocument/nesting/
|
||||
size_t nesting() const {
|
||||
return _data.nesting();
|
||||
return variantNesting(&_data);
|
||||
}
|
||||
|
||||
// Returns the capacity of the memory pool.
|
||||
// https://arduinojson.org/v6/api/jsondocument/capacity/
|
||||
size_t capacity() const {
|
||||
return _pool.capacity();
|
||||
}
|
||||
|
||||
// Returns the number of elements in the root array or object.
|
||||
// https://arduinojson.org/v6/api/jsondocument/size/
|
||||
size_t size() const {
|
||||
return _data.size();
|
||||
}
|
||||
|
||||
// Copies the specified document.
|
||||
// https://arduinojson.org/v6/api/jsondocument/set/
|
||||
bool set(const JsonDocument& src) {
|
||||
return to<VariantRef>().set(src.as<VariantConstRef>());
|
||||
return to<JsonVariant>().set(src.as<JsonVariantConst>());
|
||||
}
|
||||
|
||||
// Replaces the root with the specified value.
|
||||
// https://arduinojson.org/v6/api/jsondocument/set/
|
||||
template <typename T>
|
||||
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
|
||||
const T& src) {
|
||||
return to<VariantRef>().set(src);
|
||||
return to<JsonVariant>().set(src);
|
||||
}
|
||||
|
||||
// Clears the document and converts it to the specified type.
|
||||
// https://arduinojson.org/v6/api/jsondocument/to/
|
||||
template <typename T>
|
||||
typename VariantTo<T>::type to() {
|
||||
clear();
|
||||
return getVariant().template to<T>();
|
||||
}
|
||||
|
||||
// for internal use only
|
||||
MemoryPool& memoryPool() {
|
||||
return _pool;
|
||||
// Creates an array and appends it to the root array.
|
||||
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
|
||||
JsonArray createNestedArray() {
|
||||
return add().to<JsonArray>();
|
||||
}
|
||||
|
||||
// for internal use only
|
||||
VariantData& data() {
|
||||
return _data;
|
||||
}
|
||||
|
||||
ArrayRef createNestedArray() {
|
||||
return addElement().to<ArrayRef>();
|
||||
}
|
||||
|
||||
// createNestedArray(char*)
|
||||
// createNestedArray(const char*)
|
||||
// createNestedArray(const __FlashStringHelper*)
|
||||
// Creates an array and adds it to the root object.
|
||||
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
|
||||
template <typename TChar>
|
||||
ArrayRef createNestedArray(TChar* key) {
|
||||
return getOrAddMember(key).template to<ArrayRef>();
|
||||
JsonArray createNestedArray(TChar* key) {
|
||||
return operator[](key).template to<JsonArray>();
|
||||
}
|
||||
|
||||
// createNestedArray(const std::string&)
|
||||
// createNestedArray(const String&)
|
||||
// Creates an array and adds it to the root object.
|
||||
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
|
||||
template <typename TString>
|
||||
ArrayRef createNestedArray(const TString& key) {
|
||||
return getOrAddMember(key).template to<ArrayRef>();
|
||||
JsonArray createNestedArray(const TString& key) {
|
||||
return operator[](key).template to<JsonArray>();
|
||||
}
|
||||
|
||||
ObjectRef createNestedObject() {
|
||||
return addElement().to<ObjectRef>();
|
||||
// Creates an object and appends it to the root array.
|
||||
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
|
||||
JsonObject createNestedObject() {
|
||||
return add().to<JsonObject>();
|
||||
}
|
||||
|
||||
// createNestedObject(char*)
|
||||
// createNestedObject(const char*)
|
||||
// createNestedObject(const __FlashStringHelper*)
|
||||
// Creates an object and adds it to the root object.
|
||||
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
|
||||
template <typename TChar>
|
||||
ObjectRef createNestedObject(TChar* key) {
|
||||
return getOrAddMember(key).template to<ObjectRef>();
|
||||
JsonObject createNestedObject(TChar* key) {
|
||||
return operator[](key).template to<JsonObject>();
|
||||
}
|
||||
|
||||
// createNestedObject(const std::string&)
|
||||
// createNestedObject(const String&)
|
||||
// Creates an object and adds it to the root object.
|
||||
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
|
||||
template <typename TString>
|
||||
ObjectRef createNestedObject(const TString& key) {
|
||||
return getOrAddMember(key).template to<ObjectRef>();
|
||||
JsonObject createNestedObject(const TString& key) {
|
||||
return operator[](key).template to<JsonObject>();
|
||||
}
|
||||
|
||||
// containsKey(char*) const
|
||||
// containsKey(const char*) const
|
||||
// containsKey(const __FlashStringHelper*) const
|
||||
// Returns true if the root object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
||||
template <typename TChar>
|
||||
bool containsKey(TChar* key) const {
|
||||
return !getMember(key).isUnbound();
|
||||
return _data.getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
// containsKey(const std::string&) const
|
||||
// containsKey(const String&) const
|
||||
// Returns true if the root object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
||||
template <typename TString>
|
||||
bool containsKey(const TString& key) const {
|
||||
return !getMember(key).isUnbound();
|
||||
return _data.getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
// operator[](const std::string&)
|
||||
// operator[](const String&)
|
||||
// Gets or sets a root object's member.
|
||||
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||
MemberProxy<JsonDocument&, TString> >::type
|
||||
@@ -159,9 +176,8 @@ class JsonDocument : public Visitable,
|
||||
return MemberProxy<JsonDocument&, TString>(*this, key);
|
||||
}
|
||||
|
||||
// operator[](char*)
|
||||
// operator[](const char*)
|
||||
// operator[](const __FlashStringHelper*)
|
||||
// Gets or sets a root object's member.
|
||||
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
|
||||
MemberProxy<JsonDocument&, TChar*> >::type
|
||||
@@ -169,138 +185,87 @@ class JsonDocument : public Visitable,
|
||||
return MemberProxy<JsonDocument&, TChar*>(*this, key);
|
||||
}
|
||||
|
||||
// operator[](const std::string&) const
|
||||
// operator[](const String&) const
|
||||
// Gets a root object's member.
|
||||
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value, VariantConstRef>::type
|
||||
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
|
||||
operator[](const TString& key) const {
|
||||
return getMember(key);
|
||||
return JsonVariantConst(_data.getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// operator[](char*) const
|
||||
// operator[](const char*) const
|
||||
// operator[](const __FlashStringHelper*) const
|
||||
// Gets a root object's member.
|
||||
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
|
||||
typename enable_if<IsString<TChar*>::value, JsonVariantConst>::type
|
||||
operator[](TChar* key) const {
|
||||
return getMember(key);
|
||||
return JsonVariantConst(_data.getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// Gets or sets a root array's element.
|
||||
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
|
||||
return ElementProxy<JsonDocument&>(*this, index);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
||||
return getElement(index);
|
||||
// Gets a root array's member.
|
||||
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||
return JsonVariantConst(_data.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,
|
||||
getStringStoragePolicy(key)));
|
||||
}
|
||||
|
||||
// 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,
|
||||
getStringStoragePolicy(key)));
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef addElement() {
|
||||
return VariantRef(&_pool, _data.addElement(&_pool));
|
||||
// Appends a new (null) element to the root array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v6/api/jsondocument/add/
|
||||
FORCE_INLINE JsonVariant add() {
|
||||
return JsonVariant(&_pool, _data.addElement(&_pool));
|
||||
}
|
||||
|
||||
// Appends a value to the root array.
|
||||
// https://arduinojson.org/v6/api/jsondocument/add/
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool add(const TValue& value) {
|
||||
return addElement().set(value);
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
// add(char*) const
|
||||
// add(const char*) const
|
||||
// add(const __FlashStringHelper*) const
|
||||
// Appends a value to the root array.
|
||||
// https://arduinojson.org/v6/api/jsondocument/add/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE bool add(TChar* value) {
|
||||
return addElement().set(value);
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
// Removes an element of the root array.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsondocument/remove/
|
||||
FORCE_INLINE void remove(size_t index) {
|
||||
_data.remove(index);
|
||||
}
|
||||
// remove(char*)
|
||||
// remove(const char*)
|
||||
// remove(const __FlashStringHelper*)
|
||||
|
||||
// Removes a member of the root object.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsondocument/remove/
|
||||
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&)
|
||||
|
||||
// Removes a member of the root object.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsondocument/remove/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
|
||||
const TString& key) {
|
||||
_data.remove(adaptString(key));
|
||||
}
|
||||
|
||||
FORCE_INLINE operator VariantRef() {
|
||||
FORCE_INLINE operator JsonVariant() {
|
||||
return getVariant();
|
||||
}
|
||||
|
||||
FORCE_INLINE operator VariantConstRef() const {
|
||||
FORCE_INLINE operator JsonVariantConst() const {
|
||||
return getVariant();
|
||||
}
|
||||
|
||||
@@ -323,12 +288,12 @@ class JsonDocument : public Visitable,
|
||||
_pool = pool;
|
||||
}
|
||||
|
||||
VariantRef getVariant() {
|
||||
return VariantRef(&_pool, &_data);
|
||||
JsonVariant getVariant() {
|
||||
return JsonVariant(&_pool, &_data);
|
||||
}
|
||||
|
||||
VariantConstRef getVariant() const {
|
||||
return VariantConstRef(&_data);
|
||||
JsonVariantConst getVariant() const {
|
||||
return JsonVariantConst(&_data);
|
||||
}
|
||||
|
||||
MemoryPool _pool;
|
||||
@@ -337,10 +302,27 @@ class JsonDocument : public Visitable,
|
||||
private:
|
||||
JsonDocument(const JsonDocument&);
|
||||
JsonDocument& operator=(const JsonDocument&);
|
||||
|
||||
protected:
|
||||
MemoryPool* getPool() {
|
||||
return &_pool;
|
||||
}
|
||||
|
||||
VariantData* getData() {
|
||||
return &_data;
|
||||
}
|
||||
|
||||
const VariantData* getData() const {
|
||||
return &_data;
|
||||
}
|
||||
|
||||
VariantData* getOrCreateData() {
|
||||
return &_data;
|
||||
}
|
||||
};
|
||||
|
||||
inline void convertToJson(const JsonDocument& src, VariantRef dst) {
|
||||
dst.set(src.as<VariantConstRef>());
|
||||
inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
|
||||
dst.set(src.as<JsonVariantConst>());
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// A JsonDocument with a memory pool on the stack.
|
||||
template <size_t desiredCapacity>
|
||||
class StaticJsonDocument : public JsonDocument {
|
||||
static const size_t _capacity =
|
||||
@@ -22,14 +23,15 @@ class StaticJsonDocument : public JsonDocument {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
StaticJsonDocument(const T& src,
|
||||
typename enable_if<IsVisitable<T>::value>::type* = 0)
|
||||
StaticJsonDocument(
|
||||
const T& src,
|
||||
typename enable_if<is_convertible<T, JsonVariantConst>::value>::type* = 0)
|
||||
: JsonDocument(_buffer, _capacity) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
// disambiguate
|
||||
StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) {
|
||||
StaticJsonDocument(JsonVariant src) : JsonDocument(_buffer, _capacity) {
|
||||
set(src);
|
||||
}
|
||||
|
||||
@@ -44,6 +46,8 @@ class StaticJsonDocument : public JsonDocument {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Reclaims the memory leaked when removing and replacing values.
|
||||
// https://arduinojson.org/v6/api/jsondocument/garbagecollect/
|
||||
void garbageCollect() {
|
||||
StaticJsonDocument tmp(*this);
|
||||
set(tmp);
|
||||
|
||||
@@ -12,7 +12,7 @@ class EscapeSequence {
|
||||
public:
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char escapeChar(char c) {
|
||||
const char *p = escapeTable(true);
|
||||
const char* p = escapeTable(true);
|
||||
while (p[0] && p[1] != c) {
|
||||
p += 2;
|
||||
}
|
||||
@@ -21,7 +21,7 @@ class EscapeSequence {
|
||||
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char unescapeChar(char c) {
|
||||
const char *p = escapeTable(false);
|
||||
const char* p = escapeTable(false);
|
||||
for (;;) {
|
||||
if (p[0] == '\0')
|
||||
return 0;
|
||||
@@ -32,7 +32,7 @@ class EscapeSequence {
|
||||
}
|
||||
|
||||
private:
|
||||
static const char *escapeTable(bool excludeSolidus) {
|
||||
static const char* escapeTable(bool excludeSolidus) {
|
||||
return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -20,25 +20,26 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class JsonDeserializer {
|
||||
public:
|
||||
JsonDeserializer(MemoryPool &pool, TReader reader,
|
||||
JsonDeserializer(MemoryPool* pool, TReader reader,
|
||||
TStringStorage stringStorage)
|
||||
: _stringStorage(stringStorage),
|
||||
_foundSomething(false),
|
||||
_latch(reader),
|
||||
_pool(&pool),
|
||||
_error(DeserializationError::Ok) {}
|
||||
_pool(pool) {}
|
||||
|
||||
template <typename TFilter>
|
||||
DeserializationError parse(VariantData &variant, TFilter filter,
|
||||
DeserializationError parse(VariantData& variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
parseVariant(variant, filter, nestingLimit);
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
|
||||
err = parseVariant(variant, filter, nestingLimit);
|
||||
|
||||
if (!err && _latch.last() != 0 && !variant.isEnclosed()) {
|
||||
// We don't detect trailing characters earlier, so we need to check now
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
return _error;
|
||||
return err;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -58,10 +59,13 @@ class JsonDeserializer {
|
||||
}
|
||||
|
||||
template <typename TFilter>
|
||||
bool parseVariant(VariantData &variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
DeserializationError::Code parseVariant(VariantData& variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (current()) {
|
||||
case '[':
|
||||
@@ -81,7 +85,22 @@ class JsonDeserializer {
|
||||
if (filter.allowValue())
|
||||
return parseStringValue(variant);
|
||||
else
|
||||
return skipString();
|
||||
return skipQuotedString();
|
||||
|
||||
case 't':
|
||||
if (filter.allowValue())
|
||||
variant.setBoolean(true);
|
||||
return skipKeyword("true");
|
||||
|
||||
case 'f':
|
||||
if (filter.allowValue())
|
||||
variant.setBoolean(false);
|
||||
return skipKeyword("false");
|
||||
|
||||
case 'n':
|
||||
// the variant should already by null, except if the same object key was
|
||||
// used twice, as in {"a":1,"a":null}
|
||||
return skipKeyword("null");
|
||||
|
||||
default:
|
||||
if (filter.allowValue())
|
||||
@@ -91,9 +110,12 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
bool skipVariant(NestingLimit nestingLimit) {
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
DeserializationError::Code skipVariant(NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (current()) {
|
||||
case '[':
|
||||
@@ -104,7 +126,16 @@ class JsonDeserializer {
|
||||
|
||||
case '\"':
|
||||
case '\'':
|
||||
return skipString();
|
||||
return skipQuotedString();
|
||||
|
||||
case 't':
|
||||
return skipKeyword("true");
|
||||
|
||||
case 'f':
|
||||
return skipKeyword("false");
|
||||
|
||||
case 'n':
|
||||
return skipKeyword("null");
|
||||
|
||||
default:
|
||||
return skipNumericValue();
|
||||
@@ -112,24 +143,25 @@ class JsonDeserializer {
|
||||
}
|
||||
|
||||
template <typename TFilter>
|
||||
bool parseArray(CollectionData &array, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
if (nestingLimit.reached()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
DeserializationError::Code parseArray(CollectionData& array, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
// Skip opening braket
|
||||
ARDUINOJSON_ASSERT(current() == '[');
|
||||
move();
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Empty array?
|
||||
if (eat(']'))
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
TFilter memberFilter = filter[0UL];
|
||||
|
||||
@@ -137,39 +169,38 @@ class JsonDeserializer {
|
||||
for (;;) {
|
||||
if (memberFilter.allow()) {
|
||||
// Allocate slot in array
|
||||
VariantData *value = array.addElement(_pool);
|
||||
if (!value) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
VariantData* value = array.addElement(_pool);
|
||||
if (!value)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
// 1 - Parse value
|
||||
if (!parseVariant(*value, memberFilter, nestingLimit.decrement()))
|
||||
return false;
|
||||
err = parseVariant(*value, memberFilter, nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
if (!skipVariant(nestingLimit.decrement()))
|
||||
return false;
|
||||
err = skipVariant(nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
// 2 - Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// 3 - More values?
|
||||
if (eat(']'))
|
||||
return true;
|
||||
if (!eat(',')) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
if (!eat(','))
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
}
|
||||
|
||||
bool skipArray(NestingLimit nestingLimit) {
|
||||
if (nestingLimit.reached()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
DeserializationError::Code skipArray(NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
// Skip opening braket
|
||||
ARDUINOJSON_ASSERT(current() == '[');
|
||||
@@ -178,76 +209,75 @@ class JsonDeserializer {
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// 1 - Skip value
|
||||
if (!skipVariant(nestingLimit.decrement()))
|
||||
return false;
|
||||
err = skipVariant(nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// 2 - Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// 3 - More values?
|
||||
if (eat(']'))
|
||||
return true;
|
||||
if (!eat(',')) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
if (!eat(','))
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TFilter>
|
||||
bool parseObject(CollectionData &object, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
if (nestingLimit.reached()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
DeserializationError::Code parseObject(CollectionData& object, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
// Skip opening brace
|
||||
ARDUINOJSON_ASSERT(current() == '{');
|
||||
move();
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Empty object?
|
||||
if (eat('}'))
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// Parse key
|
||||
if (!parseKey())
|
||||
return false;
|
||||
err = parseKey();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Colon
|
||||
if (!eat(':')) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
if (!eat(':'))
|
||||
return DeserializationError::InvalidInput;
|
||||
|
||||
String key = _stringStorage.str();
|
||||
JsonString key = _stringStorage.str();
|
||||
|
||||
TFilter memberFilter = filter[key.c_str()];
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
VariantData *variant = object.getMember(adaptString(key.c_str()));
|
||||
VariantData* variant = object.getMember(adaptString(key.c_str()));
|
||||
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;
|
||||
}
|
||||
VariantSlot* slot = object.addSlot(_pool);
|
||||
if (!slot)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
slot->setKey(key);
|
||||
|
||||
@@ -255,84 +285,91 @@ class JsonDeserializer {
|
||||
}
|
||||
|
||||
// Parse value
|
||||
if (!parseVariant(*variant, memberFilter, nestingLimit.decrement()))
|
||||
return false;
|
||||
err = parseVariant(*variant, memberFilter, nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
if (!skipVariant(nestingLimit.decrement()))
|
||||
return false;
|
||||
err = skipVariant(nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// More keys/values?
|
||||
if (eat('}'))
|
||||
return true;
|
||||
if (!eat(',')) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
if (!eat(','))
|
||||
return DeserializationError::InvalidInput;
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
bool skipObject(NestingLimit nestingLimit) {
|
||||
if (nestingLimit.reached()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
DeserializationError::Code skipObject(NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
// Skip opening brace
|
||||
ARDUINOJSON_ASSERT(current() == '{');
|
||||
move();
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Empty object?
|
||||
if (eat('}'))
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// Skip key
|
||||
if (!skipVariant(nestingLimit.decrement()))
|
||||
return false;
|
||||
err = skipKey();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Colon
|
||||
if (!eat(':')) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
if (!eat(':'))
|
||||
return DeserializationError::InvalidInput;
|
||||
|
||||
// Skip value
|
||||
if (!skipVariant(nestingLimit.decrement()))
|
||||
return false;
|
||||
err = skipVariant(nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// Skip spaces
|
||||
if (!skipSpacesAndComments())
|
||||
return false;
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
// More keys/values?
|
||||
if (eat('}'))
|
||||
return true;
|
||||
if (!eat(',')) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
if (!eat(','))
|
||||
return DeserializationError::InvalidInput;
|
||||
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
bool parseKey() {
|
||||
DeserializationError::Code parseKey() {
|
||||
_stringStorage.startString();
|
||||
if (isQuote(current())) {
|
||||
return parseQuotedString();
|
||||
@@ -341,17 +378,24 @@ class JsonDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
bool parseStringValue(VariantData &variant) {
|
||||
DeserializationError::Code parseStringValue(VariantData& variant) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
_stringStorage.startString();
|
||||
if (!parseQuotedString())
|
||||
return false;
|
||||
|
||||
err = parseQuotedString();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant.setString(_stringStorage.save());
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool parseQuotedString() {
|
||||
DeserializationError::Code parseQuotedString() {
|
||||
#if ARDUINOJSON_DECODE_UNICODE
|
||||
Utf16::Codepoint codepoint;
|
||||
DeserializationError::Code err;
|
||||
#endif
|
||||
const char stopChar = current();
|
||||
|
||||
@@ -362,25 +406,22 @@ class JsonDeserializer {
|
||||
if (c == stopChar)
|
||||
break;
|
||||
|
||||
if (c == '\0') {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (c == '\0')
|
||||
return DeserializationError::IncompleteInput;
|
||||
|
||||
if (c == '\\') {
|
||||
c = current();
|
||||
|
||||
if (c == '\0') {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (c == '\0')
|
||||
return DeserializationError::IncompleteInput;
|
||||
|
||||
if (c == 'u') {
|
||||
#if ARDUINOJSON_DECODE_UNICODE
|
||||
move();
|
||||
uint16_t codeunit;
|
||||
if (!parseHex4(codeunit))
|
||||
return false;
|
||||
err = parseHex4(codeunit);
|
||||
if (err)
|
||||
return err;
|
||||
if (codepoint.append(codeunit))
|
||||
Utf8::encodeCodepoint(codepoint.value(), _stringStorage);
|
||||
#else
|
||||
@@ -391,25 +432,21 @@ class JsonDeserializer {
|
||||
|
||||
// replace char
|
||||
c = EscapeSequence::unescapeChar(c);
|
||||
if (c == '\0') {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
if (c == '\0')
|
||||
return DeserializationError::InvalidInput;
|
||||
move();
|
||||
}
|
||||
|
||||
_stringStorage.append(c);
|
||||
}
|
||||
|
||||
if (!_stringStorage.isValid()) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
if (!_stringStorage.isValid())
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool parseNonQuotedString() {
|
||||
DeserializationError::Code parseNonQuotedString() {
|
||||
char c = current();
|
||||
ARDUINOJSON_ASSERT(c);
|
||||
|
||||
@@ -420,19 +457,24 @@ class JsonDeserializer {
|
||||
c = current();
|
||||
} while (canBeInNonQuotedString(c));
|
||||
} else {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
if (!_stringStorage.isValid()) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
if (!_stringStorage.isValid())
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool skipString() {
|
||||
DeserializationError::Code skipKey() {
|
||||
if (isQuote(current())) {
|
||||
return skipQuotedString();
|
||||
} else {
|
||||
return skipNonQuotedString();
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError::Code skipQuotedString() {
|
||||
const char stopChar = current();
|
||||
|
||||
move();
|
||||
@@ -441,99 +483,83 @@ class JsonDeserializer {
|
||||
move();
|
||||
if (c == stopChar)
|
||||
break;
|
||||
if (c == '\0') {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (c == '\0')
|
||||
return DeserializationError::IncompleteInput;
|
||||
if (c == '\\') {
|
||||
if (current() != '\0')
|
||||
move();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool parseNumericValue(VariantData &result) {
|
||||
DeserializationError::Code skipNonQuotedString() {
|
||||
char c = current();
|
||||
while (canBeInNonQuotedString(c)) {
|
||||
move();
|
||||
c = current();
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError::Code parseNumericValue(VariantData& result) {
|
||||
uint8_t n = 0;
|
||||
|
||||
char c = current();
|
||||
while (canBeInNonQuotedString(c) && n < 63) {
|
||||
while (canBeInNumber(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))
|
||||
return DeserializationError::InvalidInput;
|
||||
|
||||
if (!parseNumber(_buffer, result)) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool skipNumericValue() {
|
||||
DeserializationError::Code skipNumericValue() {
|
||||
char c = current();
|
||||
while (canBeInNonQuotedString(c)) {
|
||||
while (canBeInNumber(c)) {
|
||||
move();
|
||||
c = current();
|
||||
}
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool parseHex4(uint16_t &result) {
|
||||
DeserializationError::Code parseHex4(uint16_t& result) {
|
||||
result = 0;
|
||||
for (uint8_t i = 0; i < 4; ++i) {
|
||||
char digit = current();
|
||||
if (!digit) {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (!digit)
|
||||
return DeserializationError::IncompleteInput;
|
||||
uint8_t value = decodeHex(digit);
|
||||
if (value > 0x0F) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
if (value > 0x0F)
|
||||
return DeserializationError::InvalidInput;
|
||||
result = uint16_t((result << 4) | value);
|
||||
move();
|
||||
}
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
static inline bool isBetween(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool canBeInNumber(char c) {
|
||||
return isBetween(c, '0', '9') || c == '+' || c == '-' || c == '.' ||
|
||||
#if ARDUINOJSON_ENABLE_NAN || ARDUINOJSON_ENABLE_INFINITY
|
||||
isBetween(c, 'A', 'Z') || isBetween(c, 'a', 'z');
|
||||
#else
|
||||
c == 'e' || c == 'E';
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool canBeInNonQuotedString(char c) {
|
||||
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
|
||||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
isBetween(c, 'A', 'Z');
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
@@ -547,14 +573,13 @@ class JsonDeserializer {
|
||||
return uint8_t(c - 'A' + 10);
|
||||
}
|
||||
|
||||
bool skipSpacesAndComments() {
|
||||
DeserializationError::Code skipSpacesAndComments() {
|
||||
for (;;) {
|
||||
switch (current()) {
|
||||
// end of string
|
||||
case '\0':
|
||||
_error = _foundSomething ? DeserializationError::IncompleteInput
|
||||
: DeserializationError::EmptyInput;
|
||||
return false;
|
||||
return _foundSomething ? DeserializationError::IncompleteInput
|
||||
: DeserializationError::EmptyInput;
|
||||
|
||||
// spaces
|
||||
case ' ':
|
||||
@@ -575,10 +600,8 @@ class JsonDeserializer {
|
||||
bool wasStar = false;
|
||||
for (;;) {
|
||||
char c = current();
|
||||
if (c == '\0') {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (c == '\0')
|
||||
return DeserializationError::IncompleteInput;
|
||||
if (c == '/' && wasStar) {
|
||||
move();
|
||||
break;
|
||||
@@ -595,10 +618,8 @@ class JsonDeserializer {
|
||||
for (;;) {
|
||||
move();
|
||||
char c = current();
|
||||
if (c == '\0') {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (c == '\0')
|
||||
return DeserializationError::IncompleteInput;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
@@ -606,126 +627,145 @@ class JsonDeserializer {
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
_foundSomething = true;
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError::Code skipKeyword(const char* s) {
|
||||
while (*s) {
|
||||
char c = current();
|
||||
if (c == '\0')
|
||||
return DeserializationError::IncompleteInput;
|
||||
if (*s != c)
|
||||
return DeserializationError::InvalidInput;
|
||||
++s;
|
||||
move();
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
TStringStorage _stringStorage;
|
||||
bool _foundSomething;
|
||||
Latch<TReader> _latch;
|
||||
MemoryPool *_pool;
|
||||
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
|
||||
// Parses a JSON input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TString>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, const TString &input,
|
||||
JsonDocument& doc, const TString& input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TString>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, const TString &input, Filter filter,
|
||||
JsonDocument& doc, const TString& input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TString>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, const TString &input,
|
||||
DeserializationError deserializeJson(JsonDocument& doc, const TString& input,
|
||||
NestingLimit nestingLimit, Filter filter) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeJson(JsonDocument&, std::istream&, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
// Parses a JSON input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TStream &input,
|
||||
JsonDocument& doc, TStream& input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TStream &input, Filter filter,
|
||||
JsonDocument& doc, TStream& input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, TStream &input,
|
||||
DeserializationError deserializeJson(JsonDocument& doc, TStream& input,
|
||||
NestingLimit nestingLimit, Filter filter) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeJson(JsonDocument&, char*, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
// Parses a JSON input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input,
|
||||
JsonDocument& doc, TChar* input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input, Filter filter,
|
||||
JsonDocument& doc, TChar* input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
||||
DeserializationError deserializeJson(JsonDocument& doc, TChar* input,
|
||||
NestingLimit nestingLimit, Filter filter) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeJson(JsonDocument&, char*, size_t, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
// Parses a JSON input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input, size_t inputSize,
|
||||
JsonDocument& doc, TChar* input, size_t inputSize,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
|
||||
JsonDocument& doc, TChar* input, size_t inputSize, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a JSON input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/json/deserializejson/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
||||
DeserializationError deserializeJson(JsonDocument& doc, TChar* input,
|
||||
size_t inputSize,
|
||||
NestingLimit nestingLimit, Filter filter) {
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Json/TextFormatter.hpp>
|
||||
#include <ArduinoJson/Misc/Visitable.hpp>
|
||||
#include <ArduinoJson/Serialization/measure.hpp>
|
||||
#include <ArduinoJson/Serialization/serialize.hpp>
|
||||
#include <ArduinoJson/Variant/Visitor.hpp>
|
||||
@@ -19,10 +18,10 @@ class JsonSerializer : public Visitor<size_t> {
|
||||
|
||||
JsonSerializer(TWriter writer) : _formatter(writer) {}
|
||||
|
||||
FORCE_INLINE size_t visitArray(const CollectionData &array) {
|
||||
FORCE_INLINE size_t visitArray(const CollectionData& array) {
|
||||
write('[');
|
||||
|
||||
VariantSlot *slot = array.head();
|
||||
const VariantSlot* slot = array.head();
|
||||
|
||||
while (slot != 0) {
|
||||
slot->data()->accept(*this);
|
||||
@@ -38,10 +37,10 @@ class JsonSerializer : public Visitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitObject(const CollectionData &object) {
|
||||
size_t visitObject(const CollectionData& object) {
|
||||
write('{');
|
||||
|
||||
VariantSlot *slot = object.head();
|
||||
const VariantSlot* slot = object.head();
|
||||
|
||||
while (slot != 0) {
|
||||
_formatter.writeString(slot->key());
|
||||
@@ -59,32 +58,32 @@ class JsonSerializer : public Visitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitFloat(Float value) {
|
||||
size_t visitFloat(JsonFloat value) {
|
||||
_formatter.writeFloat(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitString(const char *value) {
|
||||
size_t visitString(const char* value) {
|
||||
_formatter.writeString(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitString(const char *value, size_t n) {
|
||||
size_t visitString(const char* value, size_t n) {
|
||||
_formatter.writeString(value, n);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitRawJson(const char *data, size_t n) {
|
||||
size_t visitRawJson(const char* data, size_t n) {
|
||||
_formatter.writeRaw(data, n);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitSignedInteger(Integer value) {
|
||||
size_t visitSignedInteger(JsonInteger value) {
|
||||
_formatter.writeInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitUnsignedInteger(UInt value) {
|
||||
size_t visitUnsignedInteger(JsonUInt value) {
|
||||
_formatter.writeInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
@@ -108,7 +107,7 @@ class JsonSerializer : public Visitor<size_t> {
|
||||
_formatter.writeRaw(c);
|
||||
}
|
||||
|
||||
void write(const char *s) {
|
||||
void write(const char* s) {
|
||||
_formatter.writeRaw(s);
|
||||
}
|
||||
|
||||
@@ -116,25 +115,31 @@ class JsonSerializer : public Visitor<size_t> {
|
||||
TextFormatter<TWriter> _formatter;
|
||||
};
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJson(const TSource &source, TDestination &destination) {
|
||||
// Produces a minified JSON document.
|
||||
// https://arduinojson.org/v6/api/json/serializejson/
|
||||
template <typename TDestination>
|
||||
size_t serializeJson(JsonVariantConst source, TDestination& destination) {
|
||||
return serialize<JsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJson(const TSource &source, void *buffer, size_t bufferSize) {
|
||||
// Produces a minified JSON document.
|
||||
// https://arduinojson.org/v6/api/json/serializejson/
|
||||
inline size_t serializeJson(JsonVariantConst source, void* buffer,
|
||||
size_t bufferSize) {
|
||||
return serialize<JsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJson(const TSource &source) {
|
||||
// Computes the length of the document that serializeJson() produces.
|
||||
// https://arduinojson.org/v6/api/json/measurejson/
|
||||
inline size_t measureJson(JsonVariantConst 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) {
|
||||
inline typename enable_if<is_convertible<T, JsonVariantConst>::value,
|
||||
std::ostream&>::type
|
||||
operator<<(std::ostream& os, const T& source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
public:
|
||||
PrettyJsonSerializer(TWriter writer) : base(writer), _nesting(0) {}
|
||||
|
||||
size_t visitArray(const CollectionData &array) {
|
||||
VariantSlot *slot = array.head();
|
||||
size_t visitArray(const CollectionData& array) {
|
||||
const VariantSlot* slot = array.head();
|
||||
if (slot) {
|
||||
base::write("[\r\n");
|
||||
_nesting++;
|
||||
@@ -39,8 +39,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
return this->bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitObject(const CollectionData &object) {
|
||||
VariantSlot *slot = object.head();
|
||||
size_t visitObject(const CollectionData& object) {
|
||||
const VariantSlot* slot = object.head();
|
||||
if (slot) {
|
||||
base::write("{\r\n");
|
||||
_nesting++;
|
||||
@@ -64,25 +64,30 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
|
||||
private:
|
||||
void indent() {
|
||||
for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
|
||||
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) {
|
||||
// Produces JsonDocument to create a prettified JSON document.
|
||||
// https://arduinojson.org/v6/api/json/serializejsonpretty/
|
||||
template <typename TDestination>
|
||||
size_t serializeJsonPretty(JsonVariantConst source, TDestination& destination) {
|
||||
return serialize<PrettyJsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJsonPretty(const TSource &source, void *buffer,
|
||||
size_t bufferSize) {
|
||||
// Produces JsonDocument to create a prettified JSON document.
|
||||
// https://arduinojson.org/v6/api/json/serializejsonpretty/
|
||||
inline size_t serializeJsonPretty(JsonVariantConst source, void* buffer,
|
||||
size_t bufferSize) {
|
||||
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJsonPretty(const TSource &source) {
|
||||
// Computes the length of the document that serializeJsonPretty() produces.
|
||||
// https://arduinojson.org/v6/api/json/measurejsonpretty/
|
||||
inline size_t measureJsonPretty(JsonVariantConst source) {
|
||||
return measure<PrettyJsonSerializer>(source);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <ArduinoJson/Json/EscapeSequence.hpp>
|
||||
#include <ArduinoJson/Numbers/FloatParts.hpp>
|
||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonInteger.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
@@ -34,17 +34,19 @@ class TextFormatter {
|
||||
writeRaw("false");
|
||||
}
|
||||
|
||||
void writeString(const char *value) {
|
||||
void writeString(const char* value) {
|
||||
ARDUINOJSON_ASSERT(value != NULL);
|
||||
writeRaw('\"');
|
||||
while (*value) writeChar(*value++);
|
||||
while (*value)
|
||||
writeChar(*value++);
|
||||
writeRaw('\"');
|
||||
}
|
||||
|
||||
void writeString(const char *value, size_t n) {
|
||||
void writeString(const char* value, size_t n) {
|
||||
ARDUINOJSON_ASSERT(value != NULL);
|
||||
writeRaw('\"');
|
||||
while (n--) writeChar(*value++);
|
||||
while (n--)
|
||||
writeChar(*value++);
|
||||
writeRaw('\"');
|
||||
}
|
||||
|
||||
@@ -111,8 +113,8 @@ class TextFormatter {
|
||||
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;
|
||||
char* end = buffer + sizeof(buffer);
|
||||
char* begin = end;
|
||||
|
||||
// write the string in reverse order
|
||||
do {
|
||||
@@ -127,8 +129,8 @@ class TextFormatter {
|
||||
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;
|
||||
char* end = buffer + sizeof(buffer);
|
||||
char* begin = end;
|
||||
|
||||
// write the string in reverse order
|
||||
while (width--) {
|
||||
@@ -141,22 +143,22 @@ class TextFormatter {
|
||||
writeRaw(begin, end);
|
||||
}
|
||||
|
||||
void writeRaw(const char *s) {
|
||||
_writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
|
||||
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* 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),
|
||||
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);
|
||||
_writer.write(reinterpret_cast<const uint8_t*>(s), N - 1);
|
||||
}
|
||||
void writeRaw(char c) {
|
||||
_writer.write(static_cast<uint8_t>(c));
|
||||
@@ -166,6 +168,6 @@ class TextFormatter {
|
||||
CountingDecorator<TWriter> _writer;
|
||||
|
||||
private:
|
||||
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
|
||||
TextFormatter& operator=(const TextFormatter&); // cannot be assigned
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -13,19 +13,19 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
#if ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
|
||||
inline bool isAligned(size_t value) {
|
||||
const size_t mask = sizeof(void *) - 1;
|
||||
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;
|
||||
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 mask = sizeof(void*) - 1;
|
||||
static const size_t value = (bytes + mask) & ~mask;
|
||||
};
|
||||
|
||||
@@ -47,14 +47,14 @@ struct AddPadding {
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline bool isAligned(T *ptr) {
|
||||
inline bool isAligned(T* ptr) {
|
||||
return isAligned(reinterpret_cast<size_t>(ptr));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *addPadding(T *p) {
|
||||
inline T* addPadding(T* p) {
|
||||
size_t address = addPadding(reinterpret_cast<size_t>(p));
|
||||
return reinterpret_cast<T *>(address);
|
||||
return reinterpret_cast<T*>(address);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -14,6 +14,16 @@
|
||||
|
||||
#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
|
||||
|
||||
// Computes the size required to store an array in a JsonDocument.
|
||||
// https://arduinojson.org/v6/how-to/determine-the-capacity-of-the-jsondocument/
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
|
||||
|
||||
// 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 {
|
||||
|
||||
// _begin _end
|
||||
@@ -173,7 +183,8 @@ class MemoryPool {
|
||||
return next;
|
||||
|
||||
// jump to next terminator
|
||||
while (*next) ++next;
|
||||
while (*next)
|
||||
++next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -208,4 +219,35 @@ class MemoryPool {
|
||||
bool _overflowed;
|
||||
};
|
||||
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool storeString(MemoryPool* pool, TAdaptedString str,
|
||||
StringStoragePolicy::Copy, TCallback callback) {
|
||||
const char* copy = pool->saveString(str);
|
||||
JsonString storedString(copy, str.size(), JsonString::Copied);
|
||||
callback(storedString);
|
||||
return copy != 0;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool storeString(MemoryPool*, TAdaptedString str, StringStoragePolicy::Link,
|
||||
TCallback callback) {
|
||||
JsonString storedString(str.data(), str.size(), JsonString::Linked);
|
||||
callback(storedString);
|
||||
return !str.isNull();
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool storeString(MemoryPool* pool, TAdaptedString str,
|
||||
StringStoragePolicy::LinkOrCopy policy, TCallback callback) {
|
||||
if (policy.link)
|
||||
return storeString(pool, str, StringStoragePolicy::Link(), callback);
|
||||
else
|
||||
return storeString(pool, str, StringStoragePolicy::Copy(), callback);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool storeString(MemoryPool* pool, TAdaptedString str, TCallback callback) {
|
||||
return storeString(pool, str, str.storagePolicy(), callback);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -16,33 +16,31 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class MsgPackDeserializer {
|
||||
public:
|
||||
MsgPackDeserializer(MemoryPool &pool, TReader reader,
|
||||
MsgPackDeserializer(MemoryPool* pool, TReader reader,
|
||||
TStringStorage stringStorage)
|
||||
: _pool(&pool),
|
||||
: _pool(pool),
|
||||
_reader(reader),
|
||||
_stringStorage(stringStorage),
|
||||
_error(DeserializationError::Ok),
|
||||
_foundSomething(false) {}
|
||||
|
||||
template <typename TFilter>
|
||||
DeserializationError parse(VariantData &variant, TFilter filter,
|
||||
DeserializationError parse(VariantData& variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
parseVariant(&variant, filter, nestingLimit);
|
||||
return _foundSomething ? _error : DeserializationError::EmptyInput;
|
||||
DeserializationError::Code err;
|
||||
err = parseVariant(&variant, filter, nestingLimit);
|
||||
return _foundSomething ? err : DeserializationError::EmptyInput;
|
||||
}
|
||||
|
||||
private:
|
||||
bool invalidInput() {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TFilter>
|
||||
bool parseVariant(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code parseVariant(VariantData* variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
uint8_t code = 0; // TODO: why do we need to initialize this variable?
|
||||
if (!readByte(code))
|
||||
return false;
|
||||
err = readByte(code);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
_foundSomething = true;
|
||||
|
||||
@@ -56,20 +54,20 @@ class MsgPackDeserializer {
|
||||
switch (code) {
|
||||
case 0xc0:
|
||||
// already null
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc1:
|
||||
return invalidInput();
|
||||
return DeserializationError::InvalidInput;
|
||||
|
||||
case 0xc2:
|
||||
if (allowValue)
|
||||
variant->setBoolean(false);
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc3:
|
||||
if (allowValue)
|
||||
variant->setBoolean(true);
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
|
||||
case 0xc4: // bin 8 (not supported)
|
||||
return skipString<uint8_t>();
|
||||
@@ -221,210 +219,260 @@ class MsgPackDeserializer {
|
||||
if (allowValue)
|
||||
variant->setInteger(static_cast<int8_t>(code));
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readByte(uint8_t &value) {
|
||||
DeserializationError::Code readByte(uint8_t& value) {
|
||||
int c = _reader.read();
|
||||
if (c < 0) {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (c < 0)
|
||||
return DeserializationError::IncompleteInput;
|
||||
value = static_cast<uint8_t>(c);
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readBytes(uint8_t *p, size_t n) {
|
||||
if (_reader.readBytes(reinterpret_cast<char *>(p), n) == n)
|
||||
return true;
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
DeserializationError::Code readBytes(uint8_t* p, size_t n) {
|
||||
if (_reader.readBytes(reinterpret_cast<char*>(p), n) == n)
|
||||
return DeserializationError::Ok;
|
||||
return DeserializationError::IncompleteInput;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readBytes(T &value) {
|
||||
return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
|
||||
DeserializationError::Code readBytes(T& value) {
|
||||
return readBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
||||
}
|
||||
|
||||
bool skipBytes(size_t n) {
|
||||
DeserializationError::Code skipBytes(size_t n) {
|
||||
for (; n; --n) {
|
||||
if (_reader.read() < 0) {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
return false;
|
||||
}
|
||||
if (_reader.read() < 0)
|
||||
return DeserializationError::IncompleteInput;
|
||||
}
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readInteger(T &value) {
|
||||
if (!readBytes(value))
|
||||
return false;
|
||||
DeserializationError::Code readInteger(T& value) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
err = readBytes(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fixEndianess(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readInteger(VariantData *variant) {
|
||||
DeserializationError::Code readInteger(VariantData* variant) {
|
||||
DeserializationError::Code err;
|
||||
T value;
|
||||
if (!readInteger(value))
|
||||
return false;
|
||||
|
||||
err = readInteger(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant->setInteger(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4, bool>::type readFloat(
|
||||
VariantData *variant) {
|
||||
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
|
||||
readFloat(VariantData* variant) {
|
||||
DeserializationError::Code err;
|
||||
T value;
|
||||
if (!readBytes(value))
|
||||
return false;
|
||||
|
||||
err = readBytes(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fixEndianess(value);
|
||||
variant->setFloat(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 8, bool>::type readDouble(
|
||||
VariantData *variant) {
|
||||
typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type
|
||||
readDouble(VariantData* variant) {
|
||||
DeserializationError::Code err;
|
||||
T value;
|
||||
if (!readBytes(value))
|
||||
return false;
|
||||
|
||||
err = readBytes(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fixEndianess(value);
|
||||
variant->setFloat(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4, bool>::type readDouble(
|
||||
VariantData *variant) {
|
||||
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
|
||||
readDouble(VariantData* variant) {
|
||||
DeserializationError::Code err;
|
||||
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;
|
||||
uint8_t* o = reinterpret_cast<uint8_t*>(&value);
|
||||
|
||||
err = readBytes(i, 8);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
doubleToFloat(i, o);
|
||||
fixEndianess(value);
|
||||
variant->setFloat(value);
|
||||
return true;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readString(VariantData *variant) {
|
||||
DeserializationError::Code readString(VariantData* variant) {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return readString(variant, size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readString() {
|
||||
DeserializationError::Code readString() {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return readString(size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool skipString() {
|
||||
DeserializationError::Code skipString() {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return skipBytes(size);
|
||||
}
|
||||
|
||||
bool readString(VariantData *variant, size_t n) {
|
||||
if (!readString(n))
|
||||
return false;
|
||||
DeserializationError::Code readString(VariantData* variant, size_t n) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
err = readString(n);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant->setString(_stringStorage.save());
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readString(size_t n) {
|
||||
DeserializationError::Code readString(size_t n) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
_stringStorage.startString();
|
||||
for (; n; --n) {
|
||||
uint8_t c;
|
||||
if (!readBytes(c))
|
||||
return false;
|
||||
|
||||
err = readBytes(c);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
_stringStorage.append(static_cast<char>(c));
|
||||
}
|
||||
if (!_stringStorage.isValid()) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!_stringStorage.isValid())
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize, typename TFilter>
|
||||
bool readArray(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code readArray(VariantData* variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
TSize size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
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;
|
||||
}
|
||||
DeserializationError::Code readArray(VariantData* variant, size_t n,
|
||||
TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
bool allowArray = filter.allowArray();
|
||||
|
||||
CollectionData *array = allowArray ? &variant->toArray() : 0;
|
||||
CollectionData* array = allowArray ? &variant->toArray() : 0;
|
||||
|
||||
TFilter memberFilter = filter[0U];
|
||||
|
||||
for (; n; --n) {
|
||||
VariantData *value;
|
||||
VariantData* value;
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
value = array->addElement(_pool);
|
||||
if (!value) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
if (!value)
|
||||
return DeserializationError::NoMemory;
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
if (!parseVariant(value, memberFilter, nestingLimit.decrement()))
|
||||
return false;
|
||||
err = parseVariant(value, memberFilter, nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename TSize, typename TFilter>
|
||||
bool readObject(VariantData *variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code readObject(VariantData* variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
TSize size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
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;
|
||||
}
|
||||
DeserializationError::Code readObject(VariantData* variant, size_t n,
|
||||
TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
CollectionData *object = filter.allowObject() ? &variant->toObject() : 0;
|
||||
if (nestingLimit.reached())
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
CollectionData* object = filter.allowObject() ? &variant->toObject() : 0;
|
||||
|
||||
for (; n; --n) {
|
||||
if (!readKey())
|
||||
return false;
|
||||
err = readKey();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
String key = _stringStorage.str();
|
||||
JsonString key = _stringStorage.str();
|
||||
TFilter memberFilter = filter[key.c_str()];
|
||||
VariantData *member;
|
||||
VariantData* member;
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
ARDUINOJSON_ASSERT(object);
|
||||
@@ -433,11 +481,9 @@ class MsgPackDeserializer {
|
||||
// This MUST be done before adding the slot.
|
||||
key = _stringStorage.save();
|
||||
|
||||
VariantSlot *slot = object->addSlot(_pool);
|
||||
if (!slot) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
}
|
||||
VariantSlot* slot = object->addSlot(_pool);
|
||||
if (!slot)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
slot->setKey(key);
|
||||
|
||||
@@ -446,17 +492,21 @@ class MsgPackDeserializer {
|
||||
member = 0;
|
||||
}
|
||||
|
||||
if (!parseVariant(member, memberFilter, nestingLimit.decrement()))
|
||||
return false;
|
||||
err = parseVariant(member, memberFilter, nestingLimit.decrement());
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return true;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
bool readKey() {
|
||||
DeserializationError::Code readKey() {
|
||||
DeserializationError::Code err;
|
||||
uint8_t code;
|
||||
if (!readByte(code))
|
||||
return false;
|
||||
|
||||
err = readByte(code);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if ((code & 0xe0) == 0xa0)
|
||||
return readString(code & 0x1f);
|
||||
@@ -472,125 +522,136 @@ class MsgPackDeserializer {
|
||||
return readString<uint32_t>();
|
||||
|
||||
default:
|
||||
return invalidInput();
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool skipExt() {
|
||||
DeserializationError::Code skipExt() {
|
||||
DeserializationError::Code err;
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
|
||||
err = readInteger(size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return skipBytes(size + 1U);
|
||||
}
|
||||
|
||||
MemoryPool *_pool;
|
||||
MemoryPool* _pool;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
DeserializationError _error;
|
||||
bool _foundSomething;
|
||||
};
|
||||
|
||||
//
|
||||
// deserializeMsgPack(JsonDocument&, const std::string&, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TString>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, const TString &input,
|
||||
JsonDocument& doc, const TString& input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TString>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, const TString &input, Filter filter,
|
||||
JsonDocument& doc, const TString& input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TString>
|
||||
DeserializationError deserializeMsgPack(JsonDocument &doc, const TString &input,
|
||||
DeserializationError deserializeMsgPack(JsonDocument& doc, const TString& input,
|
||||
NestingLimit nestingLimit,
|
||||
Filter filter) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeMsgPack(JsonDocument&, std::istream&, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, TStream &input,
|
||||
JsonDocument& doc, TStream& input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, TStream &input, Filter filter,
|
||||
JsonDocument& doc, TStream& input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeMsgPack(JsonDocument &doc, TStream &input,
|
||||
DeserializationError deserializeMsgPack(JsonDocument& doc, TStream& input,
|
||||
NestingLimit nestingLimit,
|
||||
Filter filter) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeMsgPack(JsonDocument&, char*, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, TChar *input,
|
||||
JsonDocument& doc, TChar* input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, TChar *input, Filter filter,
|
||||
JsonDocument& doc, TChar* input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
|
||||
DeserializationError deserializeMsgPack(JsonDocument& doc, TChar* input,
|
||||
NestingLimit nestingLimit,
|
||||
Filter filter) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeMsgPack(JsonDocument&, char*, size_t, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, TChar *input, size_t inputSize,
|
||||
JsonDocument& doc, TChar* input, size_t inputSize,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
|
||||
JsonDocument& doc, TChar* input, size_t inputSize, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
|
||||
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
|
||||
DeserializationError deserializeMsgPack(JsonDocument& doc, TChar* input,
|
||||
size_t inputSize,
|
||||
NestingLimit nestingLimit,
|
||||
Filter filter) {
|
||||
|
||||
@@ -23,8 +23,8 @@ class MsgPackSerializer : public Visitor<size_t> {
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
|
||||
if (canConvertNumber<Integer>(value32)) {
|
||||
Integer truncatedValue = Integer(value32);
|
||||
if (canConvertNumber<JsonInteger>(value32)) {
|
||||
JsonInteger truncatedValue = JsonInteger(value32);
|
||||
if (value32 == T(truncatedValue))
|
||||
return visitSignedInteger(truncatedValue);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ class MsgPackSerializer : public Visitor<size_t> {
|
||||
writeByte(0xDD);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
|
||||
for (const VariantSlot* slot = array.head(); slot; slot = slot->next()) {
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
return bytesWritten();
|
||||
@@ -72,7 +72,7 @@ class MsgPackSerializer : public Visitor<size_t> {
|
||||
writeByte(0xDF);
|
||||
writeInteger(uint32_t(n));
|
||||
}
|
||||
for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
|
||||
for (const VariantSlot* slot = object.head(); slot; slot = slot->next()) {
|
||||
visitString(slot->key());
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
@@ -107,9 +107,9 @@ class MsgPackSerializer : public Visitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitSignedInteger(Integer value) {
|
||||
size_t visitSignedInteger(JsonInteger value) {
|
||||
if (value > 0) {
|
||||
visitUnsignedInteger(static_cast<UInt>(value));
|
||||
visitUnsignedInteger(static_cast<JsonUInt>(value));
|
||||
} else if (value >= -0x20) {
|
||||
writeInteger(int8_t(value));
|
||||
} else if (value >= -0x80) {
|
||||
@@ -137,7 +137,7 @@ class MsgPackSerializer : public Visitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitUnsignedInteger(UInt value) {
|
||||
size_t visitUnsignedInteger(JsonUInt value) {
|
||||
if (value <= 0x7F) {
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFF) {
|
||||
@@ -197,19 +197,23 @@ class MsgPackSerializer : public Visitor<size_t> {
|
||||
CountingDecorator<TWriter> _writer;
|
||||
};
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
|
||||
// Produces a MessagePack document.
|
||||
// https://arduinojson.org/v6/api/msgpack/serializemsgpack/
|
||||
template <typename TDestination>
|
||||
inline size_t serializeMsgPack(JsonVariantConst source, TDestination& output) {
|
||||
return serialize<MsgPackSerializer>(source, output);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
inline size_t serializeMsgPack(const TSource& source, void* output,
|
||||
// Produces a MessagePack document.
|
||||
// https://arduinojson.org/v6/api/msgpack/serializemsgpack/
|
||||
inline size_t serializeMsgPack(JsonVariantConst source, void* output,
|
||||
size_t size) {
|
||||
return serialize<MsgPackSerializer>(source, output, size);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
inline size_t measureMsgPack(const TSource& source) {
|
||||
// Computes the length of the document that serializeMsgPack() produces.
|
||||
// https://arduinojson.org/v6/api/msgpack/measuremsgpack/
|
||||
inline size_t measureMsgPack(JsonVariantConst source) {
|
||||
return measure<MsgPackSerializer>(source);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,38 +9,38 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
#if ARDUINOJSON_LITTLE_ENDIAN
|
||||
inline void swapBytes(uint8_t &a, uint8_t &b) {
|
||||
inline void swapBytes(uint8_t& a, uint8_t& b) {
|
||||
uint8_t t(a);
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 8>) {
|
||||
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 8>) {
|
||||
swapBytes(p[0], p[7]);
|
||||
swapBytes(p[1], p[6]);
|
||||
swapBytes(p[2], p[5]);
|
||||
swapBytes(p[3], p[4]);
|
||||
}
|
||||
|
||||
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 4>) {
|
||||
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 4>) {
|
||||
swapBytes(p[0], p[3]);
|
||||
swapBytes(p[1], p[2]);
|
||||
}
|
||||
|
||||
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 2>) {
|
||||
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 2>) {
|
||||
swapBytes(p[0], p[1]);
|
||||
}
|
||||
|
||||
inline void fixEndianess(uint8_t *, integral_constant<size_t, 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),
|
||||
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 &) {}
|
||||
inline void fixEndianess(T&) {}
|
||||
#endif
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <ArduinoJson/Polyfills/math.hpp>
|
||||
#include <ArduinoJson/Polyfills/preprocessor.hpp>
|
||||
#include <ArduinoJson/Polyfills/static_array.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@@ -116,6 +117,22 @@ struct FloatTraits<T, 8 /*64bits*/> {
|
||||
return forge(0x7FEFFFFF, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
template <typename TOut> // int64_t
|
||||
static T highest_for(
|
||||
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
|
||||
sizeof(TOut) == 8,
|
||||
signed>::type* = 0) {
|
||||
return forge(0x43DFFFFF, 0xFFFFFFFF); // 9.2233720368547748e+18
|
||||
}
|
||||
|
||||
template <typename TOut> // uint64_t
|
||||
static T highest_for(
|
||||
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
|
||||
sizeof(TOut) == 8,
|
||||
unsigned>::type* = 0) {
|
||||
return forge(0x43EFFFFF, 0xFFFFFFFF); // 1.8446744073709549568e+19
|
||||
}
|
||||
|
||||
static T lowest() {
|
||||
return forge(0xFFEFFFFF, 0xFFFFFFFF);
|
||||
}
|
||||
@@ -212,6 +229,38 @@ struct FloatTraits<T, 4 /*32bits*/> {
|
||||
return forge(0x7f7fffff);
|
||||
}
|
||||
|
||||
template <typename TOut> // int32_t
|
||||
static T highest_for(
|
||||
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
|
||||
sizeof(TOut) == 4,
|
||||
signed>::type* = 0) {
|
||||
return forge(0x4EFFFFFF); // 2.14748352E9
|
||||
}
|
||||
|
||||
template <typename TOut> // uint32_t
|
||||
static T highest_for(
|
||||
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
|
||||
sizeof(TOut) == 4,
|
||||
unsigned>::type* = 0) {
|
||||
return forge(0x4F7FFFFF); // 4.29496704E9
|
||||
}
|
||||
|
||||
template <typename TOut> // int64_t
|
||||
static T highest_for(
|
||||
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
|
||||
sizeof(TOut) == 8,
|
||||
signed>::type* = 0) {
|
||||
return forge(0x5EFFFFFF); // 9.22337148709896192E18
|
||||
}
|
||||
|
||||
template <typename TOut> // uint64_t
|
||||
static T highest_for(
|
||||
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
|
||||
sizeof(TOut) == 8,
|
||||
unsigned>::type* = 0) {
|
||||
return forge(0x5F7FFFFF); // 1.844674297419792384E19
|
||||
}
|
||||
|
||||
static T lowest() {
|
||||
return forge(0xFf7fffff);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
typedef double Float;
|
||||
typedef double JsonFloat;
|
||||
#else
|
||||
typedef float Float;
|
||||
typedef float JsonFloat;
|
||||
#endif
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -12,18 +12,18 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
typedef int64_t Integer;
|
||||
typedef uint64_t UInt;
|
||||
typedef int64_t JsonInteger;
|
||||
typedef uint64_t JsonUInt;
|
||||
#else
|
||||
typedef long Integer;
|
||||
typedef unsigned long UInt;
|
||||
typedef long JsonInteger;
|
||||
typedef unsigned long JsonUInt;
|
||||
#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), \
|
||||
static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::JsonInteger), \
|
||||
"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/");
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonInteger.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
@@ -20,7 +20,7 @@ enum CompareResult {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
|
||||
CompareResult arithmeticCompare(const T& lhs, const T& rhs) {
|
||||
if (lhs < rhs)
|
||||
return COMPARE_RESULT_LESS;
|
||||
else if (lhs > rhs)
|
||||
@@ -31,38 +31,38 @@ CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CompareResult arithmeticCompare(
|
||||
const T1 &lhs, const T2 &rhs,
|
||||
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) {
|
||||
>::type* = 0) {
|
||||
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CompareResult arithmeticCompare(
|
||||
const T1 &lhs, const T2 &rhs,
|
||||
const T1& lhs, const T2& rhs,
|
||||
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
|
||||
sizeof(T2) < sizeof(T1)>::type * = 0) {
|
||||
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,
|
||||
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) {
|
||||
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,
|
||||
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) {
|
||||
sizeof(T2) == sizeof(T1)>::type* = 0) {
|
||||
if (rhs < 0)
|
||||
return COMPARE_RESULT_GREATER;
|
||||
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
|
||||
@@ -70,10 +70,10 @@ CompareResult arithmeticCompare(
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CompareResult arithmeticCompare(
|
||||
const T1 &lhs, const T2 &rhs,
|
||||
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) {
|
||||
sizeof(T2) == sizeof(T1)>::type* = 0) {
|
||||
if (lhs < 0)
|
||||
return COMPARE_RESULT_LESS;
|
||||
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
|
||||
@@ -81,23 +81,24 @@ CompareResult arithmeticCompare(
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CompareResult arithmeticCompare(
|
||||
const T1 &lhs, const T2 &rhs,
|
||||
const T1& lhs, const T2& rhs,
|
||||
typename enable_if<is_floating_point<T1>::value ||
|
||||
is_floating_point<T2>::value>::type * = 0) {
|
||||
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) {
|
||||
JsonUInt, 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) {
|
||||
JsonUInt 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));
|
||||
@@ -105,14 +106,15 @@ CompareResult arithmeticCompareNegateLeft(
|
||||
|
||||
template <typename T1>
|
||||
CompareResult arithmeticCompareNegateRight(
|
||||
const T1 &, UInt, typename enable_if<is_unsigned<T1>::value>::type * = 0) {
|
||||
const T1&, JsonUInt,
|
||||
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) {
|
||||
const T1& lhs, JsonUInt rhs,
|
||||
typename enable_if<is_signed<T1>::value>::type* = 0) {
|
||||
if (lhs > 0)
|
||||
return COMPARE_RESULT_GREATER;
|
||||
return arithmeticCompare(static_cast<T1>(rhs), -lhs);
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
# pragma GCC diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
|
||||
#include <ArduinoJson/Numbers/Float.hpp>
|
||||
#include <ArduinoJson/Numbers/FloatTraits.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonFloat.hpp>
|
||||
#include <ArduinoJson/Polyfills/limits.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
|
||||
@@ -95,17 +96,34 @@ canConvertNumber(TIn value) {
|
||||
return value <= TIn(numeric_limits<TOut>::highest());
|
||||
}
|
||||
|
||||
// float -> int32
|
||||
// float -> int64
|
||||
// float32 -> int16
|
||||
// float64 -> int32
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_floating_point<TIn>::value &&
|
||||
!is_floating_point<TOut>::value,
|
||||
typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
|
||||
sizeof(TOut) < sizeof(TIn),
|
||||
bool>::type
|
||||
canConvertNumber(TIn value) {
|
||||
return value >= numeric_limits<TOut>::lowest() &&
|
||||
value <= numeric_limits<TOut>::highest();
|
||||
}
|
||||
|
||||
// float32 -> int32
|
||||
// float32 -> uint32
|
||||
// float32 -> int64
|
||||
// float32 -> uint64
|
||||
// float64 -> int64
|
||||
// float64 -> uint64
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
|
||||
sizeof(TOut) >= sizeof(TIn),
|
||||
bool>::type
|
||||
canConvertNumber(TIn value) {
|
||||
// Avoid error "9.22337e+18 is outside the range of representable values of
|
||||
// type 'long'"
|
||||
return value >= numeric_limits<TOut>::lowest() &&
|
||||
value <= FloatTraits<TIn>::template highest_for<TOut>();
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
TOut convertNumber(TIn value) {
|
||||
return canConvertNumber<TOut>(value) ? TOut(value) : 0;
|
||||
|
||||
@@ -19,8 +19,8 @@ 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 FloatTraits<JsonFloat> traits;
|
||||
typedef choose_largest<traits::mantissa_type, JsonUInt>::type mantissa_t;
|
||||
typedef traits::exponent_type exponent_t;
|
||||
|
||||
ARDUINOJSON_ASSERT(s != 0);
|
||||
@@ -55,7 +55,7 @@ inline bool parseNumber(const char* s, VariantData& result) {
|
||||
|
||||
mantissa_t mantissa = 0;
|
||||
exponent_t exponent_offset = 0;
|
||||
const mantissa_t maxUint = UInt(-1);
|
||||
const mantissa_t maxUint = JsonUInt(-1);
|
||||
|
||||
while (isdigit(*s)) {
|
||||
uint8_t digit = uint8_t(*s - '0');
|
||||
@@ -71,13 +71,13 @@ inline bool parseNumber(const char* s, VariantData& result) {
|
||||
if (*s == '\0') {
|
||||
if (is_negative) {
|
||||
const mantissa_t sintMantissaMax = mantissa_t(1)
|
||||
<< (sizeof(Integer) * 8 - 1);
|
||||
<< (sizeof(JsonInteger) * 8 - 1);
|
||||
if (mantissa <= sintMantissaMax) {
|
||||
result.setInteger(Integer(~mantissa + 1));
|
||||
result.setInteger(JsonInteger(~mantissa + 1));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
result.setInteger(UInt(mantissa));
|
||||
result.setInteger(JsonUInt(mantissa));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -136,8 +136,8 @@ inline bool parseNumber(const char* s, VariantData& result) {
|
||||
if (*s != '\0')
|
||||
return false;
|
||||
|
||||
Float final_result =
|
||||
traits::make_float(static_cast<Float>(mantissa), exponent);
|
||||
JsonFloat final_result =
|
||||
traits::make_float(static_cast<JsonFloat>(mantissa), exponent);
|
||||
|
||||
result.setFloat(is_negative ? -final_result : final_result);
|
||||
return true;
|
||||
@@ -148,6 +148,6 @@ 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));
|
||||
return Converter<T>::fromJson(JsonVariantConst(&value));
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
246
lib/ArduinoJson/src/ArduinoJson/Object/JsonObject.hpp
Normal file
246
lib/ArduinoJson/src/ArduinoJson/Object/JsonObject.hpp
Normal file
@@ -0,0 +1,246 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Object/JsonObjectConst.hpp>
|
||||
#include <ArduinoJson/Object/MemberProxy.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonArray;
|
||||
|
||||
// A reference to an object in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/jsonobject/
|
||||
class JsonObject : public VariantOperators<JsonObject> {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
typedef JsonObjectIterator iterator;
|
||||
|
||||
// Creates an unbound reference.
|
||||
FORCE_INLINE JsonObject() : _data(0), _pool(0) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
FORCE_INLINE JsonObject(MemoryPool* buf, CollectionData* data)
|
||||
: _data(data), _pool(buf) {}
|
||||
|
||||
operator JsonVariant() const {
|
||||
void* data = _data; // prevent warning cast-align
|
||||
return JsonVariant(_pool, reinterpret_cast<VariantData*>(data));
|
||||
}
|
||||
|
||||
operator JsonObjectConst() const {
|
||||
return JsonObjectConst(_data);
|
||||
}
|
||||
|
||||
operator JsonVariantConst() const {
|
||||
return JsonVariantConst(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns true if the reference is unbound.
|
||||
// https://arduinojson.org/v6/api/jsonobject/isnull/
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
// Returns true if the reference is bound.
|
||||
// https://arduinojson.org/v6/api/jsonobject/isnull/
|
||||
FORCE_INLINE operator bool() const {
|
||||
return _data != 0;
|
||||
}
|
||||
|
||||
// Returns the number of bytes occupied by the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/memoryusage/
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
return _data ? _data->memoryUsage() : 0;
|
||||
}
|
||||
|
||||
// Returns the depth (nesting level) of the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/nesting/
|
||||
FORCE_INLINE size_t nesting() const {
|
||||
return variantNesting(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns the number of members in the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/size/
|
||||
FORCE_INLINE size_t size() const {
|
||||
return _data ? _data->size() : 0;
|
||||
}
|
||||
|
||||
// Returns an iterator to the first key-value pair of the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/begin/
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data)
|
||||
return iterator();
|
||||
return iterator(_pool, _data->head());
|
||||
}
|
||||
|
||||
// Returns an iterator following the last key-value pair of the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/end/
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Removes all the members of the object.
|
||||
// ⚠️ Doesn't release the memory associated with the removed members.
|
||||
// https://arduinojson.org/v6/api/jsonobject/clear/
|
||||
void clear() const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->clear();
|
||||
}
|
||||
|
||||
// Copies an object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/set/
|
||||
FORCE_INLINE bool set(JsonObjectConst src) {
|
||||
if (!_data || !src._data)
|
||||
return false;
|
||||
return _data->copyFrom(*src._data, _pool);
|
||||
}
|
||||
|
||||
// Compares the content of two objects.
|
||||
FORCE_INLINE bool operator==(JsonObject rhs) const {
|
||||
return JsonObjectConst(_data) == JsonObjectConst(rhs._data);
|
||||
}
|
||||
|
||||
// Gets or sets the member with specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobject/subscript/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||
MemberProxy<JsonObject, TString> >::type
|
||||
operator[](const TString& key) const {
|
||||
return MemberProxy<JsonObject, TString>(*this, key);
|
||||
}
|
||||
|
||||
// Gets or sets the member with specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobject/subscript/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
|
||||
MemberProxy<JsonObject, TChar*> >::type
|
||||
operator[](TChar* key) const {
|
||||
return MemberProxy<JsonObject, TChar*>(*this, key);
|
||||
}
|
||||
|
||||
// Removes the member at the specified iterator.
|
||||
// ⚠️ Doesn't release the memory associated with the removed member.
|
||||
// https://arduinojson.org/v6/api/jsonobject/remove/
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->removeSlot(it._slot);
|
||||
}
|
||||
|
||||
// Removes the member with the specified key.
|
||||
// ⚠️ Doesn't release the memory associated with the removed member.
|
||||
// https://arduinojson.org/v6/api/jsonobject/remove/
|
||||
template <typename TString>
|
||||
FORCE_INLINE void remove(const TString& key) const {
|
||||
removeMember(adaptString(key));
|
||||
}
|
||||
|
||||
// Removes the member with the specified key.
|
||||
// ⚠️ Doesn't release the memory associated with the removed member.
|
||||
// https://arduinojson.org/v6/api/jsonobject/remove/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE void remove(TChar* key) const {
|
||||
removeMember(adaptString(key));
|
||||
}
|
||||
|
||||
// Returns true if the object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobject/containskey/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
|
||||
containsKey(const TString& key) const {
|
||||
return getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
// Returns true if the object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobject/containskey/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value, bool>::type
|
||||
containsKey(TChar* key) const {
|
||||
return getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
// Creates an array and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/createnestedarray/
|
||||
template <typename TString>
|
||||
FORCE_INLINE JsonArray createNestedArray(const TString& key) const;
|
||||
|
||||
// Creates an array and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/createnestedarray/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE JsonArray createNestedArray(TChar* key) const;
|
||||
|
||||
// Creates an object and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/createnestedobject/
|
||||
template <typename TString>
|
||||
JsonObject createNestedObject(const TString& key) const {
|
||||
return operator[](key).template to<JsonObject>();
|
||||
}
|
||||
|
||||
// Creates an object and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/createnestedobject/
|
||||
template <typename TChar>
|
||||
JsonObject createNestedObject(TChar* key) const {
|
||||
return operator[](key).template to<JsonObject>();
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* getPool() const {
|
||||
return _pool;
|
||||
}
|
||||
|
||||
VariantData* getData() const {
|
||||
return collectionToVariant(_data);
|
||||
}
|
||||
|
||||
VariantData* getOrCreateData() const {
|
||||
return collectionToVariant(_data);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* getMember(TAdaptedString key) const {
|
||||
if (!_data)
|
||||
return 0;
|
||||
return _data->getMember(key);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void removeMember(TAdaptedString key) const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->removeMember(key);
|
||||
}
|
||||
|
||||
CollectionData* _data;
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<JsonObject> : private VariantAttorney {
|
||||
static void toJson(JsonVariantConst src, JsonVariant dst) {
|
||||
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||
}
|
||||
|
||||
static JsonObject fromJson(JsonVariant src) {
|
||||
VariantData* data = getData(src);
|
||||
MemoryPool* pool = getPool(src);
|
||||
return JsonObject(pool, data != 0 ? data->asObject() : 0);
|
||||
}
|
||||
|
||||
static InvalidConversion<JsonVariantConst, JsonObject> fromJson(
|
||||
JsonVariantConst);
|
||||
|
||||
static bool checkJson(JsonVariantConst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariant src) {
|
||||
VariantData* data = getData(src);
|
||||
return data && data->isObject();
|
||||
}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
156
lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectConst.hpp
Normal file
156
lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectConst.hpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Object/JsonObjectIterator.hpp>
|
||||
#include <ArduinoJson/Variant/VariantOperators.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// A read-only reference to an object in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/
|
||||
class JsonObjectConst : public VariantOperators<JsonObjectConst> {
|
||||
friend class JsonObject;
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
typedef JsonObjectConstIterator iterator;
|
||||
|
||||
// Creates an unbound reference.
|
||||
JsonObjectConst() : _data(0) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonObjectConst(const CollectionData* data) : _data(data) {}
|
||||
|
||||
operator JsonVariantConst() const {
|
||||
return JsonVariantConst(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns true if the reference is unbound.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return _data == 0;
|
||||
}
|
||||
|
||||
// Returns true if the reference is bound.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
|
||||
FORCE_INLINE operator bool() const {
|
||||
return _data != 0;
|
||||
}
|
||||
|
||||
// Returns the number of bytes occupied by the object.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/memoryusage/
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
return _data ? _data->memoryUsage() : 0;
|
||||
}
|
||||
|
||||
// Returns the depth (nesting level) of the object.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/nesting/
|
||||
FORCE_INLINE size_t nesting() const {
|
||||
return variantNesting(collectionToVariant(_data));
|
||||
}
|
||||
|
||||
// Returns the number of members in the object.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/size/
|
||||
FORCE_INLINE size_t size() const {
|
||||
return _data ? _data->size() : 0;
|
||||
}
|
||||
|
||||
// Returns an iterator to the first key-value pair of the object.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/begin/
|
||||
FORCE_INLINE iterator begin() const {
|
||||
if (!_data)
|
||||
return iterator();
|
||||
return iterator(_data->head());
|
||||
}
|
||||
|
||||
// Returns an iterator following the last key-value pair of the object.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/end/
|
||||
FORCE_INLINE iterator end() const {
|
||||
return iterator();
|
||||
}
|
||||
|
||||
// Returns true if the object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/containskey/
|
||||
template <typename TString>
|
||||
FORCE_INLINE bool containsKey(const TString& key) const {
|
||||
return getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
// Returns true if the object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/containskey/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE bool containsKey(TChar* key) const {
|
||||
return getMember(adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
// Gets the member with specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/subscript/
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
|
||||
operator[](const TString& key) const {
|
||||
return JsonVariantConst(getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// Gets the member with specified key.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/subscript/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TChar*>::value, JsonVariantConst>::type
|
||||
operator[](TChar* key) const {
|
||||
return JsonVariantConst(getMember(adaptString(key)));
|
||||
}
|
||||
|
||||
// Compares objects.
|
||||
FORCE_INLINE bool operator==(JsonObjectConst rhs) const {
|
||||
if (_data == rhs._data)
|
||||
return true;
|
||||
|
||||
if (!_data || !rhs._data)
|
||||
return false;
|
||||
|
||||
size_t count = 0;
|
||||
for (iterator it = begin(); it != end(); ++it) {
|
||||
if (it->value() != rhs[it->key()])
|
||||
return false;
|
||||
count++;
|
||||
}
|
||||
return count == rhs.size();
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantData* getData() const {
|
||||
return collectionToVariant(_data);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
const VariantData* getMember(TAdaptedString key) const {
|
||||
if (!_data)
|
||||
return 0;
|
||||
return _data->getMember(key);
|
||||
}
|
||||
|
||||
const CollectionData* _data;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<JsonObjectConst> : private VariantAttorney {
|
||||
static void toJson(JsonVariantConst src, JsonVariant dst) {
|
||||
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||
}
|
||||
|
||||
static JsonObjectConst fromJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data != 0 ? data->asObject() : 0;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data && data->isObject();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
81
lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectImpl.hpp
Normal file
81
lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectImpl.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/JsonArray.hpp>
|
||||
#include <ArduinoJson/Object/JsonObject.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TString>
|
||||
inline JsonArray JsonObject::createNestedArray(const TString& key) const {
|
||||
return operator[](key).template to<JsonArray>();
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline JsonArray JsonObject::createNestedArray(TChar* key) const {
|
||||
return operator[](key).template to<JsonArray>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline JsonArray VariantRefBase<TDerived>::createNestedArray(
|
||||
const TString& key) const {
|
||||
return operator[](key).template to<JsonArray>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TChar>
|
||||
inline JsonArray VariantRefBase<TDerived>::createNestedArray(TChar* key) const {
|
||||
return operator[](key).template to<JsonArray>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline JsonObject VariantRefBase<TDerived>::createNestedObject(
|
||||
const TString& key) const {
|
||||
return operator[](key).template to<JsonObject>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TChar>
|
||||
inline JsonObject VariantRefBase<TDerived>::createNestedObject(
|
||||
TChar* key) const {
|
||||
return operator[](key).template to<JsonObject>();
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value, bool>::type
|
||||
VariantRefBase<TDerived>::containsKey(const TString& key) const {
|
||||
return variantGetMember(VariantAttorney::getData(derived()),
|
||||
adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TChar>
|
||||
inline typename enable_if<IsString<TChar*>::value, bool>::type
|
||||
VariantRefBase<TDerived>::containsKey(TChar* key) const {
|
||||
return variantGetMember(VariantAttorney::getData(derived()),
|
||||
adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString*>::value,
|
||||
MemberProxy<TDerived, TString*> >::type
|
||||
VariantRefBase<TDerived>::operator[](TString* key) const {
|
||||
return MemberProxy<TDerived, TString*>(derived(), key);
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename TString>
|
||||
inline typename enable_if<IsString<TString>::value,
|
||||
MemberProxy<TDerived, TString> >::type
|
||||
VariantRefBase<TDerived>::operator[](const TString& key) const {
|
||||
return MemberProxy<TDerived, TString>(derived(), key);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
119
lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectIterator.hpp
Normal file
119
lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectIterator.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Object/JsonPair.hpp>
|
||||
#include <ArduinoJson/Variant/SlotFunctions.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonPairPtr {
|
||||
public:
|
||||
JsonPairPtr(MemoryPool* pool, VariantSlot* slot) : _pair(pool, slot) {}
|
||||
|
||||
const JsonPair* operator->() const {
|
||||
return &_pair;
|
||||
}
|
||||
|
||||
const JsonPair& operator*() const {
|
||||
return _pair;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonPair _pair;
|
||||
};
|
||||
|
||||
class JsonObjectIterator {
|
||||
friend class JsonObject;
|
||||
|
||||
public:
|
||||
JsonObjectIterator() : _slot(0) {}
|
||||
|
||||
explicit JsonObjectIterator(MemoryPool* pool, VariantSlot* slot)
|
||||
: _pool(pool), _slot(slot) {}
|
||||
|
||||
JsonPair operator*() const {
|
||||
return JsonPair(_pool, _slot);
|
||||
}
|
||||
JsonPairPtr operator->() {
|
||||
return JsonPairPtr(_pool, _slot);
|
||||
}
|
||||
|
||||
bool operator==(const JsonObjectIterator& other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonObjectIterator& other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonObjectIterator& operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonObjectIterator& operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryPool* _pool;
|
||||
VariantSlot* _slot;
|
||||
};
|
||||
|
||||
class JsonPairConstPtr {
|
||||
public:
|
||||
JsonPairConstPtr(const VariantSlot* slot) : _pair(slot) {}
|
||||
|
||||
const JsonPairConst* operator->() const {
|
||||
return &_pair;
|
||||
}
|
||||
|
||||
const JsonPairConst& operator*() const {
|
||||
return _pair;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonPairConst _pair;
|
||||
};
|
||||
|
||||
class JsonObjectConstIterator {
|
||||
friend class JsonObject;
|
||||
|
||||
public:
|
||||
JsonObjectConstIterator() : _slot(0) {}
|
||||
|
||||
explicit JsonObjectConstIterator(const VariantSlot* slot) : _slot(slot) {}
|
||||
|
||||
JsonPairConst operator*() const {
|
||||
return JsonPairConst(_slot);
|
||||
}
|
||||
JsonPairConstPtr operator->() {
|
||||
return JsonPairConstPtr(_slot);
|
||||
}
|
||||
|
||||
bool operator==(const JsonObjectConstIterator& other) const {
|
||||
return _slot == other._slot;
|
||||
}
|
||||
|
||||
bool operator!=(const JsonObjectConstIterator& other) const {
|
||||
return _slot != other._slot;
|
||||
}
|
||||
|
||||
JsonObjectConstIterator& operator++() {
|
||||
_slot = _slot->next();
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonObjectConstIterator& operator+=(size_t distance) {
|
||||
_slot = _slot->next(distance);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantSlot* _slot;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
67
lib/ArduinoJson/src/ArduinoJson/Object/JsonPair.hpp
Normal file
67
lib/ArduinoJson/src/ArduinoJson/Object/JsonPair.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// A key-value pair.
|
||||
// https://arduinojson.org/v6/api/jsonobject/begin_end/
|
||||
class JsonPair {
|
||||
public:
|
||||
// INTERNAL USE ONLY
|
||||
JsonPair(MemoryPool* pool, VariantSlot* slot) {
|
||||
if (slot) {
|
||||
_key = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
|
||||
: JsonString::Linked);
|
||||
_value = JsonVariant(pool, slot->data());
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the key.
|
||||
JsonString key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
// Returns the value.
|
||||
JsonVariant value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonString _key;
|
||||
JsonVariant _value;
|
||||
};
|
||||
|
||||
// A read-only key-value pair.
|
||||
// https://arduinojson.org/v6/api/jsonobjectconst/begin_end/
|
||||
class JsonPairConst {
|
||||
public:
|
||||
JsonPairConst(const VariantSlot* slot) {
|
||||
if (slot) {
|
||||
_key = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
|
||||
: JsonString::Linked);
|
||||
_value = JsonVariantConst(slot->data());
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the key.
|
||||
JsonString key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
// Returns the value.
|
||||
JsonVariantConst value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonString _key;
|
||||
JsonVariantConst _value;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -4,203 +4,61 @@
|
||||
|
||||
#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
|
||||
#include <ArduinoJson/Variant/VariantRefBase.hpp>
|
||||
|
||||
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;
|
||||
// A proxy class to get or set a member of an object.
|
||||
// https://arduinojson.org/v6/api/jsonobject/subscript/
|
||||
template <typename TUpstream, typename TStringRef>
|
||||
class MemberProxy
|
||||
: public VariantRefBase<MemberProxy<TUpstream, TStringRef> >,
|
||||
public VariantOperators<MemberProxy<TUpstream, TStringRef> > {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
typedef VariantRef variant_type;
|
||||
FORCE_INLINE MemberProxy(TUpstream upstream, TStringRef key)
|
||||
: _upstream(upstream), _key(key) {}
|
||||
|
||||
FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
|
||||
: _object(variant), _key(key) {}
|
||||
MemberProxy(const MemberProxy& src)
|
||||
: _upstream(src._upstream), _key(src._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);
|
||||
FORCE_INLINE MemberProxy& operator=(const MemberProxy& src) {
|
||||
this->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);
|
||||
template <typename T>
|
||||
FORCE_INLINE MemberProxy& operator=(const T& src) {
|
||||
this->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);
|
||||
template <typename T>
|
||||
FORCE_INLINE MemberProxy& operator=(T* src) {
|
||||
this->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 size_t memoryUsage() const {
|
||||
return getUpstreamMember().memoryUsage();
|
||||
}
|
||||
|
||||
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 MemoryPool* getPool() const {
|
||||
return VariantAttorney::getPool(_upstream);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef getOrAddUpstreamMember() const {
|
||||
return _object.getOrAddMember(_key);
|
||||
FORCE_INLINE VariantData* getData() const {
|
||||
return variantGetMember(VariantAttorney::getData(_upstream),
|
||||
adaptString(_key));
|
||||
}
|
||||
|
||||
friend void convertToJson(const this_type &src, VariantRef dst) {
|
||||
dst.set(src.getUpstreamMember());
|
||||
FORCE_INLINE VariantData* getOrCreateData() const {
|
||||
return variantGetOrAddMember(VariantAttorney::getOrCreateData(_upstream),
|
||||
adaptString(_key),
|
||||
VariantAttorney::getPool(_upstream));
|
||||
}
|
||||
|
||||
TObject _object;
|
||||
private:
|
||||
TUpstream _upstream;
|
||||
TStringRef _key;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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, typename TStoragePolicy>
|
||||
inline VariantData *objectGetOrAddMember(CollectionData *obj,
|
||||
TAdaptedString key, MemoryPool *pool,
|
||||
TStoragePolicy storage_policy) {
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
return obj->getOrAddMember(key, pool, storage_policy);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -1,69 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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).isUnbound();
|
||||
}
|
||||
|
||||
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).isUnbound();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -1,123 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -1,282 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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).isUnbound();
|
||||
}
|
||||
|
||||
// containsKey(char*) const
|
||||
// containsKey(const char*) const
|
||||
// containsKey(const __FlashStringHelper*) const
|
||||
template <typename TChar>
|
||||
FORCE_INLINE bool containsKey(TChar* key) const {
|
||||
return !getMember(key).isUnbound();
|
||||
}
|
||||
|
||||
// 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,
|
||||
getStringStoragePolicy(key)));
|
||||
}
|
||||
|
||||
// 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,
|
||||
getStringStoragePolicy(key)));
|
||||
}
|
||||
|
||||
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 void toJson(VariantConstRef src, VariantRef dst) {
|
||||
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 void toJson(VariantConstRef src, VariantRef dst) {
|
||||
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 InvalidConversion<VariantConstRef, ObjectRef> fromJson(
|
||||
VariantConstRef);
|
||||
|
||||
static bool checkJson(VariantConstRef) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantRef src) {
|
||||
VariantData* data = getData(src);
|
||||
return data && data->isObject();
|
||||
}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -1,73 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -1,57 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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() ? String::Copied : String::Linked);
|
||||
_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() ? String::Copied : String::Linked);
|
||||
_value = VariantConstRef(slot->data());
|
||||
}
|
||||
}
|
||||
|
||||
String key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
VariantConstRef value() const {
|
||||
return _value;
|
||||
}
|
||||
|
||||
private:
|
||||
String _key;
|
||||
VariantConstRef _value;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -9,32 +9,16 @@
|
||||
# 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
|
||||
|
||||
@@ -23,7 +23,8 @@ struct pgm_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++;
|
||||
while (pgm_read_byte(p))
|
||||
p++;
|
||||
return size_t(p - s.address);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,14 +13,11 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
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(...);
|
||||
static int probe(const TBase*);
|
||||
static char probe(...);
|
||||
|
||||
public:
|
||||
static const bool value =
|
||||
sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes);
|
||||
sizeof(probe(reinterpret_cast<TDerived*>(0))) == sizeof(int);
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -11,16 +11,13 @@ 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));
|
||||
static int probe(void (U::*)(void));
|
||||
template <typename>
|
||||
static No &probe(...);
|
||||
static char probe(...);
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(probe<T>(0)) == sizeof(Yes);
|
||||
static const bool value = sizeof(probe<T>(0)) == sizeof(int);
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -24,14 +24,13 @@ 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 int probe(To);
|
||||
static char probe(...);
|
||||
|
||||
static Yes &probe(To);
|
||||
static No &probe(...);
|
||||
static From& _from;
|
||||
|
||||
public:
|
||||
static const bool value = sizeof(probe(declval<From>())) == sizeof(Yes);
|
||||
static const bool value = sizeof(probe(_from)) == sizeof(int);
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -13,7 +13,7 @@ class Writer< ::String, void> {
|
||||
static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
|
||||
|
||||
public:
|
||||
explicit Writer(::String &str) : _destination(&str) {
|
||||
explicit Writer(::String& str) : _destination(&str) {
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class Writer< ::String, void> {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t *s, size_t n) {
|
||||
size_t write(const uint8_t* s, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
write(s[i]);
|
||||
}
|
||||
@@ -45,7 +45,7 @@ class Writer< ::String, void> {
|
||||
}
|
||||
|
||||
private:
|
||||
::String *_destination;
|
||||
::String* _destination;
|
||||
char _buffer[bufferCapacity];
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StaticStringWriter {
|
||||
public:
|
||||
StaticStringWriter(char *buf, size_t size) : end(buf + size), p(buf) {}
|
||||
StaticStringWriter(char* buf, size_t size) : end(buf + size), p(buf) {}
|
||||
|
||||
size_t write(uint8_t c) {
|
||||
if (p >= end)
|
||||
@@ -19,8 +19,8 @@ class StaticStringWriter {
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t write(const uint8_t *s, size_t n) {
|
||||
char *begin = p;
|
||||
size_t write(const uint8_t* s, size_t n) {
|
||||
char* begin = p;
|
||||
while (p < end && n > 0) {
|
||||
*p++ = static_cast<char>(*s++);
|
||||
n--;
|
||||
@@ -29,7 +29,7 @@ class StaticStringWriter {
|
||||
}
|
||||
|
||||
private:
|
||||
char *end;
|
||||
char *p;
|
||||
char* end;
|
||||
char* p;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -22,19 +22,19 @@ template <typename TDestination>
|
||||
class Writer<TDestination,
|
||||
typename enable_if<is_std_string<TDestination>::value>::type> {
|
||||
public:
|
||||
Writer(TDestination &str) : _str(&str) {}
|
||||
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);
|
||||
size_t write(const uint8_t* s, size_t n) {
|
||||
_str->append(reinterpret_cast<const char*>(s), n);
|
||||
return n;
|
||||
}
|
||||
|
||||
private:
|
||||
TDestination *_str;
|
||||
TDestination* _str;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Serialization/Writers/DummyWriter.hpp>
|
||||
#include <ArduinoJson/Variant/VariantFunctions.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource>
|
||||
size_t measure(const TSource &source) {
|
||||
template <template <typename> class TSerializer>
|
||||
size_t measure(JsonVariantConst source) {
|
||||
DummyWriter dp;
|
||||
TSerializer<DummyWriter> serializer(dp);
|
||||
return source.accept(serializer);
|
||||
return variantAccept(VariantAttorney::getData(source), serializer);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -5,49 +5,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Serialization/Writer.hpp>
|
||||
#include <ArduinoJson/Variant/VariantFunctions.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource,
|
||||
typename TWriter>
|
||||
size_t doSerialize(const TSource &source, TWriter writer) {
|
||||
template <template <typename> class TSerializer, typename TWriter>
|
||||
size_t doSerialize(JsonVariantConst source, TWriter writer) {
|
||||
TSerializer<TWriter> serializer(writer);
|
||||
return source.accept(serializer);
|
||||
return variantAccept(VariantAttorney::getData(source), serializer);
|
||||
}
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource,
|
||||
typename TDestination>
|
||||
size_t serialize(const TSource &source, TDestination &destination) {
|
||||
template <template <typename> class TSerializer, typename TDestination>
|
||||
size_t serialize(JsonVariantConst source, TDestination& destination) {
|
||||
Writer<TDestination> writer(destination);
|
||||
return doSerialize<TSerializer>(source, writer);
|
||||
}
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource>
|
||||
template <template <typename> class TSerializer>
|
||||
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);
|
||||
serialize(JsonVariantConst 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>
|
||||
template <template <typename> class TSerializer>
|
||||
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);
|
||||
serialize(JsonVariantConst 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;
|
||||
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]) {
|
||||
template <template <typename> class TSerializer, typename TChar, size_t N>
|
||||
typename enable_if<IsChar<TChar>::value, size_t>::type serialize(
|
||||
JsonVariantConst source, TChar (&buffer)[N]) {
|
||||
return serialize<TSerializer>(source, buffer, N);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StringCopier {
|
||||
public:
|
||||
StringCopier(MemoryPool& pool) : _pool(&pool) {}
|
||||
StringCopier(MemoryPool* pool) : _pool(pool) {}
|
||||
|
||||
void startString() {
|
||||
_pool->getFreeZone(&_ptr, &_capacity);
|
||||
@@ -19,18 +19,21 @@ class StringCopier {
|
||||
_pool->markAsOverflowed();
|
||||
}
|
||||
|
||||
String save() {
|
||||
JsonString save() {
|
||||
ARDUINOJSON_ASSERT(_ptr);
|
||||
ARDUINOJSON_ASSERT(_size < _capacity); // needs room for the terminator
|
||||
return String(_pool->saveStringFromFreeZone(_size), _size, String::Copied);
|
||||
return JsonString(_pool->saveStringFromFreeZone(_size), _size,
|
||||
JsonString::Copied);
|
||||
}
|
||||
|
||||
void append(const char* s) {
|
||||
while (*s) append(*s++);
|
||||
while (*s)
|
||||
append(*s++);
|
||||
}
|
||||
|
||||
void append(const char* s, size_t n) {
|
||||
while (n-- > 0) append(*s++);
|
||||
while (n-- > 0)
|
||||
append(*s++);
|
||||
}
|
||||
|
||||
void append(char c) {
|
||||
@@ -48,11 +51,11 @@ class StringCopier {
|
||||
return _size;
|
||||
}
|
||||
|
||||
String str() const {
|
||||
JsonString str() const {
|
||||
ARDUINOJSON_ASSERT(_ptr);
|
||||
ARDUINOJSON_ASSERT(_size < _capacity);
|
||||
_ptr[_size] = 0;
|
||||
return String(_ptr, _size, String::Copied);
|
||||
return JsonString(_ptr, _size, JsonString::Copied);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Namespace.hpp>
|
||||
#include <ArduinoJson/Strings/String.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@@ -17,8 +17,8 @@ class StringMover {
|
||||
_startPtr = _writePtr;
|
||||
}
|
||||
|
||||
FORCE_INLINE String save() {
|
||||
String s = str();
|
||||
FORCE_INLINE JsonString save() {
|
||||
JsonString s = str();
|
||||
_writePtr++;
|
||||
return s;
|
||||
}
|
||||
@@ -31,9 +31,9 @@ class StringMover {
|
||||
return true;
|
||||
}
|
||||
|
||||
String str() const {
|
||||
JsonString str() const {
|
||||
_writePtr[0] = 0; // terminator
|
||||
return String(_startPtr, size(), String::Linked);
|
||||
return JsonString(_startPtr, size(), JsonString::Linked);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TInput>
|
||||
StringCopier makeStringStorage(TInput&, MemoryPool& pool) {
|
||||
StringCopier makeStringStorage(TInput&, MemoryPool* pool) {
|
||||
ARDUINOJSON_ASSERT(pool != 0);
|
||||
return StringCopier(pool);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
StringMover makeStringStorage(
|
||||
TChar* input, MemoryPool&,
|
||||
TChar* input, MemoryPool*,
|
||||
typename enable_if<!is_const<TChar>::value>::type* = 0) {
|
||||
return StringMover(reinterpret_cast<char*>(input));
|
||||
}
|
||||
|
||||
@@ -7,18 +7,19 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||
#include <ArduinoJson/Strings/IsString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline SizedRamString adaptString(const ::String& s) {
|
||||
return SizedRamString(s.c_str(), s.length());
|
||||
}
|
||||
template <typename T>
|
||||
struct StringAdapter<
|
||||
T, typename enable_if<is_same<T, ::String>::value ||
|
||||
is_same<T, ::StringSumHelper>::value>::type> {
|
||||
typedef SizedRamString AdaptedString;
|
||||
|
||||
template <>
|
||||
struct IsString< ::String> : true_type {};
|
||||
|
||||
template <>
|
||||
struct IsString< ::StringSumHelper> : true_type {};
|
||||
static AdaptedString adapt(const ::String& s) {
|
||||
return AdaptedString(s.c_str(), s.length());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
||||
#include <ArduinoJson/Strings/IsString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@@ -61,20 +61,31 @@ class FlashString {
|
||||
::memcpy_P(p, s._str, n);
|
||||
}
|
||||
|
||||
StringStoragePolicy::Copy storagePolicy() const {
|
||||
return StringStoragePolicy::Copy();
|
||||
}
|
||||
|
||||
private:
|
||||
const char* _str;
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
inline FlashString adaptString(const __FlashStringHelper* s) {
|
||||
return FlashString(s, s ? strlen_P(reinterpret_cast<const char*>(s)) : 0);
|
||||
}
|
||||
template <>
|
||||
struct StringAdapter<const __FlashStringHelper*, void> {
|
||||
typedef FlashString AdaptedString;
|
||||
|
||||
inline FlashString adaptString(const __FlashStringHelper* s, size_t n) {
|
||||
return FlashString(s, n);
|
||||
}
|
||||
static AdaptedString adapt(const __FlashStringHelper* s) {
|
||||
return AdaptedString(s, s ? strlen_P(reinterpret_cast<const char*>(s)) : 0);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsString<const __FlashStringHelper*> : true_type {};
|
||||
struct SizedStringAdapter<const __FlashStringHelper*, void> {
|
||||
typedef FlashString AdaptedString;
|
||||
|
||||
static AdaptedString adapt(const __FlashStringHelper* s, size_t n) {
|
||||
return AdaptedString(s, n);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -5,16 +5,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
|
||||
#include <ArduinoJson/Strings/IsString.hpp>
|
||||
#include <ArduinoJson/Strings/String.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline SizedRamString adaptString(const String& s) {
|
||||
return SizedRamString(s.c_str(), s.size());
|
||||
}
|
||||
class JsonStringAdapter : public SizedRamString {
|
||||
public:
|
||||
JsonStringAdapter(const JsonString& s)
|
||||
: SizedRamString(s.c_str(), s.size()), _linked(s.isLinked()) {}
|
||||
|
||||
StringStoragePolicy::LinkOrCopy storagePolicy() const {
|
||||
StringStoragePolicy::LinkOrCopy policy = {_linked};
|
||||
return policy;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _linked;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsString<String> : true_type {};
|
||||
struct StringAdapter<JsonString> {
|
||||
typedef JsonStringAdapter AdaptedString;
|
||||
|
||||
static AdaptedString adapt(const JsonString& s) {
|
||||
return AdaptedString(s);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -8,10 +8,15 @@
|
||||
#include <string.h> // strcmp
|
||||
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
#include <ArduinoJson/Strings/IsString.hpp>
|
||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
struct IsChar
|
||||
: integral_constant<bool, is_integral<T>::value && sizeof(T) == 1> {};
|
||||
|
||||
class ZeroTerminatedRamString {
|
||||
public:
|
||||
static const size_t typeSortKey = 3;
|
||||
@@ -48,30 +53,49 @@ class ZeroTerminatedRamString {
|
||||
return stringCompare(a, b) == 0;
|
||||
}
|
||||
|
||||
StringStoragePolicy::Copy storagePolicy() const {
|
||||
return StringStoragePolicy::Copy();
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* _str;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsString<char*> : true_type {};
|
||||
template <typename TChar>
|
||||
struct StringAdapter<TChar*, typename enable_if<IsChar<TChar>::value>::type> {
|
||||
typedef ZeroTerminatedRamString AdaptedString;
|
||||
|
||||
inline ZeroTerminatedRamString adaptString(const char* s) {
|
||||
return ZeroTerminatedRamString(s);
|
||||
}
|
||||
static AdaptedString adapt(const TChar* p) {
|
||||
return AdaptedString(reinterpret_cast<const char*>(p));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar, size_t N>
|
||||
struct StringAdapter<TChar[N], typename enable_if<IsChar<TChar>::value>::type> {
|
||||
typedef ZeroTerminatedRamString AdaptedString;
|
||||
|
||||
static AdaptedString adapt(const TChar* p) {
|
||||
return AdaptedString(reinterpret_cast<const char*>(p));
|
||||
}
|
||||
};
|
||||
|
||||
class StaticStringAdapter : public ZeroTerminatedRamString {
|
||||
public:
|
||||
StaticStringAdapter(const char* str) : ZeroTerminatedRamString(str) {}
|
||||
|
||||
StringStoragePolicy::Link storagePolicy() const {
|
||||
return StringStoragePolicy::Link();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IsString<unsigned char*> : true_type {};
|
||||
struct StringAdapter<const char*, void> {
|
||||
typedef StaticStringAdapter AdaptedString;
|
||||
|
||||
inline ZeroTerminatedRamString adaptString(const unsigned char* s) {
|
||||
return adaptString(reinterpret_cast<const char*>(s));
|
||||
}
|
||||
|
||||
template <>
|
||||
struct IsString<signed char*> : true_type {};
|
||||
|
||||
inline ZeroTerminatedRamString adaptString(const signed char* s) {
|
||||
return adaptString(reinterpret_cast<const char*>(s));
|
||||
}
|
||||
static AdaptedString adapt(const char* p) {
|
||||
return AdaptedString(p);
|
||||
}
|
||||
};
|
||||
|
||||
class SizedRamString {
|
||||
public:
|
||||
@@ -97,23 +121,23 @@ class SizedRamString {
|
||||
return _str;
|
||||
}
|
||||
|
||||
StringStoragePolicy::Copy storagePolicy() const {
|
||||
return StringStoragePolicy::Copy();
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* _str;
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
inline SizedRamString adaptString(const char* s, size_t n) {
|
||||
return SizedRamString(s, n);
|
||||
}
|
||||
template <typename TChar>
|
||||
struct SizedStringAdapter<TChar*,
|
||||
typename enable_if<IsChar<TChar>::value>::type> {
|
||||
typedef SizedRamString AdaptedString;
|
||||
|
||||
template <size_t N>
|
||||
struct IsString<char[N]> : true_type {};
|
||||
static AdaptedString adapt(const TChar* p, size_t n) {
|
||||
return AdaptedString(reinterpret_cast<const char*>(p), n);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct IsString<const char[N]> : true_type {};
|
||||
|
||||
template <size_t N>
|
||||
inline SizedRamString adaptString(char s[N]) {
|
||||
return SizedRamString(s, strlen(s));
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TCharTraits, typename TAllocator>
|
||||
inline SizedRamString adaptString(
|
||||
const std::basic_string<char, TCharTraits, TAllocator>& s) {
|
||||
return SizedRamString(s.c_str(), s.size());
|
||||
}
|
||||
struct StringAdapter<std::basic_string<char, TCharTraits, TAllocator>, void> {
|
||||
typedef SizedRamString AdaptedString;
|
||||
|
||||
template <typename TCharTraits, typename TAllocator>
|
||||
struct IsString<std::basic_string<char, TCharTraits, TAllocator> > : true_type {
|
||||
static AdaptedString adapt(
|
||||
const std::basic_string<char, TCharTraits, TAllocator>& s) {
|
||||
return AdaptedString(s.c_str(), s.size());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline SizedRamString adaptString(const std::string_view& s) {
|
||||
return SizedRamString(s.data(), s.size());
|
||||
}
|
||||
|
||||
template <>
|
||||
struct IsString<std::string_view> : true_type {};
|
||||
struct StringAdapter<std::string_view, void> {
|
||||
typedef SizedRamString AdaptedString;
|
||||
|
||||
static AdaptedString adapt(const std::string_view& s) {
|
||||
return AdaptedString(s.data(), s.size());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct IsString : false_type {};
|
||||
|
||||
template <typename TChar>
|
||||
struct IsString<const TChar*> : IsString<TChar*> {};
|
||||
template <typename T>
|
||||
struct IsString<
|
||||
T, typename make_void<typename StringAdapter<T>::AdaptedString>::type>
|
||||
: true_type {};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -12,30 +12,37 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class String : public SafeBoolIdom<String> {
|
||||
// A string.
|
||||
// https://arduinojson.org/v6/api/jsonstring/
|
||||
class JsonString : public SafeBoolIdom<JsonString> {
|
||||
public:
|
||||
enum Ownership { Copied, Linked };
|
||||
|
||||
String() : _data(0), _size(0), _ownership(Linked) {}
|
||||
JsonString() : _data(0), _size(0), _ownership(Linked) {}
|
||||
|
||||
String(const char* data, Ownership ownership = Linked)
|
||||
JsonString(const char* data, Ownership ownership = Linked)
|
||||
: _data(data), _size(data ? ::strlen(data) : 0), _ownership(ownership) {}
|
||||
|
||||
String(const char* data, size_t sz, Ownership ownership = Linked)
|
||||
JsonString(const char* data, size_t sz, Ownership ownership = Linked)
|
||||
: _data(data), _size(sz), _ownership(ownership) {}
|
||||
|
||||
// Returns a pointer to the characters.
|
||||
const char* c_str() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
// Returns true if the string is null.
|
||||
bool isNull() const {
|
||||
return !_data;
|
||||
}
|
||||
|
||||
// Returns true if the string is stored by address.
|
||||
// Returns false if the string is stored by copy.
|
||||
bool isLinked() const {
|
||||
return _ownership == Linked;
|
||||
}
|
||||
|
||||
// Returns length of the string.
|
||||
size_t size() const {
|
||||
return _size;
|
||||
}
|
||||
@@ -45,7 +52,8 @@ class String : public SafeBoolIdom<String> {
|
||||
return _data ? safe_true() : safe_false();
|
||||
}
|
||||
|
||||
friend bool operator==(String lhs, String rhs) {
|
||||
// Returns true if strings are equal.
|
||||
friend bool operator==(JsonString lhs, JsonString rhs) {
|
||||
if (lhs._size != rhs._size)
|
||||
return false;
|
||||
if (lhs._data == rhs._data)
|
||||
@@ -57,12 +65,13 @@ class String : public SafeBoolIdom<String> {
|
||||
return memcmp(lhs._data, rhs._data, lhs._size) == 0;
|
||||
}
|
||||
|
||||
friend bool operator!=(String lhs, String rhs) {
|
||||
// Returns true if strings differs.
|
||||
friend bool operator!=(JsonString lhs, JsonString rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const String& rhs) {
|
||||
friend std::ostream& operator<<(std::ostream& lhs, const JsonString& rhs) {
|
||||
lhs.write(rhs.c_str(), static_cast<std::streamsize>(rhs.size()));
|
||||
return lhs;
|
||||
}
|
||||
@@ -4,53 +4,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Strings/String.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct LinkStringStoragePolicy {
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool store(TAdaptedString str, MemoryPool *, TCallback callback) {
|
||||
String storedString(str.data(), str.size(), String::Linked);
|
||||
callback(storedString);
|
||||
return !str.isNull();
|
||||
}
|
||||
namespace StringStoragePolicy {
|
||||
|
||||
struct Link {};
|
||||
struct Copy {};
|
||||
struct LinkOrCopy {
|
||||
bool link;
|
||||
};
|
||||
|
||||
struct CopyStringStoragePolicy {
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool store(TAdaptedString str, MemoryPool *pool, TCallback callback);
|
||||
};
|
||||
|
||||
class LinkOrCopyStringStoragePolicy : LinkStringStoragePolicy,
|
||||
CopyStringStoragePolicy {
|
||||
public:
|
||||
LinkOrCopyStringStoragePolicy(bool link) : _link(link) {}
|
||||
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool store(TAdaptedString str, MemoryPool *pool, TCallback callback) {
|
||||
if (_link)
|
||||
return LinkStringStoragePolicy::store(str, pool, callback);
|
||||
else
|
||||
return CopyStringStoragePolicy::store(str, pool, callback);
|
||||
}
|
||||
|
||||
private:
|
||||
bool _link;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline CopyStringStoragePolicy getStringStoragePolicy(const T &) {
|
||||
return CopyStringStoragePolicy();
|
||||
}
|
||||
|
||||
inline LinkStringStoragePolicy getStringStoragePolicy(const char *) {
|
||||
return LinkStringStoragePolicy();
|
||||
}
|
||||
|
||||
inline LinkOrCopyStringStoragePolicy getStringStoragePolicy(const String &s) {
|
||||
return LinkOrCopyStringStoragePolicy(s.isLinked());
|
||||
}
|
||||
} // namespace StringStoragePolicy
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
31
lib/ArduinoJson/src/ArduinoJson/Strings/StringAdapter.hpp
Normal file
31
lib/ArduinoJson/src/ArduinoJson/Strings/StringAdapter.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TString, typename Enable = void>
|
||||
struct StringAdapter;
|
||||
|
||||
template <typename TString, typename Enable = void>
|
||||
struct SizedStringAdapter;
|
||||
|
||||
template <typename TString>
|
||||
typename StringAdapter<TString>::AdaptedString adaptString(const TString& s) {
|
||||
return StringAdapter<TString>::adapt(s);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
typename StringAdapter<TChar*>::AdaptedString adaptString(TChar* p) {
|
||||
return StringAdapter<TChar*>::adapt(p);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
typename SizedStringAdapter<TChar*>::AdaptedString adaptString(TChar* p,
|
||||
size_t n) {
|
||||
return SizedStringAdapter<TChar*>::adapt(p, n);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Namespace.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
@@ -14,4 +16,7 @@ template <typename T1, typename T2>
|
||||
class InvalidConversion; // Error here? See https://arduinojson.org/v6/invalid-conversion/
|
||||
// clang-format on
|
||||
|
||||
template <typename T>
|
||||
struct ConverterNeedsWriteableRef;
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Json/JsonSerializer.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
|
||||
#include <ArduinoJson/Variant/VariantFunctions.hpp>
|
||||
#include <ArduinoJson/Variant/VariantRef.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T, typename Enable>
|
||||
struct Converter {
|
||||
static void toJson(const T& src, VariantRef dst) {
|
||||
static void toJson(const T& src, JsonVariant dst) {
|
||||
// clang-format off
|
||||
convertToJson(src, dst); // Error here? See https://arduinojson.org/v6/unsupported-set/
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
static T fromJson(VariantConstRef src) {
|
||||
static T fromJson(JsonVariantConst 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/
|
||||
@@ -26,7 +26,7 @@ struct Converter {
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
T dummy = T();
|
||||
// clang-format off
|
||||
return canConvertFromJson(src, dummy); // Error here? See https://arduinojson.org/v6/unsupported-is/
|
||||
@@ -37,112 +37,113 @@ struct Converter {
|
||||
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 void toJson(T src, VariantRef dst) {
|
||||
!is_same<char, T>::value>::type>
|
||||
: private VariantAttorney {
|
||||
static void toJson(T src, JsonVariant dst) {
|
||||
VariantData* data = getData(dst);
|
||||
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
|
||||
if (data)
|
||||
data->setInteger(src);
|
||||
}
|
||||
|
||||
static T fromJson(VariantConstRef src) {
|
||||
static T fromJson(JsonVariantConst src) {
|
||||
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
|
||||
const VariantData* data = getData(src);
|
||||
return data ? data->asIntegral<T>() : T();
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst 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 void toJson(T src, VariantRef dst) {
|
||||
dst.set(static_cast<Integer>(src));
|
||||
struct Converter<T, typename enable_if<is_enum<T>::value>::type>
|
||||
: private VariantAttorney {
|
||||
static void toJson(T src, JsonVariant dst) {
|
||||
dst.set(static_cast<JsonInteger>(src));
|
||||
}
|
||||
|
||||
static T fromJson(VariantConstRef src) {
|
||||
static T fromJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data ? static_cast<T>(data->asIntegral<int>()) : T();
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data && data->isInteger<int>();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<bool> {
|
||||
static void toJson(bool src, VariantRef dst) {
|
||||
struct Converter<bool> : private VariantAttorney {
|
||||
static void toJson(bool src, JsonVariant dst) {
|
||||
VariantData* data = getData(dst);
|
||||
if (data)
|
||||
data->setBoolean(src);
|
||||
}
|
||||
|
||||
static bool fromJson(VariantConstRef src) {
|
||||
static bool fromJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data ? data->asBoolean() : false;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst 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 void toJson(T src, VariantRef dst) {
|
||||
struct Converter<T, typename enable_if<is_floating_point<T>::value>::type>
|
||||
: private VariantAttorney {
|
||||
static void toJson(T src, JsonVariant dst) {
|
||||
VariantData* data = getData(dst);
|
||||
if (data)
|
||||
data->setFloat(static_cast<Float>(src));
|
||||
data->setFloat(static_cast<JsonFloat>(src));
|
||||
}
|
||||
|
||||
static T fromJson(VariantConstRef src) {
|
||||
static T fromJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data ? data->asFloat<T>() : false;
|
||||
return data ? data->asFloat<T>() : 0;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data && data->isFloat();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<const char*> {
|
||||
static void toJson(const char* src, VariantRef dst) {
|
||||
variantSetString(getData(dst), adaptString(src), getPool(dst),
|
||||
getStringStoragePolicy(src));
|
||||
struct Converter<const char*> : private VariantAttorney {
|
||||
static void toJson(const char* src, JsonVariant dst) {
|
||||
variantSetString(getData(dst), adaptString(src), getPool(dst));
|
||||
}
|
||||
|
||||
static const char* fromJson(VariantConstRef src) {
|
||||
static const char* fromJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data ? data->asString().c_str() : 0;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data && data->isString();
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<String> {
|
||||
static void toJson(String src, VariantRef dst) {
|
||||
variantSetString(getData(dst), adaptString(src), getPool(dst),
|
||||
getStringStoragePolicy(src));
|
||||
struct Converter<JsonString> : private VariantAttorney {
|
||||
static void toJson(JsonString src, JsonVariant dst) {
|
||||
variantSetString(getData(dst), adaptString(src), getPool(dst));
|
||||
}
|
||||
|
||||
static String fromJson(VariantConstRef src) {
|
||||
static JsonString fromJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data ? data->asString() : 0;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data && data->isString();
|
||||
}
|
||||
@@ -150,17 +151,16 @@ struct Converter<String> {
|
||||
|
||||
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,
|
||||
getStringStoragePolicy(src));
|
||||
const T& src, JsonVariant dst) {
|
||||
VariantData* data = VariantAttorney::getData(dst);
|
||||
MemoryPool* pool = VariantAttorney::getPool(dst);
|
||||
return variantSetString(data, adaptString(src), pool);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct Converter<SerializedValue<const char*> > {
|
||||
static void toJson(SerializedValue<const char*> src, VariantRef dst) {
|
||||
VariantData* data = getData(dst);
|
||||
static void toJson(SerializedValue<const char*> src, JsonVariant dst) {
|
||||
VariantData* data = VariantAttorney::getData(dst);
|
||||
if (data)
|
||||
data->setLinkedRaw(src);
|
||||
}
|
||||
@@ -171,8 +171,9 @@ struct Converter<SerializedValue<const char*> > {
|
||||
// SerializedValue<const __FlashStringHelper*>
|
||||
template <typename T>
|
||||
struct Converter<SerializedValue<T>,
|
||||
typename enable_if<!is_same<const char*, T>::value>::type> {
|
||||
static void toJson(SerializedValue<T> src, VariantRef dst) {
|
||||
typename enable_if<!is_same<const char*, T>::value>::type>
|
||||
: private VariantAttorney {
|
||||
static void toJson(SerializedValue<T> src, JsonVariant dst) {
|
||||
VariantData* data = getData(dst);
|
||||
MemoryPool* pool = getPool(dst);
|
||||
if (data)
|
||||
@@ -183,14 +184,14 @@ struct Converter<SerializedValue<T>,
|
||||
#if ARDUINOJSON_HAS_NULLPTR
|
||||
|
||||
template <>
|
||||
struct Converter<decltype(nullptr)> {
|
||||
static void toJson(decltype(nullptr), VariantRef dst) {
|
||||
struct Converter<decltype(nullptr)> : private VariantAttorney {
|
||||
static void toJson(decltype(nullptr), JsonVariant dst) {
|
||||
variantSetNull(getData(dst));
|
||||
}
|
||||
static decltype(nullptr) fromJson(VariantConstRef) {
|
||||
static decltype(nullptr) fromJson(JsonVariantConst) {
|
||||
return nullptr;
|
||||
}
|
||||
static bool checkJson(VariantConstRef src) {
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return data == 0 || data->isNull();
|
||||
}
|
||||
@@ -206,9 +207,10 @@ class MemoryPoolPrint : public Print {
|
||||
pool->getFreeZone(&_string, &_capacity);
|
||||
}
|
||||
|
||||
String str() {
|
||||
JsonString str() {
|
||||
ARDUINOJSON_ASSERT(_size < _capacity);
|
||||
return String(_pool->saveStringFromFreeZone(_size), _size, String::Copied);
|
||||
return JsonString(_pool->saveStringFromFreeZone(_size), _size,
|
||||
JsonString::Copied);
|
||||
}
|
||||
|
||||
size_t write(uint8_t c) {
|
||||
@@ -240,9 +242,9 @@ class MemoryPoolPrint : public Print {
|
||||
size_t _capacity;
|
||||
};
|
||||
|
||||
inline void convertToJson(const ::Printable& src, VariantRef dst) {
|
||||
MemoryPool* pool = getPool(dst);
|
||||
VariantData* data = getData(dst);
|
||||
inline void convertToJson(const ::Printable& src, JsonVariant dst) {
|
||||
MemoryPool* pool = VariantAttorney::getPool(dst);
|
||||
VariantData* data = VariantAttorney::getData(dst);
|
||||
if (!pool || !data)
|
||||
return;
|
||||
MemoryPoolPrint print(pool);
|
||||
@@ -259,48 +261,59 @@ inline void convertToJson(const ::Printable& src, VariantRef dst) {
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
|
||||
inline void convertFromJson(VariantConstRef src, ::String& dst) {
|
||||
String str = src.as<String>();
|
||||
inline void convertFromJson(JsonVariantConst src, ::String& dst) {
|
||||
JsonString str = src.as<JsonString>();
|
||||
if (str)
|
||||
dst = str.c_str();
|
||||
else
|
||||
serializeJson(src, dst);
|
||||
}
|
||||
|
||||
inline bool canConvertFromJson(VariantConstRef src, const ::String&) {
|
||||
return src.is<String>();
|
||||
inline bool canConvertFromJson(JsonVariantConst src, const ::String&) {
|
||||
return src.is<JsonString>();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||
|
||||
inline void convertFromJson(VariantConstRef src, std::string& dst) {
|
||||
String str = src.as<String>();
|
||||
inline void convertFromJson(JsonVariantConst src, std::string& dst) {
|
||||
JsonString str = src.as<JsonString>();
|
||||
if (str)
|
||||
dst.assign(str.c_str(), str.size());
|
||||
else
|
||||
serializeJson(src, dst);
|
||||
}
|
||||
|
||||
inline bool canConvertFromJson(VariantConstRef src, const std::string&) {
|
||||
return src.is<String>();
|
||||
inline bool canConvertFromJson(JsonVariantConst src, const std::string&) {
|
||||
return src.is<JsonString>();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STRING_VIEW
|
||||
|
||||
inline void convertFromJson(VariantConstRef src, std::string_view& dst) {
|
||||
String str = src.as<String>();
|
||||
inline void convertFromJson(JsonVariantConst src, std::string_view& dst) {
|
||||
JsonString str = src.as<JsonString>();
|
||||
if (str) // the standard doesn't allow passing null to the constructor
|
||||
dst = std::string_view(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
inline bool canConvertFromJson(VariantConstRef src, const std::string_view&) {
|
||||
return src.is<String>();
|
||||
inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) {
|
||||
return src.is<JsonString>();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct ConverterNeedsWriteableRef {
|
||||
protected: // <- to avoid GCC's "all member functions in class are private"
|
||||
static int probe(T (*f)(JsonVariant));
|
||||
static char probe(T (*f)(JsonVariantConst));
|
||||
|
||||
public:
|
||||
static const bool value =
|
||||
sizeof(probe(Converter<T>::fromJson)) == sizeof(int);
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
80
lib/ArduinoJson/src/ArduinoJson/Variant/JsonVariant.hpp
Normal file
80
lib/ArduinoJson/src/ArduinoJson/Variant/JsonVariant.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Variant/VariantRefBase.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// A reference to a value in a JsonDocument.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/
|
||||
class JsonVariant : public VariantRefBase<JsonVariant>,
|
||||
public VariantOperators<JsonVariant> {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
// Creates an unbound reference.
|
||||
JsonVariant() : _data(0), _pool(0) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonVariant(MemoryPool* pool, VariantData* data) : _data(data), _pool(pool) {}
|
||||
|
||||
private:
|
||||
FORCE_INLINE MemoryPool* getPool() const {
|
||||
return _pool;
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantData* getData() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantData* getOrCreateData() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
VariantData* _data;
|
||||
MemoryPool* _pool;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<JsonVariant> : private VariantAttorney {
|
||||
static void toJson(JsonVariant src, JsonVariant dst) {
|
||||
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||
}
|
||||
|
||||
static JsonVariant fromJson(JsonVariant src) {
|
||||
return src;
|
||||
}
|
||||
|
||||
static InvalidConversion<JsonVariantConst, JsonVariant> fromJson(
|
||||
JsonVariantConst);
|
||||
|
||||
static bool checkJson(JsonVariant src) {
|
||||
VariantData* data = getData(src);
|
||||
return !!data;
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<JsonVariantConst> : private VariantAttorney {
|
||||
static void toJson(JsonVariantConst src, JsonVariant dst) {
|
||||
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||
}
|
||||
|
||||
static JsonVariantConst fromJson(JsonVariantConst src) {
|
||||
return JsonVariantConst(getData(src));
|
||||
}
|
||||
|
||||
static bool checkJson(JsonVariantConst src) {
|
||||
const VariantData* data = getData(src);
|
||||
return !!data;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
141
lib/ArduinoJson/src/ArduinoJson/Variant/JsonVariantConst.hpp
Normal file
141
lib/ArduinoJson/src/ArduinoJson/Variant/JsonVariantConst.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Strings/IsString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||
#include <ArduinoJson/Variant/VariantAttorney.hpp>
|
||||
#include <ArduinoJson/Variant/VariantFunctions.hpp>
|
||||
#include <ArduinoJson/Variant/VariantOperators.hpp>
|
||||
#include <ArduinoJson/Variant/VariantTag.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// A read-only reference to a value in a JsonDocument
|
||||
// https://arduinojson.org/v6/api/jsonarrayconst/
|
||||
class JsonVariantConst : public VariantTag,
|
||||
public VariantOperators<JsonVariantConst> {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
// Creates an unbound reference.
|
||||
JsonVariantConst() : _data(0) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
explicit JsonVariantConst(const VariantData* data) : _data(data) {}
|
||||
|
||||
// Returns true if the value is null or the reference is unbound.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/isnull/
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return variantIsNull(_data);
|
||||
}
|
||||
|
||||
// Returns true if the reference is unbound.
|
||||
FORCE_INLINE bool isUnbound() const {
|
||||
return !_data;
|
||||
}
|
||||
|
||||
// Returns the number of bytes occupied by the value.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/memoryusage/
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
return _data ? _data->memoryUsage() : 0;
|
||||
}
|
||||
|
||||
// Returns the depth (nesting level) of the value.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/nesting/
|
||||
FORCE_INLINE size_t nesting() const {
|
||||
return variantNesting(_data);
|
||||
}
|
||||
|
||||
// Returns the size of the array or object.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/size/
|
||||
size_t size() const {
|
||||
return variantSize(_data);
|
||||
}
|
||||
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/as/
|
||||
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);
|
||||
}
|
||||
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/is/
|
||||
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 operator T() const {
|
||||
return as<T>();
|
||||
}
|
||||
|
||||
// Gets array's element at specified index.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
|
||||
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||
return JsonVariantConst(variantGetElement(_data, index));
|
||||
}
|
||||
|
||||
// Gets object's member with specified key.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
|
||||
template <typename TString>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
|
||||
operator[](const TString& key) const {
|
||||
return JsonVariantConst(variantGetMember(_data, adaptString(key)));
|
||||
}
|
||||
|
||||
// Gets object's member with specified key.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE
|
||||
typename enable_if<IsString<TChar*>::value, JsonVariantConst>::type
|
||||
operator[](TChar* key) const {
|
||||
return JsonVariantConst(variantGetMember(_data, adaptString(key)));
|
||||
}
|
||||
|
||||
// Returns true if tge object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/containskey/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
|
||||
containsKey(const TString& key) const {
|
||||
return variantGetMember(getData(), adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
// Returns true if tge object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonvariantconst/containskey/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value, bool>::type
|
||||
containsKey(TChar* key) const {
|
||||
return variantGetMember(getData(), adaptString(key)) != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
const VariantData* getData() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
private:
|
||||
const VariantData* _data;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -23,12 +23,11 @@ struct SlotKeySetter {
|
||||
VariantSlot* _instance;
|
||||
};
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
|
||||
TStoragePolicy storage) {
|
||||
template <typename TAdaptedString>
|
||||
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
|
||||
if (!var)
|
||||
return false;
|
||||
return storage.store(key, pool, SlotKeySetter(var));
|
||||
return storeString(pool, key, SlotKeySetter(var));
|
||||
}
|
||||
|
||||
inline size_t slotSize(const VariantSlot* var) {
|
||||
|
||||
48
lib/ArduinoJson/src/ArduinoJson/Variant/VariantAttorney.hpp
Normal file
48
lib/ArduinoJson/src/ArduinoJson/Variant/VariantAttorney.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Variant/VariantTo.hpp>
|
||||
#include "JsonVariantConst.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// Grants access to the internal variant API
|
||||
class VariantAttorney {
|
||||
// Tells whether getData() returns a const pointer
|
||||
template <typename TClient>
|
||||
struct ResultOfGetData {
|
||||
protected: // <- to avoid GCC's "all member functions in class are private"
|
||||
static int probe(const VariantData*);
|
||||
static char probe(VariantData*);
|
||||
|
||||
static TClient& client;
|
||||
|
||||
public:
|
||||
typedef typename conditional<sizeof(probe(client.getData())) == sizeof(int),
|
||||
const VariantData*, VariantData*>::type type;
|
||||
};
|
||||
|
||||
public:
|
||||
template <typename TClient>
|
||||
FORCE_INLINE static MemoryPool* getPool(TClient& client) {
|
||||
return client.getPool();
|
||||
}
|
||||
|
||||
template <typename TClient>
|
||||
FORCE_INLINE static typename ResultOfGetData<TClient>::type getData(
|
||||
TClient& client) {
|
||||
return client.getData();
|
||||
}
|
||||
|
||||
template <typename TClient>
|
||||
FORCE_INLINE static VariantData* getOrCreateData(TClient& client) {
|
||||
return client.getOrCreateData();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -5,7 +5,6 @@
|
||||
#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/StringAdapters.hpp>
|
||||
@@ -27,7 +26,7 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
||||
|
||||
explicit Comparer(T value) : rhs(value) {}
|
||||
|
||||
CompareResult visitString(const char *lhs, size_t n) {
|
||||
CompareResult visitString(const char* lhs, size_t n) {
|
||||
int i = stringCompare(adaptString(rhs), adaptString(lhs, n));
|
||||
if (i < 0)
|
||||
return COMPARE_RESULT_GREATER;
|
||||
@@ -53,20 +52,20 @@ struct Comparer<T, typename enable_if<is_integral<T>::value ||
|
||||
|
||||
explicit Comparer(T value) : rhs(value) {}
|
||||
|
||||
CompareResult visitFloat(Float lhs) {
|
||||
CompareResult visitFloat(JsonFloat lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitSignedInteger(Integer lhs) {
|
||||
CompareResult visitSignedInteger(JsonInteger lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitUnsignedInteger(UInt lhs) {
|
||||
CompareResult visitUnsignedInteger(JsonUInt lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitBoolean(bool lhs) {
|
||||
return visitUnsignedInteger(static_cast<UInt>(lhs));
|
||||
return visitUnsignedInteger(static_cast<JsonUInt>(lhs));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -84,12 +83,12 @@ struct Comparer<decltype(nullptr), void> : NullComparer {
|
||||
#endif
|
||||
|
||||
struct ArrayComparer : ComparerBase {
|
||||
const CollectionData *_rhs;
|
||||
const CollectionData* _rhs;
|
||||
|
||||
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
||||
explicit ArrayComparer(const CollectionData& rhs) : _rhs(&rhs) {}
|
||||
|
||||
CompareResult visitArray(const CollectionData &lhs) {
|
||||
if (lhs.equalsArray(*_rhs))
|
||||
CompareResult visitArray(const CollectionData& lhs) {
|
||||
if (JsonArrayConst(&lhs) == JsonArrayConst(_rhs))
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
else
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
@@ -97,12 +96,12 @@ struct ArrayComparer : ComparerBase {
|
||||
};
|
||||
|
||||
struct ObjectComparer : ComparerBase {
|
||||
const CollectionData *_rhs;
|
||||
const CollectionData* _rhs;
|
||||
|
||||
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
||||
explicit ObjectComparer(const CollectionData& rhs) : _rhs(&rhs) {}
|
||||
|
||||
CompareResult visitObject(const CollectionData &lhs) {
|
||||
if (lhs.equalsObject(*_rhs))
|
||||
CompareResult visitObject(const CollectionData& lhs) {
|
||||
if (JsonObjectConst(&lhs) == JsonObjectConst(_rhs))
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
else
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
@@ -110,13 +109,13 @@ struct ObjectComparer : ComparerBase {
|
||||
};
|
||||
|
||||
struct RawComparer : ComparerBase {
|
||||
const char *_rhsData;
|
||||
const char* _rhsData;
|
||||
size_t _rhsSize;
|
||||
|
||||
explicit RawComparer(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) {
|
||||
CompareResult visitRawJson(const char* lhsData, size_t lhsSize) {
|
||||
size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
|
||||
int n = memcmp(lhsData, _rhsData, size);
|
||||
if (n < 0)
|
||||
@@ -128,45 +127,43 @@ struct RawComparer : ComparerBase {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
|
||||
: ComparerBase {
|
||||
const T *rhs; // TODO: should be a VariantConstRef
|
||||
struct VariantComparer : ComparerBase {
|
||||
const VariantData* rhs;
|
||||
|
||||
explicit Comparer(const T &value) : rhs(&value) {}
|
||||
explicit VariantComparer(const VariantData* value) : rhs(value) {}
|
||||
|
||||
CompareResult visitArray(const CollectionData &lhs) {
|
||||
CompareResult visitArray(const CollectionData& lhs) {
|
||||
ArrayComparer comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitObject(const CollectionData &lhs) {
|
||||
CompareResult visitObject(const CollectionData& lhs) {
|
||||
ObjectComparer comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitFloat(Float lhs) {
|
||||
Comparer<Float> comparer(lhs);
|
||||
CompareResult visitFloat(JsonFloat lhs) {
|
||||
Comparer<JsonFloat> comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitString(const char *lhs, size_t) {
|
||||
Comparer<const char *> comparer(lhs);
|
||||
CompareResult visitString(const char* lhs, size_t) {
|
||||
Comparer<const char*> comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
|
||||
CompareResult visitRawJson(const char* lhsData, size_t lhsSize) {
|
||||
RawComparer comparer(lhsData, lhsSize);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitSignedInteger(Integer lhs) {
|
||||
Comparer<Integer> comparer(lhs);
|
||||
CompareResult visitSignedInteger(JsonInteger lhs) {
|
||||
Comparer<JsonInteger> comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitUnsignedInteger(UInt lhs) {
|
||||
Comparer<UInt> comparer(lhs);
|
||||
CompareResult visitUnsignedInteger(JsonUInt lhs) {
|
||||
Comparer<JsonUInt> comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
@@ -182,8 +179,8 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
|
||||
|
||||
private:
|
||||
template <typename TComparer>
|
||||
CompareResult accept(TComparer &comparer) {
|
||||
CompareResult reversedResult = rhs->accept(comparer);
|
||||
CompareResult accept(TComparer& comparer) {
|
||||
CompareResult reversedResult = variantAccept(rhs, comparer);
|
||||
switch (reversedResult) {
|
||||
case COMPARE_RESULT_GREATER:
|
||||
return COMPARE_RESULT_LESS;
|
||||
@@ -195,14 +192,18 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CompareResult compare(const T1 &lhs, const T2 &rhs) {
|
||||
Comparer<T2> comparer(rhs);
|
||||
return lhs.accept(comparer);
|
||||
}
|
||||
template <typename T>
|
||||
struct Comparer<
|
||||
T, typename enable_if<is_convertible<T, JsonVariantConst>::value>::type>
|
||||
: VariantComparer {
|
||||
explicit Comparer(const T& value)
|
||||
: VariantComparer(VariantAttorney::getData(value)) {}
|
||||
};
|
||||
|
||||
inline int variantCompare(const VariantData *a, const VariantData *b) {
|
||||
return compare(VariantConstRef(a), VariantConstRef(b));
|
||||
template <typename T>
|
||||
CompareResult compare(JsonVariantConst lhs, const T& rhs) {
|
||||
Comparer<T> comparer(rhs);
|
||||
return variantAccept(VariantAttorney::getData(lhs), comparer);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
||||
#include <ArduinoJson/Numbers/Float.hpp>
|
||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonFloat.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonInteger.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@@ -39,18 +39,18 @@ enum {
|
||||
};
|
||||
|
||||
struct RawData {
|
||||
const char *data;
|
||||
const char* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
union VariantContent {
|
||||
Float asFloat;
|
||||
JsonFloat asFloat;
|
||||
bool asBoolean;
|
||||
UInt asUnsignedInteger;
|
||||
Integer asSignedInteger;
|
||||
JsonUInt asUnsignedInteger;
|
||||
JsonInteger asSignedInteger;
|
||||
CollectionData asCollection;
|
||||
struct {
|
||||
const char *data;
|
||||
const char* data;
|
||||
size_t size;
|
||||
} asString;
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Strings/String.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||
|
||||
@@ -37,8 +37,13 @@ class VariantData {
|
||||
_flags = VALUE_IS_NULL;
|
||||
}
|
||||
|
||||
void operator=(const VariantData& src) {
|
||||
_content = src._content;
|
||||
_flags = uint8_t((_flags & OWNED_KEY_BIT) | (src._flags & ~OWNED_KEY_BIT));
|
||||
}
|
||||
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_FLOAT:
|
||||
return visitor.visitFloat(_content.asFloat);
|
||||
@@ -79,27 +84,31 @@ class VariantData {
|
||||
template <typename T>
|
||||
T asFloat() const;
|
||||
|
||||
String asString() const;
|
||||
JsonString asString() const;
|
||||
|
||||
bool asBoolean() const;
|
||||
|
||||
CollectionData *asArray() {
|
||||
CollectionData* asArray() {
|
||||
return isArray() ? &_content.asCollection : 0;
|
||||
}
|
||||
|
||||
const CollectionData *asArray() const {
|
||||
return const_cast<VariantData *>(this)->asArray();
|
||||
const CollectionData* asArray() const {
|
||||
return const_cast<VariantData*>(this)->asArray();
|
||||
}
|
||||
|
||||
CollectionData *asObject() {
|
||||
const CollectionData* asCollection() const {
|
||||
return isCollection() ? &_content.asCollection : 0;
|
||||
}
|
||||
|
||||
CollectionData* asObject() {
|
||||
return isObject() ? &_content.asCollection : 0;
|
||||
}
|
||||
|
||||
const CollectionData *asObject() const {
|
||||
return const_cast<VariantData *>(this)->asObject();
|
||||
const CollectionData* asObject() const {
|
||||
return const_cast<VariantData*>(this)->asObject();
|
||||
}
|
||||
|
||||
bool copyFrom(const VariantData &src, MemoryPool *pool);
|
||||
bool copyFrom(const VariantData& src, MemoryPool* pool);
|
||||
|
||||
bool isArray() const {
|
||||
return (_flags & VALUE_IS_ARRAY) != 0;
|
||||
@@ -163,12 +172,12 @@ class VariantData {
|
||||
_content.asBoolean = value;
|
||||
}
|
||||
|
||||
void setFloat(Float value) {
|
||||
void setFloat(JsonFloat value) {
|
||||
setType(VALUE_IS_FLOAT);
|
||||
_content.asFloat = value;
|
||||
}
|
||||
|
||||
void setLinkedRaw(SerializedValue<const char *> value) {
|
||||
void setLinkedRaw(SerializedValue<const char*> value) {
|
||||
if (value.data()) {
|
||||
setType(VALUE_IS_LINKED_RAW);
|
||||
_content.asString.data = value.data();
|
||||
@@ -179,8 +188,8 @@ class VariantData {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool storeOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
|
||||
const char *dup = pool->saveString(adaptString(value.data(), value.size()));
|
||||
bool storeOwnedRaw(SerializedValue<T> value, MemoryPool* pool) {
|
||||
const char* dup = pool->saveString(adaptString(value.data(), value.size()));
|
||||
if (dup) {
|
||||
setType(VALUE_IS_OWNED_RAW);
|
||||
_content.asString.data = dup;
|
||||
@@ -195,7 +204,7 @@ class VariantData {
|
||||
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);
|
||||
_content.asUnsignedInteger = static_cast<JsonUInt>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -208,7 +217,7 @@ class VariantData {
|
||||
setType(VALUE_IS_NULL);
|
||||
}
|
||||
|
||||
void setString(String s) {
|
||||
void setString(JsonString s) {
|
||||
ARDUINOJSON_ASSERT(s);
|
||||
if (s.isLinked())
|
||||
setType(VALUE_IS_LINKED_STRING);
|
||||
@@ -218,13 +227,13 @@ class VariantData {
|
||||
_content.asString.size = s.size();
|
||||
}
|
||||
|
||||
CollectionData &toArray() {
|
||||
CollectionData& toArray() {
|
||||
setType(VALUE_IS_ARRAY);
|
||||
_content.asCollection.clear();
|
||||
return _content.asCollection;
|
||||
}
|
||||
|
||||
CollectionData &toObject() {
|
||||
CollectionData& toObject() {
|
||||
setType(VALUE_IS_OBJECT);
|
||||
_content.asCollection.clear();
|
||||
return _content.asCollection;
|
||||
@@ -245,15 +254,11 @@ class VariantData {
|
||||
}
|
||||
}
|
||||
|
||||
size_t nesting() const {
|
||||
return isCollection() ? _content.asCollection.nesting() : 0;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return isCollection() ? _content.asCollection.size() : 0;
|
||||
}
|
||||
|
||||
VariantData *addElement(MemoryPool *pool) {
|
||||
VariantData* addElement(MemoryPool* pool) {
|
||||
if (isNull())
|
||||
toArray();
|
||||
if (!isArray())
|
||||
@@ -261,11 +266,12 @@ class VariantData {
|
||||
return _content.asCollection.addElement(pool);
|
||||
}
|
||||
|
||||
VariantData *getElement(size_t index) const {
|
||||
return isArray() ? _content.asCollection.getElement(index) : 0;
|
||||
VariantData* getElement(size_t index) const {
|
||||
const CollectionData* col = asArray();
|
||||
return col ? col->getElement(index) : 0;
|
||||
}
|
||||
|
||||
VariantData *getOrAddElement(size_t index, MemoryPool *pool) {
|
||||
VariantData* getOrAddElement(size_t index, MemoryPool* pool) {
|
||||
if (isNull())
|
||||
toArray();
|
||||
if (!isArray())
|
||||
@@ -274,18 +280,18 @@ class VariantData {
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *getMember(TAdaptedString key) const {
|
||||
return isObject() ? _content.asCollection.getMember(key) : 0;
|
||||
VariantData* getMember(TAdaptedString key) const {
|
||||
const CollectionData* col = asObject();
|
||||
return col ? col->getMember(key) : 0;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool,
|
||||
TStoragePolicy storage_policy) {
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool) {
|
||||
if (isNull())
|
||||
toObject();
|
||||
if (!isObject())
|
||||
return 0;
|
||||
return _content.asCollection.getOrAddMember(key, pool, storage_policy);
|
||||
return _content.asCollection.getOrAddMember(key, pool);
|
||||
}
|
||||
|
||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
||||
@@ -299,15 +305,14 @@ class VariantData {
|
||||
return _flags & VALUE_MASK;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
inline bool storeString(TAdaptedString value, MemoryPool *pool,
|
||||
TStoragePolicy storage) {
|
||||
template <typename TAdaptedString>
|
||||
inline bool setString(TAdaptedString value, MemoryPool* pool) {
|
||||
if (value.isNull()) {
|
||||
setNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
return storage.store(value, pool, VariantStringSetter(this));
|
||||
return storeString(pool, value, VariantStringSetter(this));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -317,7 +322,7 @@ class VariantData {
|
||||
}
|
||||
|
||||
struct VariantStringSetter {
|
||||
VariantStringSetter(VariantData *instance) : _instance(instance) {}
|
||||
VariantStringSetter(VariantData* instance) : _instance(instance) {}
|
||||
|
||||
template <typename TStoredString>
|
||||
void operator()(TStoredString s) {
|
||||
@@ -327,7 +332,7 @@ class VariantData {
|
||||
_instance->setNull();
|
||||
}
|
||||
|
||||
VariantData *_instance;
|
||||
VariantData* _instance;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -7,32 +7,21 @@
|
||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
#include <ArduinoJson/Variant/Visitor.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TVisitor>
|
||||
inline typename TVisitor::result_type variantAccept(const VariantData *var,
|
||||
TVisitor &visitor) {
|
||||
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) {
|
||||
inline bool variantCopyFrom(VariantData* dst, const VariantData* src,
|
||||
MemoryPool* pool) {
|
||||
if (!dst)
|
||||
return false;
|
||||
if (!src) {
|
||||
@@ -42,68 +31,83 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
|
||||
return dst->copyFrom(*src, pool);
|
||||
}
|
||||
|
||||
inline int variantCompare(const VariantData *a, const VariantData *b);
|
||||
|
||||
inline void variantSetNull(VariantData *var) {
|
||||
inline void variantSetNull(VariantData* var) {
|
||||
if (!var)
|
||||
return;
|
||||
var->setNull();
|
||||
}
|
||||
|
||||
template <typename TAdaptedString, typename TStoragePolicy>
|
||||
inline bool variantSetString(VariantData *var, TAdaptedString value,
|
||||
MemoryPool *pool, TStoragePolicy storage_policy) {
|
||||
return var != 0 ? var->storeString(value, pool, storage_policy) : 0;
|
||||
template <typename TAdaptedString>
|
||||
inline bool variantSetString(VariantData* var, TAdaptedString value,
|
||||
MemoryPool* pool) {
|
||||
return var != 0 ? var->setString(value, pool) : 0;
|
||||
}
|
||||
|
||||
inline size_t variantSize(const VariantData *var) {
|
||||
inline size_t variantSize(const VariantData* var) {
|
||||
return var != 0 ? var->size() : 0;
|
||||
}
|
||||
|
||||
inline CollectionData *variantToArray(VariantData *var) {
|
||||
inline CollectionData* variantToArray(VariantData* var) {
|
||||
if (!var)
|
||||
return 0;
|
||||
return &var->toArray();
|
||||
}
|
||||
|
||||
inline CollectionData *variantToObject(VariantData *var) {
|
||||
inline CollectionData* variantToObject(VariantData* var) {
|
||||
if (!var)
|
||||
return 0;
|
||||
return &var->toObject();
|
||||
}
|
||||
|
||||
inline NO_INLINE VariantData *variantAddElement(VariantData *var,
|
||||
MemoryPool *pool) {
|
||||
inline VariantData* variantGetElement(const VariantData* var, size_t index) {
|
||||
return var != 0 ? var->getElement(index) : 0;
|
||||
}
|
||||
|
||||
inline NO_INLINE VariantData* variantAddElement(VariantData* var,
|
||||
MemoryPool* pool) {
|
||||
return var != 0 ? var->addElement(pool) : 0;
|
||||
}
|
||||
|
||||
inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var,
|
||||
inline NO_INLINE VariantData* variantGetOrAddElement(VariantData* var,
|
||||
size_t index,
|
||||
MemoryPool *pool) {
|
||||
MemoryPool* pool) {
|
||||
return var != 0 ? var->getOrAddElement(index, pool) : 0;
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
|
||||
MemoryPool *pool) {
|
||||
template <typename TAdaptedString>
|
||||
VariantData* variantGetMember(const VariantData* var, TAdaptedString key) {
|
||||
if (!var)
|
||||
return 0;
|
||||
return var->getOrAddMember(adaptString(key), pool,
|
||||
getStringStoragePolicy(key));
|
||||
return var->getMember(key);
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
|
||||
const TString &key,
|
||||
MemoryPool *pool) {
|
||||
template <typename TAdaptedString>
|
||||
VariantData* variantGetOrAddMember(VariantData* var, TAdaptedString key,
|
||||
MemoryPool* pool) {
|
||||
if (!var)
|
||||
return 0;
|
||||
return var->getOrAddMember(adaptString(key), pool,
|
||||
getStringStoragePolicy(key));
|
||||
return var->getOrAddMember(key, pool);
|
||||
}
|
||||
|
||||
inline bool variantIsNull(const VariantData *var) {
|
||||
inline bool variantIsNull(const VariantData* var) {
|
||||
return var == 0 || var->isNull();
|
||||
}
|
||||
|
||||
inline size_t variantNesting(const VariantData* var) {
|
||||
if (!var)
|
||||
return 0;
|
||||
|
||||
const CollectionData* collection = var->asCollection();
|
||||
if (!collection)
|
||||
return 0;
|
||||
|
||||
size_t maxChildNesting = 0;
|
||||
for (const VariantSlot* s = collection->head(); s; s = s->next()) {
|
||||
size_t childNesting = variantNesting(s->data());
|
||||
if (childNesting > maxChildNesting)
|
||||
maxChildNesting = childNesting;
|
||||
}
|
||||
return maxChildNesting + 1;
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/ArrayRef.hpp>
|
||||
#include <ArduinoJson/Array/JsonArray.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 <ArduinoJson/Object/JsonObject.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariant.hpp>
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
@@ -70,29 +70,28 @@ inline T VariantData::asFloat() const {
|
||||
}
|
||||
}
|
||||
|
||||
inline String VariantData::asString() const {
|
||||
inline JsonString VariantData::asString() const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
return String(_content.asString.data, _content.asString.size,
|
||||
String::Linked);
|
||||
return JsonString(_content.asString.data, _content.asString.size,
|
||||
JsonString::Linked);
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return String(_content.asString.data, _content.asString.size,
|
||||
String::Copied);
|
||||
return JsonString(_content.asString.data, _content.asString.size,
|
||||
JsonString::Copied);
|
||||
default:
|
||||
return String();
|
||||
return JsonString();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool VariantData::copyFrom(const VariantData &src, MemoryPool *pool) {
|
||||
inline bool VariantData::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: {
|
||||
String value = src.asString();
|
||||
return storeString(adaptString(value), pool,
|
||||
getStringStoragePolicy(value));
|
||||
JsonString value = src.asString();
|
||||
return setString(adaptString(value), pool);
|
||||
}
|
||||
case VALUE_IS_OWNED_RAW:
|
||||
return storeOwnedRaw(
|
||||
@@ -105,80 +104,48 @@ inline bool VariantData::copyFrom(const VariantData &src, MemoryPool *pool) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
|
||||
VariantRef::to() const {
|
||||
return ArrayRef(_pool, variantToArray(_data));
|
||||
template <typename TDerived>
|
||||
inline JsonVariant VariantRefBase<TDerived>::add() const {
|
||||
return JsonVariant(getPool(),
|
||||
variantAddElement(getOrCreateData(), getPool()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type
|
||||
VariantRef::to() const {
|
||||
return ObjectRef(_pool, variantToObject(_data));
|
||||
template <typename TDerived>
|
||||
inline JsonVariant VariantRefBase<TDerived>::getVariant() const {
|
||||
return JsonVariant(getPool(), getData());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const {
|
||||
return JsonVariant(getPool(), getOrCreateData());
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type
|
||||
VariantRef::to() const {
|
||||
variantSetNull(_data);
|
||||
inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
|
||||
VariantRefBase<TDerived>::to() const {
|
||||
return JsonArray(getPool(), variantToArray(getOrCreateData()));
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
|
||||
VariantRefBase<TDerived>::to() const {
|
||||
return JsonObject(getPool(), variantToObject(getOrCreateData()));
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
|
||||
VariantRefBase<TDerived>::to() const {
|
||||
variantSetNull(getOrCreateData());
|
||||
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;
|
||||
}
|
||||
|
||||
// Out of class definition to avoid #1560
|
||||
inline bool VariantRef::set(char value) const {
|
||||
return set(static_cast<signed char>(value));
|
||||
}
|
||||
|
||||
// TODO: move somewhere else
|
||||
template <typename TAdaptedString, typename TCallback>
|
||||
bool CopyStringStoragePolicy::store(TAdaptedString str, MemoryPool *pool,
|
||||
TCallback callback) {
|
||||
const char *copy = pool->saveString(str);
|
||||
String storedString(copy, str.size(), String::Copied);
|
||||
callback(storedString);
|
||||
return copy != 0;
|
||||
template <typename TDerived>
|
||||
inline void convertToJson(const VariantRefBase<TDerived>& src,
|
||||
JsonVariant dst) {
|
||||
dst.set(src.template as<JsonVariantConst>());
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Misc/Visitable.hpp>
|
||||
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
|
||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
@@ -12,12 +11,17 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T1, typename T2>
|
||||
CompareResult compare(const T1 &lhs, const T2 &rhs); // VariantCompare.cpp
|
||||
class JsonVariantConst;
|
||||
|
||||
template <typename T>
|
||||
CompareResult compare(JsonVariantConst lhs,
|
||||
const T& rhs); // VariantCompare.cpp
|
||||
|
||||
struct VariantOperatorTag {};
|
||||
|
||||
template <typename TVariant>
|
||||
struct VariantOperators {
|
||||
// Returns the default value if the VariantRef is unbound or incompatible
|
||||
struct VariantOperators : VariantOperatorTag {
|
||||
// Returns the default value if the JsonVariant is unbound or incompatible
|
||||
//
|
||||
// int operator|(JsonVariant, int)
|
||||
// float operator|(JsonVariant, float)
|
||||
@@ -25,7 +29,7 @@ struct VariantOperators {
|
||||
template <typename T>
|
||||
friend
|
||||
typename enable_if<!IsVariant<T>::value && !is_array<T>::value, T>::type
|
||||
operator|(const TVariant &variant, const T &defaultValue) {
|
||||
operator|(const TVariant& variant, const T& defaultValue) {
|
||||
if (variant.template is<T>())
|
||||
return variant.template as<T>();
|
||||
else
|
||||
@@ -33,18 +37,18 @@ struct VariantOperators {
|
||||
}
|
||||
//
|
||||
// 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 *>();
|
||||
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) {
|
||||
friend typename enable_if<IsVariant<T>::value, JsonVariantConst>::type
|
||||
operator|(const TVariant& variant, T defaultValue) {
|
||||
if (variant)
|
||||
return variant;
|
||||
else
|
||||
@@ -53,127 +57,133 @@ struct VariantOperators {
|
||||
|
||||
// value == TVariant
|
||||
template <typename T>
|
||||
friend bool operator==(T *lhs, TVariant rhs) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
friend
|
||||
typename enable_if<!is_base_of<VariantOperatorTag, 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
friend
|
||||
typename enable_if<!is_base_of<VariantOperatorTag, 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
friend
|
||||
typename enable_if<!is_base_of<VariantOperatorTag, 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
friend
|
||||
typename enable_if<!is_base_of<VariantOperatorTag, 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
friend
|
||||
typename enable_if<!is_base_of<VariantOperatorTag, 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
friend
|
||||
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
|
||||
operator>=(TVariant lhs, const T& rhs) {
|
||||
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,381 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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 isUnbound() 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 {
|
||||
Converter<T>::toJson(value, *this);
|
||||
return _pool && !_pool->overflowed();
|
||||
}
|
||||
|
||||
bool ARDUINOJSON_DEPRECATED(
|
||||
"Support for char is deprecated, use int8_t or uint8_t instead")
|
||||
set(char value) const;
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool set(T *value) const {
|
||||
Converter<T *>::toJson(value, *this);
|
||||
return _pool && !_pool->overflowed();
|
||||
}
|
||||
|
||||
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 static_cast<char>(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 static_cast<char>(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 void toJson(VariantRef src, VariantRef dst) {
|
||||
variantCopyFrom(getData(dst), getData(src), getPool(dst));
|
||||
}
|
||||
|
||||
static VariantRef fromJson(VariantRef src) {
|
||||
return src;
|
||||
}
|
||||
|
||||
static InvalidConversion<VariantConstRef, VariantRef> fromJson(
|
||||
VariantConstRef);
|
||||
|
||||
static bool checkJson(VariantRef src) {
|
||||
VariantData *data = getData(src);
|
||||
return !!data;
|
||||
}
|
||||
|
||||
static bool checkJson(VariantConstRef) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<VariantConstRef> {
|
||||
static void toJson(VariantConstRef src, VariantRef dst) {
|
||||
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
|
||||
299
lib/ArduinoJson/src/ArduinoJson/Variant/VariantRefBase.hpp
Normal file
299
lib/ArduinoJson/src/ArduinoJson/Variant/VariantRefBase.hpp
Normal file
@@ -0,0 +1,299 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Configuration.hpp>
|
||||
#include <ArduinoJson/Variant/Converter.hpp>
|
||||
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
|
||||
#include <ArduinoJson/Variant/VariantOperators.hpp>
|
||||
#include <ArduinoJson/Variant/VariantTo.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonVariant;
|
||||
|
||||
template <typename>
|
||||
class ElementProxy;
|
||||
|
||||
template <typename, typename>
|
||||
class MemberProxy;
|
||||
|
||||
template <typename TDerived>
|
||||
class VariantRefBase : public VariantTag {
|
||||
friend class VariantAttorney;
|
||||
|
||||
public:
|
||||
// Sets the value to null.
|
||||
// ⚠️ Doesn't release the memory associated with the previous value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/clear/
|
||||
FORCE_INLINE void clear() const {
|
||||
variantSetNull(getData());
|
||||
}
|
||||
|
||||
// Returns true if the value is null or the reference is unbound.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/isnull/
|
||||
FORCE_INLINE bool isNull() const {
|
||||
return variantIsNull(getData());
|
||||
}
|
||||
|
||||
// Returns true if the reference is unbound.
|
||||
FORCE_INLINE bool isUnbound() const {
|
||||
return !getData();
|
||||
}
|
||||
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/as/
|
||||
template <typename T>
|
||||
FORCE_INLINE typename enable_if<!is_same<T, char*>::value &&
|
||||
!is_same<T, char>::value &&
|
||||
!ConverterNeedsWriteableRef<T>::value,
|
||||
T>::type
|
||||
as() const {
|
||||
return Converter<T>::fromJson(getVariantConst());
|
||||
}
|
||||
|
||||
// Casts the value to the specified type.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/as/
|
||||
template <typename T>
|
||||
FORCE_INLINE typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
|
||||
as() const {
|
||||
return Converter<T>::fromJson(getVariant());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE operator T() const {
|
||||
return as<T>();
|
||||
}
|
||||
|
||||
// Sets the value to an empty array.
|
||||
// ⚠️ Doesn't release the memory associated with the previous value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/to/
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type to() const;
|
||||
|
||||
// Sets the value to an empty object.
|
||||
// ⚠️ Doesn't release the memory associated with the previous value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/to/
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type to()
|
||||
const;
|
||||
|
||||
// Sets the value to null.
|
||||
// ⚠️ Doesn't release the memory associated with the previous value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/to/
|
||||
template <typename T>
|
||||
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type to()
|
||||
const;
|
||||
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/is/
|
||||
template <typename T>
|
||||
FORCE_INLINE
|
||||
typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
|
||||
is() const {
|
||||
return Converter<T>::checkJson(getVariant());
|
||||
}
|
||||
|
||||
// Returns true if the value is of the specified type.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/is/
|
||||
template <typename T>
|
||||
FORCE_INLINE typename enable_if<!ConverterNeedsWriteableRef<T>::value &&
|
||||
!is_same<T, char*>::value &&
|
||||
!is_same<T, char>::value,
|
||||
bool>::type
|
||||
is() const {
|
||||
return Converter<T>::checkJson(getVariantConst());
|
||||
}
|
||||
|
||||
// Shallow copies the specified value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/shallowcopy/
|
||||
FORCE_INLINE void shallowCopy(JsonVariantConst target) {
|
||||
VariantData* data = getOrCreateData();
|
||||
if (!data)
|
||||
return;
|
||||
const VariantData* targetData = VariantAttorney::getData(target);
|
||||
if (targetData)
|
||||
*data = *targetData;
|
||||
else
|
||||
data->setNull();
|
||||
}
|
||||
|
||||
// Copies the specified value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/set/
|
||||
template <typename T>
|
||||
FORCE_INLINE bool set(const T& value) const {
|
||||
Converter<T>::toJson(value, getOrCreateVariant());
|
||||
MemoryPool* pool = getPool();
|
||||
return pool && !pool->overflowed();
|
||||
}
|
||||
|
||||
// Copies the specified value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/set/
|
||||
template <typename T>
|
||||
FORCE_INLINE bool set(T* value) const {
|
||||
Converter<T*>::toJson(value, getOrCreateVariant());
|
||||
MemoryPool* pool = getPool();
|
||||
return pool && !pool->overflowed();
|
||||
}
|
||||
|
||||
// Returns the size of the array or object.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/size/
|
||||
FORCE_INLINE size_t size() const {
|
||||
return variantSize(getData());
|
||||
}
|
||||
|
||||
// Returns the number of bytes occupied by the value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/memoryusage/
|
||||
FORCE_INLINE size_t memoryUsage() const {
|
||||
VariantData* data = getData();
|
||||
return data ? data->memoryUsage() : 0;
|
||||
}
|
||||
|
||||
// Returns the depth (nesting level) of the value.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/nesting/
|
||||
FORCE_INLINE size_t nesting() const {
|
||||
return variantNesting(getData());
|
||||
}
|
||||
|
||||
// Appends a new (null) element to the array.
|
||||
// Returns a reference to the new element.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/add/
|
||||
FORCE_INLINE JsonVariant add() const;
|
||||
|
||||
// Appends a value to the array.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/add/
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(const T& value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
// Appends a value to the array.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/add/
|
||||
template <typename T>
|
||||
FORCE_INLINE bool add(T* value) const {
|
||||
return add().set(value);
|
||||
}
|
||||
|
||||
// Removes an element of the array.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/remove/
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
VariantData* data = getData();
|
||||
if (data)
|
||||
data->remove(index);
|
||||
}
|
||||
|
||||
// Removes a member of the object.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/remove/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
|
||||
TChar* key) const {
|
||||
VariantData* data = getData();
|
||||
if (data)
|
||||
data->remove(adaptString(key));
|
||||
}
|
||||
|
||||
// Removes a member of the object.
|
||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/remove/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
|
||||
const TString& key) const {
|
||||
VariantData* data = getData();
|
||||
if (data)
|
||||
data->remove(adaptString(key));
|
||||
}
|
||||
|
||||
// Creates an array and appends it to the array.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/createnestedarray/
|
||||
FORCE_INLINE JsonArray createNestedArray() const;
|
||||
|
||||
// Creates an object and appends it to the array.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/createnestedobject/
|
||||
FORCE_INLINE JsonObject createNestedObject() const;
|
||||
|
||||
// Gets or sets an array element.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/subscript/
|
||||
FORCE_INLINE ElementProxy<TDerived> operator[](size_t index) const;
|
||||
|
||||
// Returns true if the object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/containskey/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
|
||||
containsKey(const TString& key) const;
|
||||
|
||||
// Returns true if the object contains the specified key.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/containskey/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value, bool>::type
|
||||
containsKey(TChar* key) const;
|
||||
|
||||
// Gets or sets an object member.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/subscript/
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename enable_if<IsString<TString>::value,
|
||||
MemberProxy<TDerived, TString> >::type
|
||||
operator[](const TString& key) const;
|
||||
|
||||
// Gets or sets an object member.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/subscript/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
|
||||
MemberProxy<TDerived, TChar*> >::type
|
||||
operator[](TChar* key) const;
|
||||
|
||||
// Creates an array and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/createnestedarray/
|
||||
template <typename TString>
|
||||
FORCE_INLINE JsonArray createNestedArray(const TString& key) const;
|
||||
|
||||
// Creates an array and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/createnestedarray/
|
||||
template <typename TChar>
|
||||
FORCE_INLINE JsonArray createNestedArray(TChar* key) const;
|
||||
|
||||
// Creates an object and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/createnestedobject/
|
||||
template <typename TString>
|
||||
JsonObject createNestedObject(const TString& key) const;
|
||||
|
||||
// Creates an object and adds it to the object.
|
||||
// https://arduinojson.org/v6/api/jsonvariant/createnestedobject/
|
||||
template <typename TChar>
|
||||
JsonObject createNestedObject(TChar* key) const;
|
||||
|
||||
private:
|
||||
TDerived& derived() {
|
||||
return static_cast<TDerived&>(*this);
|
||||
}
|
||||
|
||||
const TDerived& derived() const {
|
||||
return static_cast<const TDerived&>(*this);
|
||||
}
|
||||
|
||||
FORCE_INLINE MemoryPool* getPool() const {
|
||||
return VariantAttorney::getPool(derived());
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantData* getData() const {
|
||||
return VariantAttorney::getData(derived());
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantData* getOrCreateData() const {
|
||||
return VariantAttorney::getOrCreateData(derived());
|
||||
}
|
||||
|
||||
private:
|
||||
FORCE_INLINE JsonVariant getVariant() const;
|
||||
|
||||
FORCE_INLINE JsonVariantConst getVariantConst() const {
|
||||
return JsonVariantConst(getData());
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariant getOrCreateVariant() const;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
@@ -1,23 +0,0 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright © 2014-2022, Benoit BLANCHON
|
||||
// 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
|
||||
@@ -76,7 +76,7 @@ class VariantSlot {
|
||||
_next = VariantSlotDiff(slot - this);
|
||||
}
|
||||
|
||||
void setKey(String k) {
|
||||
void setKey(JsonString k) {
|
||||
ARDUINOJSON_ASSERT(k);
|
||||
if (k.isLinked())
|
||||
_flags &= VALUE_MASK;
|
||||
|
||||
@@ -7,26 +7,26 @@
|
||||
#include <ArduinoJson/Namespace.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class ArrayRef;
|
||||
class ObjectRef;
|
||||
class VariantRef;
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
class JsonVariant;
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// VariantRef::to<T>()
|
||||
// JsonVariant::to<T>()
|
||||
template <typename T>
|
||||
struct VariantTo {};
|
||||
|
||||
template <>
|
||||
struct VariantTo<ArrayRef> {
|
||||
typedef ArrayRef type;
|
||||
struct VariantTo<JsonArray> {
|
||||
typedef JsonArray type;
|
||||
};
|
||||
template <>
|
||||
struct VariantTo<ObjectRef> {
|
||||
typedef ObjectRef type;
|
||||
struct VariantTo<JsonObject> {
|
||||
typedef JsonObject type;
|
||||
};
|
||||
template <>
|
||||
struct VariantTo<VariantRef> {
|
||||
typedef VariantRef type;
|
||||
struct VariantTo<JsonVariant> {
|
||||
typedef JsonVariant type;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Collection/CollectionData.hpp>
|
||||
#include <ArduinoJson/Numbers/Float.hpp>
|
||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonFloat.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonInteger.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@@ -14,7 +14,7 @@ template <typename TResult>
|
||||
struct Visitor {
|
||||
typedef TResult result_type;
|
||||
|
||||
TResult visitArray(const CollectionData &) {
|
||||
TResult visitArray(const CollectionData&) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@ struct Visitor {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitFloat(Float) {
|
||||
TResult visitFloat(JsonFloat) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitSignedInteger(Integer) {
|
||||
TResult visitSignedInteger(JsonInteger) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
@@ -34,19 +34,19 @@ struct Visitor {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitObject(const CollectionData &) {
|
||||
TResult visitObject(const CollectionData&) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitUnsignedInteger(UInt) {
|
||||
TResult visitUnsignedInteger(JsonUInt) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitRawJson(const char *, size_t) {
|
||||
TResult visitRawJson(const char*, size_t) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitString(const char *, size_t) {
|
||||
TResult visitString(const char*, size_t) {
|
||||
return TResult();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ARDUINOJSON_VERSION "6.19.4"
|
||||
#define ARDUINOJSON_VERSION "6.20.0"
|
||||
#define ARDUINOJSON_VERSION_MAJOR 6
|
||||
#define ARDUINOJSON_VERSION_MINOR 19
|
||||
#define ARDUINOJSON_VERSION_REVISION 4
|
||||
#define ARDUINOJSON_VERSION_MINOR 20
|
||||
#define ARDUINOJSON_VERSION_REVISION 0
|
||||
|
||||
Reference in New Issue
Block a user