From 2540b4e01baa9da5de1a2d009f87dc5b0ab53934 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sun, 1 Mar 2020 17:24:29 +0100 Subject: [PATCH] Added move-constructor and move-assignment to `BasicJsonDocument` --- CHANGELOG.md | 1 + .../tests/JsonDocument/BasicJsonDocument.cpp | 64 ++++++++++++++++++- src/ArduinoJson/Configuration.hpp | 2 + .../Document/BasicJsonDocument.hpp | 19 ++++++ src/ArduinoJson/Polyfills/utility.hpp | 14 +++- 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a307d1d..2e1738a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ HEAD * Fixed `MemberProxy::set(char[])` not duplicating the string (issue #1191) * Fixed enums serialized as booleans (issue #1197) * Fixed incorrect string comparison on some platforms (issue #1198) +* Added move-constructor and move-assignment to `BasicJsonDocument` v6.14.1 (2020-01-27) ------- diff --git a/extras/tests/JsonDocument/BasicJsonDocument.cpp b/extras/tests/JsonDocument/BasicJsonDocument.cpp index 8524c911..07800b00 100644 --- a/extras/tests/JsonDocument/BasicJsonDocument.cpp +++ b/extras/tests/JsonDocument/BasicJsonDocument.cpp @@ -8,6 +8,7 @@ #include using ARDUINOJSON_NAMESPACE::addPadding; +using ARDUINOJSON_NAMESPACE::move; class SpyingAllocator { public: @@ -19,7 +20,7 @@ class SpyingAllocator { return malloc(n); } void deallocate(void* p) { - _log << "F"; + _log << (p ? "F" : "f"); free(p); } @@ -43,8 +44,69 @@ TEST_CASE("BasicJsonDocument") { { MyJsonDocument doc1(4096, log); doc1.set(std::string("The size of this string is 32!!")); + MyJsonDocument doc2(doc1); + + REQUIRE(doc1.as() == "The size of this string is 32!!"); + REQUIRE(doc2.as() == "The size of this string is 32!!"); } REQUIRE(log.str() == "A4096A32FF"); } + + SECTION("Move construct") { + { + MyJsonDocument doc1(4096, log); + doc1.set(std::string("The size of this string is 32!!")); + + MyJsonDocument doc2(move(doc1)); + + REQUIRE(doc2.as() == "The size of this string is 32!!"); +#if ARDUINOJSON_HAS_RVALUE_REFERENCES + REQUIRE(doc1.as() == "null"); + REQUIRE(doc1.capacity() == 0); + REQUIRE(doc2.capacity() == 4096); +#endif + } +#if ARDUINOJSON_HAS_RVALUE_REFERENCES + REQUIRE(log.str() == "A4096Ff"); +#else + REQUIRE(log.str() == "A4096A32FF"); +#endif + } + + SECTION("Copy assign") { + { + MyJsonDocument doc1(4096, log); + doc1.set(std::string("The size of this string is 32!!")); + MyJsonDocument doc2(8, log); + + doc2 = doc1; + + REQUIRE(doc1.as() == "The size of this string is 32!!"); + REQUIRE(doc2.as() == "The size of this string is 32!!"); + } + REQUIRE(log.str() == "A4096A8FA32FF"); + } + + SECTION("Move assign") { + { + MyJsonDocument doc1(4096, log); + doc1.set(std::string("The size of this string is 32!!")); + MyJsonDocument doc2(8, log); + + doc2 = move(doc1); + + REQUIRE(doc2.as() == "The size of this string is 32!!"); +#if ARDUINOJSON_HAS_RVALUE_REFERENCES + REQUIRE(doc1.as() == "null"); + REQUIRE(doc1.capacity() == 0); + REQUIRE(doc2.capacity() == 4096); +#endif + } +#if ARDUINOJSON_HAS_RVALUE_REFERENCES + REQUIRE(log.str() == "A4096A8FFf"); +#else + REQUIRE(log.str() == "A4096A8FA32FF"); +#endif + } } diff --git a/src/ArduinoJson/Configuration.hpp b/src/ArduinoJson/Configuration.hpp index 7eb9c5dc..74ef2e1f 100644 --- a/src/ArduinoJson/Configuration.hpp +++ b/src/ArduinoJson/Configuration.hpp @@ -13,9 +13,11 @@ #if __cplusplus >= 201103L #define ARDUINOJSON_HAS_LONG_LONG 1 #define ARDUINOJSON_HAS_NULLPTR 1 +#define ARDUINOJSON_HAS_RVALUE_REFERENCES 1 #else #define ARDUINOJSON_HAS_LONG_LONG 0 #define ARDUINOJSON_HAS_NULLPTR 0 +#define ARDUINOJSON_HAS_RVALUE_REFERENCES 0 #endif // Small or big machine? diff --git a/src/ArduinoJson/Document/BasicJsonDocument.hpp b/src/ArduinoJson/Document/BasicJsonDocument.hpp index 0550168a..9319ce56 100644 --- a/src/ArduinoJson/Document/BasicJsonDocument.hpp +++ b/src/ArduinoJson/Document/BasicJsonDocument.hpp @@ -52,6 +52,14 @@ class BasicJsonDocument : AllocatorOwner, public JsonDocument { set(src); } +#if ARDUINOJSON_HAS_RVALUE_REFERENCES + BasicJsonDocument(BasicJsonDocument&& src) + : AllocatorOwner(src), JsonDocument(src) { + src._data.setNull(); + src._pool = MemoryPool(0, 0); + } +#endif + // disambiguate BasicJsonDocument(VariantRef src) : JsonDocument(allocPool(src.memoryUsage())) { @@ -68,6 +76,17 @@ class BasicJsonDocument : AllocatorOwner, public JsonDocument { return *this; } +#if ARDUINOJSON_HAS_RVALUE_REFERENCES + BasicJsonDocument& operator=(BasicJsonDocument&& src) { + freePool(); + _data = src._data; + _pool = src._pool; + src._data.setNull(); + src._pool = MemoryPool(0, 0); + return *this; + } +#endif + template BasicJsonDocument& operator=(const T& src) { reallocPoolIfTooSmall(src.memoryUsage()); diff --git a/src/ArduinoJson/Polyfills/utility.hpp b/src/ArduinoJson/Polyfills/utility.hpp index f61f776b..be736350 100644 --- a/src/ArduinoJson/Polyfills/utility.hpp +++ b/src/ArduinoJson/Polyfills/utility.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include "type_traits.hpp" namespace ARDUINOJSON_NAMESPACE { template @@ -13,4 +13,16 @@ inline void swap(T& a, T& b) { a = b; b = t; } + +#if ARDUINOJSON_HAS_RVALUE_REFERENCES +template +typename remove_reference::type&& move(T&& t) { + return static_cast::type&&>(t); +} +#else +template +T& move(T& t) { + return t; +} +#endif } // namespace ARDUINOJSON_NAMESPACE