Bläddra i källkod

Added move-constructor and move-assignment to `BasicJsonDocument`

Benoit Blanchon 6 år sedan
förälder
incheckning
2540b4e01b

+ 1 - 0
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)
 -------

+ 63 - 1
extras/tests/JsonDocument/BasicJsonDocument.cpp

@@ -8,6 +8,7 @@
 #include <sstream>
 
 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<std::string>() == "The size of this string is 32!!");
+      REQUIRE(doc2.as<std::string>() == "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<std::string>() == "The size of this string is 32!!");
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+      REQUIRE(doc1.as<std::string>() == "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<std::string>() == "The size of this string is 32!!");
+      REQUIRE(doc2.as<std::string>() == "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<std::string>() == "The size of this string is 32!!");
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+      REQUIRE(doc1.as<std::string>() == "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
   }
 }

+ 2 - 0
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?

+ 19 - 0
src/ArduinoJson/Document/BasicJsonDocument.hpp

@@ -52,6 +52,14 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
     set(src);
   }
 
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+  BasicJsonDocument(BasicJsonDocument&& src)
+      : AllocatorOwner<TAllocator>(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<TAllocator>, 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 <typename T>
   BasicJsonDocument& operator=(const T& src) {
     reallocPoolIfTooSmall(src.memoryUsage());

+ 13 - 1
src/ArduinoJson/Polyfills/utility.hpp

@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <ArduinoJson/Namespace.hpp>
+#include "type_traits.hpp"
 
 namespace ARDUINOJSON_NAMESPACE {
 template <typename T>
@@ -13,4 +13,16 @@ inline void swap(T& a, T& b) {
   a = b;
   b = t;
 }
+
+#if ARDUINOJSON_HAS_RVALUE_REFERENCES
+template <typename T>
+typename remove_reference<T>::type&& move(T&& t) {
+  return static_cast<typename remove_reference<T>::type&&>(t);
+}
+#else
+template <typename T>
+T& move(T& t) {
+  return t;
+}
+#endif
 }  // namespace ARDUINOJSON_NAMESPACE