初始化提交

This commit is contained in:
王立帮
2024-07-20 22:09:06 +08:00
commit c247dd07a6
6876 changed files with 2743096 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
if (!var)
return false;
return slotSetKey(var, key, pool, typename TAdaptedString::storage_policy());
}
template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
storage_policies::decide_at_runtime) {
if (key.isStatic()) {
return slotSetKey(var, key, pool, storage_policies::store_by_address());
} else {
return slotSetKey(var, key, pool, storage_policies::store_by_copy());
}
}
template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
storage_policies::store_by_address) {
ARDUINOJSON_ASSERT(var);
var->setKey(key.data(), storage_policies::store_by_address());
return true;
}
template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
storage_policies::store_by_copy) {
const char* dup = pool->saveString(key);
if (!dup)
return false;
ARDUINOJSON_ASSERT(var);
var->setKey(dup, storage_policies::store_by_copy());
return true;
}
inline size_t slotSize(const VariantSlot* var) {
size_t n = 0;
while (var) {
n++;
var = var->next();
}
return n;
}
inline VariantData* slotData(VariantSlot* slot) {
return reinterpret_cast<VariantData*>(slot);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,113 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Strings/IsWriteableString.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
namespace ARDUINOJSON_NAMESPACE {
class ArrayRef;
class ArrayConstRef;
class ObjectRef;
class ObjectConstRef;
class VariantRef;
class VariantConstRef;
// A metafunction that returns the type of the value returned by
// VariantRef::as<T>()
template <typename T>
struct VariantAs {
typedef T type;
};
template <>
struct VariantAs<char*> {
typedef const char* type;
};
// A metafunction that returns the type of the value returned by
// VariantRef::as<T>()
template <typename T>
struct VariantConstAs {
typedef typename VariantAs<T>::type type;
};
template <>
struct VariantConstAs<VariantRef> {
typedef VariantConstRef type;
};
template <>
struct VariantConstAs<ObjectRef> {
typedef ObjectConstRef type;
};
template <>
struct VariantConstAs<ArrayRef> {
typedef ArrayConstRef type;
};
// ---
template <typename T>
inline typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
T>::type
variantAs(const VariantData* data) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
return data != 0 ? data->asIntegral<T>() : T(0);
}
template <typename T>
inline typename enable_if<is_enum<T>::value, T>::type variantAs(
const VariantData* data) {
return data != 0 ? static_cast<T>(data->asIntegral<int>()) : T();
}
template <typename T>
inline typename enable_if<is_same<T, bool>::value, T>::type variantAs(
const VariantData* data) {
return data != 0 ? data->asBoolean() : false;
}
template <typename T>
inline typename enable_if<is_floating_point<T>::value, T>::type variantAs(
const VariantData* data) {
return data != 0 ? data->asFloat<T>() : T(0);
}
template <typename T>
inline typename enable_if<is_same<T, const char*>::value ||
is_same<T, char*>::value,
const char*>::type
variantAs(const VariantData* data) {
return data != 0 ? data->asString() : 0;
}
template <typename T>
T variantAs(VariantData* data, MemoryPool*) {
// By default use the read-only conversion.
// There are specializations for
// - ArrayRef
return variantAs<T>(data);
}
template <typename T>
inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
const VariantData* data);
template <typename T>
inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
const VariantData* data);
template <typename T>
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
variantAs(const VariantData* data);
template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const VariantData* data);
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,57 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Strings/IsWriteableString.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
const VariantData* _data) {
return ArrayConstRef(variantAsArray(_data));
}
template <typename T>
inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
const VariantData* _data) {
return ObjectConstRef(variantAsObject(_data));
}
template <typename T>
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
variantAs(const VariantData* _data) {
return VariantConstRef(_data);
}
template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const VariantData* _data) {
const char* cstr = _data != 0 ? _data->asString() : 0;
if (cstr)
return T(cstr);
T s;
serializeJson(VariantConstRef(_data), s);
return s;
}
template <>
inline ArrayRef variantAs<ArrayRef>(VariantData* data, MemoryPool* pool) {
return ArrayRef(pool, data != 0 ? data->asArray() : 0);
}
template <>
inline ObjectRef variantAs<ObjectRef>(VariantData* data, MemoryPool* pool) {
return ObjectRef(pool, data != 0 ? data->asObject() : 0);
}
template <>
inline VariantRef variantAs<VariantRef>(VariantData* data, MemoryPool* pool) {
return VariantRef(pool, data);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,257 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
namespace ARDUINOJSON_NAMESPACE {
class CollectionData;
struct ComparerBase : Visitor<CompareResult> {
CompareResult visitArray(const CollectionData &) {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitBoolean(bool) {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitFloat(Float) {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitNegativeInteger(UInt) {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitNull() {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitObject(const CollectionData &) {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitPositiveInteger(UInt) {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitRawJson(const char *, size_t) {
return COMPARE_RESULT_DIFFER;
}
CompareResult visitString(const char *) {
return COMPARE_RESULT_DIFFER;
}
};
template <typename T, typename Enable = void>
struct Comparer;
template <typename T>
struct Comparer<T, typename enable_if<IsString<T>::value>::type>
: ComparerBase {
T rhs;
explicit Comparer(T value) : rhs(value) {}
CompareResult visitString(const char *lhs) {
int i = adaptString(rhs).compare(lhs);
if (i < 0)
return COMPARE_RESULT_GREATER;
else if (i > 0)
return COMPARE_RESULT_LESS;
else
return COMPARE_RESULT_EQUAL;
}
CompareResult visitNull() {
if (adaptString(rhs).isNull())
return COMPARE_RESULT_EQUAL;
else
return COMPARE_RESULT_DIFFER;
}
};
template <typename T>
struct Comparer<T, typename enable_if<is_integral<T>::value ||
is_floating_point<T>::value>::type>
: ComparerBase {
T rhs;
explicit Comparer(T value) : rhs(value) {}
CompareResult visitFloat(Float lhs) {
return arithmeticCompare(lhs, rhs);
}
CompareResult visitNegativeInteger(UInt lhs) {
return arithmeticCompareNegateLeft(lhs, rhs);
}
CompareResult visitPositiveInteger(UInt lhs) {
return arithmeticCompare(lhs, rhs);
}
CompareResult visitBoolean(bool lhs) {
return visitPositiveInteger(static_cast<UInt>(lhs));
}
};
struct NullComparer : ComparerBase {
CompareResult visitNull() {
return COMPARE_RESULT_EQUAL;
}
};
#if ARDUINOJSON_HAS_NULLPTR
template <>
struct Comparer<decltype(nullptr), void> : NullComparer {
explicit Comparer(decltype(nullptr)) : NullComparer() {}
};
#endif
struct ArrayComparer : ComparerBase {
const CollectionData *_rhs;
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
CompareResult visitArray(const CollectionData &lhs) {
if (lhs.equalsArray(*_rhs))
return COMPARE_RESULT_EQUAL;
else
return COMPARE_RESULT_DIFFER;
}
};
struct NegativeIntegerComparer : ComparerBase {
UInt _rhs;
explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
CompareResult visitFloat(Float lhs) {
return arithmeticCompareNegateRight(lhs, _rhs);
}
CompareResult visitNegativeInteger(UInt lhs) {
return arithmeticCompare(_rhs, lhs);
}
CompareResult visitPositiveInteger(UInt) {
return COMPARE_RESULT_GREATER;
}
CompareResult visitBoolean(bool) {
return COMPARE_RESULT_GREATER;
}
};
struct ObjectComparer : ComparerBase {
const CollectionData *_rhs;
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
CompareResult visitObject(const CollectionData &lhs) {
if (lhs.equalsObject(*_rhs))
return COMPARE_RESULT_EQUAL;
else
return COMPARE_RESULT_DIFFER;
}
};
struct RawComparer : ComparerBase {
const char *_rhsData;
size_t _rhsSize;
explicit RawComparer(const char *rhsData, size_t rhsSize)
: _rhsData(rhsData), _rhsSize(rhsSize) {}
CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
int n = memcmp(lhsData, _rhsData, size);
if (n < 0)
return COMPARE_RESULT_LESS;
else if (n > 0)
return COMPARE_RESULT_GREATER;
else
return COMPARE_RESULT_EQUAL;
}
};
template <typename T>
struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
: ComparerBase {
T rhs;
explicit Comparer(T value) : rhs(value) {}
CompareResult visitArray(const CollectionData &lhs) {
ArrayComparer comparer(lhs);
return accept(comparer);
}
CompareResult visitObject(const CollectionData &lhs) {
ObjectComparer comparer(lhs);
return accept(comparer);
}
CompareResult visitFloat(Float lhs) {
Comparer<Float> comparer(lhs);
return accept(comparer);
}
CompareResult visitString(const char *lhs) {
Comparer<const char *> comparer(lhs);
return accept(comparer);
}
CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
RawComparer comparer(lhsData, lhsSize);
return accept(comparer);
}
CompareResult visitNegativeInteger(UInt lhs) {
NegativeIntegerComparer comparer(lhs);
return accept(comparer);
}
CompareResult visitPositiveInteger(UInt lhs) {
Comparer<UInt> comparer(lhs);
return accept(comparer);
}
CompareResult visitBoolean(bool lhs) {
Comparer<bool> comparer(lhs);
return accept(comparer);
}
CompareResult visitNull() {
NullComparer comparer;
return accept(comparer);
}
private:
template <typename TComparer>
CompareResult accept(TComparer &comparer) {
CompareResult reversedResult = rhs.accept(comparer);
switch (reversedResult) {
case COMPARE_RESULT_GREATER:
return COMPARE_RESULT_LESS;
case COMPARE_RESULT_LESS:
return COMPARE_RESULT_GREATER;
default:
return reversedResult;
}
}
};
template <typename T1, typename T2>
CompareResult compare(const T1 &lhs, const T2 &rhs) {
Comparer<T2> comparer(rhs);
return lhs.accept(comparer);
}
inline int variantCompare(const VariantData *a, const VariantData *b) {
return compare(VariantConstRef(a), VariantConstRef(b));
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,54 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <stddef.h> // size_t
#include <ArduinoJson/Collection/CollectionData.hpp>
#include <ArduinoJson/Numbers/Float.hpp>
#include <ArduinoJson/Numbers/Integer.hpp>
namespace ARDUINOJSON_NAMESPACE {
//
enum {
VALUE_MASK = 0x7F,
VALUE_IS_OWNED = 0x01,
VALUE_IS_NULL = 0,
VALUE_IS_LINKED_RAW = 0x02,
VALUE_IS_OWNED_RAW = 0x03,
VALUE_IS_LINKED_STRING = 0x04,
VALUE_IS_OWNED_STRING = 0x05,
// CAUTION: no VALUE_IS_OWNED below
VALUE_IS_BOOLEAN = 0x06,
VALUE_IS_POSITIVE_INTEGER = 0x08,
VALUE_IS_NEGATIVE_INTEGER = 0x0A,
VALUE_IS_FLOAT = 0x0C,
COLLECTION_MASK = 0x60,
VALUE_IS_OBJECT = 0x20,
VALUE_IS_ARRAY = 0x40,
KEY_IS_OWNED = 0x80
};
struct RawData {
const char *data;
size_t size;
};
union VariantContent {
Float asFloat;
UInt asInteger;
CollectionData asCollection;
const char *asString;
struct {
const char *data;
size_t size;
} asRaw;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,389 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Misc/SerializedValue.hpp>
#include <ArduinoJson/Numbers/convertNumber.hpp>
#include <ArduinoJson/Strings/RamStringAdapter.hpp>
#include <ArduinoJson/Variant/VariantContent.hpp>
// VariantData can't have a constructor (to be a POD), so we have no way to fix
// this warning
#if defined(__GNUC__)
#if __GNUC__ >= 7
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
#endif
namespace ARDUINOJSON_NAMESPACE {
class VariantData {
VariantContent _content; // must be first to allow cast from array to variant
uint8_t _flags;
public:
// Must be a POD!
// - no constructor
// - no destructor
// - no virtual
// - no inheritance
void init() {
_flags = 0;
}
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor &visitor) const {
switch (type()) {
case VALUE_IS_FLOAT:
return visitor.visitFloat(_content.asFloat);
case VALUE_IS_ARRAY:
return visitor.visitArray(_content.asCollection);
case VALUE_IS_OBJECT:
return visitor.visitObject(_content.asCollection);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return visitor.visitString(_content.asString);
case VALUE_IS_OWNED_RAW:
case VALUE_IS_LINKED_RAW:
return visitor.visitRawJson(_content.asRaw.data, _content.asRaw.size);
case VALUE_IS_NEGATIVE_INTEGER:
return visitor.visitNegativeInteger(_content.asInteger);
case VALUE_IS_POSITIVE_INTEGER:
return visitor.visitPositiveInteger(_content.asInteger);
case VALUE_IS_BOOLEAN:
return visitor.visitBoolean(_content.asInteger != 0);
default:
return visitor.visitNull();
}
}
template <typename T>
T asIntegral() const;
template <typename T>
T asFloat() const;
const char *asString() const;
bool asBoolean() const;
CollectionData *asArray() {
return isArray() ? &_content.asCollection : 0;
}
const CollectionData *asArray() const {
return const_cast<VariantData *>(this)->asArray();
}
CollectionData *asObject() {
return isObject() ? &_content.asCollection : 0;
}
const CollectionData *asObject() const {
return const_cast<VariantData *>(this)->asObject();
}
bool copyFrom(const VariantData &src, MemoryPool *pool) {
switch (src.type()) {
case VALUE_IS_ARRAY:
return toArray().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OBJECT:
return toObject().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OWNED_STRING:
return setString(RamStringAdapter(src._content.asString), pool);
case VALUE_IS_OWNED_RAW:
return setOwnedRaw(
serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
default:
setType(src.type());
_content = src._content;
return true;
}
}
bool isArray() const {
return (_flags & VALUE_IS_ARRAY) != 0;
}
bool isBoolean() const {
return type() == VALUE_IS_BOOLEAN;
}
bool isCollection() const {
return (_flags & COLLECTION_MASK) != 0;
}
template <typename T>
bool isInteger() const {
switch (type()) {
case VALUE_IS_POSITIVE_INTEGER:
return canStorePositiveInteger<T>(_content.asInteger);
case VALUE_IS_NEGATIVE_INTEGER:
return canStoreNegativeInteger<T>(_content.asInteger);
default:
return false;
}
}
bool isFloat() const {
return type() == VALUE_IS_FLOAT || type() == VALUE_IS_POSITIVE_INTEGER ||
type() == VALUE_IS_NEGATIVE_INTEGER;
}
bool isString() const {
return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
}
bool isObject() const {
return (_flags & VALUE_IS_OBJECT) != 0;
}
bool isNull() const {
return type() == VALUE_IS_NULL;
}
bool isEnclosed() const {
return !isFloat();
}
void remove(size_t index) {
if (isArray())
_content.asCollection.removeElement(index);
}
template <typename TAdaptedString>
void remove(TAdaptedString key) {
if (isObject())
_content.asCollection.removeMember(key);
}
void setBoolean(bool value) {
setType(VALUE_IS_BOOLEAN);
_content.asInteger = static_cast<UInt>(value);
}
void setFloat(Float value) {
setType(VALUE_IS_FLOAT);
_content.asFloat = value;
}
void setLinkedRaw(SerializedValue<const char *> value) {
if (value.data()) {
setType(VALUE_IS_LINKED_RAW);
_content.asRaw.data = value.data();
_content.asRaw.size = value.size();
} else {
setType(VALUE_IS_NULL);
}
}
template <typename T>
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
const char *dup = pool->saveString(adaptString(value.data(), value.size()));
if (dup) {
setType(VALUE_IS_OWNED_RAW);
_content.asRaw.data = dup;
_content.asRaw.size = value.size();
return true;
} else {
setType(VALUE_IS_NULL);
return false;
}
}
template <typename T>
typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
setUnsignedInteger(value);
}
template <typename T>
typename enable_if<is_signed<T>::value>::type setInteger(T value) {
setSignedInteger(value);
}
template <typename T>
void setSignedInteger(T value) {
if (value >= 0) {
setPositiveInteger(static_cast<UInt>(value));
} else {
setNegativeInteger(~static_cast<UInt>(value) + 1);
}
}
void setUnsignedInteger(UInt value) {
setType(VALUE_IS_POSITIVE_INTEGER);
_content.asInteger = static_cast<UInt>(value);
}
void setPositiveInteger(UInt value) {
setType(VALUE_IS_POSITIVE_INTEGER);
_content.asInteger = value;
}
void setNegativeInteger(UInt value) {
setType(VALUE_IS_NEGATIVE_INTEGER);
_content.asInteger = value;
}
void setNull() {
setType(VALUE_IS_NULL);
}
void setStringPointer(const char *s, storage_policies::store_by_copy) {
setType(VALUE_IS_OWNED_STRING);
_content.asString = s;
}
void setStringPointer(const char *s, storage_policies::store_by_address) {
setType(VALUE_IS_LINKED_STRING);
_content.asString = s;
}
template <typename TAdaptedString>
bool setString(TAdaptedString value, MemoryPool *pool) {
return setString(value, pool, typename TAdaptedString::storage_policy());
}
template <typename TAdaptedString>
inline bool setString(TAdaptedString value, MemoryPool *pool,
storage_policies::decide_at_runtime) {
if (value.isStatic())
return setString(value, pool, storage_policies::store_by_address());
else
return setString(value, pool, storage_policies::store_by_copy());
}
template <typename TAdaptedString>
inline bool setString(TAdaptedString value, MemoryPool *,
storage_policies::store_by_address) {
if (value.isNull())
setNull();
else
setStringPointer(value.data(), storage_policies::store_by_address());
return true;
}
template <typename TAdaptedString>
inline bool setString(TAdaptedString value, MemoryPool *pool,
storage_policies::store_by_copy) {
if (value.isNull()) {
setNull();
return true;
}
const char *copy = pool->saveString(value);
if (!copy) {
setNull();
return false;
}
setStringPointer(copy, storage_policies::store_by_copy());
return true;
}
CollectionData &toArray() {
setType(VALUE_IS_ARRAY);
_content.asCollection.clear();
return _content.asCollection;
}
CollectionData &toObject() {
setType(VALUE_IS_OBJECT);
_content.asCollection.clear();
return _content.asCollection;
}
size_t memoryUsage() const {
switch (type()) {
case VALUE_IS_OWNED_STRING:
return strlen(_content.asString) + 1;
case VALUE_IS_OWNED_RAW:
return _content.asRaw.size;
case VALUE_IS_OBJECT:
case VALUE_IS_ARRAY:
return _content.asCollection.memoryUsage();
default:
return 0;
}
}
size_t nesting() const {
return isCollection() ? _content.asCollection.nesting() : 0;
}
size_t size() const {
return isCollection() ? _content.asCollection.size() : 0;
}
VariantData *addElement(MemoryPool *pool) {
if (isNull())
toArray();
if (!isArray())
return 0;
return _content.asCollection.addElement(pool);
}
VariantData *getElement(size_t index) const {
return isArray() ? _content.asCollection.getElement(index) : 0;
}
VariantData *getOrAddElement(size_t index, MemoryPool *pool) {
if (isNull())
toArray();
if (!isArray())
return 0;
return _content.asCollection.getOrAddElement(index, pool);
}
template <typename TAdaptedString>
VariantData *getMember(TAdaptedString key) const {
return isObject() ? _content.asCollection.getMember(key) : 0;
}
template <typename TAdaptedString>
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) {
if (isNull())
toObject();
if (!isObject())
return 0;
return _content.asCollection.getOrAddMember(key, pool);
}
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
if (_flags & VALUE_IS_OWNED)
_content.asString += stringDistance;
if (_flags & COLLECTION_MASK)
_content.asCollection.movePointers(stringDistance, variantDistance);
}
uint8_t type() const {
return _flags & VALUE_MASK;
}
private:
void setType(uint8_t t) {
_flags &= KEY_IS_OWNED;
_flags |= t;
}
};
} // namespace ARDUINOJSON_NAMESPACE
#if defined(__GNUC__)
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#endif

View File

@@ -0,0 +1,166 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TVisitor>
inline typename TVisitor::result_type variantAccept(const VariantData *var,
TVisitor &visitor) {
if (var != 0)
return var->accept(visitor);
else
return visitor.visitNull();
}
inline const CollectionData *variantAsArray(const VariantData *var) {
return var != 0 ? var->asArray() : 0;
}
inline const CollectionData *variantAsObject(const VariantData *var) {
return var != 0 ? var->asObject() : 0;
}
inline CollectionData *variantAsObject(VariantData *var) {
return var != 0 ? var->asObject() : 0;
}
inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
MemoryPool *pool) {
if (!dst)
return false;
if (!src) {
dst->setNull();
return true;
}
return dst->copyFrom(*src, pool);
}
inline int variantCompare(const VariantData *a, const VariantData *b);
inline bool variantIsArray(const VariantData *var) {
return var && var->isArray();
}
inline bool variantIsBoolean(const VariantData *var) {
return var && var->isBoolean();
}
template <typename T>
inline bool variantIsInteger(const VariantData *var) {
return var && var->isInteger<T>();
}
inline bool variantIsFloat(const VariantData *var) {
return var && var->isFloat();
}
inline bool variantIsString(const VariantData *var) {
return var && var->isString();
}
inline bool variantIsObject(const VariantData *var) {
return var && var->isObject();
}
inline bool variantIsNull(const VariantData *var) {
return var == 0 || var->isNull();
}
inline bool variantSetBoolean(VariantData *var, bool value) {
if (!var)
return false;
var->setBoolean(value);
return true;
}
inline bool variantSetFloat(VariantData *var, Float value) {
if (!var)
return false;
var->setFloat(value);
return true;
}
inline bool variantSetLinkedRaw(VariantData *var,
SerializedValue<const char *> value) {
if (!var)
return false;
var->setLinkedRaw(value);
return true;
}
template <typename T>
inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value,
MemoryPool *pool) {
return var != 0 && var->setOwnedRaw(value, pool);
}
inline void variantSetNull(VariantData *var) {
if (!var)
return;
var->setNull();
}
template <typename TAdaptedString>
inline bool variantSetString(VariantData *var, TAdaptedString value,
MemoryPool *pool) {
if (!var)
return false;
return var->setString(value, pool);
}
template <typename T>
inline bool variantSetInteger(VariantData *var, T value) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
if (!var)
return false;
var->setInteger(value);
return true;
}
inline size_t variantSize(const VariantData *var) {
return var != 0 ? var->size() : 0;
}
inline CollectionData *variantToArray(VariantData *var) {
if (!var)
return 0;
return &var->toArray();
}
inline CollectionData *variantToObject(VariantData *var) {
if (!var)
return 0;
return &var->toObject();
}
inline NO_INLINE VariantData *variantAddElement(VariantData *var,
MemoryPool *pool) {
return var != 0 ? var->addElement(pool) : 0;
}
inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var,
size_t index,
MemoryPool *pool) {
return var != 0 ? var->getOrAddElement(index, pool) : 0;
}
template <typename TChar>
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
MemoryPool *pool) {
return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
}
template <typename TString>
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
const TString &key,
MemoryPool *pool) {
return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,147 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Numbers/convertNumber.hpp>
#include <ArduinoJson/Numbers/parseNumber.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <string.h> // for strcmp
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline T VariantData::asIntegral() const {
switch (type()) {
case VALUE_IS_POSITIVE_INTEGER:
case VALUE_IS_BOOLEAN:
return convertPositiveInteger<T>(_content.asInteger);
case VALUE_IS_NEGATIVE_INTEGER:
return convertNegativeInteger<T>(_content.asInteger);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return parseNumber<T>(_content.asString);
case VALUE_IS_FLOAT:
return convertFloat<T>(_content.asFloat);
default:
return 0;
}
}
inline bool VariantData::asBoolean() const {
switch (type()) {
case VALUE_IS_POSITIVE_INTEGER:
case VALUE_IS_BOOLEAN:
case VALUE_IS_NEGATIVE_INTEGER:
return _content.asInteger != 0;
case VALUE_IS_FLOAT:
return _content.asFloat != 0;
case VALUE_IS_NULL:
return false;
default:
return true;
}
}
// T = float/double
template <typename T>
inline T VariantData::asFloat() const {
switch (type()) {
case VALUE_IS_POSITIVE_INTEGER:
case VALUE_IS_BOOLEAN:
return static_cast<T>(_content.asInteger);
case VALUE_IS_NEGATIVE_INTEGER:
return -static_cast<T>(_content.asInteger);
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return parseNumber<T>(_content.asString);
case VALUE_IS_FLOAT:
return static_cast<T>(_content.asFloat);
default:
return 0;
}
}
inline const char *VariantData::asString() const {
switch (type()) {
case VALUE_IS_LINKED_STRING:
case VALUE_IS_OWNED_STRING:
return _content.asString;
default:
return 0;
}
}
template <typename TVariant>
typename enable_if<IsVisitable<TVariant>::value, bool>::type VariantRef::set(
const TVariant &value) const {
VariantConstRef v = value;
return variantCopyFrom(_data, v._data, _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 T>
typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type
VariantRef::to() const {
return ObjectRef(_pool, variantToObject(_data));
}
template <typename T>
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type
VariantRef::to() const {
variantSetNull(_data);
return *this;
}
inline VariantConstRef VariantConstRef::getElement(size_t index) const {
return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
}
inline VariantRef VariantRef::addElement() const {
return VariantRef(_pool, variantAddElement(_data, _pool));
}
inline VariantRef VariantRef::getElement(size_t index) const {
return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0);
}
inline VariantRef VariantRef::getOrAddElement(size_t index) const {
return VariantRef(_pool, variantGetOrAddElement(_data, index, _pool));
}
template <typename TChar>
inline VariantRef VariantRef::getMember(TChar *key) const {
return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
}
template <typename TString>
inline typename enable_if<IsString<TString>::value, VariantRef>::type
VariantRef::getMember(const TString &key) const {
return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
}
template <typename TChar>
inline VariantRef VariantRef::getOrAddMember(TChar *key) const {
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
}
template <typename TString>
inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
}
inline VariantConstRef operator|(VariantConstRef preferedValue,
VariantConstRef defaultValue) {
return preferedValue ? preferedValue : defaultValue;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,174 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantAs.hpp>
#include <ArduinoJson/Variant/VariantTag.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T1, typename T2>
CompareResult compare(const T1 &lhs, const T2 &rhs); // VariantCompare.cpp
template <typename TVariant>
struct VariantOperators {
// Returns the default value if the VariantRef is undefined or incompatible
//
// int operator|(JsonVariant, int)
// float operator|(JsonVariant, float)
// bool operator|(JsonVariant, bool)
// const char* operator|(JsonVariant, const char*)
// char* operator|(JsonVariant, const char*)
template <typename T>
friend typename enable_if<!IsVariant<T>::value,
typename VariantAs<T>::type>::type
operator|(const TVariant &variant, T defaultValue) {
if (variant.template is<T>())
return variant.template as<T>();
else
return defaultValue;
}
//
// JsonVariant operator|(JsonVariant, JsonVariant)
template <typename T>
friend typename enable_if<IsVariant<T>::value, typename T::variant_type>::type
operator|(const TVariant &variant, T defaultValue) {
if (variant)
return variant;
else
return defaultValue;
}
// value == TVariant
template <typename T>
friend bool operator==(T *lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend bool operator==(const T &lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
// TVariant == value
template <typename T>
friend bool operator==(TVariant lhs, T *rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
// value != TVariant
template <typename T>
friend bool operator!=(T *lhs, TVariant rhs) {
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend bool operator!=(const T &lhs, TVariant rhs) {
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
// TVariant != value
template <typename T>
friend bool operator!=(TVariant lhs, T *rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
// value < TVariant
template <typename T>
friend bool operator<(T *lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend bool operator<(const T &lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
// TVariant < value
template <typename T>
friend bool operator<(TVariant lhs, T *rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<(
TVariant lhs, const T &rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
// value <= TVariant
template <typename T>
friend bool operator<=(T *lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator<=(const T &lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
// TVariant <= value
template <typename T>
friend bool operator<=(TVariant lhs, T *rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<=(
TVariant lhs, const T &rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// value > TVariant
template <typename T>
friend bool operator>(T *lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend bool operator>(const T &lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
// TVariant > value
template <typename T>
friend bool operator>(TVariant lhs, T *rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>(
TVariant lhs, const T &rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
// value >= TVariant
template <typename T>
friend bool operator>=(T *lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator>=(const T &lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// TVariant >= value
template <typename T>
friend bool operator>=(TVariant lhs, T *rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>=(
TVariant lhs, const T &rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,405 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// 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/VariantAs.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:
// Tells wether the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// bool is<char>() const;
// bool is<signed char>() const;
// bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
FORCE_INLINE
typename enable_if<is_integral<T>::value && !is_same<bool, T>::value,
bool>::type
is() const {
return variantIsInteger<T>(_data);
}
//
// bool is<double>() const;
// bool is<float>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_floating_point<T>::value, bool>::type is()
const {
return variantIsFloat(_data);
}
//
// bool is<bool>() const
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, bool>::value, bool>::type is()
const {
return variantIsBoolean(_data);
}
//
// bool is<const char*>() const;
// bool is<char*>() const;
// bool is<std::string>() const;
// bool is<String>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, const char *>::value ||
is_same<T, char *>::value ||
IsWriteableString<T>::value,
bool>::type
is() const {
return variantIsString(_data);
}
//
// bool is<ArrayRef> const;
// bool is<const ArrayRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ArrayRef>::value, bool>::type
is() const {
return variantIsArray(_data);
}
//
// bool is<ObjectRef> const;
// bool is<const ObjectRef> const;
template <typename T>
FORCE_INLINE typename enable_if<
is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type
is() const {
return variantIsObject(_data);
}
#if ARDUINOJSON_HAS_NULLPTR
//
// bool is<nullptr_t> const;
template <typename T>
FORCE_INLINE
typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type
is() const {
return variantIsNull(_data);
}
#endif
// bool is<enum>() const;
template <typename T>
FORCE_INLINE typename enable_if<is_enum<T>::value, bool>::type is() const {
return variantIsInteger<int>(_data);
}
FORCE_INLINE bool isNull() const {
return variantIsNull(_data);
}
FORCE_INLINE bool isUndefined() const {
return !_data;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
size_t size() const {
return variantSize(_data);
}
protected:
VariantRefBase(TData *data) : _data(data) {}
TData *_data;
};
// 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);
}
// set(bool value)
template <typename T>
FORCE_INLINE bool set(
T value, typename enable_if<is_same<T, bool>::value>::type * = 0) const {
return variantSetBoolean(_data, value);
}
// set(double value);
// set(float value);
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_floating_point<T>::value>::type * = 0) const {
return variantSetFloat(_data, static_cast<Float>(value));
}
// set(char)
// set(signed short)
// set(signed int)
// set(signed long)
// set(signed char)
// set(unsigned short)
// set(unsigned int)
// set(unsigned long)
template <typename T>
FORCE_INLINE bool set(
T value, typename enable_if<is_integral<T>::value &&
!is_same<bool, T>::value>::type * = 0) const {
return variantSetInteger<T>(_data, value);
}
// set(SerializedValue<const char *>)
FORCE_INLINE bool set(SerializedValue<const char *> value) const {
return variantSetLinkedRaw(_data, value);
}
// set(SerializedValue<std::string>)
// set(SerializedValue<String>)
// set(SerializedValue<const __FlashStringHelper*>)
template <typename T>
FORCE_INLINE bool set(
SerializedValue<T> value,
typename enable_if<!is_same<const char *, T>::value>::type * = 0) const {
return variantSetOwnedRaw(_data, value, _pool);
}
// set(const std::string&)
// set(const String&)
template <typename T>
FORCE_INLINE bool set(
const T &value,
typename enable_if<IsString<T>::value>::type * = 0) const {
return variantSetString(_data, adaptString(value), _pool);
}
// set(char*)
// set(const __FlashStringHelper*)
// set(const char*)
template <typename T>
FORCE_INLINE bool set(
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
return variantSetString(_data, adaptString(value), _pool);
}
// set(VariantRef)
// set(VariantConstRef)
// set(ArrayRef)
// set(ArrayConstRef)
// set(ObjectRef)
// set(ObjecConstRef)
// set(const JsonDocument&)
template <typename TVariant>
typename enable_if<IsVisitable<TVariant>::value, bool>::type set(
const TVariant &value) const;
// set(enum value)
template <typename T>
FORCE_INLINE bool set(
T value, typename enable_if<is_enum<T>::value>::type * = 0) const {
return variantSetInteger(_data, static_cast<Integer>(value));
}
#if ARDUINOJSON_HAS_NULLPTR
// set(nullptr_t)
FORCE_INLINE bool set(decltype(nullptr)) const {
variantSetNull(_data);
return true;
}
#endif
template <typename T>
FORCE_INLINE typename VariantAs<T>::type as() const {
return variantAs<typename VariantAs<T>::type>(_data, _pool);
}
template <typename T>
FORCE_INLINE operator T() const {
return variantAs<T>(_data, _pool);
}
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;
}; // namespace ARDUINOJSON_NAMESPACE
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 VariantConstAs<T>::type as() const {
return variantAs<typename VariantConstAs<T>::type>(_data);
}
template <typename T>
FORCE_INLINE operator T() const {
return variantAs<T>(_data);
}
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);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,23 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// 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

View File

@@ -0,0 +1,116 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/integer.hpp>
#include <ArduinoJson/Polyfills/limits.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Variant/VariantContent.hpp>
namespace ARDUINOJSON_NAMESPACE {
typedef int_t<ARDUINOJSON_SLOT_OFFSET_SIZE * 8>::type VariantSlotDiff;
class VariantSlot {
// CAUTION: same layout as VariantData
// we cannot use composition because it adds padding
// (+20% on ESP8266 for example)
VariantContent _content;
uint8_t _flags;
VariantSlotDiff _next;
const char* _key;
public:
// Must be a POD!
// - no constructor
// - no destructor
// - no virtual
// - no inheritance
VariantData* data() {
return reinterpret_cast<VariantData*>(&_content);
}
const VariantData* data() const {
return reinterpret_cast<const VariantData*>(&_content);
}
VariantSlot* next() {
return _next ? this + _next : 0;
}
const VariantSlot* next() const {
return const_cast<VariantSlot*>(this)->next();
}
VariantSlot* next(size_t distance) {
VariantSlot* slot = this;
while (distance--) {
if (!slot->_next)
return 0;
slot += slot->_next;
}
return slot;
}
const VariantSlot* next(size_t distance) const {
return const_cast<VariantSlot*>(this)->next(distance);
}
void setNext(VariantSlot* slot) {
ARDUINOJSON_ASSERT(!slot || slot - this >=
numeric_limits<VariantSlotDiff>::lowest());
ARDUINOJSON_ASSERT(!slot || slot - this <=
numeric_limits<VariantSlotDiff>::highest());
_next = VariantSlotDiff(slot ? slot - this : 0);
}
void setNextNotNull(VariantSlot* slot) {
ARDUINOJSON_ASSERT(slot != 0);
ARDUINOJSON_ASSERT(slot - this >=
numeric_limits<VariantSlotDiff>::lowest());
ARDUINOJSON_ASSERT(slot - this <=
numeric_limits<VariantSlotDiff>::highest());
_next = VariantSlotDiff(slot - this);
}
void setKey(const char* k, storage_policies::store_by_copy) {
ARDUINOJSON_ASSERT(k != NULL);
_flags |= KEY_IS_OWNED;
_key = k;
}
void setKey(const char* k, storage_policies::store_by_address) {
ARDUINOJSON_ASSERT(k != NULL);
_flags &= VALUE_MASK;
_key = k;
}
const char* key() const {
return _key;
}
bool ownsKey() const {
return (_flags & KEY_IS_OWNED) != 0;
}
void clear() {
_next = 0;
_flags = 0;
_key = 0;
}
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
if (_flags & KEY_IS_OWNED)
_key += stringDistance;
if (_flags & VALUE_IS_OWNED)
_content.asString += stringDistance;
if (_flags & COLLECTION_MASK)
_content.asCollection.movePointers(stringDistance, variantDistance);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,16 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
struct VariantTag {};
template <typename T>
struct IsVariant : is_base_of<VariantTag, T> {};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,32 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
class ArrayRef;
class ObjectRef;
class VariantRef;
// A metafunction that returns the type of the value returned by
// VariantRef::to<T>()
template <typename T>
struct VariantTo {};
template <>
struct VariantTo<ArrayRef> {
typedef ArrayRef type;
};
template <>
struct VariantTo<ObjectRef> {
typedef ObjectRef type;
};
template <>
struct VariantTo<VariantRef> {
typedef VariantRef type;
};
} // namespace ARDUINOJSON_NAMESPACE