mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	Added operators == and != for two JsonVariants (issue #436)
				
					
				
			This commit is contained in:
		
							
								
								
									
										4
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							| @@ -2,10 +2,10 @@ | ||||
| Thanks for using ArduinoJson :-) | ||||
|  | ||||
| Before opening an issue, please make sure you've read these: | ||||
| https://github.com/bblanchon/ArduinoJson/wiki/FAQ | ||||
| https://bblanchon.github.io/ArduinoJson/faq/ | ||||
| https://github.com/bblanchon/ArduinoJson/wiki/Avoiding-pitfalls | ||||
|  | ||||
| Next, make sure you provide all the relevant information: platform, code snippet, and error messages. | ||||
|  | ||||
| Please be concise! | ||||
| --> | ||||
| --> | ||||
|   | ||||
| @@ -5,6 +5,7 @@ HEAD | ||||
| ---- | ||||
|  | ||||
| * Fixed an access violation in `DynamicJsonBuffer` when memory allocation fails (issue #433) | ||||
| * Added operators `==` and `!=` for two `JsonVariant`s (issue #436) | ||||
|  | ||||
| v5.8.2 | ||||
| ------ | ||||
|   | ||||
							
								
								
									
										69
									
								
								include/ArduinoJson/Data/JsonVariantComparer.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								include/ArduinoJson/Data/JsonVariantComparer.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| // Copyright Benoit Blanchon 2014-2017 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/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 <typename TComparand, typename Enable = void> | ||||
| struct JsonVariantComparer {}; | ||||
|  | ||||
| template <typename TString> | ||||
| struct JsonVariantComparer< | ||||
|     TString, | ||||
|     typename TypeTraits::EnableIf<TypeTraits::IsString<TString>::value>::type> { | ||||
|   template <typename TVariant> | ||||
|   static bool equals(const JsonVariantBase<TVariant> &variant, | ||||
|                      const TString &comparand) { | ||||
|     const char *value = variant.template as<const char *>(); | ||||
|     return Internals::StringTraits<TString>::equals(comparand, value); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TComparand> | ||||
| struct JsonVariantComparer< | ||||
|     TComparand, typename TypeTraits::EnableIf< | ||||
|                     !TypeTraits::IsVariant<TComparand>::value && | ||||
|                     !TypeTraits::IsString<TComparand>::value>::type> { | ||||
|   template <typename TVariant> | ||||
|   static bool equals(const JsonVariantBase<TVariant> &variant, | ||||
|                      const TComparand &comparand) { | ||||
|     return variant.template as<TComparand>() == comparand; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TVariant2> | ||||
| struct JsonVariantComparer<TVariant2, | ||||
|                            typename TypeTraits::EnableIf< | ||||
|                                TypeTraits::IsVariant<TVariant2>::value>::type> { | ||||
|   template <typename TVariant1> | ||||
|   static bool equals(const JsonVariantBase<TVariant1> &left, | ||||
|                      const TVariant2 &right) { | ||||
|     if (left.template is<bool>() && right.template is<bool>()) | ||||
|       return left.template as<bool>() == right.template as<bool>(); | ||||
|     if (left.template is<JsonInteger>() && right.template is<JsonInteger>()) | ||||
|       return left.template as<JsonInteger>() == | ||||
|              right.template as<JsonInteger>(); | ||||
|     if (left.template is<JsonFloat>() && right.template is<JsonFloat>()) | ||||
|       return left.template as<JsonFloat>() == right.template as<JsonFloat>(); | ||||
|     if (left.template is<JsonArray>() && right.template is<JsonArray>()) | ||||
|       return left.template as<JsonArray>() == right.template as<JsonArray>(); | ||||
|     if (left.template is<JsonObject>() && right.template is<JsonObject>()) | ||||
|       return left.template as<JsonObject>() == right.template as<JsonObject>(); | ||||
|     if (left.template is<char *>() && right.template is<char *>()) | ||||
|       return strcmp(left.template as<char *>(), right.template as<char *>()) == | ||||
|              0; | ||||
|  | ||||
|     return false; | ||||
|   } | ||||
| }; | ||||
| } | ||||
| } | ||||
| @@ -63,6 +63,11 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | ||||
|     return impl()->template as<T>(); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FORCE_INLINE bool is() const { | ||||
|     return impl()->template is<T>(); | ||||
|   } | ||||
|  | ||||
|   // 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 | ||||
| @@ -126,4 +131,9 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> { | ||||
|     return static_cast<const TImpl *>(this); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| namespace TypeTraits { | ||||
| template <typename T> | ||||
| struct IsVariant : IsBaseOf<JsonVariantBase<T>, T> {}; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -7,100 +7,82 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "JsonVariantBase.hpp" | ||||
| #include "StringTraits/StringTraits.hpp" | ||||
| #include "TypeTraits/EnableIf.hpp" | ||||
| #include "Data/JsonVariantComparer.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| template <typename TVariant, typename TComparand, typename Enable = void> | ||||
| struct JsonVariantComparer { | ||||
|   static bool equals(const TVariant &variant, const TComparand &comparand) { | ||||
|     return variant.template as<TComparand>() == comparand; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TVariant, typename TString> | ||||
| struct JsonVariantComparer< | ||||
|     TVariant, TString, typename TypeTraits::EnableIf<Internals::StringTraits< | ||||
|                            TString>::has_equals>::type> { | ||||
|   static bool equals(const TVariant &variant, const TString &comparand) { | ||||
|     const char *value = variant.template as<const char *>(); | ||||
|     return Internals::StringTraits<TString>::equals(comparand, value); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator==(const JsonVariantBase<TImpl> &variant, | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator==(const JsonVariantBase<TVariant> &variant, | ||||
|                        TComparand comparand) { | ||||
|   typedef JsonVariantBase<TImpl> TVariant; | ||||
|   return JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand); | ||||
|   return Internals::JsonVariantComparer<TComparand>::equals(variant, comparand); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator==(TComparand comparand, | ||||
|                        const JsonVariantBase<TImpl> &variant) { | ||||
|   typedef JsonVariantBase<TImpl> TVariant; | ||||
|   return JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand); | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value, | ||||
|                                      bool>::type | ||||
| operator==(TComparand comparand, const JsonVariantBase<TVariant> &variant) { | ||||
|   return Internals::JsonVariantComparer<TComparand>::equals(variant, comparand); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator!=(const JsonVariantBase<TImpl> &variant, | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator!=(const JsonVariantBase<TVariant> &variant, | ||||
|                        TComparand comparand) { | ||||
|   typedef JsonVariantBase<TImpl> TVariant; | ||||
|   return !JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand); | ||||
|   return !Internals::JsonVariantComparer<TComparand>::equals(variant, | ||||
|                                                              comparand); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator!=(TComparand comparand, | ||||
|                        const JsonVariantBase<TImpl> &variant) { | ||||
|   typedef JsonVariantBase<TImpl> TVariant; | ||||
|   return !JsonVariantComparer<TVariant, TComparand>::equals(variant, comparand); | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value, | ||||
|                                      bool>::type | ||||
| operator!=(TComparand comparand, const JsonVariantBase<TVariant> &variant) { | ||||
|   return !Internals::JsonVariantComparer<TComparand>::equals(variant, | ||||
|                                                              comparand); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator<=(const JsonVariantBase<TImpl> &left, TComparand right) { | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator<=(const JsonVariantBase<TVariant> &left, | ||||
|                        TComparand right) { | ||||
|   return left.template as<TComparand>() <= right; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator<=(TComparand comparand, | ||||
|                        const JsonVariantBase<TImpl> &variant) { | ||||
|                        const JsonVariantBase<TVariant> &variant) { | ||||
|   return comparand <= variant.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator>=(const JsonVariantBase<TImpl> &variant, | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator>=(const JsonVariantBase<TVariant> &variant, | ||||
|                        TComparand comparand) { | ||||
|   return variant.template as<TComparand>() >= comparand; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator>=(TComparand comparand, | ||||
|                        const JsonVariantBase<TImpl> &variant) { | ||||
|                        const JsonVariantBase<TVariant> &variant) { | ||||
|   return comparand >= variant.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator<(const JsonVariantBase<TImpl> &varian, | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator<(const JsonVariantBase<TVariant> &varian, | ||||
|                       TComparand comparand) { | ||||
|   return varian.template as<TComparand>() < comparand; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator<(TComparand comparand, | ||||
|                       const JsonVariantBase<TImpl> &variant) { | ||||
|                       const JsonVariantBase<TVariant> &variant) { | ||||
|   return comparand < variant.template as<TComparand>(); | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| inline bool operator>(const JsonVariantBase<TImpl> &variant, | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator>(const JsonVariantBase<TVariant> &variant, | ||||
|                       TComparand comparand) { | ||||
|   return variant.template as<TComparand>() > comparand; | ||||
| } | ||||
|  | ||||
| template <typename TImpl, typename TComparand> | ||||
| template <typename TVariant, typename TComparand> | ||||
| inline bool operator>(TComparand comparand, | ||||
|                       const JsonVariantBase<TImpl> &variant) { | ||||
|                       const JsonVariantBase<TVariant> &variant) { | ||||
|   return comparand > variant.template as<TComparand>(); | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -34,7 +34,7 @@ struct StdStringTraits { | ||||
|   }; | ||||
|  | ||||
|   static bool equals(const TString& str, const char* expected) { | ||||
|     return str == expected; | ||||
|     return 0 == strcmp(str.c_str(), expected); | ||||
|   } | ||||
|  | ||||
|   static void append(TString& str, char c) { | ||||
|   | ||||
| @@ -40,3 +40,18 @@ struct StringTraits<TString&, void> : StringTraits<TString> {}; | ||||
| #if ARDUINOJSON_ENABLE_PROGMEM | ||||
| #include "FlashString.hpp" | ||||
| #endif | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| namespace TypeTraits { | ||||
| template <typename T, typename Enable = void> | ||||
| struct IsString { | ||||
|   static const bool value = false; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct IsString<T, typename TypeTraits::EnableIf< | ||||
|                        Internals::StringTraits<T>::has_equals>::type> { | ||||
|   static const bool value = Internals::StringTraits<T>::has_equals; | ||||
| }; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -126,3 +126,103 @@ TEST_F(JsonVariant_Comparison_Tests, String) { | ||||
|   ASSERT_TRUE(std::string("world") != variant); | ||||
|   ASSERT_FALSE(std::string("world") == variant); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Comparison_Tests, IntegerInVariant) { | ||||
|   JsonVariant variant1 = 42; | ||||
|   JsonVariant variant2 = 42; | ||||
|   JsonVariant variant3 = 666; | ||||
|  | ||||
|   ASSERT_TRUE(variant1 == variant2); | ||||
|   ASSERT_FALSE(variant1 != variant2); | ||||
|  | ||||
|   ASSERT_TRUE(variant1 != variant3); | ||||
|   ASSERT_FALSE(variant1 == variant3); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Comparison_Tests, StringInVariant) { | ||||
|   JsonVariant variant1 = "0hello" + 1;  // make sure they have | ||||
|   JsonVariant variant2 = "1hello" + 1;  // different addresses | ||||
|   JsonVariant variant3 = "world"; | ||||
|  | ||||
|   ASSERT_TRUE(variant1 == variant2); | ||||
|   ASSERT_FALSE(variant1 != variant2); | ||||
|  | ||||
|   ASSERT_TRUE(variant1 != variant3); | ||||
|   ASSERT_FALSE(variant1 == variant3); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Comparison_Tests, DoubleInVariant) { | ||||
|   JsonVariant variant1 = 42.0; | ||||
|   JsonVariant variant2 = 42.0; | ||||
|   JsonVariant variant3 = 666.0; | ||||
|  | ||||
|   ASSERT_TRUE(variant1 == variant2); | ||||
|   ASSERT_FALSE(variant1 != variant2); | ||||
|  | ||||
|   ASSERT_TRUE(variant1 != variant3); | ||||
|   ASSERT_FALSE(variant1 == variant3); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Comparison_Tests, BoolInVariant) { | ||||
|   JsonVariant variant1 = true; | ||||
|   JsonVariant variant2 = true; | ||||
|   JsonVariant variant3 = false; | ||||
|  | ||||
|   ASSERT_TRUE(variant1 == variant2); | ||||
|   ASSERT_FALSE(variant1 != variant2); | ||||
|  | ||||
|   ASSERT_TRUE(variant1 != variant3); | ||||
|   ASSERT_FALSE(variant1 == variant3); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Comparison_Tests, ArrayInVariant) { | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonArray& array1 = jsonBuffer.createArray(); | ||||
|   JsonArray& array2 = jsonBuffer.createArray(); | ||||
|  | ||||
|   JsonVariant variant1 = array1; | ||||
|   JsonVariant variant2 = array1; | ||||
|   JsonVariant variant3 = array2; | ||||
|  | ||||
|   ASSERT_TRUE(variant1 == variant2); | ||||
|   ASSERT_FALSE(variant1 != variant2); | ||||
|  | ||||
|   ASSERT_TRUE(variant1 != variant3); | ||||
|   ASSERT_FALSE(variant1 == variant3); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Comparison_Tests, ObjectInVariant) { | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonObject& obj1 = jsonBuffer.createObject(); | ||||
|   JsonObject& obj2 = jsonBuffer.createObject(); | ||||
|  | ||||
|   JsonVariant variant1 = obj1; | ||||
|   JsonVariant variant2 = obj1; | ||||
|   JsonVariant variant3 = obj2; | ||||
|  | ||||
|   ASSERT_TRUE(variant1 == variant2); | ||||
|   ASSERT_FALSE(variant1 != variant2); | ||||
|  | ||||
|   ASSERT_TRUE(variant1 != variant3); | ||||
|   ASSERT_FALSE(variant1 == variant3); | ||||
| } | ||||
|  | ||||
| TEST_F(JsonVariant_Comparison_Tests, VariantsOfDifferentTypes) { | ||||
|   DynamicJsonBuffer jsonBuffer; | ||||
|   JsonVariant variants[] = { | ||||
|       true, | ||||
|       42, | ||||
|       666.667, | ||||
|       "hello", | ||||
|       jsonBuffer.createArray(), | ||||
|       jsonBuffer.createObject(), | ||||
|   }; | ||||
|   size_t n = sizeof(variants) / sizeof(variants[0]); | ||||
|  | ||||
|   for (size_t i = 0; i < n; i++) { | ||||
|     for (size_t j = i + 1; j < n; j++) { | ||||
|       ASSERT_TRUE(variants[i] != variants[j]); | ||||
|       ASSERT_FALSE(variants[i] == variants[j]); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -11,13 +11,26 @@ | ||||
|  | ||||
| using namespace ArduinoJson::TypeTraits; | ||||
|  | ||||
| TEST(StdStream, IsBaseOf) { | ||||
| TEST(TypeTraits, IsBaseOf) { | ||||
|   ASSERT_FALSE((IsBaseOf<std::istream, std::ostringstream>::value)); | ||||
|   ASSERT_TRUE((IsBaseOf<std::istream, std::istringstream>::value)); | ||||
|   ASSERT_TRUE((IsBaseOf<JsonVariantBase<JsonObjectSubscript<const char*> >, | ||||
|                         JsonObjectSubscript<const char*> >::value)); | ||||
| } | ||||
|  | ||||
| TEST(StdStream, IsArray) { | ||||
| TEST(TypeTraits, IsArray) { | ||||
|   ASSERT_FALSE((IsArray<const char*>::value)); | ||||
|   ASSERT_TRUE((IsArray<const char[]>::value)); | ||||
|   ASSERT_TRUE((IsArray<const char[10]>::value)); | ||||
| } | ||||
|  | ||||
| TEST(TypeTraits, IsVariant) { | ||||
|   ASSERT_TRUE((IsVariant<JsonObjectSubscript<const char*> >::value)); | ||||
|   ASSERT_TRUE((IsVariant<JsonVariant>::value)); | ||||
| } | ||||
|  | ||||
| TEST(TypeTraits, IsString) { | ||||
|   ASSERT_TRUE((IsString<const char*>::value)); | ||||
|   ASSERT_TRUE((IsString<std::string>::value)); | ||||
|   ASSERT_FALSE((IsString<double>::value)); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user