// Copyright Benoit Blanchon 2014-2015 // MIT License // // Arduino JSON library // https://github.com/bblanchon/ArduinoJson #pragma once #include #include // for uint8_t #include "Internals/JsonPrintable.hpp" #include "Internals/JsonVariantContent.hpp" #include "Internals/JsonVariantType.hpp" namespace ArduinoJson { // Forward declarations. class JsonArray; class JsonObject; // 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 Internals::JsonPrintable { public: // Creates an uninitialized JsonVariant JsonVariant() : _type(Internals::JSON_UNDEFINED) {} // Initializes a JsonVariant with the specified value. template explicit JsonVariant(T value) { set(value); } // Tells weither the variant is valid. bool success() const { return _type != Internals::JSON_INVALID && _type != Internals::JSON_UNDEFINED; } // Sets the variant to a boolean value. // It will be serialized as "true" or "false" in JSON. void set(bool value); // Sets the variant to a floating point value. // The second argument specifies the number of decimal digits to write in // the JSON string. void set(double value, uint8_t decimals = 2); // Sets the variant to be an integer value. void set(signed long value); void set(signed char value) { set(static_cast(value)); } void set(signed int value) { set(static_cast(value)); } void set(signed short value) { set(static_cast(value)); } void set(unsigned char value) { set(static_cast(value)); } void set(unsigned int value) { set(static_cast(value)); } void set(unsigned long value) { set(static_cast(value)); } void set(unsigned short value) { set(static_cast(value)); } // Sets the variant to be a string. void set(const char *value); // Sets the variant to be a reference to an array. void set(JsonArray &array); // Sets the variant to be a reference to an object. void set(JsonObject &object); // Sets the variant to the specified value. template JsonVariant &operator=(T value) { set(value); return *this; } // Sets the variant to be a reference to an array. JsonVariant &operator=(JsonArray &array) { set(array); return *this; } // Sets the variant to be a reference to an object. JsonVariant &operator=(JsonObject &object) { set(object); return *this; } // Gets the variant as a boolean value. // Returns false if the variant is not a boolean value. operator bool() const; // Gets the variant as a floating-point value. // Returns 0.0 if the variant is not a floating-point value operator double() const; operator float() const { return static_cast(as()); } // Gets the variant as an integer value. // Returns 0 if the variant is not an integer value. operator signed long() const; operator signed char() const { return cast_long_to(); } operator signed int() const { return cast_long_to(); } operator signed short() const { return cast_long_to(); } operator unsigned char() const { return cast_long_to(); } operator unsigned int() const { return cast_long_to(); } operator unsigned long() const { return cast_long_to(); } operator unsigned short() const { return cast_long_to(); } // Gets the variant as a string. // Returns NULL if variant is not a string. operator const char *() const; const char *asString() const { return as(); } // Gets the variant as an array. // Returns a reference to the JsonArray or JsonArray::invalid() if the variant // is not an array. operator JsonArray &() const; JsonArray &asArray() const { return as(); } // Gets the variant as an object. // Returns a reference to the JsonObject or JsonObject::invalid() if the // variant is not an object. operator JsonObject &() const; JsonObject &asObject() const { return as(); } // Get the variant as the specified type. // See cast operators for details. template T as() const { return static_cast(*this); } // Tells weither the variant has the specified type. // Returns true if the variant has type type T, false otherwise. template bool is() const { return false; } // Returns an invalid variant. // This is meant to replace a NULL pointer. static JsonVariant &invalid() { return _invalid; } // Serialize the variant to a JsonWriter void writeTo(Internals::JsonWriter &writer) const; // Mimics an array or an object. // Returns the size of the array or object if the variant has that type. // Returns 0 if the variant is neither an array nor an object size_t size() const; // Mimics an array. // Returns the element at specified index if the variant is an array. // Returns JsonVariant::invalid() if the variant is not an array. JsonVariant &operator[](int index); // Mimics an object. // Returns the value associated with the specified key if the variant is an // object. // Return JsonVariant::invalid() if the variant is not an object. JsonVariant &operator[](const char *key); private: // Special constructor used only to create _invalid. explicit JsonVariant(Internals::JsonVariantType type) : _type(type) {} // Helper for interger cast operators template T cast_long_to() const { return static_cast(as()); } // The current type of the variant Internals::JsonVariantType _type; // The various alternatives for the value of the variant. Internals::JsonVariantContent _content; // The instance returned by JsonVariant::invalid() static JsonVariant _invalid; }; template <> inline bool JsonVariant::is() const { return _type == Internals::JSON_LONG; } template <> inline bool JsonVariant::is() const { return _type >= Internals::JSON_DOUBLE_0_DECIMALS; } template <> inline bool JsonVariant::is() const { return _type == Internals::JSON_BOOLEAN; } template <> inline bool JsonVariant::is() const { return _type == Internals::JSON_STRING; } template <> inline bool JsonVariant::is() const { return _type == Internals::JSON_ARRAY; } template <> inline bool JsonVariant::is() const { return _type == Internals::JSON_ARRAY; } template <> inline bool JsonVariant::is() const { return _type == Internals::JSON_OBJECT; } template <> inline bool JsonVariant::is() const { return _type == Internals::JSON_OBJECT; } template inline bool operator==(const JsonVariant &left, T right) { return left.as() == right; } template inline bool operator==(T left, const JsonVariant &right) { return left == right.as(); } template inline bool operator!=(const JsonVariant &left, T right) { return left.as() != right; } template inline bool operator!=(T left, const JsonVariant &right) { return left != right.as(); } template inline bool operator<=(const JsonVariant &left, T right) { return left.as() <= right; } template inline bool operator<=(T left, const JsonVariant &right) { return left <= right.as(); } template inline bool operator>=(const JsonVariant &left, T right) { return left.as() >= right; } template inline bool operator>=(T left, const JsonVariant &right) { return left >= right.as(); } template inline bool operator<(const JsonVariant &left, T right) { return left.as() < right; } template inline bool operator<(T left, const JsonVariant &right) { return left < right.as(); } template inline bool operator>(const JsonVariant &left, T right) { return left.as() > right; } template inline bool operator>(T left, const JsonVariant &right) { return left > right.as(); } }