// Copyright Benoit Blanchon 2014-2016 // MIT License // // Arduino JSON library // https://github.com/bblanchon/ArduinoJson // If you like this project, please add a star! #pragma once #include #include // for uint8_t #include "Internals/JsonPrintable.hpp" #include "Internals/JsonVariantContent.hpp" #include "Internals/JsonVariantType.hpp" #include "JsonVariantBase.hpp" #include "RawJson.hpp" #include "TypeTraits/EnableIf.hpp" #include "TypeTraits/IsFloatingPoint.hpp" #include "TypeTraits/IsIntegral.hpp" #include "TypeTraits/IsSame.hpp" #include "TypeTraits/RemoveConst.hpp" #include "TypeTraits/RemoveReference.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 JsonVariantBase { public: template struct IsConstructibleFrom; // Creates an uninitialized JsonVariant JsonVariant() : _type(Internals::JSON_UNDEFINED) {} // Create a JsonVariant containing a boolean value. // It will be serialized as "true" or "false" in JSON. JsonVariant(bool value) { using namespace Internals; _type = JSON_BOOLEAN; _content.asInteger = static_cast(value); } // Create a JsonVariant containing a floating point value. // The second argument specifies the number of decimal digits to write in // the JSON string. // JsonVariant(double value, uint8_t decimals); // JsonVariant(float value, uint8_t decimals); template JsonVariant(T value, uint8_t decimals = 2, typename TypeTraits::EnableIf< TypeTraits::IsFloatingPoint::value>::type * = 0) { using namespace Internals; _type = static_cast(JSON_FLOAT_0_DECIMALS + decimals); _content.asFloat = static_cast(value); } // Create a JsonVariant containing an integer value. // JsonVariant(signed short) // JsonVariant(signed int) // JsonVariant(signed long) template JsonVariant(T value, typename TypeTraits::EnableIf< TypeTraits::IsSignedIntegral::value>::type * = 0) { using namespace Internals; if (value >= 0) { _type = JSON_POSITIVE_INTEGER; _content.asInteger = static_cast(value); } else { _type = JSON_NEGATIVE_INTEGER; _content.asInteger = static_cast(-value); } } // JsonVariant(unsigned short) // JsonVariant(unsigned int) // JsonVariant(unsigned long) template JsonVariant(T value, typename TypeTraits::EnableIf< TypeTraits::IsUnsignedIntegral::value>::type * = 0) { using namespace Internals; _type = JSON_POSITIVE_INTEGER; _content.asInteger = static_cast(value); } // Create a JsonVariant containing a string. JsonVariant(const char *value) { _type = Internals::JSON_STRING; _content.asString = value; } // Create a JsonVariant containing an unparsed string JsonVariant(RawJson value) { _type = Internals::JSON_UNPARSED; _content.asString = value; } // Create a JsonVariant containing a reference to an array. JsonVariant(JsonArray &array) { _type = Internals::JSON_ARRAY; _content.asArray = &array; } // Create a JsonVariant containing a reference to an object. JsonVariant(JsonObject &object) { _type = Internals::JSON_OBJECT; _content.asObject = &object; } // Get the variant as the specified type. // // short as() const; // int as() const; // long as() const; template const typename TypeTraits::EnableIf::value, T>::type as() const { return static_cast(asInteger()); } // // short as() const; // int as() const; // long as() const; template const typename TypeTraits::EnableIf::value, T>::type as() const { return static_cast(asUnsignedInteger()); } // // double as() const; // float as() const; template const typename TypeTraits::EnableIf::value, T>::type as() const { return static_cast(asFloat()); } // // const String as() const; template const typename TypeTraits::EnableIf::value, T>::type as() const { return toString(); } // // const char* as() const; // const char* as() const; template typename TypeTraits::EnableIf::value || TypeTraits::IsSame::value, const char *>::type as() const { return asString(); } // // const bool as() const template const typename TypeTraits::EnableIf::value, T>::type as() const { return asInteger() != 0; } // // JsonArray& as const; // JsonArray& as const; // JsonArray& as const; template typename TypeTraits::EnableIf< TypeTraits::IsSame< typename TypeTraits::RemoveConst< typename TypeTraits::RemoveReference::type>::type, JsonArray>::value, JsonArray &>::type as() const { return asArray(); } // // JsonObject& as const; // JsonObject& as const; // JsonObject& as const; template typename TypeTraits::EnableIf< TypeTraits::IsSame< typename TypeTraits::RemoveConst< typename TypeTraits::RemoveReference::type>::type, JsonObject>::value, JsonObject &>::type as() const { return asObject(); } // Tells weither the variant has the specified type. // Returns true if the variant has type type T, false otherwise. // // short as() const; // int as() const; // long as() const; template const typename TypeTraits::EnableIf::value, bool>::type is() const { return isInteger(); } // // double is() const; // float is() const; template const typename TypeTraits::EnableIf::value, bool>::type is() const { return isFloat(); } // // const bool is() const template const typename TypeTraits::EnableIf::value, bool>::type is() const { return isBoolean(); } // // bool is() const; // bool is() const; template typename TypeTraits::EnableIf::value || TypeTraits::IsSame::value, bool>::type is() const { return isString(); } // // bool is const; // bool is const; // bool is const; template typename TypeTraits::EnableIf< TypeTraits::IsSame< typename TypeTraits::RemoveConst< typename TypeTraits::RemoveReference::type>::type, JsonArray>::value, bool>::type is() const { return isArray(); } // // JsonObject& as const; // JsonObject& as const; // JsonObject& as const; template typename TypeTraits::EnableIf< TypeTraits::IsSame< typename TypeTraits::RemoveConst< typename TypeTraits::RemoveReference::type>::type, JsonObject>::value, bool>::type is() const { return isObject(); } // Returns true if the variant has a value bool success() const { return _type != Internals::JSON_UNDEFINED; } // Serialize the variant to a JsonWriter void writeTo(Internals::JsonWriter &writer) const; // Value returned if the variant has an incompatible type template static T defaultValue() { return T(); } const char *asString() const; JsonArray &asArray() const; JsonObject &asObject() const; private: // It's not allowed to store a char template JsonVariant(T value, typename TypeTraits::EnableIf< TypeTraits::IsSame::value>::type * = 0); String toString() const; Internals::JsonFloat asFloat() const; Internals::JsonInteger asInteger() const; Internals::JsonUInt asUnsignedInteger() const; bool isBoolean() const; bool isFloat() const; bool isInteger() const; bool isArray() const { return _type == Internals::JSON_ARRAY; } bool isObject() const { return _type == Internals::JSON_OBJECT; } bool isString() const { return _type == Internals::JSON_STRING; } // The current type of the variant Internals::JsonVariantType _type; // The various alternatives for the value of the variant. Internals::JsonVariantContent _content; }; inline JsonVariant float_with_n_digits(float value, uint8_t digits) { return JsonVariant(value, digits); } inline JsonVariant double_with_n_digits(double value, uint8_t digits) { return JsonVariant(value, digits); } template struct JsonVariant::IsConstructibleFrom { static const bool value = TypeTraits::IsIntegral::value || TypeTraits::IsFloatingPoint::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame &>::value || TypeTraits::IsSame &>::value || TypeTraits::IsSame &>::value || TypeTraits::IsSame &>::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value; }; }