mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Add JsonVariant::link()
				
					
				
			This commit is contained in:
		| @@ -245,3 +245,11 @@ TEST_CASE("ElementProxy cast to JsonVariant") { | |||||||
|  |  | ||||||
|   CHECK(doc.as<std::string>() == "[\"toto\"]"); |   CHECK(doc.as<std::string>() == "[\"toto\"]"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST_CASE("ElementProxy::link()") { | ||||||
|  |   StaticJsonDocument<1024> doc1, doc2; | ||||||
|  |   doc1[0].link(doc2); | ||||||
|  |   doc2["hello"] = "world"; | ||||||
|  |  | ||||||
|  |   CHECK(doc1.as<std::string>() == "[{\"hello\":\"world\"}]"); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -285,3 +285,43 @@ TEST_CASE("MemberProxy cast to JsonVariant") { | |||||||
|  |  | ||||||
|   CHECK(doc.as<std::string>() == "{\"hello\":\"toto\"}"); |   CHECK(doc.as<std::string>() == "{\"hello\":\"toto\"}"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::createNestedArray()") { | ||||||
|  |   StaticJsonDocument<1024> doc; | ||||||
|  |   JsonArray arr = doc["items"].createNestedArray(); | ||||||
|  |   arr.add(42); | ||||||
|  |  | ||||||
|  |   CHECK(doc["items"][0][0] == 42); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::createNestedArray(key)") { | ||||||
|  |   StaticJsonDocument<1024> doc; | ||||||
|  |   JsonArray arr = doc["weather"].createNestedArray("temp"); | ||||||
|  |   arr.add(42); | ||||||
|  |  | ||||||
|  |   CHECK(doc["weather"]["temp"][0] == 42); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::createNestedObject()") { | ||||||
|  |   StaticJsonDocument<1024> doc; | ||||||
|  |   JsonObject obj = doc["items"].createNestedObject(); | ||||||
|  |   obj["value"] = 42; | ||||||
|  |  | ||||||
|  |   CHECK(doc["items"][0]["value"] == 42); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::createNestedObject(key)") { | ||||||
|  |   StaticJsonDocument<1024> doc; | ||||||
|  |   JsonObject obj = doc["status"].createNestedObject("weather"); | ||||||
|  |   obj["temp"] = 42; | ||||||
|  |  | ||||||
|  |   CHECK(doc["status"]["weather"]["temp"] == 42); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | TEST_CASE("MemberProxy::link()") { | ||||||
|  |   StaticJsonDocument<1024> doc1, doc2; | ||||||
|  |   doc1["obj"].link(doc2); | ||||||
|  |   doc2["hello"] = "world"; | ||||||
|  |  | ||||||
|  |   CHECK(doc1.as<std::string>() == "{\"obj\":{\"hello\":\"world\"}}"); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -8,11 +8,12 @@ add_executable(JsonVariantTests | |||||||
| 	clear.cpp | 	clear.cpp | ||||||
| 	compare.cpp | 	compare.cpp | ||||||
| 	containsKey.cpp | 	containsKey.cpp | ||||||
| 	copy.cpp |  | ||||||
| 	converters.cpp | 	converters.cpp | ||||||
|  | 	copy.cpp | ||||||
| 	createNested.cpp | 	createNested.cpp | ||||||
| 	is.cpp | 	is.cpp | ||||||
| 	isnull.cpp | 	isnull.cpp | ||||||
|  | 	link.cpp | ||||||
| 	memoryUsage.cpp | 	memoryUsage.cpp | ||||||
| 	misc.cpp | 	misc.cpp | ||||||
| 	nesting.cpp | 	nesting.cpp | ||||||
| @@ -20,6 +21,7 @@ add_executable(JsonVariantTests | |||||||
| 	overflow.cpp | 	overflow.cpp | ||||||
| 	remove.cpp | 	remove.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
|  | 	size.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
| 	types.cpp | 	types.cpp | ||||||
| 	unbound.cpp | 	unbound.cpp | ||||||
|   | |||||||
| @@ -43,4 +43,14 @@ TEST_CASE("JsonVariant::add()") { | |||||||
|  |  | ||||||
|     REQUIRE(var.as<std::string>() == "{\"val\":123}"); |     REQUIRE(var.as<std::string>() == "{\"val\":123}"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("add to linked array") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2.add(42); | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     var.add(666);  // no-op | ||||||
|  |  | ||||||
|  |     CHECK(var.as<std::string>() == "[42]"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -267,4 +267,97 @@ TEST_CASE("JsonVariant::as()") { | |||||||
|  |  | ||||||
|     REQUIRE(variant.as<MY_ENUM>() == ONE); |     REQUIRE(variant.as<MY_ENUM>() == ONE); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked object") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     SECTION("as<std::string>()") { | ||||||
|  |       CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("as<JsonArray>()") { | ||||||
|  |       JsonArray a = variant.as<JsonArray>(); | ||||||
|  |       CHECK(a.isNull() == true); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("as<JsonObject>()") { | ||||||
|  |       JsonObject o = variant.as<JsonObject>(); | ||||||
|  |       CHECK(o.isNull() == true); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("as<JsonObjectConst>()") { | ||||||
|  |       JsonObjectConst o = variant.as<JsonObjectConst>(); | ||||||
|  |       CHECK(o.isNull() == false); | ||||||
|  |       CHECK(o.size() == 1); | ||||||
|  |       CHECK(o["hello"] == "world"); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked array") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2.add("hello"); | ||||||
|  |     doc2.add("world"); | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     SECTION("as<std::string>()") { | ||||||
|  |       CHECK(variant.as<std::string>() == "[\"hello\",\"world\"]"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("as<JsonArray>()") { | ||||||
|  |       JsonArray a = variant.as<JsonArray>(); | ||||||
|  |       CHECK(a.isNull() == true); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("as<JsonArrayConst>()") { | ||||||
|  |       JsonArrayConst a = variant.as<JsonArrayConst>(); | ||||||
|  |       CHECK(a.isNull() == false); | ||||||
|  |       CHECK(a.size() == 2); | ||||||
|  |       CHECK(a[0] == "hello"); | ||||||
|  |       CHECK(a[1] == "world"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     SECTION("as<JsonObject>()") { | ||||||
|  |       JsonObject o = variant.as<JsonObject>(); | ||||||
|  |       CHECK(o.isNull() == true); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked int") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2.set(42); | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<int>() == 42); | ||||||
|  |     CHECK(variant.as<double>() == 42.0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked double") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2.set(42.0); | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<int>() == 42); | ||||||
|  |     CHECK(variant.as<double>() == 42.0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked string") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2.set("hello"); | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "hello"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked bool") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     doc2.set(true); | ||||||
|  |     CHECK(variant.as<bool>() == true); | ||||||
|  |  | ||||||
|  |     doc2.set(false); | ||||||
|  |     CHECK(variant.as<bool>() == false); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,4 +23,15 @@ TEST_CASE("JsonVariant::clear()") { | |||||||
|  |  | ||||||
|     REQUIRE(var.isNull() == true); |     REQUIRE(var.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("doesn't alter linked object") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     var.clear(); | ||||||
|  |  | ||||||
|  |     CHECK(var.isNull() == true); | ||||||
|  |     CHECK(doc2.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -34,6 +34,20 @@ TEST_CASE("Compare JsonVariant with value") { | |||||||
|     CHECK_FALSE(a < b); |     CHECK_FALSE(a < b); | ||||||
|     CHECK_FALSE(a > b); |     CHECK_FALSE(a > b); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked 42 vs 42") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2.set(42); | ||||||
|  |     a.link(doc2); | ||||||
|  |     int b = 42; | ||||||
|  |  | ||||||
|  |     CHECK(a == b); | ||||||
|  |     CHECK(a <= b); | ||||||
|  |     CHECK(a >= b); | ||||||
|  |     CHECK_FALSE(a != b); | ||||||
|  |     CHECK_FALSE(a < b); | ||||||
|  |     CHECK_FALSE(a > b); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("Compare JsonVariant with JsonVariant") { | TEST_CASE("Compare JsonVariant with JsonVariant") { | ||||||
| @@ -313,4 +327,19 @@ TEST_CASE("Compare JsonVariant with JsonVariant") { | |||||||
|     CHECK_FALSE(a > b); |     CHECK_FALSE(a > b); | ||||||
|     CHECK_FALSE(a >= b); |     CHECK_FALSE(a >= b); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked 42 vs link 42") { | ||||||
|  |     StaticJsonDocument<128> doc2, doc3; | ||||||
|  |     doc2.set(42); | ||||||
|  |     doc3.set(42); | ||||||
|  |     a.link(doc2); | ||||||
|  |     b.link(doc3); | ||||||
|  |  | ||||||
|  |     CHECK(a == b); | ||||||
|  |     CHECK(a <= b); | ||||||
|  |     CHECK(a >= b); | ||||||
|  |     CHECK_FALSE(a != b); | ||||||
|  |     CHECK_FALSE(a < b); | ||||||
|  |     CHECK_FALSE(a > b); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,19 +12,28 @@ TEST_CASE("JsonVariant::containsKey()") { | |||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   JsonVariant var = doc.to<JsonVariant>(); |   JsonVariant var = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|   SECTION("containsKey(const char*) returns true") { |   SECTION("containsKey(const char*)") { | ||||||
|     var["hello"] = "world"; |     var["hello"] = "world"; | ||||||
|  |  | ||||||
|     REQUIRE(var.containsKey("hello") == true); |     REQUIRE(var.containsKey("hello") == true); | ||||||
|     REQUIRE(var.containsKey("world") == false); |     REQUIRE(var.containsKey("world") == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("containsKey(std::string) returns true") { |   SECTION("containsKey(std::string)") { | ||||||
|     var["hello"] = "world"; |     var["hello"] = "world"; | ||||||
|  |  | ||||||
|     REQUIRE(var.containsKey(std::string("hello")) == true); |     REQUIRE(var.containsKey(std::string("hello")) == true); | ||||||
|     REQUIRE(var.containsKey(std::string("world")) == false); |     REQUIRE(var.containsKey(std::string("world")) == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked object") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(var.containsKey("hello") == true); | ||||||
|  |     CHECK(var.containsKey("world") == false); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariantConst::containsKey()") { | TEST_CASE("JsonVariantConst::containsKey()") { | ||||||
|   | |||||||
| @@ -84,6 +84,16 @@ TEST_CASE("JsonVariant::set(JsonVariant)") { | |||||||
|     REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7)); |     REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("stores linked object by pointer") { | ||||||
|  |     StaticJsonDocument<128> doc3; | ||||||
|  |     doc3["hello"] = "world"; | ||||||
|  |     var1.link(doc3); | ||||||
|  |     var2.set(var1); | ||||||
|  |  | ||||||
|  |     REQUIRE(doc1.memoryUsage() == 0); | ||||||
|  |     REQUIRE(doc2.memoryUsage() == 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   SECTION("destination is unbound") { |   SECTION("destination is unbound") { | ||||||
|     JsonVariant unboundVariant; |     JsonVariant unboundVariant; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,11 +19,15 @@ TEST_CASE("JsonVariant::createNestedObject()") { | |||||||
|     REQUIRE(obj.isNull() == false); |     REQUIRE(obj.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("works on MemberProxy") { |   SECTION("does nothing on linked array") { | ||||||
|     JsonObject obj = variant["items"].createNestedObject(); |     StaticJsonDocument<128> doc2; | ||||||
|     obj["value"] = 42; |     doc2[0] = 42; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|     REQUIRE(variant["items"][0]["value"] == 42); |     variant.createNestedObject(); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 1); | ||||||
|  |     CHECK(variant[0] == 42); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -38,11 +42,15 @@ TEST_CASE("JsonVariant::createNestedArray()") { | |||||||
|     REQUIRE(arr.isNull() == false); |     REQUIRE(arr.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("works on MemberProxy") { |   SECTION("does nothing on linked array") { | ||||||
|     JsonArray arr = variant["items"].createNestedArray(); |     StaticJsonDocument<128> doc2; | ||||||
|     arr.add(42); |     doc2[0] = 42; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|     REQUIRE(variant["items"][0][0] == 42); |     variant.createNestedArray(); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 1); | ||||||
|  |     CHECK(variant[0] == 42); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -58,11 +66,15 @@ TEST_CASE("JsonVariant::createNestedObject(key)") { | |||||||
|     REQUIRE(variant["weather"]["temp"] == 42); |     REQUIRE(variant["weather"]["temp"] == 42); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("works on MemberProxy") { |   SECTION("does nothing on linked object") { | ||||||
|     JsonObject obj = variant["status"].createNestedObject("weather"); |     StaticJsonDocument<128> doc2; | ||||||
|     obj["temp"] = 42; |     doc2["hello"] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|     REQUIRE(variant["status"]["weather"]["temp"] == 42); |     variant.createNestedObject("weather"); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 1); | ||||||
|  |     CHECK(variant["hello"] == "world"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -77,10 +89,14 @@ TEST_CASE("JsonVariant::createNestedArray(key)") { | |||||||
|     REQUIRE(arr.isNull() == false); |     REQUIRE(arr.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("works on MemberProxy") { |   SECTION("does nothing on linked object") { | ||||||
|     JsonArray arr = variant["weather"].createNestedArray("temp"); |     StaticJsonDocument<128> doc2; | ||||||
|     arr.add(42); |     doc2["hello"] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|     REQUIRE(variant["weather"]["temp"][0] == 42); |     variant.createNestedArray("items"); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 1); | ||||||
|  |     CHECK(variant["hello"] == "world"); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -144,6 +144,24 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<MYENUM2>() == false); |     CHECK(variant.is<MYENUM2>() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked array") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2[0] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.is<JsonArray>() == false); | ||||||
|  |     CHECK(variant.is<JsonArrayConst>() == true); | ||||||
|  |     CHECK(variant.is<JsonVariant>() == true); | ||||||
|  |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
|  |     CHECK(variant.is<JsonObject>() == false); | ||||||
|  |     CHECK(variant.is<JsonObjectConst>() == false); | ||||||
|  |     CHECK(variant.is<int>() == false); | ||||||
|  |     CHECK(variant.is<float>() == false); | ||||||
|  |     CHECK(variant.is<bool>() == false); | ||||||
|  |     CHECK(variant.is<const char *>() == false); | ||||||
|  |     CHECK(variant.is<MYENUM2>() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   SECTION("JsonObject") { |   SECTION("JsonObject") { | ||||||
|     variant.to<JsonObject>(); |     variant.to<JsonObject>(); | ||||||
|  |  | ||||||
| @@ -161,6 +179,44 @@ TEST_CASE("JsonVariant::is<T>()") { | |||||||
|     CHECK(variant.is<JsonVariant>() == true); |     CHECK(variant.is<JsonVariant>() == true); | ||||||
|     CHECK(variant.is<JsonVariantConst>() == true); |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked object") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.is<JsonObject>() == false); | ||||||
|  |     CHECK(variant.is<JsonObjectConst>() == true); | ||||||
|  |     CHECK(variant.is<JsonVariant>() == true); | ||||||
|  |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
|  |     CHECK(variant.is<JsonArray>() == false); | ||||||
|  |     CHECK(variant.is<JsonArrayConst>() == false); | ||||||
|  |     CHECK(variant.is<int>() == false); | ||||||
|  |     CHECK(variant.is<float>() == false); | ||||||
|  |     CHECK(variant.is<bool>() == false); | ||||||
|  |     CHECK(variant.is<const char *>() == false); | ||||||
|  |     CHECK(variant.is<MYENUM2>() == false); | ||||||
|  |     CHECK(variant.is<JsonVariant>() == true); | ||||||
|  |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked int") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2.set(42); | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.is<JsonObjectConst>() == false); | ||||||
|  |     CHECK(variant.is<JsonVariantConst>() == true); | ||||||
|  |     CHECK(variant.is<JsonObject>() == false); | ||||||
|  |     CHECK(variant.is<JsonVariant>() == true); | ||||||
|  |     CHECK(variant.is<JsonArray>() == false); | ||||||
|  |     CHECK(variant.is<JsonArrayConst>() == false); | ||||||
|  |     CHECK(variant.is<int>() == true); | ||||||
|  |     CHECK(variant.is<float>() == false); | ||||||
|  |     CHECK(variant.is<bool>() == false); | ||||||
|  |     CHECK(variant.is<const char *>() == false); | ||||||
|  |     CHECK(variant.is<MYENUM2>() == true); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariantConst::is<T>()") { | TEST_CASE("JsonVariantConst::is<T>()") { | ||||||
| @@ -316,4 +372,58 @@ TEST_CASE("JsonVariantConst::is<T>()") { | |||||||
|     CHECK(cvariant.is<const char *>() == false); |     CHECK(cvariant.is<const char *>() == false); | ||||||
|     CHECK(cvariant.is<MYENUM2>() == false); |     CHECK(cvariant.is<MYENUM2>() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked array") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2[0] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(cvariant.is<JsonArrayConst>() == true); | ||||||
|  |     CHECK(cvariant.is<JsonVariantConst>() == true); | ||||||
|  |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonObject>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonObjectConst>() == false); | ||||||
|  |     CHECK(cvariant.is<int>() == false); | ||||||
|  |     CHECK(cvariant.is<float>() == false); | ||||||
|  |     CHECK(cvariant.is<bool>() == false); | ||||||
|  |     CHECK(cvariant.is<const char *>() == false); | ||||||
|  |     CHECK(cvariant.is<MYENUM2>() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked object") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(cvariant.is<JsonObjectConst>() == true); | ||||||
|  |     CHECK(cvariant.is<JsonVariantConst>() == true); | ||||||
|  |     CHECK(cvariant.is<JsonObject>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonArrayConst>() == false); | ||||||
|  |     CHECK(cvariant.is<int>() == false); | ||||||
|  |     CHECK(cvariant.is<float>() == false); | ||||||
|  |     CHECK(cvariant.is<bool>() == false); | ||||||
|  |     CHECK(cvariant.is<const char *>() == false); | ||||||
|  |     CHECK(cvariant.is<MYENUM2>() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked int") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2.set(42); | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(cvariant.is<JsonObjectConst>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonVariantConst>() == true); | ||||||
|  |     CHECK(cvariant.is<JsonObject>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonVariant>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonArray>() == false); | ||||||
|  |     CHECK(cvariant.is<JsonArrayConst>() == false); | ||||||
|  |     CHECK(cvariant.is<int>() == true); | ||||||
|  |     CHECK(cvariant.is<float>() == false); | ||||||
|  |     CHECK(cvariant.is<bool>() == false); | ||||||
|  |     CHECK(cvariant.is<const char *>() == false); | ||||||
|  |     CHECK(cvariant.is<MYENUM2>() == true); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,17 +9,17 @@ TEST_CASE("JsonVariant::isNull()") { | |||||||
|   DynamicJsonDocument doc(4096); |   DynamicJsonDocument doc(4096); | ||||||
|   JsonVariant variant = doc.to<JsonVariant>(); |   JsonVariant variant = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|   SECTION("return true when Undefined") { |   SECTION("returns true when Undefined") { | ||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return false when Integer") { |   SECTION("returns false when Integer") { | ||||||
|     variant.set(42); |     variant.set(42); | ||||||
|  |  | ||||||
|     REQUIRE(variant.isNull() == false); |     REQUIRE(variant.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return false when EmptyArray") { |   SECTION("returns false when EmptyArray") { | ||||||
|     DynamicJsonDocument doc2(4096); |     DynamicJsonDocument doc2(4096); | ||||||
|     JsonArray array = doc2.to<JsonArray>(); |     JsonArray array = doc2.to<JsonArray>(); | ||||||
|  |  | ||||||
| @@ -27,7 +27,7 @@ TEST_CASE("JsonVariant::isNull()") { | |||||||
|     REQUIRE(variant.isNull() == false); |     REQUIRE(variant.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return false when EmptyObject") { |   SECTION("returns false when EmptyObject") { | ||||||
|     DynamicJsonDocument doc2(4096); |     DynamicJsonDocument doc2(4096); | ||||||
|     JsonObject obj = doc2.to<JsonObject>(); |     JsonObject obj = doc2.to<JsonObject>(); | ||||||
|  |  | ||||||
| @@ -35,41 +35,54 @@ TEST_CASE("JsonVariant::isNull()") { | |||||||
|     REQUIRE(variant.isNull() == false); |     REQUIRE(variant.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return true after set(JsonArray())") { |   SECTION("returns true after set(JsonArray())") { | ||||||
|     variant.set(JsonArray()); |     variant.set(JsonArray()); | ||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return true after set(JsonObject())") { |   SECTION("returns true after set(JsonObject())") { | ||||||
|     variant.set(JsonObject()); |     variant.set(JsonObject()); | ||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return false after set('hello')") { |   SECTION("returns false after set('hello')") { | ||||||
|     variant.set("hello"); |     variant.set("hello"); | ||||||
|     REQUIRE(variant.isNull() == false); |     REQUIRE(variant.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return true after set((char*)0)") { |   SECTION("returns true after set((char*)0)") { | ||||||
|     variant.set(static_cast<char*>(0)); |     variant.set(static_cast<char*>(0)); | ||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return true after set((const char*)0)") { |   SECTION("returns true after set((const char*)0)") { | ||||||
|     variant.set(static_cast<const char*>(0)); |     variant.set(static_cast<const char*>(0)); | ||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return true after set(serialized((char*)0))") { |   SECTION("returns true after set(serialized((char*)0))") { | ||||||
|     variant.set(serialized(static_cast<char*>(0))); |     variant.set(serialized(static_cast<char*>(0))); | ||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("return true after set(serialized((const char*)0))") { |   SECTION("returns true after set(serialized((const char*)0))") { | ||||||
|     variant.set(serialized(static_cast<const char*>(0))); |     variant.set(serialized(static_cast<const char*>(0))); | ||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("returns true for a linked null") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     variant.link(doc2); | ||||||
|  |     CHECK(variant.isNull() == true); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("returns false for a linked array") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2[0] = 42; | ||||||
|  |     variant.link(doc2); | ||||||
|  |     CHECK(variant.isNull() == false); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   SECTION("works with JsonVariantConst") { |   SECTION("works with JsonVariantConst") { | ||||||
|     variant.set(42); |     variant.set(42); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								extras/tests/JsonVariant/link.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								extras/tests/JsonVariant/link.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | // ArduinoJson - https://arduinojson.org | ||||||
|  | // Copyright © 2014-2022, Benoit BLANCHON | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant::link()") { | ||||||
|  |   StaticJsonDocument<1024> doc1, doc2; | ||||||
|  |   JsonVariant variant = doc1.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   SECTION("JsonVariant::link(JsonDocument&)") { | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |  | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |     CHECK(variant.memoryUsage() == 0); | ||||||
|  |  | ||||||
|  |     // altering the linked document should change the result | ||||||
|  |     doc2["hello"] = "WORLD!"; | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "{\"hello\":\"WORLD!\"}"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonVariant::link(MemberProxy)") { | ||||||
|  |     doc2["obj"]["hello"] = "world"; | ||||||
|  |  | ||||||
|  |     variant.link(doc2["obj"]); | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |     CHECK(variant.memoryUsage() == 0); | ||||||
|  |  | ||||||
|  |     // altering the linked document should change the result | ||||||
|  |     doc2["obj"]["hello"] = "WORLD!"; | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "{\"hello\":\"WORLD!\"}"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("JsonVariant::link(ElementProxy)") { | ||||||
|  |     doc2[0]["hello"] = "world"; | ||||||
|  |  | ||||||
|  |     variant.link(doc2[0]); | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |     CHECK(variant.memoryUsage() == 0); | ||||||
|  |  | ||||||
|  |     // altering the linked document should change the result | ||||||
|  |     doc2[0]["hello"] = "WORLD!"; | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "{\"hello\":\"WORLD!\"}"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("target is unbound") { | ||||||
|  |     JsonVariant unbound; | ||||||
|  |     variant["hello"] = "world"; | ||||||
|  |  | ||||||
|  |     variant.link(unbound); | ||||||
|  |  | ||||||
|  |     CHECK(variant.isUnbound() == false); | ||||||
|  |     CHECK(variant.isNull() == true); | ||||||
|  |     CHECK(variant.memoryUsage() == 0); | ||||||
|  |     CHECK(variant.size() == 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("variant is unbound") { | ||||||
|  |     JsonVariant unbound; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |  | ||||||
|  |     unbound.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(unbound.isUnbound() == true); | ||||||
|  |     CHECK(unbound.isNull() == true); | ||||||
|  |     CHECK(unbound.memoryUsage() == 0); | ||||||
|  |     CHECK(unbound.size() == 0); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -38,4 +38,12 @@ TEST_CASE("JsonVariant::memoryUsage()") { | |||||||
|     REQUIRE(var.memoryUsage() == 6); |     REQUIRE(var.memoryUsage() == 6); | ||||||
|     REQUIRE(var.memoryUsage() == doc.memoryUsage()); |     REQUIRE(var.memoryUsage() == doc.memoryUsage()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("ignore size of linked document") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     var.link(doc2); | ||||||
|  |     CHECK(var.memoryUsage() == 0); | ||||||
|  |     CHECK(var.memoryUsage() == doc.memoryUsage()); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,4 +28,12 @@ TEST_CASE("JsonVariant::nesting()") { | |||||||
|     var.to<JsonArray>(); |     var.to<JsonArray>(); | ||||||
|     REQUIRE(var.nesting() == 1); |     REQUIRE(var.nesting() == 1); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("return depth of linked array") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2[0][0] = 42; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(var.nesting() == 2); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -156,4 +156,12 @@ TEST_CASE("JsonVariant::operator|()") { | |||||||
|     int result = variant | 42; |     int result = variant | 42; | ||||||
|     REQUIRE(result == 42); |     REQUIRE(result == 42); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked int | int") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2.set(42); | ||||||
|  |     variant.link(doc2); | ||||||
|  |     int result = variant | 666; | ||||||
|  |     CHECK(result == 42); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -39,4 +39,24 @@ TEST_CASE("JsonVariant::remove()") { | |||||||
|  |  | ||||||
|     REQUIRE(var.as<std::string>() == "{\"a\":1}"); |     REQUIRE(var.as<std::string>() == "{\"a\":1}"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked array") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2[0] = 42; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     var.remove(0); | ||||||
|  |  | ||||||
|  |     CHECK(var.as<std::string>() == "[42]"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked object") { | ||||||
|  |     StaticJsonDocument<128> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     var.remove("hello"); | ||||||
|  |  | ||||||
|  |     CHECK(var.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -155,18 +155,21 @@ TEST_CASE("JsonVariant::set() with not enough memory") { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariant::set(DynamicJsonDocument)") { | TEST_CASE("Copy/link from other document") { | ||||||
|   DynamicJsonDocument doc1(1024); |   StaticJsonDocument<1024> doc1, doc2; | ||||||
|   doc1["hello"] = "world"; |   JsonVariant variant = doc1.to<JsonVariant>(); | ||||||
|  |  | ||||||
|   DynamicJsonDocument doc2(1024); |   SECTION("JsonVariant::set(JsonDocument&)") { | ||||||
|   JsonVariant v = doc2.to<JsonVariant>(); |     doc2["hello"] = "world"; | ||||||
|  |  | ||||||
|   // Should copy the doc |     variant.set(doc2); | ||||||
|   v.set(doc1); |  | ||||||
|   doc1.clear(); |  | ||||||
|  |  | ||||||
|   std::string json; |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|   serializeJson(doc2, json); |     CHECK(variant.memoryUsage() == JSON_OBJECT_SIZE(1)); | ||||||
|   REQUIRE(json == "{\"hello\":\"world\"}"); |  | ||||||
|  |     // altering the copied document should change the result | ||||||
|  |     doc2["hello"] = "WORLD!"; | ||||||
|  |  | ||||||
|  |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										53
									
								
								extras/tests/JsonVariant/size.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								extras/tests/JsonVariant/size.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | // ArduinoJson - https://arduinojson.org | ||||||
|  | // Copyright © 2014-2022, Benoit BLANCHON | ||||||
|  | // MIT License | ||||||
|  |  | ||||||
|  | #include <ArduinoJson.h> | ||||||
|  | #include <catch.hpp> | ||||||
|  |  | ||||||
|  | TEST_CASE("JsonVariant::size()") { | ||||||
|  |   DynamicJsonDocument doc(4096); | ||||||
|  |   JsonVariant variant = doc.to<JsonVariant>(); | ||||||
|  |  | ||||||
|  |   SECTION("unbound reference") { | ||||||
|  |     JsonVariant unbound; | ||||||
|  |  | ||||||
|  |     CHECK(unbound.size() == 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("int") { | ||||||
|  |     variant.set(42); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("string") { | ||||||
|  |     variant.set("hello"); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 0); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("object") { | ||||||
|  |     variant["a"] = 1; | ||||||
|  |     variant["b"] = 2; | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 2); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked object") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 1); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("linked array") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2.add(1); | ||||||
|  |     doc2.add(2); | ||||||
|  |     variant.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(variant.size() == 2); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -129,6 +129,44 @@ TEST_CASE("JsonVariant::operator[]") { | |||||||
|     REQUIRE(std::string("world") == variant[vla]); |     REQUIRE(std::string("world") == variant[vla]); | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |   SECTION("get value from linked object") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(var["hello"].as<std::string>() == "world"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("set value to linked object") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     var["tutu"] = "toto";  // no-op | ||||||
|  |  | ||||||
|  |     CHECK(doc.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |     CHECK(doc2.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("get value from linked array") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2.add(42); | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(var[0].as<int>() == 42); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("set value to linked array") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2.add(42); | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     var[0] = 666;  // no-op | ||||||
|  |  | ||||||
|  |     CHECK(doc.as<std::string>() == "[42]"); | ||||||
|  |     CHECK(doc2.as<std::string>() == "[42]"); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("JsonVariantConst::operator[]") { | TEST_CASE("JsonVariantConst::operator[]") { | ||||||
| @@ -201,4 +239,20 @@ TEST_CASE("JsonVariantConst::operator[]") { | |||||||
|     REQUIRE(var.is<JsonObject>() == false); |     REQUIRE(var.is<JsonObject>() == false); | ||||||
|     REQUIRE(value == 0); |     REQUIRE(value == 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   SECTION("get value from linked object") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2["hello"] = "world"; | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(cvar["hello"].as<std::string>() == "world"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   SECTION("get value from linked array") { | ||||||
|  |     StaticJsonDocument<1024> doc2; | ||||||
|  |     doc2.add(42); | ||||||
|  |     var.link(doc2); | ||||||
|  |  | ||||||
|  |     CHECK(cvar[0].as<int>() == 42); | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -207,7 +207,7 @@ struct Converter<ArrayRef> { | |||||||
|  |  | ||||||
|   static bool checkJson(VariantRef src) { |   static bool checkJson(VariantRef src) { | ||||||
|     VariantData* data = getData(src); |     VariantData* data = getData(src); | ||||||
|     return data && data->isArray(); |     return data && data->isArrayStrict(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -92,6 +92,10 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|     return getOrAddUpstreamElement().template to<T>(); |     return getOrAddUpstreamElement().template to<T>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE void link(VariantConstRef value) const { | ||||||
|  |     getOrAddUpstreamElement().link(value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Replaces the value |   // Replaces the value | ||||||
|   // |   // | ||||||
|   // bool set(const TValue&) |   // bool set(const TValue&) | ||||||
|   | |||||||
| @@ -117,6 +117,10 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | |||||||
|     getUpstreamMember().remove(key); |     getUpstreamMember().remove(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   FORCE_INLINE void link(VariantConstRef value) { | ||||||
|  |     getOrAddUpstreamMember().link(value); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   FORCE_INLINE typename VariantTo<TValue>::type to() { |   FORCE_INLINE typename VariantTo<TValue>::type to() { | ||||||
|     return getOrAddUpstreamMember().template to<TValue>(); |     return getOrAddUpstreamMember().template to<TValue>(); | ||||||
|   | |||||||
| @@ -276,7 +276,7 @@ struct Converter<ObjectRef> { | |||||||
|  |  | ||||||
|   static bool checkJson(VariantRef src) { |   static bool checkJson(VariantRef src) { | ||||||
|     VariantData* data = getData(src); |     VariantData* data = getData(src); | ||||||
|     return data && data->isObject(); |     return data && data->isObjectStrict(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -31,6 +31,8 @@ enum { | |||||||
|   VALUE_IS_SIGNED_INTEGER = 0x0A, |   VALUE_IS_SIGNED_INTEGER = 0x0A, | ||||||
|   VALUE_IS_FLOAT = 0x0C, |   VALUE_IS_FLOAT = 0x0C, | ||||||
|  |  | ||||||
|  |   VALUE_IS_POINTER = 0x10, | ||||||
|  |  | ||||||
|   COLLECTION_MASK = 0x60, |   COLLECTION_MASK = 0x60, | ||||||
|   VALUE_IS_OBJECT = 0x20, |   VALUE_IS_OBJECT = 0x20, | ||||||
|   VALUE_IS_ARRAY = 0x40, |   VALUE_IS_ARRAY = 0x40, | ||||||
| @@ -49,6 +51,7 @@ union VariantContent { | |||||||
|   UInt asUnsignedInteger; |   UInt asUnsignedInteger; | ||||||
|   Integer asSignedInteger; |   Integer asSignedInteger; | ||||||
|   CollectionData asCollection; |   CollectionData asCollection; | ||||||
|  |   const class VariantData *asPointer; | ||||||
|   struct { |   struct { | ||||||
|     const char *data; |     const char *data; | ||||||
|     size_t size; |     size_t size; | ||||||
|   | |||||||
| @@ -68,6 +68,10 @@ class VariantData { | |||||||
|       case VALUE_IS_BOOLEAN: |       case VALUE_IS_BOOLEAN: | ||||||
|         return visitor.visitBoolean(_content.asBoolean != 0); |         return visitor.visitBoolean(_content.asBoolean != 0); | ||||||
|  |  | ||||||
|  |       case VALUE_IS_POINTER: | ||||||
|  |         ARDUINOJSON_ASSERT(_content.asPointer != 0); | ||||||
|  |         return _content.asPointer->accept(visitor); | ||||||
|  |  | ||||||
|       default: |       default: | ||||||
|         return visitor.visitNull(); |         return visitor.visitNull(); | ||||||
|     } |     } | ||||||
| @@ -84,24 +88,35 @@ class VariantData { | |||||||
|   bool asBoolean() const; |   bool asBoolean() const; | ||||||
|  |  | ||||||
|   CollectionData *asArray() { |   CollectionData *asArray() { | ||||||
|     return isArray() ? &_content.asCollection : 0; |     return isArrayStrict() ? &_content.asCollection : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const CollectionData *asArray() const { |   const CollectionData *asArray() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->asArray(); | ||||||
|     return const_cast<VariantData *>(this)->asArray(); |     return const_cast<VariantData *>(this)->asArray(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   CollectionData *asObject() { |   CollectionData *asObject() { | ||||||
|     return isObject() ? &_content.asCollection : 0; |     return isObjectStrict() ? &_content.asCollection : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const CollectionData *asObject() const { |   const CollectionData *asObject() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->asObject(); | ||||||
|     return const_cast<VariantData *>(this)->asObject(); |     return const_cast<VariantData *>(this)->asObject(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool copyFrom(const VariantData &src, MemoryPool *pool); |   bool copyFrom(const VariantData &src, MemoryPool *pool); | ||||||
|  |  | ||||||
|   bool isArray() const { |   bool isArray() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->isArray(); | ||||||
|  |     else | ||||||
|  |       return isArrayStrict(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool isArrayStrict() const { | ||||||
|     return (_flags & VALUE_IS_ARRAY) != 0; |     return (_flags & VALUE_IS_ARRAY) != 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -113,8 +128,14 @@ class VariantData { | |||||||
|     return (_flags & COLLECTION_MASK) != 0; |     return (_flags & COLLECTION_MASK) != 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   bool isPointer() const { | ||||||
|  |     return type() == VALUE_IS_POINTER; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename T> |   template <typename T> | ||||||
|   bool isInteger() const { |   bool isInteger() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->isInteger<T>(); | ||||||
|     switch (type()) { |     switch (type()) { | ||||||
|       case VALUE_IS_UNSIGNED_INTEGER: |       case VALUE_IS_UNSIGNED_INTEGER: | ||||||
|         return canConvertNumber<T>(_content.asUnsignedInteger); |         return canConvertNumber<T>(_content.asUnsignedInteger); | ||||||
| @@ -136,10 +157,18 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isObject() const { |   bool isObject() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->isObject(); | ||||||
|  |     return isObjectStrict(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   bool isObjectStrict() const { | ||||||
|     return (_flags & VALUE_IS_OBJECT) != 0; |     return (_flags & VALUE_IS_OBJECT) != 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool isNull() const { |   bool isNull() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->isNull(); | ||||||
|     return type() == VALUE_IS_NULL; |     return type() == VALUE_IS_NULL; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -148,13 +177,13 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void remove(size_t index) { |   void remove(size_t index) { | ||||||
|     if (isArray()) |     if (isArrayStrict()) | ||||||
|       _content.asCollection.removeElement(index); |       _content.asCollection.removeElement(index); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   void remove(TAdaptedString key) { |   void remove(TAdaptedString key) { | ||||||
|     if (isObject()) |     if (isObjectStrict()) | ||||||
|       _content.asCollection.removeMember(key); |       _content.asCollection.removeMember(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -208,6 +237,12 @@ class VariantData { | |||||||
|     setType(VALUE_IS_NULL); |     setType(VALUE_IS_NULL); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void setPointer(const VariantData *p) { | ||||||
|  |     ARDUINOJSON_ASSERT(p); | ||||||
|  |     setType(VALUE_IS_POINTER); | ||||||
|  |     _content.asPointer = p; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void setString(String s) { |   void setString(String s) { | ||||||
|     ARDUINOJSON_ASSERT(s); |     ARDUINOJSON_ASSERT(s); | ||||||
|     if (s.isLinked()) |     if (s.isLinked()) | ||||||
| @@ -246,36 +281,42 @@ class VariantData { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t nesting() const { |   size_t nesting() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->nesting(); | ||||||
|     return isCollection() ? _content.asCollection.nesting() : 0; |     return isCollection() ? _content.asCollection.nesting() : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|  |     if (isPointer()) | ||||||
|  |       return _content.asPointer->size(); | ||||||
|     return isCollection() ? _content.asCollection.size() : 0; |     return isCollection() ? _content.asCollection.size() : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantData *addElement(MemoryPool *pool) { |   VariantData *addElement(MemoryPool *pool) { | ||||||
|     if (isNull()) |     if (isNull()) | ||||||
|       toArray(); |       toArray(); | ||||||
|     if (!isArray()) |     if (!isArrayStrict()) | ||||||
|       return 0; |       return 0; | ||||||
|     return _content.asCollection.addElement(pool); |     return _content.asCollection.addElement(pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantData *getElement(size_t index) const { |   VariantData *getElement(size_t index) const { | ||||||
|     return isArray() ? _content.asCollection.getElement(index) : 0; |     const CollectionData *col = asArray(); | ||||||
|  |     return col ? col->getElement(index) : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   VariantData *getOrAddElement(size_t index, MemoryPool *pool) { |   VariantData *getOrAddElement(size_t index, MemoryPool *pool) { | ||||||
|     if (isNull()) |     if (isNull()) | ||||||
|       toArray(); |       toArray(); | ||||||
|     if (!isArray()) |     if (!isArrayStrict()) | ||||||
|       return 0; |       return 0; | ||||||
|     return _content.asCollection.getOrAddElement(index, pool); |     return _content.asCollection.getOrAddElement(index, pool); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString> |   template <typename TAdaptedString> | ||||||
|   VariantData *getMember(TAdaptedString key) const { |   VariantData *getMember(TAdaptedString key) const { | ||||||
|     return isObject() ? _content.asCollection.getMember(key) : 0; |     const CollectionData *col = asObject(); | ||||||
|  |     return col ? col->getMember(key) : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TAdaptedString, typename TStoragePolicy> |   template <typename TAdaptedString, typename TStoragePolicy> | ||||||
| @@ -283,7 +324,7 @@ class VariantData { | |||||||
|                               TStoragePolicy storage_policy) { |                               TStoragePolicy storage_policy) { | ||||||
|     if (isNull()) |     if (isNull()) | ||||||
|       toObject(); |       toObject(); | ||||||
|     if (!isObject()) |     if (!isObjectStrict()) | ||||||
|       return 0; |       return 0; | ||||||
|     return _content.asCollection.getOrAddMember(key, pool, storage_policy); |     return _content.asCollection.getOrAddMember(key, pool, storage_policy); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -29,6 +29,8 @@ inline T VariantData::asIntegral() const { | |||||||
|       return parseNumber<T>(_content.asString.data); |       return parseNumber<T>(_content.asString.data); | ||||||
|     case VALUE_IS_FLOAT: |     case VALUE_IS_FLOAT: | ||||||
|       return convertNumber<T>(_content.asFloat); |       return convertNumber<T>(_content.asFloat); | ||||||
|  |     case VALUE_IS_POINTER: | ||||||
|  |       return _content.asPointer->asIntegral<T>(); | ||||||
|     default: |     default: | ||||||
|       return 0; |       return 0; | ||||||
|   } |   } | ||||||
| @@ -45,6 +47,8 @@ inline bool VariantData::asBoolean() const { | |||||||
|       return _content.asFloat != 0; |       return _content.asFloat != 0; | ||||||
|     case VALUE_IS_NULL: |     case VALUE_IS_NULL: | ||||||
|       return false; |       return false; | ||||||
|  |     case VALUE_IS_POINTER: | ||||||
|  |       return _content.asPointer->asBoolean(); | ||||||
|     default: |     default: | ||||||
|       return true; |       return true; | ||||||
|   } |   } | ||||||
| @@ -65,6 +69,8 @@ inline T VariantData::asFloat() const { | |||||||
|       return parseNumber<T>(_content.asString.data); |       return parseNumber<T>(_content.asString.data); | ||||||
|     case VALUE_IS_FLOAT: |     case VALUE_IS_FLOAT: | ||||||
|       return static_cast<T>(_content.asFloat); |       return static_cast<T>(_content.asFloat); | ||||||
|  |     case VALUE_IS_POINTER: | ||||||
|  |       return _content.asPointer->asFloat<T>(); | ||||||
|     default: |     default: | ||||||
|       return 0; |       return 0; | ||||||
|   } |   } | ||||||
| @@ -78,6 +84,8 @@ inline String VariantData::asString() const { | |||||||
|     case VALUE_IS_OWNED_STRING: |     case VALUE_IS_OWNED_STRING: | ||||||
|       return String(_content.asString.data, _content.asString.size, |       return String(_content.asString.data, _content.asString.size, | ||||||
|                     String::Copied); |                     String::Copied); | ||||||
|  |     case VALUE_IS_POINTER: | ||||||
|  |       return _content.asPointer->asString(); | ||||||
|     default: |     default: | ||||||
|       return String(); |       return String(); | ||||||
|   } |   } | ||||||
| @@ -181,4 +189,13 @@ bool CopyStringStoragePolicy::store(TAdaptedString str, MemoryPool *pool, | |||||||
|   return copy != 0; |   return copy != 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline void VariantRef::link(VariantConstRef target) { | ||||||
|  |   if (!_data) | ||||||
|  |     return; | ||||||
|  |   if (target._data) | ||||||
|  |     _data->setPointer(target._data); | ||||||
|  |   else | ||||||
|  |     _data->setNull(); | ||||||
|  | } | ||||||
|  |  | ||||||
| }  // namespace ARDUINOJSON_NAMESPACE | }  // namespace ARDUINOJSON_NAMESPACE | ||||||
|   | |||||||
| @@ -198,6 +198,8 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE VariantRef getOrAddMember(const TString &) const; |   FORCE_INLINE VariantRef getOrAddMember(const TString &) const; | ||||||
|  |  | ||||||
|  |   void link(class VariantConstRef var); | ||||||
|  |  | ||||||
|   FORCE_INLINE void remove(size_t index) const { |   FORCE_INLINE void remove(size_t index) const { | ||||||
|     if (_data) |     if (_data) | ||||||
|       _data->remove(index); |       _data->remove(index); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user