From ed98ea4e437ff99c785320ab164389093389bdb1 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sun, 6 Aug 2017 16:26:38 +0200 Subject: [PATCH] Implemented JsonVariant comparisons with template friends --- src/ArduinoJson.hpp | 1 - src/ArduinoJson/Data/JsonVariantComparer.hpp | 69 ------- src/ArduinoJson/JsonArraySubscript.hpp | 13 +- src/ArduinoJson/JsonVariantBase.hpp | 132 +------------ src/ArduinoJson/JsonVariantCasts.hpp | 60 ++++++ src/ArduinoJson/JsonVariantComparisons.hpp | 186 ++++++++++++------- src/ArduinoJson/JsonVariantSubscripts.hpp | 89 +++++++++ src/ArduinoJson/TypeTraits/IsVariant.hpp | 20 ++ 8 files changed, 305 insertions(+), 265 deletions(-) delete mode 100644 src/ArduinoJson/Data/JsonVariantComparer.hpp create mode 100644 src/ArduinoJson/JsonVariantCasts.hpp create mode 100644 src/ArduinoJson/JsonVariantSubscripts.hpp create mode 100644 src/ArduinoJson/TypeTraits/IsVariant.hpp diff --git a/src/ArduinoJson.hpp b/src/ArduinoJson.hpp index bdc26c69..949fa5ca 100644 --- a/src/ArduinoJson.hpp +++ b/src/ArduinoJson.hpp @@ -10,7 +10,6 @@ #include "ArduinoJson/DynamicJsonBuffer.hpp" #include "ArduinoJson/JsonArray.hpp" #include "ArduinoJson/JsonObject.hpp" -#include "ArduinoJson/JsonVariantComparisons.hpp" #include "ArduinoJson/StaticJsonBuffer.hpp" #include "ArduinoJson/Deserialization/JsonParserImpl.hpp" diff --git a/src/ArduinoJson/Data/JsonVariantComparer.hpp b/src/ArduinoJson/Data/JsonVariantComparer.hpp deleted file mode 100644 index 1e57dad4..00000000 --- a/src/ArduinoJson/Data/JsonVariantComparer.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright Benoit Blanchon 2014-2017 -// MIT License -// -// Arduino JSON library -// https://bblanchon.github.io/ArduinoJson/ -// If you like this project, please add a star! - -#pragma once - -#include "../JsonVariantBase.hpp" -#include "../StringTraits/StringTraits.hpp" -#include "../TypeTraits/EnableIf.hpp" - -namespace ArduinoJson { -namespace Internals { -template -struct JsonVariantComparer {}; - -template -struct JsonVariantComparer< - TString, - typename TypeTraits::EnableIf::value>::type> { - template - static bool equals(const JsonVariantBase &variant, - const TString &comparand) { - const char *value = variant.template as(); - return Internals::StringTraits::equals(comparand, value); - } -}; - -template -struct JsonVariantComparer< - TComparand, typename TypeTraits::EnableIf< - !TypeTraits::IsVariant::value && - !TypeTraits::IsString::value>::type> { - template - static bool equals(const JsonVariantBase &variant, - const TComparand &comparand) { - return variant.template as() == comparand; - } -}; - -template -struct JsonVariantComparer::value>::type> { - template - static bool equals(const JsonVariantBase &left, - const TVariant2 &right) { - if (left.template is() && right.template is()) - return left.template as() == right.template as(); - if (left.template is() && right.template is()) - return left.template as() == - right.template as(); - if (left.template is() && right.template is()) - return left.template as() == right.template as(); - if (left.template is() && right.template is()) - return left.template as() == right.template as(); - if (left.template is() && right.template is()) - return left.template as() == right.template as(); - if (left.template is() && right.template is()) - return strcmp(left.template as(), right.template as()) == - 0; - - return false; - } -}; -} -} diff --git a/src/ArduinoJson/JsonArraySubscript.hpp b/src/ArduinoJson/JsonArraySubscript.hpp index fc19822e..5bd6208a 100644 --- a/src/ArduinoJson/JsonArraySubscript.hpp +++ b/src/ArduinoJson/JsonArraySubscript.hpp @@ -106,15 +106,16 @@ inline const JsonArraySubscript JsonArray::operator[](size_t index) const { return JsonArraySubscript(*const_cast(this), index); } -template -inline JsonArraySubscript JsonVariantBase::operator[](size_t index) { - return as()[index]; +template +inline JsonArraySubscript JsonVariantSubscripts::operator[]( + size_t index) { + return impl()->template as()[index]; } -template -inline const JsonArraySubscript JsonVariantBase::operator[]( +template +inline const JsonArraySubscript JsonVariantSubscripts::operator[]( size_t index) const { - return as()[index]; + return impl()->template as()[index]; } } // namespace ArduinoJson diff --git a/src/ArduinoJson/JsonVariantBase.hpp b/src/ArduinoJson/JsonVariantBase.hpp index ac5ad907..a010e253 100644 --- a/src/ArduinoJson/JsonVariantBase.hpp +++ b/src/ArduinoJson/JsonVariantBase.hpp @@ -7,133 +7,17 @@ #pragma once -#include "Data/JsonVariantAs.hpp" -#include "Polyfills/attributes.hpp" +#include "JsonVariantCasts.hpp" +#include "JsonVariantComparisons.hpp" +#include "JsonVariantSubscripts.hpp" #include "Serialization/JsonPrintable.hpp" namespace ArduinoJson { -// Forward declarations. -class JsonArraySubscript; -template -class JsonObjectSubscript; - template -class JsonVariantBase : public Internals::JsonPrintable { - public: -#if ARDUINOJSON_ENABLE_DEPRECATED - DEPRECATED("use as() instead") - FORCE_INLINE JsonArray &asArray() const { - return as(); - } - - DEPRECATED("use as() instead") - FORCE_INLINE JsonObject &asObject() const { - return as(); - } - - DEPRECATED("use as() instead") - FORCE_INLINE const char *asString() const { - return as(); - } -#endif - - // Gets the variant as an array. - // Returns a reference to the JsonArray or JsonArray::invalid() if the - // variant - // is not an array. - FORCE_INLINE operator JsonArray &() 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. - FORCE_INLINE operator JsonObject &() const { - return as(); - } - - template - FORCE_INLINE operator T() const { - return as(); - } - - template - FORCE_INLINE const typename Internals::JsonVariantAs::type as() const { - return impl()->template as(); - } - - template - FORCE_INLINE bool is() const { - return impl()->template is(); - } - - // 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 { - return as().size() + as().size(); - } - - // 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. - FORCE_INLINE const JsonArraySubscript operator[](size_t index) const; - FORCE_INLINE JsonArraySubscript operator[](size_t 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. - // - // const JsonObjectSubscript operator[](TKey) const; - // TKey = const std::string&, const String& - template - FORCE_INLINE typename TypeTraits::EnableIf< - Internals::StringTraits::has_equals, - const JsonObjectSubscript >::type - operator[](const TString &key) const { - return as()[key]; - } - // - // const JsonObjectSubscript operator[](TKey) const; - // TKey = const std::string&, const String& - template - FORCE_INLINE typename TypeTraits::EnableIf< - Internals::StringTraits::has_equals, - JsonObjectSubscript >::type - operator[](const TString &key) { - return as()[key]; - } - // - // JsonObjectSubscript operator[](TKey); - // TKey = const char*, const char[N], const FlashStringHelper* - template - FORCE_INLINE typename TypeTraits::EnableIf< - Internals::StringTraits::has_equals, - JsonObjectSubscript >::type - operator[](const TString *key) { - return as()[key]; - } - // - // JsonObjectSubscript operator[](TKey); - // TKey = const char*, const char[N], const FlashStringHelper* - template - FORCE_INLINE typename TypeTraits::EnableIf< - Internals::StringTraits::has_equals, - const JsonObjectSubscript >::type - operator[](const TString *key) const { - return as()[key]; - } - - private: - const TImpl *impl() const { - return static_cast(this); - } -}; - -namespace TypeTraits { -template -struct IsVariant : IsBaseOf, T> {}; -} +class JsonVariantBase : public Internals::JsonPrintable, + public JsonVariantCasts, + public JsonVariantComparisons, + public JsonVariantSubscripts, + public TypeTraits::JsonVariantTag {}; } diff --git a/src/ArduinoJson/JsonVariantCasts.hpp b/src/ArduinoJson/JsonVariantCasts.hpp new file mode 100644 index 00000000..b3b41b4b --- /dev/null +++ b/src/ArduinoJson/JsonVariantCasts.hpp @@ -0,0 +1,60 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Data/JsonVariantAs.hpp" +#include "Polyfills/attributes.hpp" + +namespace ArduinoJson { + +template +class JsonVariantCasts { + public: +#if ARDUINOJSON_ENABLE_DEPRECATED + DEPRECATED("use as() instead") + FORCE_INLINE JsonArray &asArray() const { + return impl()->template as(); + } + + DEPRECATED("use as() instead") + FORCE_INLINE JsonObject &asObject() const { + return impl()->template as(); + } + + DEPRECATED("use as() instead") + FORCE_INLINE const char *asString() const { + return impl()->template as(); + } +#endif + + // Gets the variant as an array. + // Returns a reference to the JsonArray or JsonArray::invalid() if the + // variant + // is not an array. + FORCE_INLINE operator JsonArray &() const { + return impl()->template as(); + } + + // Gets the variant as an object. + // Returns a reference to the JsonObject or JsonObject::invalid() if the + // variant is not an object. + FORCE_INLINE operator JsonObject &() const { + return impl()->template as(); + } + + template + FORCE_INLINE operator T() const { + return impl()->template as(); + } + + private: + const TImpl *impl() const { + return static_cast(this); + } +}; +} diff --git a/src/ArduinoJson/JsonVariantComparisons.hpp b/src/ArduinoJson/JsonVariantComparisons.hpp index abbb473a..eb0ef5c2 100644 --- a/src/ArduinoJson/JsonVariantComparisons.hpp +++ b/src/ArduinoJson/JsonVariantComparisons.hpp @@ -7,82 +7,138 @@ #pragma once -#include "Data/JsonVariantComparer.hpp" +#include "StringTraits/StringTraits.hpp" +#include "TypeTraits/EnableIf.hpp" +#include "TypeTraits/IsVariant.hpp" namespace ArduinoJson { -template -inline bool operator==(const JsonVariantBase &variant, - TComparand comparand) { - return Internals::JsonVariantComparer::equals(variant, comparand); -} -template -inline typename TypeTraits::EnableIf::value, - bool>::type -operator==(TComparand comparand, const JsonVariantBase &variant) { - return Internals::JsonVariantComparer::equals(variant, comparand); -} +template +class JsonVariantComparisons { + public: + template + friend bool operator==(const JsonVariantComparisons &variant, + TComparand comparand) { + return variant.equals(comparand); + } -template -inline bool operator!=(const JsonVariantBase &variant, - TComparand comparand) { - return !Internals::JsonVariantComparer::equals(variant, - comparand); -} + template + friend + typename TypeTraits::EnableIf::value, + bool>::type + operator==(TComparand comparand, const JsonVariantComparisons &variant) { + return variant.equals(comparand); + } -template -inline typename TypeTraits::EnableIf::value, - bool>::type -operator!=(TComparand comparand, const JsonVariantBase &variant) { - return !Internals::JsonVariantComparer::equals(variant, - comparand); -} + template + friend bool operator!=(const JsonVariantComparisons &variant, + TComparand comparand) { + return !variant.equals(comparand); + } -template -inline bool operator<=(const JsonVariantBase &left, - TComparand right) { - return left.template as() <= right; -} + template + friend + typename TypeTraits::EnableIf::value, + bool>::type + operator!=(TComparand comparand, const JsonVariantComparisons &variant) { + return !variant.equals(comparand); + } -template -inline bool operator<=(TComparand comparand, - const JsonVariantBase &variant) { - return comparand <= variant.template as(); -} + template + friend bool operator<=(const JsonVariantComparisons &left, TComparand right) { + return left.as() <= right; + } -template -inline bool operator>=(const JsonVariantBase &variant, - TComparand comparand) { - return variant.template as() >= comparand; -} + template + friend bool operator<=(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand <= variant.as(); + } -template -inline bool operator>=(TComparand comparand, - const JsonVariantBase &variant) { - return comparand >= variant.template as(); -} + template + friend bool operator>=(const JsonVariantComparisons &variant, + TComparand comparand) { + return variant.as() >= comparand; + } -template -inline bool operator<(const JsonVariantBase &varian, - TComparand comparand) { - return varian.template as() < comparand; -} + template + friend bool operator>=(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand >= variant.as(); + } -template -inline bool operator<(TComparand comparand, - const JsonVariantBase &variant) { - return comparand < variant.template as(); -} + template + friend bool operator<(const JsonVariantComparisons &varian, + TComparand comparand) { + return varian.as() < comparand; + } -template -inline bool operator>(const JsonVariantBase &variant, - TComparand comparand) { - return variant.template as() > comparand; -} + template + friend bool operator<(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand < variant.as(); + } -template -inline bool operator>(TComparand comparand, - const JsonVariantBase &variant) { - return comparand > variant.template as(); -} + template + friend bool operator>(const JsonVariantComparisons &variant, + TComparand comparand) { + return variant.as() > comparand; + } + + template + friend bool operator>(TComparand comparand, + const JsonVariantComparisons &variant) { + return comparand > variant.as(); + } + + private: + const TImpl *impl() const { + return static_cast(this); + } + + template + const typename Internals::JsonVariantAs::type as() const { + return impl()->template as(); + } + + template + bool is() const { + return impl()->template is(); + } + + template + typename TypeTraits::EnableIf::value, + bool>::type + equals(const TString &comparand) const { + const char *value = as(); + return Internals::StringTraits::equals(comparand, value); + } + + template + typename TypeTraits::EnableIf::value && + !TypeTraits::IsString::value, + bool>::type + equals(const TComparand &comparand) const { + return as() == comparand; + } + + template + bool equals(const JsonVariantComparisons &right) const { + using namespace Internals; + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return as() == right.template as(); + if (is() && right.template is()) + return strcmp(as(), right.template as()) == 0; + + return false; + } +}; } diff --git a/src/ArduinoJson/JsonVariantSubscripts.hpp b/src/ArduinoJson/JsonVariantSubscripts.hpp new file mode 100644 index 00000000..2143236a --- /dev/null +++ b/src/ArduinoJson/JsonVariantSubscripts.hpp @@ -0,0 +1,89 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "Data/JsonVariantAs.hpp" +#include "Polyfills/attributes.hpp" +#include "StringTraits/StringTraits.hpp" +#include "TypeTraits/EnableIf.hpp" + +namespace ArduinoJson { + +// Forward declarations. +class JsonArraySubscript; +template +class JsonObjectSubscript; + +template +class JsonVariantSubscripts { + public: + // 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 { + return impl()->template as().size() + + impl()->template as().size(); + } + + // 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. + FORCE_INLINE const JsonArraySubscript operator[](size_t index) const; + FORCE_INLINE JsonArraySubscript operator[](size_t 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. + // + // const JsonObjectSubscript operator[](TKey) const; + // TKey = const std::string&, const String& + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + const JsonObjectSubscript >::type + operator[](const TString &key) const { + return impl()->template as()[key]; + } + // + // const JsonObjectSubscript operator[](TKey) const; + // TKey = const std::string&, const String& + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + JsonObjectSubscript >::type + operator[](const TString &key) { + return impl()->template as()[key]; + } + // + // JsonObjectSubscript operator[](TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + JsonObjectSubscript >::type + operator[](const TString *key) { + return impl()->template as()[key]; + } + // + // JsonObjectSubscript operator[](TKey); + // TKey = const char*, const char[N], const FlashStringHelper* + template + FORCE_INLINE typename TypeTraits::EnableIf< + Internals::StringTraits::has_equals, + const JsonObjectSubscript >::type + operator[](const TString *key) const { + return impl()->template as()[key]; + } + + private: + const TImpl *impl() const { + return static_cast(this); + } +}; +} diff --git a/src/ArduinoJson/TypeTraits/IsVariant.hpp b/src/ArduinoJson/TypeTraits/IsVariant.hpp new file mode 100644 index 00000000..8297cf5c --- /dev/null +++ b/src/ArduinoJson/TypeTraits/IsVariant.hpp @@ -0,0 +1,20 @@ +// Copyright Benoit Blanchon 2014-2017 +// MIT License +// +// Arduino JSON library +// https://bblanchon.github.io/ArduinoJson/ +// If you like this project, please add a star! + +#pragma once + +#include "IsBaseOf.hpp" + +namespace ArduinoJson { +namespace TypeTraits { + +class JsonVariantTag {}; + +template +struct IsVariant : IsBaseOf {}; +} +}