// ArduinoJson - https://arduinojson.org // Copyright © 2014-2022, Benoit BLANCHON // MIT License #pragma once #include #include // for uint8_t #include #include #include #include #include #include #include #include #include namespace ARDUINOJSON_NAMESPACE { // Forward declarations. class ArrayRef; class ObjectRef; // Contains the methods shared by VariantRef and VariantConstRef template class VariantRefBase : public VariantTag { public: template typename TVisitor::result_type accept(TVisitor &visitor) const { if (!_data) return visitor.visitNull(); return _data->resolve()->accept(visitor); } 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 variantNesting(_data); } size_t size() const { return variantSize(_data); } protected: VariantRefBase(TData *data) : _data(data) {} TData *_data; friend TData *getData(const VariantRefBase &variant) { return variant._data; } }; class VariantConstRef : public VariantRefBase, public VariantOperators, public VariantShortcuts { typedef VariantRefBase base_type; public: VariantConstRef() : base_type(0) {} explicit VariantConstRef(const VariantData *data) : base_type(data) {} template FORCE_INLINE typename enable_if::value && !is_same::value, T>::type as() const { return Converter::fromJson(*this); } template FORCE_INLINE typename enable_if::value, const char *>::type ARDUINOJSON_DEPRECATED("Replace as() with as()") as() const { return as(); } template FORCE_INLINE typename enable_if::value, char>::type ARDUINOJSON_DEPRECATED( "Support for char is deprecated, use int8_t or uint8_t instead") as() const { return static_cast(as()); } template FORCE_INLINE typename enable_if::value && !is_same::value, bool>::type is() const { return Converter::checkJson(*this); } template FORCE_INLINE typename enable_if::value, bool>::type ARDUINOJSON_DEPRECATED("Replace is() with is()") is() const { return is(); } template FORCE_INLINE typename enable_if::value, bool>::type ARDUINOJSON_DEPRECATED( "Support for char is deprecated, use int8_t or uint8_t instead") is() const { return is(); } template FORCE_INLINE operator T() const { return as(); } FORCE_INLINE VariantConstRef getElementConst(size_t index) const { return VariantConstRef(_data != 0 ? _data->resolve()->getElement(index) : 0); } FORCE_INLINE VariantConstRef operator[](size_t index) const { return getElementConst(index); } // getMemberConst(const std::string&) const // getMemberConst(const String&) const template FORCE_INLINE VariantConstRef getMemberConst(const TString &key) const { return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) : 0); } // getMemberConst(char*) const // getMemberConst(const char*) const // getMemberConst(const __FlashStringHelper*) const template FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) : 0); } // operator[](const std::string&) const // operator[](const String&) const template FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](const TString &key) const { return getMemberConst(key); } // operator[](char*) const // operator[](const char*) const // operator[](const __FlashStringHelper*) const template FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](TChar *key) const { return getMemberConst(key); } }; // 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, public VariantOperators, public VariantShortcuts { typedef VariantRefBase base_type; 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 FORCE_INLINE bool set(const T &value) const { Converter::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 FORCE_INLINE bool set(T *value) const { Converter::toJson(value, *this); return _pool && !_pool->overflowed(); } template FORCE_INLINE typename enable_if::value && !is_same::value, T>::type as() const { return Converter::fromJson(*this); } template FORCE_INLINE typename enable_if::value, const char *>::type ARDUINOJSON_DEPRECATED("Replace as() with as()") as() const { return as(); } template FORCE_INLINE typename enable_if::value, char>::type ARDUINOJSON_DEPRECATED( "Support for char is deprecated, use int8_t or uint8_t instead") as() const { return static_cast(as()); } template FORCE_INLINE typename enable_if::value && !is_same::value, bool>::type is() const { return Converter::checkJson(*this); } template FORCE_INLINE typename enable_if::value, bool>::type ARDUINOJSON_DEPRECATED("Replace is() with is()") is() const { return is(); } template FORCE_INLINE typename enable_if::value, bool>::type ARDUINOJSON_DEPRECATED( "Support for char is deprecated, use int8_t or uint8_t instead") is() const { return is(); } template FORCE_INLINE operator T() const { return as(); } FORCE_INLINE operator VariantConstRef() const { return VariantConstRef(_data); } // Change the type of the variant // // ArrayRef to() template typename enable_if::value, ArrayRef>::type to() const; // // ObjectRef to() template typename enable_if::value, ObjectRef>::type to() const; // // ObjectRef to() template typename enable_if::value, VariantRef>::type to() const; VariantRef addElement() const { return VariantRef(_pool, variantAddElement(_data, _pool)); } FORCE_INLINE VariantRef getElement(size_t index) const { return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0); } FORCE_INLINE VariantConstRef getElementConst(size_t index) const { return VariantConstRef(_data != 0 ? _data->resolve()->getElement(index) : 0); } FORCE_INLINE VariantRef getOrAddElement(size_t index) const { return VariantRef(_pool, variantGetOrAddElement(_data, index, _pool)); } // getMember(const char*) const // getMember(const __FlashStringHelper*) const template FORCE_INLINE VariantRef getMember(TChar *key) const { return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); } // getMember(const std::string&) const // getMember(const String&) const template FORCE_INLINE typename enable_if::value, VariantRef>::type getMember(const TString &key) const { return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0); } // getMemberConst(const char*) const // getMemberConst(const __FlashStringHelper*) const template FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) : 0); } // getMemberConst(const std::string&) const // getMemberConst(const String&) const template FORCE_INLINE typename enable_if::value, VariantConstRef>::type getMemberConst(const TString &key) const { return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) : 0); } // getOrAddMember(char*) const // getOrAddMember(const char*) const // getOrAddMember(const __FlashStringHelper*) const template FORCE_INLINE VariantRef getOrAddMember(TChar *key) const { return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool)); } // getOrAddMember(const std::string&) const // getOrAddMember(const String&) const template FORCE_INLINE VariantRef getOrAddMember(const TString &key) const { return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool)); } 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 FORCE_INLINE typename enable_if::value>::type remove( TChar *key) const { if (_data) _data->remove(adaptString(key)); } // remove(const std::string&) const // remove(const String&) const template FORCE_INLINE typename enable_if::value>::type remove( const TString &key) const { if (_data) _data->remove(adaptString(key)); } inline void link(VariantConstRef target) { if (!_data) return; const VariantData *targetData = getData(target); if (targetData) _data->setPointer(targetData); else _data->setNull(); } private: MemoryPool *_pool; friend MemoryPool *getPool(const VariantRef &variant) { return variant._pool; } }; template <> struct Converter { static void toJson(VariantRef src, VariantRef dst) { variantCopyFrom(getData(dst), getData(src), getPool(dst)); } static VariantRef fromJson(VariantRef src) { return src; } static InvalidConversion fromJson( VariantConstRef); static bool checkJson(VariantRef src) { VariantData *data = getData(src); return !!data; } static bool checkJson(VariantConstRef) { return false; } }; template <> struct Converter { 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