From 7ed92bebd3366e7ca94d3fc070aaafc63e0d078f Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Fri, 15 Feb 2019 15:33:04 +0100 Subject: [PATCH] Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()` --- CHANGELOG.md | 2 + src/ArduinoJson.hpp | 2 + src/ArduinoJson/Array/ArrayRef.hpp | 55 +------------ src/ArduinoJson/Array/Utilities.hpp | 66 +++++++++++++++ src/ArduinoJson/Object/ObjectRef.hpp | 2 +- test/JsonArray/CMakeLists.txt | 3 +- test/JsonArray/copyArray.cpp | 117 +++++++++++++++++++++++++++ test/JsonArray/copyFrom.cpp | 66 --------------- test/JsonArray/copyTo.cpp | 58 ------------- test/JsonObject/copy.cpp | 14 ++-- 10 files changed, 197 insertions(+), 188 deletions(-) create mode 100644 src/ArduinoJson/Array/Utilities.hpp create mode 100644 test/JsonArray/copyArray.cpp delete mode 100644 test/JsonArray/copyFrom.cpp delete mode 100644 test/JsonArray/copyTo.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 8599cc1a..04ddebaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ HEAD * Decode escaped Unicode characters like \u00DE (issue #304, PR #791) Many thanks to Daniel Schulte (aka @trilader) who implemented this feature. * Add option ARDUINOJSON_DECODE_UNICODE to enable it +* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()` +* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()` v6.8.0-beta (2019-01-30) ----------- diff --git a/src/ArduinoJson.hpp b/src/ArduinoJson.hpp index 8762ad99..0c373f09 100644 --- a/src/ArduinoJson.hpp +++ b/src/ArduinoJson.hpp @@ -15,6 +15,7 @@ #include "ArduinoJson/Array/ArrayImpl.hpp" #include "ArduinoJson/Array/ElementProxy.hpp" +#include "ArduinoJson/Array/Utilities.hpp" #include "ArduinoJson/Collection/CollectionImpl.hpp" #include "ArduinoJson/Object/MemberProxy.hpp" #include "ArduinoJson/Object/ObjectImpl.hpp" @@ -39,6 +40,7 @@ typedef ARDUINOJSON_NAMESPACE::String JsonString; typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt; typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst; typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant; +using ARDUINOJSON_NAMESPACE::copyArray; using ARDUINOJSON_NAMESPACE::DeserializationError; using ARDUINOJSON_NAMESPACE::deserializeJson; using ARDUINOJSON_NAMESPACE::deserializeMsgPack; diff --git a/src/ArduinoJson/Array/ArrayRef.hpp b/src/ArduinoJson/Array/ArrayRef.hpp index 9bb353fe..9716ec99 100644 --- a/src/ArduinoJson/Array/ArrayRef.hpp +++ b/src/ArduinoJson/Array/ArrayRef.hpp @@ -115,65 +115,12 @@ class ArrayRef : public ArrayRefBase, return iterator(); } - // Imports a 1D array - template - FORCE_INLINE bool copyFrom(T (&array)[N]) const { - return copyFrom(array, N); - } - - // Imports a 1D array - template - bool copyFrom(T* array, size_t len) const { - bool ok = true; - for (size_t i = 0; i < len; i++) { - ok &= add(array[i]); - } - return ok; - } - - // Imports a 2D array - template - bool copyFrom(T (&array)[N1][N2]) const { - bool ok = true; - for (size_t i = 0; i < N1; i++) { - ArrayRef nestedArray = createNestedArray(); - for (size_t j = 0; j < N2; j++) { - ok &= nestedArray.add(array[i][j]); - } - } - return ok; - } - // Copy a ArrayRef - FORCE_INLINE bool copyFrom(ArrayConstRef src) const { + FORCE_INLINE bool set(ArrayConstRef src) const { if (!_data || !src._data) return false; return _data->copyFrom(*src._data, _pool); } - // Exports a 1D array - template - FORCE_INLINE size_t copyTo(T (&array)[N]) const { - return copyTo(array, N); - } - - // Exports a 1D array - template - size_t copyTo(T* array, size_t len) const { - size_t i = 0; - for (iterator it = begin(); it != end() && i < len; ++it) array[i++] = *it; - return i; - } - - // Exports a 2D array - template - void copyTo(T (&array)[N1][N2]) const { - if (!_data) return; - size_t i = 0; - for (iterator it = begin(); it != end() && i < N1; ++it) { - it->as().copyTo(array[i++]); - } - } - FORCE_INLINE bool operator==(ArrayRef rhs) const { return arrayEquals(_data, rhs._data); } diff --git a/src/ArduinoJson/Array/Utilities.hpp b/src/ArduinoJson/Array/Utilities.hpp new file mode 100644 index 00000000..49599160 --- /dev/null +++ b/src/ArduinoJson/Array/Utilities.hpp @@ -0,0 +1,66 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2019 +// MIT License + +#pragma once + +#include "ArrayRef.hpp" + +namespace ARDUINOJSON_NAMESPACE { + +// Copy a 1D array to a JsonArray +template +inline bool copyArray(T (&src)[N], ArrayRef dst) { + return copyArray(src, N, dst); +} + +// Copy a 1D array to a JsonArray +template +inline bool copyArray(T* src, size_t len, ArrayRef dst) { + bool ok = true; + for (size_t i = 0; i < len; i++) { + ok &= dst.add(src[i]); + } + return ok; +} + +// Copy a 2D array to a JsonArray +template +inline bool copyArray(T (&src)[N1][N2], ArrayRef dst) { + bool ok = true; + for (size_t i = 0; i < N1; i++) { + ArrayRef nestedArray = dst.createNestedArray(); + for (size_t j = 0; j < N2; j++) { + ok &= nestedArray.add(src[i][j]); + } + } + return ok; +} + +// Copy a JsonArray to a 1D array +template +inline size_t copyArray(ArrayConstRef src, T (&dst)[N]) { + return copyArray(src, dst, N); +} + +// Copy a JsonArray to a 1D array +template +inline size_t copyArray(ArrayConstRef src, T* dst, size_t len) { + size_t i = 0; + for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < len; + ++it) + dst[i++] = *it; + return i; +} + +// Copy a JsonArray to a 2D array +template +inline void copyArray(ArrayConstRef src, T (&dst)[N1][N2]) { + size_t i = 0; + for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < N1; + ++it) { + copyArray(it->as(), dst[i++]); + } +} + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Object/ObjectRef.hpp b/src/ArduinoJson/Object/ObjectRef.hpp index 397fe56b..05b456ef 100644 --- a/src/ArduinoJson/Object/ObjectRef.hpp +++ b/src/ArduinoJson/Object/ObjectRef.hpp @@ -161,7 +161,7 @@ class ObjectRef : public ObjectRefBase, _data->clear(); } - FORCE_INLINE bool copyFrom(ObjectConstRef src) { + FORCE_INLINE bool set(ObjectConstRef src) { if (!_data || !src._data) return false; return _data->copyFrom(*src._data, _pool); } diff --git a/test/JsonArray/CMakeLists.txt b/test/JsonArray/CMakeLists.txt index ec47b346..fdc2cd07 100644 --- a/test/JsonArray/CMakeLists.txt +++ b/test/JsonArray/CMakeLists.txt @@ -4,8 +4,7 @@ add_executable(JsonArrayTests add.cpp - copyFrom.cpp - copyTo.cpp + copyArray.cpp createNested.cpp equals.cpp get.cpp diff --git a/test/JsonArray/copyArray.cpp b/test/JsonArray/copyArray.cpp new file mode 100644 index 00000000..1ead2b1f --- /dev/null +++ b/test/JsonArray/copyArray.cpp @@ -0,0 +1,117 @@ +// ArduinoJson - arduinojson.org +// Copyright Benoit Blanchon 2014-2019 +// MIT License + +#include +#include + +TEST_CASE("copyArray()") { + SECTION("1D -> JsonArray") { + DynamicJsonDocument doc(4096); + JsonArray array = doc.to(); + char json[32]; + int source[] = {1, 2, 3}; + + bool ok = copyArray(source, array); + REQUIRE(ok); + + serializeJson(array, json, sizeof(json)); + REQUIRE(std::string("[1,2,3]") == json); + } + + SECTION("1D -> JsonArray, but not enough memory") { + const size_t SIZE = JSON_ARRAY_SIZE(2); + StaticJsonDocument doc; + JsonArray array = doc.to(); + char json[32]; + int source[] = {1, 2, 3}; + + bool ok = copyArray(source, array); + REQUIRE_FALSE(ok); + + serializeJson(array, json, sizeof(json)); + REQUIRE(std::string("[1,2]") == json); + } + + SECTION("2D -> JsonArray") { + DynamicJsonDocument doc(4096); + JsonArray array = doc.to(); + char json[32]; + int source[][3] = {{1, 2, 3}, {4, 5, 6}}; + + bool ok = copyArray(source, array); + REQUIRE(ok); + + serializeJson(array, json, sizeof(json)); + REQUIRE(std::string("[[1,2,3],[4,5,6]]") == json); + } + + SECTION("2D -> JsonArray, but not enough memory") { + const size_t SIZE = + JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2); + StaticJsonDocument doc; + JsonArray array = doc.to(); + char json[32] = ""; + int source[][3] = {{1, 2, 3}, {4, 5, 6}}; + + CAPTURE(SIZE) + + bool ok = copyArray(source, array); + CAPTURE(doc.memoryUsage()); + CHECK_FALSE(ok); + + serializeJson(array, json, sizeof(json)); + REQUIRE(std::string("[[1,2,3],[4,5]]") == json); + } + + SECTION("JsonArray -> 1D, with more space than needed") { + DynamicJsonDocument doc(4096); + char json[] = "[1,2,3]"; + DeserializationError err = deserializeJson(doc, json); + REQUIRE(err == DeserializationError::Ok); + JsonArray array = doc.as(); + + int destination[4] = {0}; + size_t result = copyArray(array, destination); + + REQUIRE(3 == result); + REQUIRE(1 == destination[0]); + REQUIRE(2 == destination[1]); + REQUIRE(3 == destination[2]); + REQUIRE(0 == destination[3]); + } + + SECTION("JsonArray -> 1D, without enough space") { + DynamicJsonDocument doc(4096); + char json[] = "[1,2,3]"; + DeserializationError err = deserializeJson(doc, json); + REQUIRE(err == DeserializationError::Ok); + JsonArray array = doc.as(); + + int destination[2] = {0}; + size_t result = copyArray(array, destination); + + REQUIRE(2 == result); + REQUIRE(1 == destination[0]); + REQUIRE(2 == destination[1]); + } + + SECTION("JsonArray -> 2D") { + DynamicJsonDocument doc(4096); + char json[] = "[[1,2],[3],[4]]"; + + DeserializationError err = deserializeJson(doc, json); + REQUIRE(err == DeserializationError::Ok); + JsonArray array = doc.as(); + + int destination[3][2] = {{0}}; + copyArray(array, destination); + + REQUIRE(1 == destination[0][0]); + REQUIRE(2 == destination[0][1]); + REQUIRE(3 == destination[1][0]); + REQUIRE(0 == destination[1][1]); + REQUIRE(4 == destination[2][0]); + REQUIRE(0 == destination[2][1]); + } +} diff --git a/test/JsonArray/copyFrom.cpp b/test/JsonArray/copyFrom.cpp deleted file mode 100644 index 0f83c877..00000000 --- a/test/JsonArray/copyFrom.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2019 -// MIT License - -#include -#include - -TEST_CASE("JsonArray::copyFrom()") { - SECTION("OneDimension") { - DynamicJsonDocument doc(4096); - JsonArray array = doc.to(); - char json[32]; - int source[] = {1, 2, 3}; - - bool ok = array.copyFrom(source); - REQUIRE(ok); - - serializeJson(array, json, sizeof(json)); - REQUIRE(std::string("[1,2,3]") == json); - } - - SECTION("OneDimension_MemoryPoolTooSmall") { - const size_t SIZE = JSON_ARRAY_SIZE(2); - StaticJsonDocument doc; - JsonArray array = doc.to(); - char json[32]; - int source[] = {1, 2, 3}; - - bool ok = array.copyFrom(source); - REQUIRE_FALSE(ok); - - serializeJson(array, json, sizeof(json)); - REQUIRE(std::string("[1,2]") == json); - } - - SECTION("TwoDimensions") { - DynamicJsonDocument doc(4096); - JsonArray array = doc.to(); - char json[32]; - int source[][3] = {{1, 2, 3}, {4, 5, 6}}; - - bool ok = array.copyFrom(source); - REQUIRE(ok); - - serializeJson(array, json, sizeof(json)); - REQUIRE(std::string("[[1,2,3],[4,5,6]]") == json); - } - - SECTION("TwoDimensions_MemoryPoolTooSmall") { - const size_t SIZE = - JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2); - StaticJsonDocument doc; - JsonArray array = doc.to(); - char json[32] = ""; - int source[][3] = {{1, 2, 3}, {4, 5, 6}}; - - CAPTURE(SIZE) - - bool ok = array.copyFrom(source); - CAPTURE(doc.memoryUsage()); - CHECK_FALSE(ok); - - serializeJson(array, json, sizeof(json)); - REQUIRE(std::string("[[1,2,3],[4,5]]") == json); - } -} diff --git a/test/JsonArray/copyTo.cpp b/test/JsonArray/copyTo.cpp deleted file mode 100644 index f565a157..00000000 --- a/test/JsonArray/copyTo.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// ArduinoJson - arduinojson.org -// Copyright Benoit Blanchon 2014-2019 -// MIT License - -#include -#include - -TEST_CASE("JsonArray::copyTo()") { - DynamicJsonDocument doc(4096); - - SECTION("BiggerOneDimensionIntegerArray") { - char json[] = "[1,2,3]"; - DeserializationError err = deserializeJson(doc, json); - REQUIRE(err == DeserializationError::Ok); - JsonArray array = doc.as(); - - int destination[4] = {0}; - size_t result = array.copyTo(destination); - - REQUIRE(3 == result); - REQUIRE(1 == destination[0]); - REQUIRE(2 == destination[1]); - REQUIRE(3 == destination[2]); - REQUIRE(0 == destination[3]); - } - - SECTION("SmallerOneDimensionIntegerArray") { - char json[] = "[1,2,3]"; - DeserializationError err = deserializeJson(doc, json); - REQUIRE(err == DeserializationError::Ok); - JsonArray array = doc.as(); - - int destination[2] = {0}; - size_t result = array.copyTo(destination); - - REQUIRE(2 == result); - REQUIRE(1 == destination[0]); - REQUIRE(2 == destination[1]); - } - - SECTION("TwoOneDimensionIntegerArray") { - char json[] = "[[1,2],[3],[4]]"; - - DeserializationError err = deserializeJson(doc, json); - REQUIRE(err == DeserializationError::Ok); - JsonArray array = doc.as(); - - int destination[3][2] = {{0}}; - array.copyTo(destination); - - REQUIRE(1 == destination[0][0]); - REQUIRE(2 == destination[0][1]); - REQUIRE(3 == destination[1][0]); - REQUIRE(0 == destination[1][1]); - REQUIRE(4 == destination[2][0]); - REQUIRE(0 == destination[2][1]); - } -} diff --git a/test/JsonObject/copy.cpp b/test/JsonObject/copy.cpp index 26f34e73..f008d119 100644 --- a/test/JsonObject/copy.cpp +++ b/test/JsonObject/copy.cpp @@ -5,7 +5,7 @@ #include #include -TEST_CASE("JsonObject::copyFrom()") { +TEST_CASE("JsonObject::set()") { DynamicJsonDocument doc1(4096); DynamicJsonDocument doc2(4096); @@ -15,7 +15,7 @@ TEST_CASE("JsonObject::copyFrom()") { SECTION("doesn't copy static string in key or value") { obj1["hello"] = "world"; - obj2.copyFrom(obj1); + obj2.set(obj1); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); @@ -24,7 +24,7 @@ TEST_CASE("JsonObject::copyFrom()") { SECTION("copy local string value") { obj1["hello"] = std::string("world"); - obj2.copyFrom(obj1); + obj2.set(obj1); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); @@ -33,7 +33,7 @@ TEST_CASE("JsonObject::copyFrom()") { SECTION("copy local key") { obj1[std::string("hello")] = "world"; - obj2.copyFrom(obj1); + obj2.set(obj1); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); @@ -42,7 +42,7 @@ TEST_CASE("JsonObject::copyFrom()") { SECTION("copy string from deserializeJson()") { deserializeJson(doc1, "{'hello':'world'}"); - obj2.copyFrom(obj1); + obj2.set(obj1); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); @@ -51,7 +51,7 @@ TEST_CASE("JsonObject::copyFrom()") { SECTION("copy string from deserializeMsgPack()") { deserializeMsgPack(doc1, "\x81\xA5hello\xA5world"); - obj2.copyFrom(obj1); + obj2.set(obj1); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world")); @@ -60,7 +60,7 @@ TEST_CASE("JsonObject::copyFrom()") { SECTION("should work with JsonObjectConst") { obj1["hello"] = "world"; - obj2.copyFrom(static_cast(obj1)); + obj2.set(static_cast(obj1)); REQUIRE(doc1.memoryUsage() == doc2.memoryUsage()); REQUIRE(obj2["hello"] == std::string("world"));