mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 00:32:37 +01:00 
			
		
		
		
	Add JsonVariant::link() (resolves #1343)
				
					
				
			This commit is contained in:
		| @@ -4,6 +4,7 @@ ArduinoJson: change log | ||||
| HEAD | ||||
| ---- | ||||
|  | ||||
| * Add `JsonVariant::link()` (issue #1343) | ||||
| * Fix `9.22337e+18 is outside the range of representable values of type 'long'` | ||||
|  | ||||
| v6.19.4 (2022-04-05) | ||||
|   | ||||
| @@ -43,5 +43,13 @@ TEST_CASE("nullptr") { | ||||
|  | ||||
|     variant.clear(); | ||||
|     REQUIRE(variant.is<std::nullptr_t>() == true); | ||||
|  | ||||
|     StaticJsonDocument<128> doc2; | ||||
|     doc2["hello"] = "world"; | ||||
|     variant.link(doc2); | ||||
|     REQUIRE(variant.is<std::nullptr_t>() == false); | ||||
|  | ||||
|     doc2.clear(); | ||||
|     REQUIRE(variant.is<std::nullptr_t>() == true); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -245,3 +245,11 @@ TEST_CASE("ElementProxy cast to JsonVariant") { | ||||
|  | ||||
|   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\"}]"); | ||||
| } | ||||
|   | ||||
| @@ -318,3 +318,10 @@ TEST_CASE("MemberProxy::createNestedObject(key)") { | ||||
|   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\"}}"); | ||||
| } | ||||
|   | ||||
| @@ -25,4 +25,21 @@ TEST_CASE("JsonDocument::size()") { | ||||
|  | ||||
|     REQUIRE(doc.size() == 2); | ||||
|   } | ||||
|  | ||||
|   SECTION("linked array") { | ||||
|     StaticJsonDocument<128> doc2; | ||||
|     doc2.add(1); | ||||
|     doc2.add(2); | ||||
|     doc.as<JsonVariant>().link(doc2); | ||||
|  | ||||
|     REQUIRE(doc.size() == 2); | ||||
|   } | ||||
|  | ||||
|   SECTION("linked object") { | ||||
|     StaticJsonDocument<128> doc2; | ||||
|     doc2["hello"] = "world"; | ||||
|     doc.as<JsonVariant>().link(doc2); | ||||
|  | ||||
|     REQUIRE(doc.size() == 1); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -13,6 +13,7 @@ add_executable(JsonVariantTests | ||||
| 	createNested.cpp | ||||
| 	is.cpp | ||||
| 	isnull.cpp | ||||
| 	link.cpp | ||||
| 	memoryUsage.cpp | ||||
| 	misc.cpp | ||||
| 	nesting.cpp | ||||
|   | ||||
| @@ -43,4 +43,14 @@ TEST_CASE("JsonVariant::add()") { | ||||
|  | ||||
|     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); | ||||
|   } | ||||
|  | ||||
|   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); | ||||
|   } | ||||
|  | ||||
|   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); | ||||
|   } | ||||
|  | ||||
|   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") { | ||||
| @@ -313,4 +327,19 @@ TEST_CASE("Compare JsonVariant with JsonVariant") { | ||||
|     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); | ||||
|   JsonVariant var = doc.to<JsonVariant>(); | ||||
|  | ||||
|   SECTION("containsKey(const char*) returns true") { | ||||
|   SECTION("containsKey(const char*)") { | ||||
|     var["hello"] = "world"; | ||||
|  | ||||
|     REQUIRE(var.containsKey("hello") == true); | ||||
|     REQUIRE(var.containsKey("world") == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("containsKey(std::string) returns true") { | ||||
|   SECTION("containsKey(std::string)") { | ||||
|     var["hello"] = "world"; | ||||
|  | ||||
|     REQUIRE(var.containsKey(std::string("hello")) == true); | ||||
|     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()") { | ||||
|   | ||||
| @@ -84,6 +84,16 @@ TEST_CASE("JsonVariant::set(JsonVariant)") { | ||||
|     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") { | ||||
|     JsonVariant unboundVariant; | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,17 @@ TEST_CASE("JsonVariant::createNestedObject()") { | ||||
|     REQUIRE(variant[0]["value"] == 42); | ||||
|     REQUIRE(obj.isNull() == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("does nothing on linked array") { | ||||
|     StaticJsonDocument<128> doc2; | ||||
|     doc2[0] = 42; | ||||
|     variant.link(doc2); | ||||
|  | ||||
|     variant.createNestedObject(); | ||||
|  | ||||
|     CHECK(variant.size() == 1); | ||||
|     CHECK(variant[0] == 42); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("JsonVariant::createNestedArray()") { | ||||
| @@ -30,6 +41,17 @@ TEST_CASE("JsonVariant::createNestedArray()") { | ||||
|     REQUIRE(variant.is<JsonArray>() == true); | ||||
|     REQUIRE(arr.isNull() == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("does nothing on linked array") { | ||||
|     StaticJsonDocument<128> doc2; | ||||
|     doc2[0] = 42; | ||||
|     variant.link(doc2); | ||||
|  | ||||
|     variant.createNestedArray(); | ||||
|  | ||||
|     CHECK(variant.size() == 1); | ||||
|     CHECK(variant[0] == 42); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("JsonVariant::createNestedObject(key)") { | ||||
| @@ -43,6 +65,17 @@ TEST_CASE("JsonVariant::createNestedObject(key)") { | ||||
|     REQUIRE(variant.is<JsonObject>() == true); | ||||
|     REQUIRE(variant["weather"]["temp"] == 42); | ||||
|   } | ||||
|  | ||||
|   SECTION("does nothing on linked object") { | ||||
|     StaticJsonDocument<128> doc2; | ||||
|     doc2["hello"] = "world"; | ||||
|     variant.link(doc2); | ||||
|  | ||||
|     variant.createNestedObject("weather"); | ||||
|  | ||||
|     CHECK(variant.size() == 1); | ||||
|     CHECK(variant["hello"] == "world"); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("JsonVariant::createNestedArray(key)") { | ||||
| @@ -55,4 +88,15 @@ TEST_CASE("JsonVariant::createNestedArray(key)") { | ||||
|     REQUIRE(variant.is<JsonObject>() == true); | ||||
|     REQUIRE(arr.isNull() == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("does nothing on linked object") { | ||||
|     StaticJsonDocument<128> doc2; | ||||
|     doc2["hello"] = "world"; | ||||
|     variant.link(doc2); | ||||
|  | ||||
|     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); | ||||
|   } | ||||
|  | ||||
|   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") { | ||||
|     variant.to<JsonObject>(); | ||||
|  | ||||
| @@ -161,6 +179,44 @@ TEST_CASE("JsonVariant::is<T>()") { | ||||
|     CHECK(variant.is<JsonVariant>() == 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>() == true); | ||||
|     CHECK(variant.is<bool>() == false); | ||||
|     CHECK(variant.is<const char *>() == false); | ||||
|     CHECK(variant.is<MYENUM2>() == true); | ||||
|   } | ||||
| } | ||||
|  | ||||
| TEST_CASE("JsonVariantConst::is<T>()") { | ||||
| @@ -316,4 +372,58 @@ TEST_CASE("JsonVariantConst::is<T>()") { | ||||
|     CHECK(cvariant.is<const char *>() == 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>() == true); | ||||
|     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); | ||||
|   JsonVariant variant = doc.to<JsonVariant>(); | ||||
|  | ||||
|   SECTION("return true when Undefined") { | ||||
|   SECTION("returns true when Undefined") { | ||||
|     REQUIRE(variant.isNull() == true); | ||||
|   } | ||||
|  | ||||
|   SECTION("return false when Integer") { | ||||
|   SECTION("returns false when Integer") { | ||||
|     variant.set(42); | ||||
|  | ||||
|     REQUIRE(variant.isNull() == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("return false when EmptyArray") { | ||||
|   SECTION("returns false when EmptyArray") { | ||||
|     DynamicJsonDocument doc2(4096); | ||||
|     JsonArray array = doc2.to<JsonArray>(); | ||||
|  | ||||
| @@ -27,7 +27,7 @@ TEST_CASE("JsonVariant::isNull()") { | ||||
|     REQUIRE(variant.isNull() == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("return false when EmptyObject") { | ||||
|   SECTION("returns false when EmptyObject") { | ||||
|     DynamicJsonDocument doc2(4096); | ||||
|     JsonObject obj = doc2.to<JsonObject>(); | ||||
|  | ||||
| @@ -35,41 +35,54 @@ TEST_CASE("JsonVariant::isNull()") { | ||||
|     REQUIRE(variant.isNull() == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("return true after set(JsonArray())") { | ||||
|   SECTION("returns true after set(JsonArray())") { | ||||
|     variant.set(JsonArray()); | ||||
|     REQUIRE(variant.isNull() == true); | ||||
|   } | ||||
|  | ||||
|   SECTION("return true after set(JsonObject())") { | ||||
|   SECTION("returns true after set(JsonObject())") { | ||||
|     variant.set(JsonObject()); | ||||
|     REQUIRE(variant.isNull() == true); | ||||
|   } | ||||
|  | ||||
|   SECTION("return false after set('hello')") { | ||||
|   SECTION("returns false after set('hello')") { | ||||
|     variant.set("hello"); | ||||
|     REQUIRE(variant.isNull() == false); | ||||
|   } | ||||
|  | ||||
|   SECTION("return true after set((char*)0)") { | ||||
|   SECTION("returns true after set((char*)0)") { | ||||
|     variant.set(static_cast<char*>(0)); | ||||
|     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)); | ||||
|     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))); | ||||
|     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))); | ||||
|     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") { | ||||
|     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() == 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>(); | ||||
|     REQUIRE(var.nesting() == 1); | ||||
|   } | ||||
|  | ||||
|   SECTION("returns 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; | ||||
|     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}"); | ||||
|   } | ||||
|  | ||||
|   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\"}"); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -41,4 +41,13 @@ TEST_CASE("JsonVariant::size()") { | ||||
|  | ||||
|     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]); | ||||
|   } | ||||
| #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[]") { | ||||
| @@ -201,4 +239,20 @@ TEST_CASE("JsonVariantConst::operator[]") { | ||||
|     REQUIRE(var.is<JsonObject>() == false); | ||||
|     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); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -211,7 +211,7 @@ struct Converter<ArrayConstRef> { | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isArray(); | ||||
|     return data && data->resolve()->isArray(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -109,6 +109,10 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | ||||
|     return getOrAddUpstreamElement().template to<T>(); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE void link(VariantConstRef value) const { | ||||
|     getOrAddUpstreamElement().link(value); | ||||
|   } | ||||
|  | ||||
|   // Replaces the value | ||||
|   // | ||||
|   // bool set(const TValue&) | ||||
|   | ||||
| @@ -68,7 +68,7 @@ class JsonDocument : public Visitable, | ||||
|   } | ||||
|  | ||||
|   size_t size() const { | ||||
|     return _data.size(); | ||||
|     return _data.resolve()->size(); | ||||
|   } | ||||
|  | ||||
|   bool set(const JsonDocument& src) { | ||||
|   | ||||
| @@ -25,7 +25,7 @@ class JsonSerializer : public Visitor<size_t> { | ||||
|     VariantSlot *slot = array.head(); | ||||
|  | ||||
|     while (slot != 0) { | ||||
|       slot->data()->accept(*this); | ||||
|       slot->data()->resolve()->accept(*this); | ||||
|  | ||||
|       slot = slot->next(); | ||||
|       if (slot == 0) | ||||
| @@ -46,7 +46,7 @@ class JsonSerializer : public Visitor<size_t> { | ||||
|     while (slot != 0) { | ||||
|       _formatter.writeString(slot->key()); | ||||
|       write(':'); | ||||
|       slot->data()->accept(*this); | ||||
|       slot->data()->resolve()->accept(*this); | ||||
|  | ||||
|       slot = slot->next(); | ||||
|       if (slot == 0) | ||||
|   | ||||
| @@ -25,7 +25,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | ||||
|       _nesting++; | ||||
|       while (slot != 0) { | ||||
|         indent(); | ||||
|         slot->data()->accept(*this); | ||||
|         slot->data()->resolve()->accept(*this); | ||||
|  | ||||
|         slot = slot->next(); | ||||
|         base::write(slot ? ",\r\n" : "\r\n"); | ||||
| @@ -48,7 +48,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | ||||
|         indent(); | ||||
|         base::visitString(slot->key()); | ||||
|         base::write(": "); | ||||
|         slot->data()->accept(*this); | ||||
|         slot->data()->resolve()->accept(*this); | ||||
|  | ||||
|         slot = slot->next(); | ||||
|         base::write(slot ? ",\r\n" : "\r\n"); | ||||
|   | ||||
| @@ -56,7 +56,7 @@ class MsgPackSerializer : public Visitor<size_t> { | ||||
|       writeInteger(uint32_t(n)); | ||||
|     } | ||||
|     for (VariantSlot* slot = array.head(); slot; slot = slot->next()) { | ||||
|       slot->data()->accept(*this); | ||||
|       slot->data()->resolve()->accept(*this); | ||||
|     } | ||||
|     return bytesWritten(); | ||||
|   } | ||||
| @@ -74,7 +74,7 @@ class MsgPackSerializer : public Visitor<size_t> { | ||||
|     } | ||||
|     for (VariantSlot* slot = object.head(); slot; slot = slot->next()) { | ||||
|       visitString(slot->key()); | ||||
|       slot->data()->accept(*this); | ||||
|       slot->data()->resolve()->accept(*this); | ||||
|     } | ||||
|     return bytesWritten(); | ||||
|   } | ||||
|   | ||||
| @@ -135,6 +135,10 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | ||||
|     getUpstreamMember().remove(key); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE void link(VariantConstRef value) { | ||||
|     getOrAddUpstreamMember().link(value); | ||||
|   } | ||||
|  | ||||
|   template <typename TValue> | ||||
|   FORCE_INLINE typename VariantTo<TValue>::type to() { | ||||
|     return getOrAddUpstreamMember().template to<TValue>(); | ||||
|   | ||||
| @@ -278,7 +278,7 @@ struct Converter<ObjectConstRef> { | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isObject(); | ||||
|     return data && data->resolve()->isObject(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -48,12 +48,12 @@ struct Converter< | ||||
|   static T fromJson(VariantConstRef src) { | ||||
|     ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||
|     const VariantData* data = getData(src); | ||||
|     return data ? data->asIntegral<T>() : T(); | ||||
|     return data ? data->resolve()->asIntegral<T>() : T(); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isInteger<T>(); | ||||
|     return data && data->resolve()->isInteger<T>(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -65,12 +65,12 @@ struct Converter<T, typename enable_if<is_enum<T>::value>::type> { | ||||
|  | ||||
|   static T fromJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data ? static_cast<T>(data->asIntegral<int>()) : T(); | ||||
|     return data ? static_cast<T>(data->resolve()->asIntegral<int>()) : T(); | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isInteger<int>(); | ||||
|     return data && data->resolve()->isInteger<int>(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -84,12 +84,12 @@ struct Converter<bool> { | ||||
|  | ||||
|   static bool fromJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data ? data->asBoolean() : false; | ||||
|     return data ? data->resolve()->asBoolean() : false; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isBoolean(); | ||||
|     return data && data->resolve()->isBoolean(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -103,12 +103,12 @@ struct Converter<T, typename enable_if<is_floating_point<T>::value>::type> { | ||||
|  | ||||
|   static T fromJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data ? data->asFloat<T>() : false; | ||||
|     return data ? data->resolve()->asFloat<T>() : 0; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isFloat(); | ||||
|     return data && data->resolve()->isFloat(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -121,12 +121,12 @@ struct Converter<const char*> { | ||||
|  | ||||
|   static const char* fromJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data ? data->asString().c_str() : 0; | ||||
|     return data ? data->resolve()->asString().c_str() : 0; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isString(); | ||||
|     return data && data->resolve()->isString(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -139,12 +139,12 @@ struct Converter<String> { | ||||
|  | ||||
|   static String fromJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data ? data->asString() : 0; | ||||
|     return data ? data->resolve()->asString() : 0; | ||||
|   } | ||||
|  | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data && data->isString(); | ||||
|     return data && data->resolve()->isString(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -192,7 +192,7 @@ struct Converter<decltype(nullptr)> { | ||||
|   } | ||||
|   static bool checkJson(VariantConstRef src) { | ||||
|     const VariantData* data = getData(src); | ||||
|     return data == 0 || data->isNull(); | ||||
|     return data == 0 || data->resolve()->isNull(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -31,6 +31,8 @@ enum { | ||||
|   VALUE_IS_SIGNED_INTEGER = 0x0A, | ||||
|   VALUE_IS_FLOAT = 0x0C, | ||||
|  | ||||
|   VALUE_IS_POINTER = 0x10, | ||||
|  | ||||
|   COLLECTION_MASK = 0x60, | ||||
|   VALUE_IS_OBJECT = 0x20, | ||||
|   VALUE_IS_ARRAY = 0x40, | ||||
| @@ -49,6 +51,7 @@ union VariantContent { | ||||
|   UInt asUnsignedInteger; | ||||
|   Integer asSignedInteger; | ||||
|   CollectionData asCollection; | ||||
|   const class VariantData *asPointer; | ||||
|   struct { | ||||
|     const char *data; | ||||
|     size_t size; | ||||
|   | ||||
| @@ -83,6 +83,12 @@ class VariantData { | ||||
|  | ||||
|   bool asBoolean() const; | ||||
|  | ||||
|   const VariantData *resolve() const { | ||||
|     if (isPointer()) | ||||
|       return _content.asPointer->resolve(); | ||||
|     return this; | ||||
|   } | ||||
|  | ||||
|   CollectionData *asArray() { | ||||
|     return isArray() ? &_content.asCollection : 0; | ||||
|   } | ||||
| @@ -117,6 +123,10 @@ class VariantData { | ||||
|     return (_flags & COLLECTION_MASK) != 0; | ||||
|   } | ||||
|  | ||||
|   bool isPointer() const { | ||||
|     return type() == VALUE_IS_POINTER; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   bool isInteger() const { | ||||
|     switch (type()) { | ||||
| @@ -212,6 +222,12 @@ class VariantData { | ||||
|     setType(VALUE_IS_NULL); | ||||
|   } | ||||
|  | ||||
|   void setPointer(const VariantData *p) { | ||||
|     ARDUINOJSON_ASSERT(p); | ||||
|     setType(VALUE_IS_POINTER); | ||||
|     _content.asPointer = p; | ||||
|   } | ||||
|  | ||||
|   void setString(String s) { | ||||
|     ARDUINOJSON_ASSERT(s); | ||||
|     if (s.isLinked()) | ||||
| @@ -262,7 +278,8 @@ class VariantData { | ||||
|   } | ||||
|  | ||||
|   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) { | ||||
| @@ -275,7 +292,8 @@ class VariantData { | ||||
|  | ||||
|   template <typename TAdaptedString> | ||||
|   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> | ||||
|   | ||||
| @@ -15,17 +15,17 @@ template <typename TVisitor> | ||||
| inline typename TVisitor::result_type variantAccept(const VariantData *var, | ||||
|                                                     TVisitor &visitor) { | ||||
|   if (var != 0) | ||||
|     return var->accept(visitor); | ||||
|     return var->resolve()->accept(visitor); | ||||
|   else | ||||
|     return visitor.visitNull(); | ||||
| } | ||||
|  | ||||
| inline const CollectionData *variantAsArray(const VariantData *var) { | ||||
|   return var != 0 ? var->asArray() : 0; | ||||
|   return var != 0 ? var->resolve()->asArray() : 0; | ||||
| } | ||||
|  | ||||
| inline const CollectionData *variantAsObject(const VariantData *var) { | ||||
|   return var != 0 ? var->asObject() : 0; | ||||
|   return var != 0 ? var->resolve()->asObject() : 0; | ||||
| } | ||||
|  | ||||
| inline CollectionData *variantAsObject(VariantData *var) { | ||||
| @@ -56,7 +56,7 @@ inline bool variantSetString(VariantData *var, TAdaptedString value, | ||||
| } | ||||
|  | ||||
| inline size_t variantSize(const VariantData *var) { | ||||
|   return var != 0 ? var->size() : 0; | ||||
|   return var != 0 ? var->resolve()->size() : 0; | ||||
| } | ||||
|  | ||||
| inline CollectionData *variantToArray(VariantData *var) { | ||||
| @@ -102,14 +102,14 @@ NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, | ||||
| } | ||||
|  | ||||
| inline bool variantIsNull(const VariantData *var) { | ||||
|   return var == 0 || var->isNull(); | ||||
|   return var == 0 || var->resolve()->isNull(); | ||||
| } | ||||
|  | ||||
| inline size_t variantNesting(const VariantData *var) { | ||||
|   if (!var) | ||||
|     return 0; | ||||
|  | ||||
|   const CollectionData *collection = var->asCollection(); | ||||
|   const CollectionData *collection = var->resolve()->asCollection(); | ||||
|   if (!collection) | ||||
|     return 0; | ||||
|  | ||||
|   | ||||
| @@ -124,7 +124,8 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE VariantConstRef getElementConst(size_t index) const { | ||||
|     return VariantConstRef(_data != 0 ? _data->getElement(index) : 0); | ||||
|     return VariantConstRef(_data != 0 ? _data->resolve()->getElement(index) | ||||
|                                       : 0); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE VariantConstRef operator[](size_t index) const { | ||||
| @@ -135,8 +136,8 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | ||||
|   // getMemberConst(const String&) const | ||||
|   template <typename TString> | ||||
|   FORCE_INLINE VariantConstRef getMemberConst(const TString &key) const { | ||||
|     return VariantConstRef( | ||||
|         objectGetMember(variantAsObject(_data), adaptString(key))); | ||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) | ||||
|                                  : 0); | ||||
|   } | ||||
|  | ||||
|   // getMemberConst(char*) const | ||||
| @@ -144,8 +145,8 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | ||||
|   // getMemberConst(const __FlashStringHelper*) const | ||||
|   template <typename TChar> | ||||
|   FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { | ||||
|     const CollectionData *obj = variantAsObject(_data); | ||||
|     return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0); | ||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) | ||||
|                                  : 0); | ||||
|   } | ||||
|  | ||||
|   // operator[](const std::string&) const | ||||
| @@ -293,7 +294,8 @@ class VariantRef : public VariantRefBase<VariantData>, | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE VariantConstRef getElementConst(size_t index) const { | ||||
|     return VariantConstRef(_data != 0 ? _data->getElement(index) : 0); | ||||
|     return VariantConstRef(_data != 0 ? _data->resolve()->getElement(index) | ||||
|                                       : 0); | ||||
|   } | ||||
|  | ||||
|   FORCE_INLINE VariantRef getOrAddElement(size_t index) const { | ||||
| @@ -321,7 +323,8 @@ class VariantRef : public VariantRefBase<VariantData>, | ||||
|   // getMemberConst(const __FlashStringHelper*) const | ||||
|   template <typename TChar> | ||||
|   FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { | ||||
|     return VariantConstRef(_data ? _data->getMember(adaptString(key)) : 0); | ||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) | ||||
|                                  : 0); | ||||
|   } | ||||
|  | ||||
|   // getMemberConst(const std::string&) const | ||||
| @@ -330,7 +333,8 @@ class VariantRef : public VariantRefBase<VariantData>, | ||||
|   FORCE_INLINE | ||||
|       typename enable_if<IsString<TString>::value, VariantConstRef>::type | ||||
|       getMemberConst(const TString &key) const { | ||||
|     return VariantConstRef(_data ? _data->getMember(adaptString(key)) : 0); | ||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) | ||||
|                                  : 0); | ||||
|   } | ||||
|  | ||||
|   // getOrAddMember(char*) const | ||||
| @@ -370,6 +374,16 @@ class VariantRef : public VariantRefBase<VariantData>, | ||||
|       _data->remove(adaptString(key)); | ||||
|   } | ||||
|  | ||||
|   inline void link(VariantConstRef target) { | ||||
|     if (!_data) | ||||
|       return; | ||||
|     const VariantData *targetData = getData(target); | ||||
|     if (targetData) | ||||
|       _data->setPointer(targetData); | ||||
|     else | ||||
|       _data->setNull(); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   MemoryPool *_pool; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user