mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 08:42:39 +01:00 
			
		
		
		
	Change link() to shallowCopy() (issue #1343)
				
					
				
			Instead of storing a pointer, the function copies the `VariantData`. Benefits: * smaller code * no impact on programs that don't use this feature Drawbacks: * changes to the original variant are not always reflected on the copy * modifying the original from the shallow copy leads to UB
This commit is contained in:
		| @@ -4,7 +4,7 @@ ArduinoJson: change log | |||||||
| HEAD | HEAD | ||||||
| ---- | ---- | ||||||
|  |  | ||||||
| * Add `JsonVariant::link()` (issue #1343) | * Add `JsonVariant::shallowCopy()` (issue #1343) | ||||||
| * Fix `9.22337e+18 is outside the range of representable values of type 'long'` | * Fix `9.22337e+18 is outside the range of representable values of type 'long'` | ||||||
| * Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst` | * Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst` | ||||||
| * Remove undocumented `accept()` functions | * Remove undocumented `accept()` functions | ||||||
|   | |||||||
| @@ -43,13 +43,5 @@ TEST_CASE("nullptr") { | |||||||
|  |  | ||||||
|     variant.clear(); |     variant.clear(); | ||||||
|     REQUIRE(variant.is<std::nullptr_t>() == true); |     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); |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -246,10 +246,10 @@ TEST_CASE("ElementProxy cast to JsonVariant") { | |||||||
|   CHECK(doc.as<std::string>() == "[\"toto\"]"); |   CHECK(doc.as<std::string>() == "[\"toto\"]"); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("ElementProxy::link()") { | TEST_CASE("ElementProxy::shallowCopy()") { | ||||||
|   StaticJsonDocument<1024> doc1, doc2; |   StaticJsonDocument<1024> doc1, doc2; | ||||||
|   doc1[0].link(doc2); |  | ||||||
|   doc2["hello"] = "world"; |   doc2["hello"] = "world"; | ||||||
|  |   doc1[0].shallowCopy(doc2); | ||||||
|  |  | ||||||
|   CHECK(doc1.as<std::string>() == "[{\"hello\":\"world\"}]"); |   CHECK(doc1.as<std::string>() == "[{\"hello\":\"world\"}]"); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -318,10 +318,10 @@ TEST_CASE("MemberProxy::createNestedObject(key)") { | |||||||
|   CHECK(doc["status"]["weather"]["temp"] == 42); |   CHECK(doc["status"]["weather"]["temp"] == 42); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE("MemberProxy::link()") { | TEST_CASE("MemberProxy::shallowCopy()") { | ||||||
|   StaticJsonDocument<1024> doc1, doc2; |   StaticJsonDocument<1024> doc1, doc2; | ||||||
|   doc1["obj"].link(doc2); |  | ||||||
|   doc2["hello"] = "world"; |   doc2["hello"] = "world"; | ||||||
|  |   doc1["obj"].shallowCopy(doc2); | ||||||
|  |  | ||||||
|   CHECK(doc1.as<std::string>() == "{\"obj\":{\"hello\":\"world\"}}"); |   CHECK(doc1.as<std::string>() == "{\"obj\":{\"hello\":\"world\"}}"); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,21 +25,4 @@ TEST_CASE("JsonDocument::size()") { | |||||||
|  |  | ||||||
|     REQUIRE(doc.size() == 2); |     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,7 +13,6 @@ add_executable(JsonVariantTests | |||||||
| 	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 | ||||||
| @@ -21,6 +20,7 @@ add_executable(JsonVariantTests | |||||||
| 	overflow.cpp | 	overflow.cpp | ||||||
| 	remove.cpp | 	remove.cpp | ||||||
| 	set.cpp | 	set.cpp | ||||||
|  | 	shallowCopy.cpp | ||||||
| 	size.cpp | 	size.cpp | ||||||
| 	subscript.cpp | 	subscript.cpp | ||||||
| 	types.cpp | 	types.cpp | ||||||
|   | |||||||
| @@ -43,14 +43,4 @@ 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,97 +267,4 @@ 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,15 +23,4 @@ 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,20 +34,6 @@ 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") { | ||||||
| @@ -327,19 +313,4 @@ 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); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,15 +25,6 @@ TEST_CASE("JsonVariant::containsKey()") { | |||||||
|     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,16 +84,6 @@ 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; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,17 +18,6 @@ TEST_CASE("JsonVariant::createNestedObject()") { | |||||||
|     REQUIRE(variant[0]["value"] == 42); |     REQUIRE(variant[0]["value"] == 42); | ||||||
|     REQUIRE(obj.isNull() == false); |     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()") { | TEST_CASE("JsonVariant::createNestedArray()") { | ||||||
| @@ -41,17 +30,6 @@ TEST_CASE("JsonVariant::createNestedArray()") { | |||||||
|     REQUIRE(variant.is<JsonArray>() == true); |     REQUIRE(variant.is<JsonArray>() == true); | ||||||
|     REQUIRE(arr.isNull() == false); |     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)") { | TEST_CASE("JsonVariant::createNestedObject(key)") { | ||||||
| @@ -65,17 +43,6 @@ TEST_CASE("JsonVariant::createNestedObject(key)") { | |||||||
|     REQUIRE(variant.is<JsonObject>() == true); |     REQUIRE(variant.is<JsonObject>() == true); | ||||||
|     REQUIRE(variant["weather"]["temp"] == 42); |     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)") { | TEST_CASE("JsonVariant::createNestedArray(key)") { | ||||||
| @@ -88,15 +55,4 @@ TEST_CASE("JsonVariant::createNestedArray(key)") { | |||||||
|     REQUIRE(variant.is<JsonObject>() == true); |     REQUIRE(variant.is<JsonObject>() == true); | ||||||
|     REQUIRE(arr.isNull() == false); |     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,24 +144,6 @@ 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>(); | ||||||
|  |  | ||||||
| @@ -179,44 +161,6 @@ 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>() == true); |  | ||||||
|     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>()") { | ||||||
| @@ -372,58 +316,4 @@ 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>() == true); |  | ||||||
|     CHECK(cvariant.is<bool>() == false); |  | ||||||
|     CHECK(cvariant.is<const char *>() == false); |  | ||||||
|     CHECK(cvariant.is<MYENUM2>() == true); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -70,16 +70,16 @@ TEST_CASE("JsonVariant::isNull()") { | |||||||
|     REQUIRE(variant.isNull() == true); |     REQUIRE(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("returns true for a linked null") { |   SECTION("returns true for a shallow null copy") { | ||||||
|     StaticJsonDocument<128> doc2; |     StaticJsonDocument<128> doc2; | ||||||
|     variant.link(doc2); |     variant.shallowCopy(doc2); | ||||||
|     CHECK(variant.isNull() == true); |     CHECK(variant.isNull() == true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   SECTION("returns false for a linked array") { |   SECTION("returns false for a shallow array copy") { | ||||||
|     StaticJsonDocument<128> doc2; |     StaticJsonDocument<128> doc2; | ||||||
|     doc2[0] = 42; |     doc2[0] = 42; | ||||||
|     variant.link(doc2); |     variant.shallowCopy(doc2); | ||||||
|     CHECK(variant.isNull() == false); |     CHECK(variant.isNull() == false); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,12 +38,4 @@ 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,12 +28,4 @@ TEST_CASE("JsonVariant::nesting()") { | |||||||
|     var.to<JsonArray>(); |     var.to<JsonArray>(); | ||||||
|     REQUIRE(var.nesting() == 1); |     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,12 +156,4 @@ 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,24 +39,4 @@ 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\"}"); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,17 +5,16 @@ | |||||||
| #include <ArduinoJson.h> | #include <ArduinoJson.h> | ||||||
| #include <catch.hpp> | #include <catch.hpp> | ||||||
| 
 | 
 | ||||||
| TEST_CASE("JsonVariant::link()") { | TEST_CASE("JsonVariant::shallowCopy()") { | ||||||
|   StaticJsonDocument<1024> doc1, doc2; |   StaticJsonDocument<1024> doc1, doc2; | ||||||
|   JsonVariant variant = doc1.to<JsonVariant>(); |   JsonVariant variant = doc1.to<JsonVariant>(); | ||||||
| 
 | 
 | ||||||
|   SECTION("JsonVariant::link(JsonDocument&)") { |   SECTION("JsonVariant::shallowCopy(JsonDocument&)") { | ||||||
|     doc2["hello"] = "world"; |     doc2["hello"] = "world"; | ||||||
| 
 | 
 | ||||||
|     variant.link(doc2); |     variant.shallowCopy(doc2); | ||||||
| 
 | 
 | ||||||
|     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|     CHECK(variant.memoryUsage() == 0); |  | ||||||
| 
 | 
 | ||||||
|     // altering the linked document should change the result
 |     // altering the linked document should change the result
 | ||||||
|     doc2["hello"] = "WORLD!"; |     doc2["hello"] = "WORLD!"; | ||||||
| @@ -23,13 +22,12 @@ TEST_CASE("JsonVariant::link()") { | |||||||
|     CHECK(variant.as<std::string>() == "{\"hello\":\"WORLD!\"}"); |     CHECK(variant.as<std::string>() == "{\"hello\":\"WORLD!\"}"); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   SECTION("JsonVariant::link(MemberProxy)") { |   SECTION("JsonVariant::shallowCopy(MemberProxy)") { | ||||||
|     doc2["obj"]["hello"] = "world"; |     doc2["obj"]["hello"] = "world"; | ||||||
| 
 | 
 | ||||||
|     variant.link(doc2["obj"]); |     variant.shallowCopy(doc2["obj"]); | ||||||
| 
 | 
 | ||||||
|     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|     CHECK(variant.memoryUsage() == 0); |  | ||||||
| 
 | 
 | ||||||
|     // altering the linked document should change the result
 |     // altering the linked document should change the result
 | ||||||
|     doc2["obj"]["hello"] = "WORLD!"; |     doc2["obj"]["hello"] = "WORLD!"; | ||||||
| @@ -37,13 +35,12 @@ TEST_CASE("JsonVariant::link()") { | |||||||
|     CHECK(variant.as<std::string>() == "{\"hello\":\"WORLD!\"}"); |     CHECK(variant.as<std::string>() == "{\"hello\":\"WORLD!\"}"); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   SECTION("JsonVariant::link(ElementProxy)") { |   SECTION("JsonVariant::shallowCopy(ElementProxy)") { | ||||||
|     doc2[0]["hello"] = "world"; |     doc2[0]["hello"] = "world"; | ||||||
| 
 | 
 | ||||||
|     variant.link(doc2[0]); |     variant.shallowCopy(doc2[0]); | ||||||
| 
 | 
 | ||||||
|     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); |     CHECK(variant.as<std::string>() == "{\"hello\":\"world\"}"); | ||||||
|     CHECK(variant.memoryUsage() == 0); |  | ||||||
| 
 | 
 | ||||||
|     // altering the linked document should change the result
 |     // altering the linked document should change the result
 | ||||||
|     doc2[0]["hello"] = "WORLD!"; |     doc2[0]["hello"] = "WORLD!"; | ||||||
| @@ -55,7 +52,7 @@ TEST_CASE("JsonVariant::link()") { | |||||||
|     JsonVariant unbound; |     JsonVariant unbound; | ||||||
|     variant["hello"] = "world"; |     variant["hello"] = "world"; | ||||||
| 
 | 
 | ||||||
|     variant.link(unbound); |     variant.shallowCopy(unbound); | ||||||
| 
 | 
 | ||||||
|     CHECK(variant.isUnbound() == false); |     CHECK(variant.isUnbound() == false); | ||||||
|     CHECK(variant.isNull() == true); |     CHECK(variant.isNull() == true); | ||||||
| @@ -67,11 +64,24 @@ TEST_CASE("JsonVariant::link()") { | |||||||
|     JsonVariant unbound; |     JsonVariant unbound; | ||||||
|     doc2["hello"] = "world"; |     doc2["hello"] = "world"; | ||||||
| 
 | 
 | ||||||
|     unbound.link(doc2); |     unbound.shallowCopy(doc2); | ||||||
| 
 | 
 | ||||||
|     CHECK(unbound.isUnbound() == true); |     CHECK(unbound.isUnbound() == true); | ||||||
|     CHECK(unbound.isNull() == true); |     CHECK(unbound.isNull() == true); | ||||||
|     CHECK(unbound.memoryUsage() == 0); |     CHECK(unbound.memoryUsage() == 0); | ||||||
|     CHECK(unbound.size() == 0); |     CHECK(unbound.size() == 0); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   SECTION("preserves owned key bit") { | ||||||
|  |     doc2.set(42); | ||||||
|  | 
 | ||||||
|  |     doc1["a"].shallowCopy(doc2); | ||||||
|  |     doc1[std::string("b")].shallowCopy(doc2); | ||||||
|  | 
 | ||||||
|  |     JsonObject::iterator it = doc1.as<JsonObject>().begin(); | ||||||
|  | 
 | ||||||
|  |     CHECK(it->key().isLinked() == true); | ||||||
|  |     ++it; | ||||||
|  |     CHECK(it->key().isLinked() == false); | ||||||
|  |   } | ||||||
| } | } | ||||||
| @@ -33,21 +33,4 @@ TEST_CASE("JsonVariant::size()") { | |||||||
|  |  | ||||||
|     CHECK(variant.size() == 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,44 +129,6 @@ 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[]") { | ||||||
| @@ -239,20 +201,4 @@ 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); |  | ||||||
|   } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -202,12 +202,12 @@ struct Converter<ArrayConstRef> { | |||||||
|  |  | ||||||
|   static ArrayConstRef fromJson(VariantConstRef src) { |   static ArrayConstRef fromJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data ? data->resolve()->asArray() : 0; |     return data ? data->asArray() : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isArray(); |     return data && data->isArray(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -106,8 +106,8 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >, | |||||||
|     return getOrAddUpstreamElement().template to<T>(); |     return getOrAddUpstreamElement().template to<T>(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE void link(VariantConstRef value) const { |   FORCE_INLINE void shallowCopy(VariantConstRef value) const { | ||||||
|     getOrAddUpstreamElement().link(value); |     getOrAddUpstreamElement().shallowCopy(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Replaces the value |   // Replaces the value | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { | |||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   if (_tail) { |   if (_tail) { | ||||||
|  |     ARDUINOJSON_ASSERT(pool->owns(_tail));  // Can't alter a linked array/object | ||||||
|     _tail->setNextNotNull(slot); |     _tail->setNextNotNull(slot); | ||||||
|     _tail = slot; |     _tail = slot; | ||||||
|   } else { |   } else { | ||||||
|   | |||||||
| @@ -62,7 +62,7 @@ class JsonDocument : public VariantOperators<const JsonDocument&> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   size_t size() const { |   size_t size() const { | ||||||
|     return _data.resolve()->size(); |     return _data.size(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool set(const JsonDocument& src) { |   bool set(const JsonDocument& src) { | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ class JsonSerializer : public Visitor<size_t> { | |||||||
|     const VariantSlot *slot = array.head(); |     const VariantSlot *slot = array.head(); | ||||||
|  |  | ||||||
|     while (slot != 0) { |     while (slot != 0) { | ||||||
|       slot->data()->resolve()->accept(*this); |       slot->data()->accept(*this); | ||||||
|  |  | ||||||
|       slot = slot->next(); |       slot = slot->next(); | ||||||
|       if (slot == 0) |       if (slot == 0) | ||||||
| @@ -45,7 +45,7 @@ class JsonSerializer : public Visitor<size_t> { | |||||||
|     while (slot != 0) { |     while (slot != 0) { | ||||||
|       _formatter.writeString(slot->key()); |       _formatter.writeString(slot->key()); | ||||||
|       write(':'); |       write(':'); | ||||||
|       slot->data()->resolve()->accept(*this); |       slot->data()->accept(*this); | ||||||
|  |  | ||||||
|       slot = slot->next(); |       slot = slot->next(); | ||||||
|       if (slot == 0) |       if (slot == 0) | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | |||||||
|       _nesting++; |       _nesting++; | ||||||
|       while (slot != 0) { |       while (slot != 0) { | ||||||
|         indent(); |         indent(); | ||||||
|         slot->data()->resolve()->accept(*this); |         slot->data()->accept(*this); | ||||||
|  |  | ||||||
|         slot = slot->next(); |         slot = slot->next(); | ||||||
|         base::write(slot ? ",\r\n" : "\r\n"); |         base::write(slot ? ",\r\n" : "\r\n"); | ||||||
| @@ -48,7 +48,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> { | |||||||
|         indent(); |         indent(); | ||||||
|         base::visitString(slot->key()); |         base::visitString(slot->key()); | ||||||
|         base::write(": "); |         base::write(": "); | ||||||
|         slot->data()->resolve()->accept(*this); |         slot->data()->accept(*this); | ||||||
|  |  | ||||||
|         slot = slot->next(); |         slot = slot->next(); | ||||||
|         base::write(slot ? ",\r\n" : "\r\n"); |         base::write(slot ? ",\r\n" : "\r\n"); | ||||||
|   | |||||||
| @@ -56,7 +56,7 @@ class MsgPackSerializer : public Visitor<size_t> { | |||||||
|       writeInteger(uint32_t(n)); |       writeInteger(uint32_t(n)); | ||||||
|     } |     } | ||||||
|     for (const VariantSlot* slot = array.head(); slot; slot = slot->next()) { |     for (const VariantSlot* slot = array.head(); slot; slot = slot->next()) { | ||||||
|       slot->data()->resolve()->accept(*this); |       slot->data()->accept(*this); | ||||||
|     } |     } | ||||||
|     return bytesWritten(); |     return bytesWritten(); | ||||||
|   } |   } | ||||||
| @@ -74,7 +74,7 @@ class MsgPackSerializer : public Visitor<size_t> { | |||||||
|     } |     } | ||||||
|     for (const VariantSlot* slot = object.head(); slot; slot = slot->next()) { |     for (const VariantSlot* slot = object.head(); slot; slot = slot->next()) { | ||||||
|       visitString(slot->key()); |       visitString(slot->key()); | ||||||
|       slot->data()->resolve()->accept(*this); |       slot->data()->accept(*this); | ||||||
|     } |     } | ||||||
|     return bytesWritten(); |     return bytesWritten(); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -132,8 +132,8 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, | |||||||
|     getUpstreamMember().remove(key); |     getUpstreamMember().remove(key); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE void link(VariantConstRef value) { |   FORCE_INLINE void shallowCopy(VariantConstRef value) { | ||||||
|     getOrAddUpstreamMember().link(value); |     getOrAddUpstreamMember().shallowCopy(value); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   template <typename TValue> |   template <typename TValue> | ||||||
|   | |||||||
| @@ -269,12 +269,12 @@ struct Converter<ObjectConstRef> { | |||||||
|  |  | ||||||
|   static ObjectConstRef fromJson(VariantConstRef src) { |   static ObjectConstRef fromJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data != 0 ? data->resolve()->asObject() : 0; |     return data != 0 ? data->asObject() : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isObject(); |     return data && data->isObject(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -48,12 +48,12 @@ struct Converter< | |||||||
|   static T fromJson(VariantConstRef src) { |   static T fromJson(VariantConstRef src) { | ||||||
|     ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); |     ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T); | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data ? data->resolve()->asIntegral<T>() : T(); |     return data ? data->asIntegral<T>() : T(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isInteger<T>(); |     return data && data->isInteger<T>(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -65,12 +65,12 @@ struct Converter<T, typename enable_if<is_enum<T>::value>::type> { | |||||||
|  |  | ||||||
|   static T fromJson(VariantConstRef src) { |   static T fromJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data ? static_cast<T>(data->resolve()->asIntegral<int>()) : T(); |     return data ? static_cast<T>(data->asIntegral<int>()) : T(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isInteger<int>(); |     return data && data->isInteger<int>(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -84,12 +84,12 @@ struct Converter<bool> { | |||||||
|  |  | ||||||
|   static bool fromJson(VariantConstRef src) { |   static bool fromJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data ? data->resolve()->asBoolean() : false; |     return data ? data->asBoolean() : false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isBoolean(); |     return data && data->isBoolean(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -103,12 +103,12 @@ struct Converter<T, typename enable_if<is_floating_point<T>::value>::type> { | |||||||
|  |  | ||||||
|   static T fromJson(VariantConstRef src) { |   static T fromJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data ? data->resolve()->asFloat<T>() : 0; |     return data ? data->asFloat<T>() : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isFloat(); |     return data && data->isFloat(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -121,12 +121,12 @@ struct Converter<const char*> { | |||||||
|  |  | ||||||
|   static const char* fromJson(VariantConstRef src) { |   static const char* fromJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data ? data->resolve()->asString().c_str() : 0; |     return data ? data->asString().c_str() : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isString(); |     return data && data->isString(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -139,12 +139,12 @@ struct Converter<String> { | |||||||
|  |  | ||||||
|   static String fromJson(VariantConstRef src) { |   static String fromJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data ? data->resolve()->asString() : 0; |     return data ? data->asString() : 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data && data->resolve()->isString(); |     return data && data->isString(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -192,7 +192,7 @@ struct Converter<decltype(nullptr)> { | |||||||
|   } |   } | ||||||
|   static bool checkJson(VariantConstRef src) { |   static bool checkJson(VariantConstRef src) { | ||||||
|     const VariantData* data = getData(src); |     const VariantData* data = getData(src); | ||||||
|     return data == 0 || data->resolve()->isNull(); |     return data == 0 || data->isNull(); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,8 +31,6 @@ 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, | ||||||
| @@ -51,7 +49,6 @@ 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; | ||||||
|   | |||||||
| @@ -37,6 +37,11 @@ class VariantData { | |||||||
|     _flags = VALUE_IS_NULL; |     _flags = VALUE_IS_NULL; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void operator=(const VariantData &src) { | ||||||
|  |     _content = src._content; | ||||||
|  |     _flags = uint8_t((_flags & OWNED_KEY_BIT) | (src._flags & ~OWNED_KEY_BIT)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   template <typename TVisitor> |   template <typename TVisitor> | ||||||
|   typename TVisitor::result_type accept(TVisitor &visitor) const { |   typename TVisitor::result_type accept(TVisitor &visitor) const { | ||||||
|     switch (type()) { |     switch (type()) { | ||||||
| @@ -83,12 +88,6 @@ class VariantData { | |||||||
|  |  | ||||||
|   bool asBoolean() const; |   bool asBoolean() const; | ||||||
|  |  | ||||||
|   const VariantData *resolve() const { |  | ||||||
|     if (isPointer()) |  | ||||||
|       return _content.asPointer->resolve(); |  | ||||||
|     return this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   CollectionData *asArray() { |   CollectionData *asArray() { | ||||||
|     return isArray() ? &_content.asCollection : 0; |     return isArray() ? &_content.asCollection : 0; | ||||||
|   } |   } | ||||||
| @@ -123,10 +122,6 @@ 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 { | ||||||
|     switch (type()) { |     switch (type()) { | ||||||
| @@ -222,12 +217,6 @@ 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()) | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ template <typename TVisitor> | |||||||
| inline typename TVisitor::result_type variantAccept(const VariantData *var, | inline typename TVisitor::result_type variantAccept(const VariantData *var, | ||||||
|                                                     TVisitor &visitor) { |                                                     TVisitor &visitor) { | ||||||
|   if (var != 0) |   if (var != 0) | ||||||
|     return var->resolve()->accept(visitor); |     return var->accept(visitor); | ||||||
|   else |   else | ||||||
|     return visitor.visitNull(); |     return visitor.visitNull(); | ||||||
| } | } | ||||||
| @@ -44,7 +44,7 @@ inline bool variantSetString(VariantData *var, TAdaptedString value, | |||||||
| } | } | ||||||
|  |  | ||||||
| inline size_t variantSize(const VariantData *var) { | inline size_t variantSize(const VariantData *var) { | ||||||
|   return var != 0 ? var->resolve()->size() : 0; |   return var != 0 ? var->size() : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline CollectionData *variantToArray(VariantData *var) { | inline CollectionData *variantToArray(VariantData *var) { | ||||||
| @@ -90,14 +90,14 @@ NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, | |||||||
| } | } | ||||||
|  |  | ||||||
| inline bool variantIsNull(const VariantData *var) { | inline bool variantIsNull(const VariantData *var) { | ||||||
|   return var == 0 || var->resolve()->isNull(); |   return var == 0 || var->isNull(); | ||||||
| } | } | ||||||
|  |  | ||||||
| inline size_t variantNesting(const VariantData *var) { | inline size_t variantNesting(const VariantData *var) { | ||||||
|   if (!var) |   if (!var) | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   const CollectionData *collection = var->resolve()->asCollection(); |   const CollectionData *collection = var->asCollection(); | ||||||
|   if (!collection) |   if (!collection) | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -117,8 +117,7 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef getElementConst(size_t index) const { |   FORCE_INLINE VariantConstRef getElementConst(size_t index) const { | ||||||
|     return VariantConstRef(_data != 0 ? _data->resolve()->getElement(index) |     return VariantConstRef(_data != 0 ? _data->getElement(index) : 0); | ||||||
|                                       : 0); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef operator[](size_t index) const { |   FORCE_INLINE VariantConstRef operator[](size_t index) const { | ||||||
| @@ -129,8 +128,7 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | |||||||
|   // getMemberConst(const String&) const |   // getMemberConst(const String&) const | ||||||
|   template <typename TString> |   template <typename TString> | ||||||
|   FORCE_INLINE VariantConstRef getMemberConst(const TString &key) const { |   FORCE_INLINE VariantConstRef getMemberConst(const TString &key) const { | ||||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) |     return VariantConstRef(_data ? _data->getMember(adaptString(key)) : 0); | ||||||
|                                  : 0); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // getMemberConst(char*) const |   // getMemberConst(char*) const | ||||||
| @@ -138,8 +136,7 @@ class VariantConstRef : public VariantRefBase<const VariantData>, | |||||||
|   // getMemberConst(const __FlashStringHelper*) const |   // getMemberConst(const __FlashStringHelper*) const | ||||||
|   template <typename TChar> |   template <typename TChar> | ||||||
|   FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { |   FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { | ||||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) |     return VariantConstRef(_data ? _data->getMember(adaptString(key)) : 0); | ||||||
|                                  : 0); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // operator[](const std::string&) const |   // operator[](const std::string&) const | ||||||
| @@ -281,8 +278,7 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantConstRef getElementConst(size_t index) const { |   FORCE_INLINE VariantConstRef getElementConst(size_t index) const { | ||||||
|     return VariantConstRef(_data != 0 ? _data->resolve()->getElement(index) |     return VariantConstRef(_data != 0 ? _data->getElement(index) : 0); | ||||||
|                                       : 0); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   FORCE_INLINE VariantRef getOrAddElement(size_t index) const { |   FORCE_INLINE VariantRef getOrAddElement(size_t index) const { | ||||||
| @@ -310,8 +306,7 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   // getMemberConst(const __FlashStringHelper*) const |   // getMemberConst(const __FlashStringHelper*) const | ||||||
|   template <typename TChar> |   template <typename TChar> | ||||||
|   FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { |   FORCE_INLINE VariantConstRef getMemberConst(TChar *key) const { | ||||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) |     return VariantConstRef(_data ? _data->getMember(adaptString(key)) : 0); | ||||||
|                                  : 0); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // getMemberConst(const std::string&) const |   // getMemberConst(const std::string&) const | ||||||
| @@ -320,8 +315,7 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|   FORCE_INLINE |   FORCE_INLINE | ||||||
|       typename enable_if<IsString<TString>::value, VariantConstRef>::type |       typename enable_if<IsString<TString>::value, VariantConstRef>::type | ||||||
|       getMemberConst(const TString &key) const { |       getMemberConst(const TString &key) const { | ||||||
|     return VariantConstRef(_data ? _data->resolve()->getMember(adaptString(key)) |     return VariantConstRef(_data ? _data->getMember(adaptString(key)) : 0); | ||||||
|                                  : 0); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // getOrAddMember(char*) const |   // getOrAddMember(char*) const | ||||||
| @@ -361,12 +355,12 @@ class VariantRef : public VariantRefBase<VariantData>, | |||||||
|       _data->remove(adaptString(key)); |       _data->remove(adaptString(key)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   inline void link(VariantConstRef target) { |   inline void shallowCopy(VariantConstRef target) { | ||||||
|     if (!_data) |     if (!_data) | ||||||
|       return; |       return; | ||||||
|     const VariantData *targetData = getData(target); |     const VariantData *targetData = getData(target); | ||||||
|     if (targetData) |     if (targetData) | ||||||
|       _data->setPointer(targetData); |       *_data = *targetData; | ||||||
|     else |     else | ||||||
|       _data->setNull(); |       _data->setNull(); | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user