// ArduinoJson - https://arduinojson.org // Copyright Benoit Blanchon 2014-2021 // MIT License #pragma once #include #include // for uint8_t #include "lib/ArduinoJson/Memory/MemoryPool.hpp" #include "lib/ArduinoJson/Misc/Visitable.hpp" #include "lib/ArduinoJson/Polyfills/type_traits.hpp" #include "lib/ArduinoJson/Strings/StringAdapters.hpp" #include "lib/ArduinoJson/Variant/Converter.hpp" #include "lib/ArduinoJson/Variant/VariantFunctions.hpp" #include "lib/ArduinoJson/Variant/VariantOperators.hpp" #include "lib/ArduinoJson/Variant/VariantRef.hpp" #include "lib/ArduinoJson/Variant/VariantShortcuts.hpp" #include "lib/ArduinoJson/Variant/VariantTag.hpp" namespace ARDUINOJSON_NAMESPACE { // Forward declarations. class ArrayRef; class ObjectRef; // Contains the methods shared by VariantRef and VariantConstRef template class VariantRefBase : public VariantTag { public: FORCE_INLINE bool isNull() const { return variantIsNull(_data); } FORCE_INLINE bool isUndefined() const { return !_data; } FORCE_INLINE size_t memoryUsage() const { return _data ? _data->memoryUsage() : 0; } FORCE_INLINE size_t nesting() const { return _data ? _data->nesting() : 0; } size_t size() const { return variantSize(_data); } protected: VariantRefBase(TData *data) : _data(data) {} TData *_data; friend TData *getData(const VariantRefBase &variant) { return variant._data; } }; // A variant that can be a any value serializable to a JSON value. // // It can be set to: // - a boolean // - a char, short, int or a long (signed or unsigned) // - a string (const char*) // - a reference to a ArrayRef or ObjectRef class VariantRef : public VariantRefBase, public VariantOperators, public VariantShortcuts, public Visitable { typedef VariantRefBase 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 FORCE_INLINE bool set(const T &value) const { return Converter::toJson(value, *this); } FORCE_INLINE bool ARDUINOJSON_DEPRECATED( "Support for char is deprecated, use int8_t or uint8_t instead") set(char value) const { return set(value); } template FORCE_INLINE bool set(T *value) const { return Converter::toJson(value, *this); } 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 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(); } template typename TVisitor::result_type accept(TVisitor &visitor) const { return variantAccept(_data, visitor); } // 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; FORCE_INLINE VariantRef getElement(size_t) const; FORCE_INLINE VariantRef getOrAddElement(size_t) const; // getMember(const char*) const // getMember(const __FlashStringHelper*) const template FORCE_INLINE VariantRef getMember(TChar *) const; // getMember(const std::string&) const // getMember(const String&) const template FORCE_INLINE typename enable_if::value, VariantRef>::type getMember(const TString &) const; // getOrAddMember(char*) const // getOrAddMember(const char*) const // getOrAddMember(const __FlashStringHelper*) const template FORCE_INLINE VariantRef getOrAddMember(TChar *) const; // getOrAddMember(const std::string&) const // getOrAddMember(const String&) const template 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 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)); } private: MemoryPool *_pool; friend MemoryPool *getPool(const VariantRef &variant) { return variant._pool; } }; class VariantConstRef : public VariantRefBase, public VariantOperators, public VariantShortcuts, public Visitable { typedef VariantRefBase 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::result_type accept(TVisitor &visitor) const { return variantAccept(_data, visitor); } 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 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 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 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 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 FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](const TString &key) const { return getMember(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 getMember(key); } }; template <> struct Converter { static bool toJson(VariantRef src, VariantRef dst) { return variantCopyFrom(getData(dst), getData(src), getPool(dst)); } static VariantRef fromJson(VariantRef src) { return src; } static bool checkJson(VariantRef src) { VariantData *data = getData(src); return !!data; } static bool checkJson(VariantConstRef) { return false; } }; template <> struct Converter { static bool toJson(VariantConstRef src, VariantRef dst) { return variantCopyFrom(getData(dst), getData(src), getPool(dst)); } static VariantConstRef fromJson(VariantConstRef src) { return VariantConstRef(getData(src)); } static bool checkJson(VariantConstRef src) { const VariantData *data = getData(src); return !!data; } }; } // namespace ARDUINOJSON_NAMESPACE