// ArduinoJson - arduinojson.org // Copyright Benoit Blanchon 2014-2018 // MIT License #pragma once #include #include // for uint8_t #include "Data/JsonVariantData.hpp" #include "Data/VariantAs.hpp" #include "Data/VariantFunctions.hpp" #include "JsonVariant.hpp" #include "JsonVariantBase.hpp" #include "Memory/MemoryPool.hpp" #include "Numbers/parseFloat.hpp" #include "Numbers/parseInteger.hpp" #include "Polyfills/type_traits.hpp" #include "Visitable.hpp" namespace ARDUINOJSON_NAMESPACE { // Forward declarations. class JsonArray; class JsonObject; // Contains the methods shared by JsonVariant and JsonVariantConst template class JsonVariantProxy { 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 _data && _data->type == JSON_BOOLEAN; } // // 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, JsonArray>::value, bool>::type is() const { return variantIsArray(_data); } // // bool is const; // bool is const; template FORCE_INLINE typename enable_if< is_same::type, JsonObject>::value, bool>::type is() const { return variantIsObject(_data); } FORCE_INLINE bool isNull() const { return variantIsNull(_data); } FORCE_INLINE bool isInvalid() const { return _data == 0; } size_t size() const { return objectSize(variantAsObject(_data)) + arraySize(variantAsArray(_data)); } protected: JsonVariantProxy(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 JsonArray or JsonObject class JsonVariant : public JsonVariantProxy, public JsonVariantBase, public Visitable { typedef JsonVariantProxy proxy_type; friend class JsonVariantConst; public: // Intenal use only FORCE_INLINE JsonVariant(MemoryPool *memoryPool, JsonVariantData *data) : proxy_type(data), _memoryPool(memoryPool) {} // Creates an uninitialized JsonVariant FORCE_INLINE JsonVariant() : proxy_type(0), _memoryPool(0) {} // set(bool value) FORCE_INLINE bool set(bool value) const { return variantSetBoolean(_data, value, _memoryPool); } // 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), _memoryPool); } // 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, _memoryPool); } // 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), _memoryPool); } // set(SerializedValue) FORCE_INLINE bool set(SerializedValue value) const { return variantSetLinkedRaw(_data, value, _memoryPool); } // set(SerializedValue) // set(SerializedValue) // set(SerializedValue) template FORCE_INLINE bool set( SerializedValue value, typename enable_if::value>::type * = 0) const { return variantSetOwnedRaw(_data, value, _memoryPool); } // set(const std::string&) // set(const String&) template FORCE_INLINE bool set( const T &value, typename enable_if::value>::type * = 0) const { return variantSetString(_data, makeString(value), _memoryPool); } // set(char*) template FORCE_INLINE bool set( T *value, typename enable_if::value>::type * = 0) const { return variantSetString(_data, makeString(value), _memoryPool); } // set(const char*); FORCE_INLINE bool set(const char *value) const { return variantSetString(_data, value, _memoryPool); } // for internal use only FORCE_INLINE bool set(StringInMemoryPool value) const { return variantSetOwnedString(_data, value.slot(), _memoryPool); } FORCE_INLINE bool set(ZeroTerminatedRamStringConst value) const { return variantSetString(_data, value.c_str(), _memoryPool); } bool set(JsonVariantConst value) const; bool set(JsonVariant value) const; FORCE_INLINE bool set(JsonArray array) const; FORCE_INLINE bool set(const JsonArraySubscript &) const; FORCE_INLINE bool set(JsonObject object) const; template FORCE_INLINE bool set(const JsonObjectSubscript &) 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 JsonVariantAs::type>::type as() const { return variantAs(_data); } // // JsonArray as() const; // const JsonArray as() const; template FORCE_INLINE typename enable_if::value, T>::type as() const; // // JsonObject as() const; // const JsonObject as() const; template FORCE_INLINE typename enable_if::value, T>::type as() const; // // JsonVariant as const; template FORCE_INLINE typename enable_if::value, T>::type as() const { return *this; } template void accept(Visitor &visitor) const; FORCE_INLINE bool operator==(JsonVariant lhs) const { return variantEquals(_data, lhs._data); } FORCE_INLINE bool operator!=(JsonVariant lhs) const { return !variantEquals(_data, lhs._data); } // Change the type of the variant // // JsonArray to() template typename enable_if::value, JsonArray>::type to() const; // // JsonObject to() template typename enable_if::value, JsonObject>::type to() const; // // JsonObject to() template typename enable_if::value, JsonVariant>::type to() const; private: MemoryPool *_memoryPool; }; class JsonVariantConst : public JsonVariantProxy, public JsonVariantBase, public Visitable { typedef JsonVariantProxy proxy_type; friend class JsonVariant; public: JsonVariantConst() : proxy_type(0) {} JsonVariantConst(const JsonVariantData *data) : proxy_type(data) {} JsonVariantConst(JsonVariant var) : proxy_type(var._data) {} template void accept(Visitor &visitor) const; // Get the variant as the specified type. // template FORCE_INLINE typename JsonVariantConstAs::type as() const { return variantAs::type>(_data); } FORCE_INLINE JsonVariantConst operator[](size_t index) const; // // const JsonVariantConst operator[](TKey) const; // TKey = const std::string&, const String& template FORCE_INLINE typename enable_if::value, JsonVariantConst>::type operator[](const TString &key) const { return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key))); } // // JsonVariantConst operator[](TKey); // TKey = const char*, const char[N], const FlashStringHelper* template FORCE_INLINE typename enable_if::value, JsonVariantConst>::type operator[](TString *key) const { return JsonVariantConst(objectGet(variantAsObject(_data), makeString(key))); } }; } // namespace ARDUINOJSON_NAMESPACE