mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added support for custom converters (closes #687)
This commit is contained in:
		| @@ -4,6 +4,7 @@ ArduinoJson: change log | |||||||
| HEAD | HEAD | ||||||
| ---- | ---- | ||||||
|  |  | ||||||
|  | * Added support for custom converters (issue #687) | ||||||
| * Removed support for `char` values, see below (issue #1498) | * Removed support for `char` values, see below (issue #1498) | ||||||
| * `deserializeJson()` leaves `\uXXXX` unchanged instead of returning `NotSupported` | * `deserializeJson()` leaves `\uXXXX` unchanged instead of returning `NotSupported` | ||||||
| * `deserializeMsgPack()` inserts `null` instead of returning `NotSupported` | * `deserializeMsgPack()` inserts `null` instead of returning `NotSupported` | ||||||
|   | |||||||
| @@ -38,6 +38,7 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). | |||||||
|     * Supports Arduino's `Stream` and [STL's `std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme) |     * Supports Arduino's `Stream` and [STL's `std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme) | ||||||
|     * [Supports Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme) |     * [Supports Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme) | ||||||
|     * Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer) |     * Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer) | ||||||
|  |     * Supports custom converters | ||||||
| * Portable | * Portable | ||||||
|     * Usable on any C++ project (not limited to Arduino) |     * Usable on any C++ project (not limited to Arduino) | ||||||
|     * Compatible with C++98 |     * Compatible with C++98 | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ add_executable(JsonVariantTests | |||||||
| 	compare.cpp | 	compare.cpp | ||||||
| 	containsKey.cpp | 	containsKey.cpp | ||||||
| 	copy.cpp | 	copy.cpp | ||||||
|  | 	converters.cpp | ||||||
| 	createNested.cpp | 	createNested.cpp | ||||||
| 	is.cpp | 	is.cpp | ||||||
| 	isnull.cpp | 	isnull.cpp | ||||||
|   | |||||||
							
								
								
									
										144
									
								
								extras/tests/JsonVariant/converters.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								extras/tests/JsonVariant/converters.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2021 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | namespace { | ||||||
|  | struct Date { | ||||||
|  |   int day; | ||||||
|  |   int month; | ||||||
|  |   int year; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | bool convertToJson(JsonVariant variant, const Date& date) { | ||||||
|  |   variant["day"] = date.day; | ||||||
|  |   variant["month"] = date.month; | ||||||
|  |   variant["year"] = date.year; | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void convertFromJson(Date& date, JsonVariantConst variant) { | ||||||
|  |   date.day = variant["day"]; | ||||||
|  |   date.month = variant["month"]; | ||||||
|  |   date.year = variant["year"]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool canConvertFromJson(Date&, JsonVariantConst variant) { | ||||||
|  |   return variant["day"].is<int>() && variant["month"].is<int>() && | ||||||
|  |          variant["year"].is<int>(); | ||||||
|  | } | ||||||
|  | }  // namespace | ||||||
|  |  | ||||||
|  | TEST_CASE("Custom converter with overloading") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   SECTION("convert JSON to Date") { | ||||||
|  |     doc["date"]["day"] = 2; | ||||||
|  |     doc["date"]["month"] = 3; | ||||||
|  |     doc["date"]["year"] = 2021; | ||||||
|  |  | ||||||
|  |     Date date = doc["date"]; | ||||||
|  |  | ||||||
|  |     REQUIRE(date.day == 2); | ||||||
|  |     REQUIRE(date.month == 3); | ||||||
|  |     REQUIRE(date.year == 2021); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("is<Date>() returns true") { | ||||||
|  |     doc["date"]["day"] = 2; | ||||||
|  |     doc["date"]["month"] = 3; | ||||||
|  |     doc["date"]["year"] = 2021; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc["date"].is<Date>()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("is<Date>() returns false") { | ||||||
|  |     doc["date"]["day"] = 2; | ||||||
|  |     doc["date"]["month"] = 3; | ||||||
|  |     doc["date"]["year"] = "2021"; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc["date"].is<Date>() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("convert Date to JSON") { | ||||||
|  |     Date date = {19, 3, 2021}; | ||||||
|  |     doc["date"] = date; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc["date"]["day"] == 19); | ||||||
|  |     REQUIRE(doc["date"]["month"] == 3); | ||||||
|  |     REQUIRE(doc["date"]["year"] == 2021); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class Complex { | ||||||
|  |  public: | ||||||
|  |   explicit Complex(double r, double i) : _real(r), _imag(i) {} | ||||||
|  |  | ||||||
|  |   double real() const { | ||||||
|  |     return _real; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   double imag() const { | ||||||
|  |     return _imag; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   double _real, _imag; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  | template <> | ||||||
|  | struct Converter<Complex> { | ||||||
|  |   static bool toJson(VariantRef variant, const Complex& value) { | ||||||
|  |     variant["real"] = value.real(); | ||||||
|  |     variant["imag"] = value.imag(); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static Complex fromJson(VariantConstRef variant) { | ||||||
|  |     return Complex(variant["real"], variant["imag"]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     return variant["real"].is<double>() && variant["imag"].is<double>(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|  |  | ||||||
|  | TEST_CASE("Custom converter with specialization") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |  | ||||||
|  |   SECTION("convert JSON to Complex") { | ||||||
|  |     doc["value"]["real"] = 2; | ||||||
|  |     doc["value"]["imag"] = 3; | ||||||
|  |  | ||||||
|  |     Complex value = doc["value"]; | ||||||
|  |  | ||||||
|  |     REQUIRE(value.real() == 2); | ||||||
|  |     REQUIRE(value.imag() == 3); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("is<Complex>() returns true") { | ||||||
|  |     doc["value"]["real"] = 2; | ||||||
|  |     doc["value"]["imag"] = 3; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc["value"].is<Complex>()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("is<Complex>() returns false") { | ||||||
|  |     doc["value"]["real"] = 2; | ||||||
|  |     doc["value"]["imag"] = "3"; | ||||||
|  |  | ||||||
|  |     REQUIRE(doc["value"].is<Complex>() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("convert value to JSON") { | ||||||
|  |     doc["value"] = Complex(19, 3); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc["value"]["real"] == 19); | ||||||
|  |     REQUIRE(doc["value"]["imag"] == 3); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -19,7 +19,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<JsonVariant>() == false); |     CHECK(variant.is<JsonVariant>() == false); | ||||||
|     CHECK(variant.is<JsonVariantConst>() == false); |     CHECK(variant.is<JsonVariantConst>() == false); | ||||||
|     CHECK(variant.is<bool>() == false); |     CHECK(variant.is<bool>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<int>() == false); |     CHECK(variant.is<int>() == false); | ||||||
|     CHECK(variant.is<std::string>() == false); |     CHECK(variant.is<std::string>() == false); | ||||||
|     CHECK(variant.is<float>() == false); |     CHECK(variant.is<float>() == false); | ||||||
| @@ -32,7 +32,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<JsonObject>() == false); |     CHECK(variant.is<JsonObject>() == false); | ||||||
|     CHECK(variant.is<JsonArray>() == false); |     CHECK(variant.is<JsonArray>() == false); | ||||||
|     CHECK(variant.is<bool>() == false); |     CHECK(variant.is<bool>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<int>() == false); |     CHECK(variant.is<int>() == false); | ||||||
|     CHECK(variant.is<std::string>() == false); |     CHECK(variant.is<std::string>() == false); | ||||||
|     CHECK(variant.is<float>() == false); |     CHECK(variant.is<float>() == false); | ||||||
| @@ -47,7 +47,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<JsonVariantConst>() == true); |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
|     CHECK(variant.is<JsonObject>() == false); |     CHECK(variant.is<JsonObject>() == false); | ||||||
|     CHECK(variant.is<JsonArray>() == false); |     CHECK(variant.is<JsonArray>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<int>() == false); |     CHECK(variant.is<int>() == false); | ||||||
|     CHECK(variant.is<std::string>() == false); |     CHECK(variant.is<std::string>() == false); | ||||||
|     CHECK(variant.is<float>() == false); |     CHECK(variant.is<float>() == false); | ||||||
| @@ -62,7 +62,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<JsonVariantConst>() == true); |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
|     CHECK(variant.is<JsonObject>() == false); |     CHECK(variant.is<JsonObject>() == false); | ||||||
|     CHECK(variant.is<JsonArray>() == false); |     CHECK(variant.is<JsonArray>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<int>() == false); |     CHECK(variant.is<int>() == false); | ||||||
|     CHECK(variant.is<std::string>() == false); |     CHECK(variant.is<std::string>() == false); | ||||||
|     CHECK(variant.is<float>() == false); |     CHECK(variant.is<float>() == false); | ||||||
| @@ -83,7 +83,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<bool>() == false); |     CHECK(variant.is<bool>() == false); | ||||||
|     CHECK(variant.is<JsonObject>() == false); |     CHECK(variant.is<JsonObject>() == false); | ||||||
|     CHECK(variant.is<JsonArray>() == false); |     CHECK(variant.is<JsonArray>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<std::string>() == false); |     CHECK(variant.is<std::string>() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -97,7 +97,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<bool>() == false); |     CHECK(variant.is<bool>() == false); | ||||||
|     CHECK(variant.is<JsonObject>() == false); |     CHECK(variant.is<JsonObject>() == false); | ||||||
|     CHECK(variant.is<JsonArray>() == false); |     CHECK(variant.is<JsonArray>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<int>() == false); |     CHECK(variant.is<int>() == false); | ||||||
|     CHECK(variant.is<std::string>() == false); |     CHECK(variant.is<std::string>() == false); | ||||||
|     CHECK(variant.is<MYENUM2>() == false); |     CHECK(variant.is<MYENUM2>() == false); | ||||||
| @@ -106,7 +106,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|   SECTION("const char*") { |   SECTION("const char*") { | ||||||
|     variant.set("4.2"); |     variant.set("4.2"); | ||||||
|  |  | ||||||
|     CHECK(variant.is<char *>() == true); |     CHECK(variant.is<const char *>() == true); | ||||||
|     CHECK(variant.is<const char *>() == true); |     CHECK(variant.is<const char *>() == true); | ||||||
|     CHECK(variant.is<std::string>() == true); |     CHECK(variant.is<std::string>() == true); | ||||||
|     CHECK(variant.is<JsonVariant>() == true); |     CHECK(variant.is<JsonVariant>() == true); | ||||||
| @@ -132,7 +132,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<int>() == false); |     CHECK(variant.is<int>() == false); | ||||||
|     CHECK(variant.is<float>() == false); |     CHECK(variant.is<float>() == false); | ||||||
|     CHECK(variant.is<bool>() == false); |     CHECK(variant.is<bool>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<MYENUM2>() == false); |     CHECK(variant.is<MYENUM2>() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -148,7 +148,7 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<int>() == false); |     CHECK(variant.is<int>() == false); | ||||||
|     CHECK(variant.is<float>() == false); |     CHECK(variant.is<float>() == false); | ||||||
|     CHECK(variant.is<bool>() == false); |     CHECK(variant.is<bool>() == false); | ||||||
|     CHECK(variant.is<char *>() == false); |     CHECK(variant.is<const char *>() == false); | ||||||
|     CHECK(variant.is<MYENUM2>() == false); |     CHECK(variant.is<MYENUM2>() == false); | ||||||
|     CHECK(variant.is<JsonVariant>() == true); |     CHECK(variant.is<JsonVariant>() == true); | ||||||
|     CHECK(variant.is<JsonVariantConst>() == true); |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
| @@ -170,7 +170,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<JsonVariant>() == false); |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|     CHECK(cvariant.is<JsonVariantConst>() == false); |     CHECK(cvariant.is<JsonVariantConst>() == false); | ||||||
|     CHECK(cvariant.is<bool>() == false); |     CHECK(cvariant.is<bool>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<int>() == false); |     CHECK(cvariant.is<int>() == false); | ||||||
|     CHECK(cvariant.is<std::string>() == false); |     CHECK(cvariant.is<std::string>() == false); | ||||||
|     CHECK(cvariant.is<float>() == false); |     CHECK(cvariant.is<float>() == false); | ||||||
| @@ -183,7 +183,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<JsonArray>() == false); |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|     CHECK(cvariant.is<JsonVariant>() == false); |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|     CHECK(cvariant.is<bool>() == false); |     CHECK(cvariant.is<bool>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<int>() == false); |     CHECK(cvariant.is<int>() == false); | ||||||
|     CHECK(cvariant.is<std::string>() == false); |     CHECK(cvariant.is<std::string>() == false); | ||||||
|     CHECK(cvariant.is<float>() == false); |     CHECK(cvariant.is<float>() == false); | ||||||
| @@ -198,7 +198,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<JsonVariant>() == false); |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|     CHECK(cvariant.is<JsonObject>() == false); |     CHECK(cvariant.is<JsonObject>() == false); | ||||||
|     CHECK(cvariant.is<JsonArray>() == false); |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<int>() == false); |     CHECK(cvariant.is<int>() == false); | ||||||
|     CHECK(cvariant.is<std::string>() == false); |     CHECK(cvariant.is<std::string>() == false); | ||||||
|     CHECK(cvariant.is<float>() == false); |     CHECK(cvariant.is<float>() == false); | ||||||
| @@ -213,7 +213,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<JsonVariant>() == false); |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|     CHECK(cvariant.is<JsonObject>() == false); |     CHECK(cvariant.is<JsonObject>() == false); | ||||||
|     CHECK(cvariant.is<JsonArray>() == false); |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<int>() == false); |     CHECK(cvariant.is<int>() == false); | ||||||
|     CHECK(cvariant.is<std::string>() == false); |     CHECK(cvariant.is<std::string>() == false); | ||||||
|     CHECK(cvariant.is<float>() == false); |     CHECK(cvariant.is<float>() == false); | ||||||
| @@ -234,7 +234,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<JsonObject>() == false); |     CHECK(cvariant.is<JsonObject>() == false); | ||||||
|     CHECK(cvariant.is<JsonArray>() == false); |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|     CHECK(cvariant.is<JsonVariant>() == false); |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<std::string>() == false); |     CHECK(cvariant.is<std::string>() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -248,7 +248,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<JsonObject>() == false); |     CHECK(cvariant.is<JsonObject>() == false); | ||||||
|     CHECK(cvariant.is<JsonArray>() == false); |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|     CHECK(cvariant.is<JsonVariant>() == false); |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<int>() == false); |     CHECK(cvariant.is<int>() == false); | ||||||
|     CHECK(cvariant.is<std::string>() == false); |     CHECK(cvariant.is<std::string>() == false); | ||||||
|     CHECK(cvariant.is<MYENUM2>() == false); |     CHECK(cvariant.is<MYENUM2>() == false); | ||||||
| @@ -257,7 +257,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|   SECTION("const char*") { |   SECTION("const char*") { | ||||||
|     variant.set("4.2"); |     variant.set("4.2"); | ||||||
|  |  | ||||||
|     CHECK(cvariant.is<char *>() == true); |     CHECK(cvariant.is<const char *>() == true); | ||||||
|     CHECK(cvariant.is<const char *>() == true); |     CHECK(cvariant.is<const char *>() == true); | ||||||
|     CHECK(cvariant.is<std::string>() == true); |     CHECK(cvariant.is<std::string>() == true); | ||||||
|     CHECK(cvariant.is<double>() == false); |     CHECK(cvariant.is<double>() == false); | ||||||
| @@ -282,7 +282,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<int>() == false); |     CHECK(cvariant.is<int>() == false); | ||||||
|     CHECK(cvariant.is<float>() == false); |     CHECK(cvariant.is<float>() == false); | ||||||
|     CHECK(cvariant.is<bool>() == false); |     CHECK(cvariant.is<bool>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<MYENUM2>() == false); |     CHECK(cvariant.is<MYENUM2>() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -298,7 +298,7 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<int>() == false); |     CHECK(cvariant.is<int>() == false); | ||||||
|     CHECK(cvariant.is<float>() == false); |     CHECK(cvariant.is<float>() == false); | ||||||
|     CHECK(cvariant.is<bool>() == false); |     CHECK(cvariant.is<bool>() == false); | ||||||
|     CHECK(cvariant.is<char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<MYENUM2>() == false); |     CHECK(cvariant.is<MYENUM2>() == false); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -47,8 +47,8 @@ TEST_CASE("JsonVariant undefined") { | |||||||
|       REQUIRE(variant.is<unsigned>() == false); |       REQUIRE(variant.is<unsigned>() == false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SECTION("char*") { |     SECTION("const char*") { | ||||||
|       REQUIRE(variant.is<char*>() == false); |       REQUIRE(variant.is<const char*>() == false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     SECTION("double") { |     SECTION("double") { | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| // MIT License | // MIT License | ||||||
|  |  | ||||||
| #define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 | #define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 | ||||||
| #include <ArduinoJson/Deserialization/Reader.hpp> | #include <ArduinoJson.hpp> | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
|  |  | ||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|   | |||||||
| @@ -6,8 +6,7 @@ | |||||||
| #define ARDUINOJSON_ENABLE_NAN 1 | #define ARDUINOJSON_ENABLE_NAN 1 | ||||||
| #define ARDUINOJSON_ENABLE_INFINITY 1 | #define ARDUINOJSON_ENABLE_INFINITY 1 | ||||||
|  |  | ||||||
| #include <ArduinoJson/Numbers/parseNumber.hpp> | #include <ArduinoJson.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantImpl.hpp> |  | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
|  |  | ||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|   | |||||||
| @@ -6,8 +6,7 @@ | |||||||
| #define ARDUINOJSON_ENABLE_NAN 1 | #define ARDUINOJSON_ENABLE_NAN 1 | ||||||
| #define ARDUINOJSON_ENABLE_INFINITY 1 | #define ARDUINOJSON_ENABLE_INFINITY 1 | ||||||
|  |  | ||||||
| #include <ArduinoJson/Numbers/parseNumber.hpp> | #include <ArduinoJson.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantImpl.hpp> |  | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
|  |  | ||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|   | |||||||
| @@ -3,8 +3,7 @@ | |||||||
| // MIT License | // MIT License | ||||||
|  |  | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <ArduinoJson/Numbers/parseNumber.hpp> | #include <ArduinoJson.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantImpl.hpp> |  | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
|  |  | ||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|   | |||||||
| @@ -2,9 +2,7 @@ | |||||||
| // Copyright Benoit Blanchon 2014-2021 | // Copyright Benoit Blanchon 2014-2021 | ||||||
| // MIT License | // MIT License | ||||||
|  |  | ||||||
| #include <ArduinoJson/Numbers/Integer.hpp> | #include <ArduinoJson.hpp> | ||||||
| #include <ArduinoJson/Numbers/parseNumber.hpp> |  | ||||||
| #include <ArduinoJson/Variant/VariantImpl.hpp> |  | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
|  |  | ||||||
| using namespace ARDUINOJSON_NAMESPACE; | using namespace ARDUINOJSON_NAMESPACE; | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ | |||||||
| #include "ArduinoJson/Collection/CollectionImpl.hpp" | #include "ArduinoJson/Collection/CollectionImpl.hpp" | ||||||
| #include "ArduinoJson/Object/MemberProxy.hpp" | #include "ArduinoJson/Object/MemberProxy.hpp" | ||||||
| #include "ArduinoJson/Object/ObjectImpl.hpp" | #include "ArduinoJson/Object/ObjectImpl.hpp" | ||||||
| #include "ArduinoJson/Variant/VariantAsImpl.hpp" | #include "ArduinoJson/Variant/ConverterImpl.hpp" | ||||||
| #include "ArduinoJson/Variant/VariantCompare.hpp" | #include "ArduinoJson/Variant/VariantCompare.hpp" | ||||||
| #include "ArduinoJson/Variant/VariantImpl.hpp" | #include "ArduinoJson/Variant/VariantImpl.hpp" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -164,4 +164,42 @@ class ArrayRef : public ArrayRefBase<CollectionData>, | |||||||
|  private: |  private: | ||||||
|   MemoryPool* _pool; |   MemoryPool* _pool; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<ArrayConstRef> { | ||||||
|  |   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||||
|  |     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static ArrayConstRef fromJson(VariantConstRef variant) { | ||||||
|  |     return ArrayConstRef(variantAsArray(getData(variant))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data && data->isArray(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<ArrayRef> { | ||||||
|  |   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||||
|  |     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static ArrayRef fromJson(VariantRef variant) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     MemoryPool* pool = getPool(variant); | ||||||
|  |     return ArrayRef(pool, data != 0 ? data->asArray() : 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantRef variant) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     return data && data->isArray(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -9,6 +9,8 @@ | |||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| // Forward declarations. | // Forward declarations. | ||||||
|  | class ArrayRef; | ||||||
|  | class ObjectRef; | ||||||
| template <typename> | template <typename> | ||||||
| class ElementProxy; | class ElementProxy; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -170,6 +170,10 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|     return _array.getOrAddElement(_index); |     return _array.getOrAddElement(_index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   friend bool convertToJson(VariantRef variant, const this_type& value) { | ||||||
|  |     return variant.set(value.getUpstreamElement()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   TArray _array; |   TArray _array; | ||||||
|   const size_t _index; |   const size_t _index; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -76,7 +76,8 @@ class ArrayCopier1D : public Visitor<size_t> { | |||||||
|     VariantSlot* slot = array.head(); |     VariantSlot* slot = array.head(); | ||||||
|  |  | ||||||
|     while (slot != 0 && size < _capacity) { |     while (slot != 0 && size < _capacity) { | ||||||
|       _destination[size++] = variantAs<T>(slot->data()); |       _destination[size++] = | ||||||
|  |           Converter<T>::fromJson(VariantConstRef(slot->data())); | ||||||
|       slot = slot->next(); |       slot = slot->next(); | ||||||
|     } |     } | ||||||
|     return size; |     return size; | ||||||
|   | |||||||
| @@ -337,4 +337,8 @@ class JsonDocument : public Visitable { | |||||||
|   JsonDocument& operator=(const JsonDocument&); |   JsonDocument& operator=(const JsonDocument&); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | inline bool convertToJson(VariantRef variant, const JsonDocument& doc) { | ||||||
|  |   return variant.set(doc.as<VariantConstRef>()); | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
| #include <ArduinoJson/Polyfills/ctype.hpp> | #include <ArduinoJson/Polyfills/ctype.hpp> | ||||||
| #include <ArduinoJson/Polyfills/math.hpp> | #include <ArduinoJson/Polyfills/math.hpp> | ||||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantAs.hpp> | #include <ArduinoJson/Variant/Converter.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantData.hpp> | #include <ArduinoJson/Variant/VariantData.hpp> | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
| @@ -142,6 +142,6 @@ inline T parseNumber(const char* s) { | |||||||
|   VariantData value; |   VariantData value; | ||||||
|   value.init();  // VariantData is a POD, so it has no constructor |   value.init();  // VariantData is a POD, so it has no constructor | ||||||
|   parseNumber(s, value); |   parseNumber(s, value); | ||||||
|   return variantAs<T>(&value); |   return Converter<T>::fromJson(VariantConstRef(&value)); | ||||||
| } | } | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -193,6 +193,10 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | |||||||
|     return _object.getOrAddMember(_key); |     return _object.getOrAddMember(_key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   friend bool convertToJson(VariantRef variant, const this_type &value) { | ||||||
|  |     return variant.set(value.getUpstreamMember()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   TObject _object; |   TObject _object; | ||||||
|   TStringRef _key; |   TStringRef _key; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -236,4 +236,42 @@ class ObjectRef : public ObjectRefBase<CollectionData>, | |||||||
|  private: |  private: | ||||||
|   MemoryPool* _pool; |   MemoryPool* _pool; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<ObjectConstRef> { | ||||||
|  |   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||||
|  |     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static ObjectConstRef fromJson(VariantConstRef variant) { | ||||||
|  |     return ObjectConstRef(variantAsObject(getData(variant))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data && data->isObject(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<ObjectRef> { | ||||||
|  |   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||||
|  |     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static ObjectRef fromJson(VariantRef variant) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     MemoryPool* pool = getPool(variant); | ||||||
|  |     return ObjectRef(pool, data != 0 ? data->asObject() : 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantRef variant) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     return data && data->isObject(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								src/ArduinoJson/Variant/Converter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/ArduinoJson/Variant/Converter.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2021 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
|  | template <typename T, typename Enable = void> | ||||||
|  | struct Converter; | ||||||
|  |  | ||||||
|  | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
							
								
								
									
										209
									
								
								src/ArduinoJson/Variant/ConverterImpl.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								src/ArduinoJson/Variant/ConverterImpl.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | |||||||
|  | // ArduinoJson - arduinojson.org | ||||||
|  | // Copyright Benoit Blanchon 2014-2021 | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <ArduinoJson/Strings/IsWriteableString.hpp> | ||||||
|  | #include <ArduinoJson/Variant/VariantFunctions.hpp> | ||||||
|  | #include <ArduinoJson/Variant/VariantRef.hpp> | ||||||
|  |  | ||||||
|  | namespace ARDUINOJSON_NAMESPACE { | ||||||
|  |  | ||||||
|  | template <typename T, typename Enable> | ||||||
|  | struct Converter { | ||||||
|  |   static bool toJson(VariantRef variant, const T& value) { | ||||||
|  |     // clang-format off | ||||||
|  |     return convertToJson(variant, value); // Error here? See https://arduinojson.org/v6/unsupported-set/ | ||||||
|  |     // clang-format on | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static T fromJson(VariantConstRef variant) { | ||||||
|  |     // clang-format off | ||||||
|  |     T value; // Error here? See https://arduinojson.org/v6/non-default-constructible/ | ||||||
|  |     convertFromJson(value, variant);  // Error here? See https://arduinojson.org/v6/unsupported-as/ | ||||||
|  |     // clang-format on | ||||||
|  |     return value; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     T dummy; | ||||||
|  |     // clang-format off | ||||||
|  |     return canConvertFromJson(dummy, variant);  // Error here? See https://arduinojson.org/v6/unsupported-is/ | ||||||
|  |     // clang-format on | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct Converter< | ||||||
|  |     T, typename enable_if<is_integral<T>::value && !is_same<bool, T>::value && | ||||||
|  |                           !is_same<char, T>::value>::type> { | ||||||
|  |   static bool toJson(VariantRef variant, T value) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||||
|  |     if (!data) | ||||||
|  |       return false; | ||||||
|  |     data->setInteger(value); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static T fromJson(VariantConstRef variant) { | ||||||
|  |     ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data ? data->asIntegral<T>() : T(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data && data->isInteger<T>(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct Converter<T, typename enable_if<is_enum<T>::value>::type> { | ||||||
|  |   static bool toJson(VariantRef variant, T value) { | ||||||
|  |     return variant.set(static_cast<Integer>(value)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static T fromJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data ? static_cast<T>(data->asIntegral<int>()) : T(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data && data->isInteger<int>(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<bool> { | ||||||
|  |   static bool toJson(VariantRef variant, bool value) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     if (!data) | ||||||
|  |       return false; | ||||||
|  |     data->setBoolean(value); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool fromJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data ? data->asBoolean() : false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data && data->isBoolean(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | struct Converter<T, typename enable_if<is_floating_point<T>::value>::type> { | ||||||
|  |   static bool toJson(VariantRef variant, T value) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     if (!data) | ||||||
|  |       return false; | ||||||
|  |     data->setFloat(static_cast<Float>(value)); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static T fromJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data ? data->asFloat<T>() : false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data && data->isFloat(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<const char*> { | ||||||
|  |   static bool toJson(VariantRef variant, const char* value) { | ||||||
|  |     // TODO: don't pass pool | ||||||
|  |     return variantSetString(getData(variant), adaptString(value), | ||||||
|  |                             getPool(variant)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static const char* fromJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data ? data->asString() : 0; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data && data->isString(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | inline typename enable_if<IsString<T>::value, bool>::type convertToJson( | ||||||
|  |     VariantRef variant, const T& value) { | ||||||
|  |   VariantData* data = getData(variant); | ||||||
|  |   MemoryPool* pool = getPool(variant); | ||||||
|  |   return variantSetString(data, adaptString(value), pool); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | inline typename enable_if<IsWriteableString<T>::value>::type convertFromJson( | ||||||
|  |     T& value, VariantConstRef variant) { | ||||||
|  |   const VariantData* data = getData(variant); | ||||||
|  |   const char* cstr = data != 0 ? data->asString() : 0; | ||||||
|  |   if (cstr) | ||||||
|  |     value = cstr; | ||||||
|  |   else | ||||||
|  |     serializeJson(variant, value); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | inline typename enable_if<IsWriteableString<T>::value, bool>::type | ||||||
|  | canConvertFromJson(T&, VariantConstRef variant) { | ||||||
|  |   const VariantData* data = getData(variant); | ||||||
|  |   return data && data->isString(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<SerializedValue<const char*> > { | ||||||
|  |   static bool toJson(VariantRef variant, SerializedValue<const char*> value) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     if (!data) | ||||||
|  |       return false; | ||||||
|  |     data->setLinkedRaw(value); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // SerializedValue<std::string> | ||||||
|  | // SerializedValue<String> | ||||||
|  | // SerializedValue<const __FlashStringHelper*> | ||||||
|  | template <typename T> | ||||||
|  | struct Converter<SerializedValue<T>, | ||||||
|  |                  typename enable_if<!is_same<const char*, T>::value>::type> { | ||||||
|  |   static bool toJson(VariantRef variant, SerializedValue<T> value) { | ||||||
|  |     VariantData* data = getData(variant); | ||||||
|  |     MemoryPool* pool = getPool(variant); | ||||||
|  |     return data != 0 && data->setOwnedRaw(value, pool); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #if ARDUINOJSON_HAS_NULLPTR | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<decltype(nullptr)> { | ||||||
|  |   static bool toJson(VariantRef variant, decltype(nullptr)) { | ||||||
|  |     variantSetNull(getData(variant)); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  |   static decltype(nullptr) fromJson(VariantConstRef) { | ||||||
|  |     return nullptr; | ||||||
|  |   } | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData* data = getData(variant); | ||||||
|  |     return data == 0 || data->isNull(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
| @@ -1,76 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2021 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include <ArduinoJson/Strings/IsWriteableString.hpp> |  | ||||||
| #include <ArduinoJson/Variant/VariantData.hpp> |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { |  | ||||||
|  |  | ||||||
| class ArrayRef; |  | ||||||
| class ArrayConstRef; |  | ||||||
| class ObjectRef; |  | ||||||
| class ObjectConstRef; |  | ||||||
| class VariantRef; |  | ||||||
| class VariantConstRef; |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_integral<T>::value && !is_same<bool, T>::value && |  | ||||||
|                               !is_same<char, T>::value, |  | ||||||
|                           T>::type |  | ||||||
| variantAs(const VariantData* data) { |  | ||||||
|   ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); |  | ||||||
|   return data != 0 ? data->asIntegral<T>() : T(0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_enum<T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* data) { |  | ||||||
|   return data != 0 ? static_cast<T>(data->asIntegral<int>()) : T(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<T, bool>::value, T>::type variantAs( |  | ||||||
|     const VariantData* data) { |  | ||||||
|   return data != 0 ? data->asBoolean() : false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_floating_point<T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* data) { |  | ||||||
|   return data != 0 ? data->asFloat<T>() : T(0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<T, const char*>::value, T>::type variantAs( |  | ||||||
|     const VariantData* data) { |  | ||||||
|   return data != 0 ? data->asString() : 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| T variantAs(VariantData* data, MemoryPool*) { |  | ||||||
|   // By default use the read-only conversion. |  | ||||||
|   // There are specializations for |  | ||||||
|   // - ArrayRef |  | ||||||
|   return variantAs<T>(data); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* data); |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* data); |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type |  | ||||||
| variantAs(const VariantData* data); |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* data); |  | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE |  | ||||||
| @@ -1,57 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2021 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include <ArduinoJson/Strings/IsWriteableString.hpp> |  | ||||||
| #include <ArduinoJson/Variant/VariantFunctions.hpp> |  | ||||||
| #include <ArduinoJson/Variant/VariantRef.hpp> |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* _data) { |  | ||||||
|   return ArrayConstRef(variantAsArray(_data)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* _data) { |  | ||||||
|   return ObjectConstRef(variantAsObject(_data)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type |  | ||||||
| variantAs(const VariantData* _data) { |  | ||||||
|   return VariantConstRef(_data); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs( |  | ||||||
|     const VariantData* _data) { |  | ||||||
|   const char* cstr = _data != 0 ? _data->asString() : 0; |  | ||||||
|   if (cstr) |  | ||||||
|     return T(cstr); |  | ||||||
|   T s; |  | ||||||
|   serializeJson(VariantConstRef(_data), s); |  | ||||||
|   return s; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline ArrayRef variantAs<ArrayRef>(VariantData* data, MemoryPool* pool) { |  | ||||||
|   return ArrayRef(pool, data != 0 ? data->asArray() : 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline ObjectRef variantAs<ObjectRef>(VariantData* data, MemoryPool* pool) { |  | ||||||
|   return ObjectRef(pool, data != 0 ? data->asObject() : 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <> |  | ||||||
| inline VariantRef variantAs<VariantRef>(VariantData* data, MemoryPool* pool) { |  | ||||||
|   return VariantRef(pool, data); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE |  | ||||||
| @@ -43,34 +43,6 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src, | |||||||
|  |  | ||||||
| inline int variantCompare(const VariantData *a, const VariantData *b); | inline int variantCompare(const VariantData *a, const VariantData *b); | ||||||
|  |  | ||||||
| inline bool variantSetBoolean(VariantData *var, bool value) { |  | ||||||
|   if (!var) |  | ||||||
|     return false; |  | ||||||
|   var->setBoolean(value); |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool variantSetFloat(VariantData *var, Float value) { |  | ||||||
|   if (!var) |  | ||||||
|     return false; |  | ||||||
|   var->setFloat(value); |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline bool variantSetLinkedRaw(VariantData *var, |  | ||||||
|                                 SerializedValue<const char *> value) { |  | ||||||
|   if (!var) |  | ||||||
|     return false; |  | ||||||
|   var->setLinkedRaw(value); |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value, |  | ||||||
|                                MemoryPool *pool) { |  | ||||||
|   return var != 0 && var->setOwnedRaw(value, pool); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline void variantSetNull(VariantData *var) { | inline void variantSetNull(VariantData *var) { | ||||||
|   if (!var) |   if (!var) | ||||||
|     return; |     return; | ||||||
| @@ -85,15 +57,6 @@ inline bool variantSetString(VariantData *var, TAdaptedString value, | |||||||
|   return var->setString(value, pool); |   return var->setString(value, pool); | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename T> |  | ||||||
| inline bool variantSetInteger(VariantData *var, T value) { |  | ||||||
|   ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); |  | ||||||
|   if (!var) |  | ||||||
|     return false; |  | ||||||
|   var->setInteger(value); |  | ||||||
|   return true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline size_t variantSize(const VariantData *var) { | inline size_t variantSize(const VariantData *var) { | ||||||
|   return var != 0 ? var->size() : 0; |   return var != 0 ? var->size() : 0; | ||||||
| } | } | ||||||
| @@ -134,4 +97,8 @@ NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, | |||||||
|   return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; |   return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline bool variantIsNull(const VariantData *var) { | ||||||
|  |   return var == 0 || var->isNull(); | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -77,13 +77,6 @@ inline const char *VariantData::asString() const { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename TVariant> |  | ||||||
| typename enable_if<IsVisitable<TVariant>::value, bool>::type VariantRef::set( |  | ||||||
|     const TVariant &value) const { |  | ||||||
|   VariantConstRef v = value; |  | ||||||
|   return variantCopyFrom(_data, v._data, _pool); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| template <typename T> | template <typename T> | ||||||
| inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type | inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type | ||||||
| VariantRef::to() const { | VariantRef::to() const { | ||||||
|   | |||||||
| @@ -1,146 +0,0 @@ | |||||||
| // ArduinoJson - arduinojson.org |  | ||||||
| // Copyright Benoit Blanchon 2014-2021 |  | ||||||
| // MIT License |  | ||||||
|  |  | ||||||
| #pragma once |  | ||||||
|  |  | ||||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> |  | ||||||
| #include <ArduinoJson/Variant/VariantFunctions.hpp> |  | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { |  | ||||||
|  |  | ||||||
| inline bool variantIsNull(const VariantData *var) { |  | ||||||
|   return var == 0 || var->isNull(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<char>() const; |  | ||||||
| // bool is<signed char>() const; |  | ||||||
| // bool is<signed short>() const; |  | ||||||
| // bool is<signed int>() const; |  | ||||||
| // bool is<signed long>() const; |  | ||||||
| // bool is<unsigned char>() const; |  | ||||||
| // bool is<unsigned short>() const; |  | ||||||
| // bool is<unsigned int>() const; |  | ||||||
| // bool is<unsigned long>() const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if<is_integral<T>::value && !is_same<bool, T>::value, |  | ||||||
|                              bool>::type |  | ||||||
| variantIs(const VariantData *var) { |  | ||||||
|   return var && var->isInteger<T>(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<double>() const; |  | ||||||
| // bool is<float>() const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if<is_floating_point<T>::value, bool>::type variantIs( |  | ||||||
|     const VariantData *var) { |  | ||||||
|   return var && var->isFloat(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<bool>() const |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if<is_same<T, bool>::value, bool>::type variantIs( |  | ||||||
|     const VariantData *var) { |  | ||||||
|   return var && var->isBoolean(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<const char*>() const; |  | ||||||
| // bool is<char*>() const; |  | ||||||
| // bool is<std::string>() const; |  | ||||||
| // bool is<String>() const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if<is_same<T, const char *>::value || |  | ||||||
|                                  is_same<T, char *>::value || |  | ||||||
|                                  IsWriteableString<T>::value, |  | ||||||
|                              bool>::type |  | ||||||
| variantIs(const VariantData *var) { |  | ||||||
|   return var && var->isString(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<ArrayConstRef> const; |  | ||||||
| // bool is<const ArrayConstRef> const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if< |  | ||||||
|     is_same<typename remove_const<T>::type, ArrayConstRef>::value, bool>::type |  | ||||||
| variantIs(const VariantData *var) { |  | ||||||
|   return var && var->isArray(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<ObjectConstRef> const; |  | ||||||
| // bool is<const ObjectConstRef> const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if< |  | ||||||
|     is_same<typename remove_const<T>::type, ObjectConstRef>::value, bool>::type |  | ||||||
| variantIs(const VariantData *var) { |  | ||||||
|   return var && var->isObject(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<VariantConstRef> const; |  | ||||||
| // bool is<const VariantConstRef> const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if< |  | ||||||
|     is_same<typename remove_const<T>::type, VariantConstRef>::value, bool>::type |  | ||||||
| variantIs(const VariantData *var) { |  | ||||||
|   return !!var; |  | ||||||
| } |  | ||||||
| #if ARDUINOJSON_HAS_NULLPTR |  | ||||||
|  |  | ||||||
| // bool is<nullptr_t> const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if<is_same<T, decltype(nullptr)>::value, bool>::type |  | ||||||
| variantIs(const VariantData *var) { |  | ||||||
|   return variantIsNull(var); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| // bool is<enum>() const; |  | ||||||
| template <typename T> |  | ||||||
| typename enable_if<is_enum<T>::value, bool>::type variantIs( |  | ||||||
|     const VariantData *var) { |  | ||||||
|   return variantIs<int>(var); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<ArrayRef> const; |  | ||||||
| // bool is<const ArrayRef> const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE |  | ||||||
|     typename enable_if<is_same<typename remove_const<T>::type, ArrayRef>::value, |  | ||||||
|                        bool>::type |  | ||||||
|     variantIs(VariantData *var) { |  | ||||||
|   return var && var->isArray(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<ObjectRef> const; |  | ||||||
| // bool is<const ObjectRef> const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if< |  | ||||||
|     is_same<typename remove_const<T>::type, ObjectRef>::value, bool>::type |  | ||||||
| variantIs(VariantData *var) { |  | ||||||
|   return var && var->isObject(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<VariantRef> const; |  | ||||||
| // bool is<const VariantRef> const; |  | ||||||
| template <typename T> |  | ||||||
| NO_INLINE typename enable_if< |  | ||||||
|     is_same<typename remove_const<T>::type, VariantRef>::value, bool>::type |  | ||||||
| variantIs(VariantData *var) { |  | ||||||
|   return !!var; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // bool is<ArrayRef> const; |  | ||||||
| // bool is<const ArrayRef> const; |  | ||||||
| // bool is<ObjectRef> const; |  | ||||||
| // bool is<const ObjectRef> const; |  | ||||||
| // bool is<VariantRef> const; |  | ||||||
| // bool is<const VariantRef> const; |  | ||||||
| template <typename T> |  | ||||||
| typename enable_if< |  | ||||||
|     is_same<typename remove_const<T>::type, ArrayRef>::value || |  | ||||||
|         is_same<typename remove_const<T>::type, ObjectRef>::value || |  | ||||||
|         is_same<typename remove_const<T>::type, VariantRef>::value, |  | ||||||
|     bool>::type |  | ||||||
| variantIs(const VariantData *) { |  | ||||||
|   return false; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE |  | ||||||
| @@ -8,7 +8,6 @@ | |||||||
| #include <ArduinoJson/Numbers/arithmeticCompare.hpp> | #include <ArduinoJson/Numbers/arithmeticCompare.hpp> | ||||||
| #include <ArduinoJson/Polyfills/attributes.hpp> | #include <ArduinoJson/Polyfills/attributes.hpp> | ||||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantAs.hpp> |  | ||||||
| #include <ArduinoJson/Variant/VariantTag.hpp> | #include <ArduinoJson/Variant/VariantTag.hpp> | ||||||
|  |  | ||||||
| namespace ARDUINOJSON_NAMESPACE { | namespace ARDUINOJSON_NAMESPACE { | ||||||
|   | |||||||
| @@ -11,9 +11,8 @@ | |||||||
| #include <ArduinoJson/Misc/Visitable.hpp> | #include <ArduinoJson/Misc/Visitable.hpp> | ||||||
| #include <ArduinoJson/Polyfills/type_traits.hpp> | #include <ArduinoJson/Polyfills/type_traits.hpp> | ||||||
| #include <ArduinoJson/Strings/StringAdapters.hpp> | #include <ArduinoJson/Strings/StringAdapters.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantAs.hpp> | #include <ArduinoJson/Variant/Converter.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantFunctions.hpp> | #include <ArduinoJson/Variant/VariantFunctions.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantIs.hpp> |  | ||||||
| #include <ArduinoJson/Variant/VariantOperators.hpp> | #include <ArduinoJson/Variant/VariantOperators.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantRef.hpp> | #include <ArduinoJson/Variant/VariantRef.hpp> | ||||||
| #include <ArduinoJson/Variant/VariantShortcuts.hpp> | #include <ArduinoJson/Variant/VariantShortcuts.hpp> | ||||||
| @@ -29,11 +28,6 @@ class ObjectRef; | |||||||
| template <typename TData> | template <typename TData> | ||||||
| class VariantRefBase : public VariantTag { | class VariantRefBase : public VariantTag { | ||||||
|  public: |  public: | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool is() const { |  | ||||||
|     return variantIs<T>(_data); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   FORCE_INLINE bool isNull() const { |   FORCE_INLINE bool isNull() const { | ||||||
|     return variantIsNull(_data); |     return variantIsNull(_data); | ||||||
|   } |   } | ||||||
| @@ -57,6 +51,10 @@ class VariantRefBase : public VariantTag { | |||||||
|  protected: |  protected: | ||||||
|   VariantRefBase(TData *data) : _data(data) {} |   VariantRefBase(TData *data) : _data(data) {} | ||||||
|   TData *_data; |   TData *_data; | ||||||
|  |  | ||||||
|  |   friend TData *getData(const VariantRefBase &variant) { | ||||||
|  |     return variant._data; | ||||||
|  |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // A variant that can be a any value serializable to a JSON value. | // A variant that can be a any value serializable to a JSON value. | ||||||
| @@ -85,120 +83,29 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|     return variantSetNull(_data); |     return variantSetNull(_data); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(bool value) |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   FORCE_INLINE bool set(const T &value) const { | ||||||
|       T value, typename enable_if<is_same<T, bool>::value>::type * = 0) const { |     return Converter<T>::toJson(*this, value); | ||||||
|     return variantSetBoolean(_data, value); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(double value); |  | ||||||
|   // set(float value); |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE bool set( |   FORCE_INLINE bool set(T *value) const { | ||||||
|       T value, |     return Converter<T *>::toJson(*this, value); | ||||||
|       typename enable_if<is_floating_point<T>::value>::type * = 0) const { |  | ||||||
|     return variantSetFloat(_data, static_cast<Float>(value)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // set(char) |  | ||||||
|   // set(signed short) |  | ||||||
|   // set(signed int) |  | ||||||
|   // set(signed long) |  | ||||||
|   // set(signed char) |  | ||||||
|   // set(unsigned short) |  | ||||||
|   // set(unsigned int) |  | ||||||
|   // set(unsigned long) |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool set( |  | ||||||
|       T value, |  | ||||||
|       typename enable_if<is_integral<T>::value && !is_same<bool, T>::value && |  | ||||||
|                          !is_same<char, T>::value>::type * = 0) const { |  | ||||||
|     return variantSetInteger<T>(_data, value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // set(SerializedValue<const char *>) |  | ||||||
|   FORCE_INLINE bool set(SerializedValue<const char *> value) const { |  | ||||||
|     return variantSetLinkedRaw(_data, value); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // set(SerializedValue<std::string>) |  | ||||||
|   // set(SerializedValue<String>) |  | ||||||
|   // set(SerializedValue<const __FlashStringHelper*>) |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool set( |  | ||||||
|       SerializedValue<T> value, |  | ||||||
|       typename enable_if<!is_same<const char *, T>::value>::type * = 0) const { |  | ||||||
|     return variantSetOwnedRaw(_data, value, _pool); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // set(const std::string&) |  | ||||||
|   // set(const String&) |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool set( |  | ||||||
|       const T &value, |  | ||||||
|       typename enable_if<IsString<T>::value>::type * = 0) const { |  | ||||||
|     return variantSetString(_data, adaptString(value), _pool); |  | ||||||
|   } |  | ||||||
|   // set(char*) |  | ||||||
|   // set(const __FlashStringHelper*) |  | ||||||
|   // set(const char*) |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool set( |  | ||||||
|       T *value, typename enable_if<IsString<T *>::value>::type * = 0) const { |  | ||||||
|     return variantSetString(_data, adaptString(value), _pool); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // set(VariantRef) |  | ||||||
|   // set(VariantConstRef) |  | ||||||
|   // set(ArrayRef) |  | ||||||
|   // set(ArrayConstRef) |  | ||||||
|   // set(ObjectRef) |  | ||||||
|   // set(ObjecConstRef) |  | ||||||
|   // set(const JsonDocument&) |  | ||||||
|   template <typename TVariant> |  | ||||||
|   typename enable_if<IsVisitable<TVariant>::value, bool>::type set( |  | ||||||
|       const TVariant &value) const; |  | ||||||
|  |  | ||||||
|   // set(enum value) |  | ||||||
|   template <typename T> |  | ||||||
|   FORCE_INLINE bool set( |  | ||||||
|       T value, typename enable_if<is_enum<T>::value>::type * = 0) const { |  | ||||||
|     return variantSetInteger(_data, static_cast<Integer>(value)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| #if ARDUINOJSON_HAS_NULLPTR |  | ||||||
|   // set(nullptr_t) |  | ||||||
|   FORCE_INLINE bool set(decltype(nullptr)) const { |  | ||||||
|     variantSetNull(_data); |  | ||||||
|     return true; |  | ||||||
|   } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE T as() const { |   FORCE_INLINE T as() const { | ||||||
|     /******************************************************************** |     return Converter<T>::fromJson(*this); | ||||||
|      **                THIS IS NOT A BUG IN THE LIBRARY                ** |   } | ||||||
|      **                --------------------------------                ** |  | ||||||
|      **  Get a compilation error pointing here?                        ** |   template <typename T> | ||||||
|      **  It doesn't mean the error *is* here.                          ** |   FORCE_INLINE bool is() const { | ||||||
|      **  Often, it's because you try to extract the wrong value type.  ** |     return Converter<T>::checkJson(*this); | ||||||
|      **                                                                ** |  | ||||||
|      **  For example:                                                  ** |  | ||||||
|      **    char* name = doc["name"];                                   ** |  | ||||||
|      **    char age = doc["age"];                                      ** |  | ||||||
|      **    auto city = doc["city"].as<char*>()                         ** |  | ||||||
|      **  Instead, use:                                                 ** |  | ||||||
|      **    const char* name = doc["name"];                             ** |  | ||||||
|      **    int8_t age = doc["age"];                                    ** |  | ||||||
|      **    auto city = doc["city"].as<const char*>()                   ** |  | ||||||
|      ********************************************************************/ |  | ||||||
|     return variantAs<T>(_data, _pool); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE operator T() const { |   FORCE_INLINE operator T() const { | ||||||
|     return variantAs<T>(_data, _pool); |     return Converter<T>::fromJson(*this); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TVisitor> |   template <typename TVisitor> | ||||||
| @@ -273,7 +180,11 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   MemoryPool *_pool; |   MemoryPool *_pool; | ||||||
| };  // namespace ARDUINOJSON_NAMESPACE |  | ||||||
|  |   friend MemoryPool *getPool(const VariantRef &variant) { | ||||||
|  |     return variant._pool; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
| class VariantConstRef : public VariantRefBase<const VariantData>, | class VariantConstRef : public VariantRefBase<const VariantData>, | ||||||
|                         public VariantOperators<VariantConstRef>, |                         public VariantOperators<VariantConstRef>, | ||||||
| @@ -294,12 +205,17 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | |||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE T as() const { |   FORCE_INLINE T as() const { | ||||||
|     return variantAs<T>(_data); |     return Converter<T>::fromJson(*this); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   template <typename T> | ||||||
|  |   FORCE_INLINE bool is() const { | ||||||
|  |     return Converter<T>::checkJson(*this); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   FORCE_INLINE operator T() const { |   FORCE_INLINE operator T() const { | ||||||
|     return variantAs<T>(_data); |     return Converter<T>::fromJson(*this); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef getElement(size_t) const; |   FORCE_INLINE VariantConstRef getElement(size_t) const; | ||||||
| @@ -344,4 +260,38 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | |||||||
|     return getMember(key); |     return getMember(key); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<VariantRef> { | ||||||
|  |   static bool toJson(VariantRef variant, VariantRef value) { | ||||||
|  |     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||||
|  |   } | ||||||
|  |   static VariantRef fromJson(VariantRef variant) { | ||||||
|  |     return variant; | ||||||
|  |   } | ||||||
|  |   static bool checkJson(VariantRef variant) { | ||||||
|  |     VariantData *data = getData(variant); | ||||||
|  |     return !!data; | ||||||
|  |   } | ||||||
|  |   static bool checkJson(VariantConstRef) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | struct Converter<VariantConstRef> { | ||||||
|  |   static bool toJson(VariantRef variant, VariantConstRef value) { | ||||||
|  |     return variantCopyFrom(getData(variant), getData(value), getPool(variant)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static VariantConstRef fromJson(VariantConstRef variant) { | ||||||
|  |     return VariantConstRef(getData(variant)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   static bool checkJson(VariantConstRef variant) { | ||||||
|  |     const VariantData *data = getData(variant); | ||||||
|  |     return !!data; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user