// ArduinoJson - arduinojson.org // Copyright Benoit Blanchon 2014-2018 // MIT License #pragma once #include #include // for uint8_t #include "../Memory/MemoryPool.hpp" #include "../Misc/Visitable.hpp" #include "../Numbers/parseFloat.hpp" #include "../Numbers/parseInteger.hpp" #include "../Operators/VariantOperators.hpp" #include "../Polyfills/type_traits.hpp" #include "VariantAs.hpp" #include "VariantFunctions.hpp" #include "VariantRef.hpp" namespace ARDUINOJSON_NAMESPACE { // Forward declarations. class ArrayRef; class ObjectRef; // Contains the methods shared by VariantRef and VariantConstRef template class VariantRefBase { public: // Tells wether the variant has the specified type. // Returns true if the variant has type type T, false otherwise. // // bool is() const; // bool is() const; // bool is() const; // bool is() const; // bool is() const; // bool is() const; // bool is() const; // bool is() const; // bool is() const; template FORCE_INLINE typename enable_if::value, bool>::type is() const { return variantIsInteger(_data); } // // bool is() const; // bool is() const; template FORCE_INLINE typename enable_if::value, bool>::type is() const { return variantIsFloat(_data); } // // bool is() const template FORCE_INLINE typename enable_if::value, bool>::type is() const { return variantIsBoolean(_data); } // // bool is() const; // bool is() const; // bool is() const; // bool is() const; template FORCE_INLINE typename enable_if::value || is_same::value || IsWriteableString::value, bool>::type is() const { return variantIsString(_data); } // // bool is const; // bool is const; template FORCE_INLINE typename enable_if< is_same::type, ArrayRef>::value, bool>::type is() const { return variantIsArray(_data); } // // bool is const; // bool is const; template FORCE_INLINE typename enable_if< is_same::type, ObjectRef>::value, bool>::type is() const { return variantIsObject(_data); } FORCE_INLINE bool isNull() const { return variantIsNull(_data); } 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, public VariantOperators, 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) {} // set(bool value) FORCE_INLINE bool set(bool value) const { return variantSetBoolean(_data, value); } // set(double value); // set(float value); template FORCE_INLINE bool set( T value, typename enable_if::value>::type * = 0) const { return variantSetFloat(_data, static_cast(value)); } // set(char) // set(signed short) // set(signed int) // set(signed long) // set(signed char) template FORCE_INLINE bool set( T value, typename enable_if::value && is_signed::value>::type * = 0) const { return variantSetSignedInteger(_data, value); } // set(unsigned short) // set(unsigned int) // set(unsigned long) template FORCE_INLINE bool set( T value, typename enable_if::value && is_unsigned::value>::type * = 0) const { return variantSetUnsignedInteger(_data, static_cast(value)); } // set(SerializedValue) FORCE_INLINE bool set(SerializedValue value) const { return variantSetLinkedRaw(_data, value); } // set(SerializedValue) // set(SerializedValue) // set(SerializedValue) template FORCE_INLINE bool set( SerializedValue value, typename enable_if::value>::type * = 0) const { return variantSetOwnedRaw(_data, value, _pool); } // set(const std::string&) // set(const String&) template FORCE_INLINE bool set( const T &value, typename enable_if::value>::type * = 0) const { return variantSetOwnedString(_data, wrapString(value), _pool); } // set(char*) // set(const __FlashStringHelper*) template FORCE_INLINE bool set( T *value, typename enable_if::value>::type * = 0) const { return variantSetOwnedString(_data, wrapString(value), _pool); } // set(const char*); FORCE_INLINE bool set(const char *value) const { return variantSetLinkedString(_data, value); } bool set(VariantConstRef value) const; bool set(VariantRef value) const; FORCE_INLINE bool set(ArrayRef array) const; FORCE_INLINE bool set(const ArraySubscript &) const; FORCE_INLINE bool set(ObjectRef object) const; template FORCE_INLINE bool set(const ObjectSubscript &) const; // Get the variant as the specified type. // // std::string as() const; // String as() const; template FORCE_INLINE typename enable_if::value && !is_same::value && !is_same::value, typename VariantAs::type>::type as() const { return variantAs(_data); } // // ArrayRef as() const; // const ArrayRef as() const; template FORCE_INLINE typename enable_if::value, T>::type as() const; // // ObjectRef as() const; // const ObjectRef as() const; template FORCE_INLINE typename enable_if::value, T>::type as() const; // // VariantRef as const; template FORCE_INLINE typename enable_if::value, T>::type as() const { return *this; } template void accept(Visitor &visitor) const { variantAccept(_data, visitor); } FORCE_INLINE bool operator==(VariantRef lhs) const { return variantEquals(_data, lhs._data); } FORCE_INLINE bool operator!=(VariantRef lhs) const { return !variantEquals(_data, lhs._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; private: MemoryPool *_pool; }; class VariantConstRef : public VariantRefBase, public VariantOperators, 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 void accept(Visitor &visitor) const { variantAccept(_data, visitor); } // Get the variant as the specified type. // template FORCE_INLINE typename VariantConstAs::type as() const { return variantAs::type>(_data); } FORCE_INLINE VariantConstRef operator[](size_t index) const; // // const VariantConstRef operator[](TKey) const; // TKey = const std::string&, const String& template FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](const TString &key) const { return VariantConstRef(objectGet(variantAsObject(_data), wrapString(key))); } // // VariantConstRef operator[](TKey); // TKey = const char*, const char[N], const __FlashStringHelper* template FORCE_INLINE typename enable_if::value, VariantConstRef>::type operator[](TString *key) const { const CollectionData *obj = variantAsObject(_data); return VariantConstRef(obj ? obj->get(wrapString(key)) : 0); } }; } // namespace ARDUINOJSON_NAMESPACE