From 184a7c4fbdddc58bb95f93505d61710ff409117a Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Mon, 20 Dec 2021 17:51:27 +0100 Subject: [PATCH] Add support for arbitrary array rank in `copyArray()` --- CHANGELOG.md | 1 + src/ArduinoJson/Array/Utilities.hpp | 140 ++++++++---------------- src/ArduinoJson/Json/JsonSerializer.hpp | 1 + 3 files changed, 48 insertions(+), 94 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97e696db..90a61303 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ HEAD * Add `as()` and `is()` * Add safe bool idiom in `JsonString` * Add support for NUL in string values (issue #1646) +* Add support for arbitrary array rank in `copyArray()` * Remove `DeserializationError == bool` and `DeserializationError != bool` * Renamed undocumented function `isUndefined()` to `isUnbound()` * Fix `JsonVariant::memoryUsage()` for raw strings diff --git a/src/ArduinoJson/Array/Utilities.hpp b/src/ArduinoJson/Array/Utilities.hpp index 619b91d8..5d7f5a04 100644 --- a/src/ArduinoJson/Array/Utilities.hpp +++ b/src/ArduinoJson/Array/Utilities.hpp @@ -6,128 +6,80 @@ #include #include -#include namespace ARDUINOJSON_NAMESPACE { -// Copy a 1D array to a JsonArray +// Trivial form to stop the recursion +template +inline typename enable_if::value, bool>::type copyArray( + const T& src, VariantRef dst) { + return dst.set(src); +} + +// Copy array to a JsonArray/JsonVariant/MemberProxy/ElementProxy template -inline typename enable_if::value && - !is_base_of::value, +inline typename enable_if::value, bool>::type copyArray(T (&src)[N], const TDestination& dst) { return copyArray(src, N, dst); } -// Copy a 1D array to a JsonDocument -template -inline bool copyArray(T (&src)[N], JsonDocument& dst) { - return copyArray(src, dst.to()); -} - -// Copy a 1D array to a JsonArray +// Copy ptr+size to a JsonArray/JsonVariant/MemberProxy/ElementProxy template -inline typename enable_if::value && - !is_base_of::value, +inline typename enable_if::value, bool>::type -copyArray(T* src, size_t len, const TDestination& dst) { +copyArray(const T* src, size_t len, const TDestination& dst) { bool ok = true; for (size_t i = 0; i < len; i++) { - ok &= dst.add(src[i]); + ok &= copyArray(src[i], dst.addElement()); } return ok; } -// Copy a 1D array to a JsonDocument +// Copy array to a JsonDocument template -inline bool copyArray(T* src, size_t len, JsonDocument& dst) { +inline bool copyArray(const T& src, JsonDocument& dst) { + return copyArray(src, dst.to()); +} + +// Copy a ptr+size array to a JsonDocument +template +inline bool copyArray(const T* src, size_t len, JsonDocument& dst) { return copyArray(src, len, dst.to()); } -// Copy a 2D array to a JsonArray -template -inline typename enable_if::value, - bool>::type -copyArray(T (&src)[N1][N2], const TDestination& 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 2D array to a JsonDocument -template -inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) { - return copyArray(src, dst.to()); -} - +// Trivial case form to stop the recursion template -class ArrayCopier1D : public Visitor { - public: - ArrayCopier1D(T* destination, size_t capacity) - : _destination(destination), _capacity(capacity) {} - - size_t visitArray(const CollectionData& array) { - size_t size = 0; - VariantSlot* slot = array.head(); - - while (slot != 0 && size < _capacity) { - _destination[size++] = - Converter::fromJson(VariantConstRef(slot->data())); - slot = slot->next(); - } - return size; - } - - private: - T* _destination; - size_t _capacity; -}; - -template -class ArrayCopier2D : public Visitor { - public: - ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {} - - void visitArray(const CollectionData& array) { - VariantSlot* slot = array.head(); - size_t n = 0; - while (slot != 0 && n < N1) { - ArrayCopier1D copier((*_destination)[n++], N2); - variantAccept(slot->data(), copier); - slot = slot->next(); - } - } - - private: - T (*_destination)[N1][N2]; - size_t _capacity1, _capacity2; -}; - -// Copy a JsonArray to a 1D array -template inline typename enable_if::value, size_t>::type copyArray( - const TSource& src, T (&dst)[N]) { + VariantConstRef src, T& dst) { + dst = src.as(); + return 1; +} + +// Copy a JsonArray to 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(const TSource& src, T* dst, size_t len) { - ArrayCopier1D copier(dst, len); - - return src.accept(copier); +// Copy a JsonArray to ptr+size +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) + copyArray(*it, dst[i++]); + return i; } -// Copy a JsonArray to a 2D array -template -inline void copyArray(const TSource& src, T (&dst)[N1][N2]) { - ArrayCopier2D copier(&dst); - src.accept(copier); +// Copy a JsonDocument to an array +// (JsonDocument doesn't implicitly convert to JsonArrayConst) +template +inline typename enable_if::value && + is_base_of::value, + size_t>::type +copyArray(const TSource& src, T& dst) { + return copyArray(src.template as(), dst); } } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Json/JsonSerializer.hpp b/src/ArduinoJson/Json/JsonSerializer.hpp index 942513a4..52715699 100644 --- a/src/ArduinoJson/Json/JsonSerializer.hpp +++ b/src/ArduinoJson/Json/JsonSerializer.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace ARDUINOJSON_NAMESPACE {