Эх сурвалжийг харах

Remove `JsonDocument::capacity()`

Benoit Blanchon 2 жил өмнө
parent
commit
c4b879645a

+ 1 - 0
CHANGELOG.md

@@ -10,3 +10,4 @@ HEAD
 * Merge `DynamicJsonDocument` with `JsonDocument`
 * Remove `JSON_ARRAY_SIZE()`, `JSON_OBJECT_SIZE()`, and `JSON_STRING_SIZE()`
 * Remove `ARDUINOJSON_ENABLE_STRING_DEDUPLICATION` (string deduplication cannot be enabled anymore)
+* Remove `JsonDocument::capacity()`

+ 0 - 1
extras/tests/JsonDocument/CMakeLists.txt

@@ -5,7 +5,6 @@
 add_executable(JsonDocumentTests
 	add.cpp
 	assignment.cpp
-	capacity.cpp
 	cast.cpp
 	compare.cpp
 	constructor.cpp

+ 0 - 10
extras/tests/JsonDocument/assignment.cpp

@@ -22,7 +22,6 @@ TEST_CASE("JsonDocument assignment") {
       doc2 = doc1;
 
       REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
-      REQUIRE(doc2.capacity() == doc1.capacity());
     }
     REQUIRE(spyingAllocator.log() == AllocatorLog()
                                          << AllocatorLog::Allocate(1024)
@@ -40,7 +39,6 @@ TEST_CASE("JsonDocument assignment") {
       doc2 = doc1;
 
       REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
-      REQUIRE(doc2.capacity() == doc1.capacity());
     }
     REQUIRE(spyingAllocator.log() == AllocatorLog()
                                          << AllocatorLog::Allocate(4096)
@@ -60,7 +58,6 @@ TEST_CASE("JsonDocument assignment") {
       doc2 = doc1;
 
       REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
-      REQUIRE(doc2.capacity() == doc1.capacity());
     }
     REQUIRE(spyingAllocator.log() == AllocatorLog()
                                          << AllocatorLog::Allocate(1024)
@@ -81,8 +78,6 @@ TEST_CASE("JsonDocument assignment") {
 
       REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
       REQUIRE(doc1.as<std::string>() == "null");
-      REQUIRE(doc1.capacity() == 0);
-      REQUIRE(doc2.capacity() == 4096);
     }
     REQUIRE(spyingAllocator.log() == AllocatorLog()
                                          << AllocatorLog::Allocate(4096)
@@ -100,7 +95,6 @@ TEST_CASE("JsonDocument assignment") {
     doc2 = obj;
 
     REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
-    REQUIRE(doc2.capacity() == 4096);
   }
 
   SECTION("Assign from JsonArray") {
@@ -112,7 +106,6 @@ TEST_CASE("JsonDocument assignment") {
     doc2 = arr;
 
     REQUIRE(doc2.as<std::string>() == "[\"hello\"]");
-    REQUIRE(doc2.capacity() == 4096);
   }
 
   SECTION("Assign from JsonVariant") {
@@ -123,7 +116,6 @@ TEST_CASE("JsonDocument assignment") {
     doc2 = doc1.as<JsonVariant>();
 
     REQUIRE(doc2.as<std::string>() == "42");
-    REQUIRE(doc2.capacity() == 4096);
   }
 
   SECTION("Assign from MemberProxy") {
@@ -134,7 +126,6 @@ TEST_CASE("JsonDocument assignment") {
     doc2 = doc1["value"];
 
     REQUIRE(doc2.as<std::string>() == "42");
-    REQUIRE(doc2.capacity() == 4096);
   }
 
   SECTION("Assign from ElementProxy") {
@@ -145,6 +136,5 @@ TEST_CASE("JsonDocument assignment") {
     doc2 = doc1[0];
 
     REQUIRE(doc2.as<std::string>() == "42");
-    REQUIRE(doc2.capacity() == 4096);
   }
 }

+ 0 - 22
extras/tests/JsonDocument/capacity.cpp

@@ -1,22 +0,0 @@
-// ArduinoJson - https://arduinojson.org
-// Copyright © 2014-2023, Benoit BLANCHON
-// MIT License
-
-#include <ArduinoJson.h>
-#include <catch.hpp>
-
-TEST_CASE("JsonDocument") {
-  JsonDocument doc(4096);
-
-  SECTION("capacity()") {
-    SECTION("matches constructor argument") {
-      JsonDocument doc2(256);
-      REQUIRE(doc2.capacity() == 256);
-    }
-
-    SECTION("rounds up constructor argument") {
-      JsonDocument doc2(253);
-      REQUIRE(doc2.capacity() == 256);
-    }
-  }
-}

+ 11 - 11
extras/tests/JsonDocument/constructor.cpp

@@ -28,7 +28,6 @@ TEST_CASE("JsonDocument constructor") {
 
       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(doc2.capacity() == 4096);
     }
     REQUIRE(spyingAllocator.log() == AllocatorLog()
                                          << AllocatorLog::Allocate(4096)
@@ -46,8 +45,6 @@ TEST_CASE("JsonDocument constructor") {
 
       REQUIRE(doc2.as<std::string>() == "The size of this string is 32!!");
       REQUIRE(doc1.as<std::string>() == "null");
-      REQUIRE(doc1.capacity() == 0);
-      REQUIRE(doc2.capacity() == 4096);
     }
     REQUIRE(spyingAllocator.log() == AllocatorLog()
                                          << AllocatorLog::Allocate(4096)
@@ -59,10 +56,11 @@ TEST_CASE("JsonDocument constructor") {
     JsonObject obj = doc1.to<JsonObject>();
     obj["hello"] = "world";
 
-    JsonDocument doc2 = obj;
+    JsonDocument doc2(obj, &spyingAllocator);
 
     REQUIRE(doc2.as<std::string>() == "{\"hello\":\"world\"}");
-    REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
+    REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Allocate(
+                                         addPadding(doc1.memoryUsage())));
   }
 
   SECTION("Construct from JsonArray") {
@@ -70,19 +68,21 @@ TEST_CASE("JsonDocument constructor") {
     JsonArray arr = doc1.to<JsonArray>();
     arr.add("hello");
 
-    JsonDocument doc2 = arr;
+    JsonDocument doc2(arr, &spyingAllocator);
 
     REQUIRE(doc2.as<std::string>() == "[\"hello\"]");
-    REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
+    REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Allocate(
+                                         addPadding(doc1.memoryUsage())));
   }
 
   SECTION("Construct from JsonVariant") {
     JsonDocument doc1(200);
-    deserializeJson(doc1, "42");
+    deserializeJson(doc1, "\"hello\"");
 
-    JsonDocument doc2 = doc1.as<JsonVariant>();
+    JsonDocument doc2(doc1.as<JsonVariant>(), &spyingAllocator);
 
-    REQUIRE(doc2.as<std::string>() == "42");
-    REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
+    REQUIRE(doc2.as<std::string>() == "hello");
+    REQUIRE(spyingAllocator.log() == AllocatorLog() << AllocatorLog::Allocate(
+                                         addPadding(doc1.memoryUsage())));
   }
 }

+ 10 - 6
extras/tests/JsonDocument/garbageCollect.cpp

@@ -12,13 +12,12 @@
 using ArduinoJson::detail::sizeofObject;
 
 TEST_CASE("JsonDocument::garbageCollect()") {
-  SpyingAllocator spyingAllocator;
   ControllableAllocator controllableAllocator;
-  JsonDocument doc(4096, &controllableAllocator);
+  SpyingAllocator spyingAllocator(&controllableAllocator);
+  JsonDocument doc(4096, &spyingAllocator);
 
   SECTION("when allocation succeeds") {
     deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
-    REQUIRE(doc.capacity() == 4096);
     REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16);
     doc.remove("blanket");
 
@@ -26,13 +25,15 @@ TEST_CASE("JsonDocument::garbageCollect()") {
 
     REQUIRE(result == true);
     REQUIRE(doc.memoryUsage() == sizeofObject(1) + 8);
-    REQUIRE(doc.capacity() == 4096);
     REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
+    REQUIRE(spyingAllocator.log() == AllocatorLog()
+                                         << AllocatorLog::Allocate(4096)
+                                         << AllocatorLog::Allocate(4096)
+                                         << AllocatorLog::Deallocate(4096));
   }
 
   SECTION("when allocation fails") {
     deserializeJson(doc, "{\"blanket\":1,\"dancing\":2}");
-    REQUIRE(doc.capacity() == 4096);
     REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16);
     doc.remove("blanket");
     controllableAllocator.disable();
@@ -41,7 +42,10 @@ TEST_CASE("JsonDocument::garbageCollect()") {
 
     REQUIRE(result == false);
     REQUIRE(doc.memoryUsage() == sizeofObject(2) + 16);
-    REQUIRE(doc.capacity() == 4096);
     REQUIRE(doc.as<std::string>() == "{\"dancing\":2}");
+
+    REQUIRE(spyingAllocator.log() == AllocatorLog()
+                                         << AllocatorLog::Allocate(4096)
+                                         << AllocatorLog::AllocateFail(4096));
   }
 }

+ 102 - 31
extras/tests/JsonDocument/shrinkToFit.cpp

@@ -8,8 +8,11 @@
 #include <stdlib.h>  // malloc, free
 #include <string>
 
+#include "Allocators.hpp"
+
 using ArduinoJson::detail::sizeofArray;
 using ArduinoJson::detail::sizeofObject;
+using ArduinoJson::detail::sizeofString;
 
 class ArmoredAllocator : public Allocator {
  public:
@@ -46,87 +49,153 @@ class ArmoredAllocator : public Allocator {
   size_t _size;
 };
 
-void testShrinkToFit(JsonDocument& doc, std::string expected_json,
-                     size_t expected_size) {
-  // test twice: shrinkToFit() should be idempotent
-  for (int i = 0; i < 2; i++) {
-    doc.shrinkToFit();
-
-    REQUIRE(doc.capacity() == expected_size);
-    REQUIRE(doc.memoryUsage() == expected_size);
-
-    std::string json;
-    serializeJson(doc, json);
-    REQUIRE(json == expected_json);
-  }
-}
-
 TEST_CASE("JsonDocument::shrinkToFit()") {
   ArmoredAllocator armoredAllocator;
-  JsonDocument doc(4096, &armoredAllocator);
+  SpyingAllocator spyingAllocator(&armoredAllocator);
+  JsonDocument doc(4096, &spyingAllocator);
 
   SECTION("null") {
-    testShrinkToFit(doc, "null", 0);
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "null");
+    REQUIRE(spyingAllocator.log() == AllocatorLog()
+                                         << AllocatorLog::Allocate(4096)
+                                         << AllocatorLog::Reallocate(4096, 0));
   }
 
   SECTION("empty object") {
     deserializeJson(doc, "{}");
-    testShrinkToFit(doc, "{}", sizeofObject(0));
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "{}");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(4096, sizeofObject(0)));
   }
 
   SECTION("empty array") {
     deserializeJson(doc, "[]");
-    testShrinkToFit(doc, "[]", sizeofArray(0));
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "[]");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(4096, sizeofArray(0)));
   }
 
   SECTION("linked string") {
     doc.set("hello");
-    testShrinkToFit(doc, "\"hello\"", 0);
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "hello");
+    REQUIRE(spyingAllocator.log() == AllocatorLog()
+                                         << AllocatorLog::Allocate(4096)
+                                         << AllocatorLog::Reallocate(4096, 0));
   }
 
   SECTION("owned string") {
     doc.set(std::string("abcdefg"));
-    testShrinkToFit(doc, "\"abcdefg\"", 8);
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "abcdefg");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(4096, sizeofString(7)));
   }
 
   SECTION("linked raw") {
     doc.set(serialized("[{},123]"));
-    testShrinkToFit(doc, "[{},123]", 0);
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "[{},123]");
+    REQUIRE(spyingAllocator.log() == AllocatorLog()
+                                         << AllocatorLog::Allocate(4096)
+                                         << AllocatorLog::Reallocate(4096, 0));
   }
 
   SECTION("owned raw") {
     doc.set(serialized(std::string("[{},12]")));
-    testShrinkToFit(doc, "[{},12]", 8);
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "[{},12]");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(4096, sizeofString(7)));
   }
 
   SECTION("linked key") {
     doc["key"] = 42;
-    testShrinkToFit(doc, "{\"key\":42}", sizeofObject(1));
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "{\"key\":42}");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(4096, sizeofObject(1)));
   }
 
   SECTION("owned key") {
     doc[std::string("abcdefg")] = 42;
-    testShrinkToFit(doc, "{\"abcdefg\":42}", sizeofObject(1) + 8);
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "{\"abcdefg\":42}");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(
+                                  4096, sizeofObject(1) + sizeofString(7)));
   }
 
   SECTION("linked string in array") {
     doc.add("hello");
-    testShrinkToFit(doc, "[\"hello\"]", sizeofArray(1));
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "[\"hello\"]");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(4096, sizeofArray(1)));
   }
 
   SECTION("owned string in array") {
     doc.add(std::string("abcdefg"));
-    testShrinkToFit(doc, "[\"abcdefg\"]", sizeofArray(1) + 8);
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "[\"abcdefg\"]");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(
+                                  4096, sizeofArray(1) + sizeofString(7)));
   }
 
   SECTION("linked string in object") {
     doc["key"] = "hello";
-    testShrinkToFit(doc, "{\"key\":\"hello\"}", sizeofObject(1));
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "{\"key\":\"hello\"}");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(4096, sizeofObject(1)));
   }
 
   SECTION("owned string in object") {
     doc["key"] = std::string("abcdefg");
-    testShrinkToFit(doc, "{\"key\":\"abcdefg\"}", sizeofArray(1) + 8);
+
+    doc.shrinkToFit();
+
+    REQUIRE(doc.as<std::string>() == "{\"key\":\"abcdefg\"}");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(
+                                  4096, sizeofObject(1) + sizeofString(7)));
   }
 
   SECTION("unaligned") {
@@ -136,8 +205,10 @@ TEST_CASE("JsonDocument::shrinkToFit()") {
     doc.shrinkToFit();
 
     // the new capacity should be padded to align the pointers
-    REQUIRE(doc.capacity() == sizeofObject(1) + sizeof(void*));
-    REQUIRE(doc.memoryUsage() == sizeofObject(1) + 2);
     REQUIRE(doc[0] == "?");
+    REQUIRE(spyingAllocator.log() ==
+            AllocatorLog() << AllocatorLog::Allocate(4096)
+                           << AllocatorLog::Reallocate(
+                                  4096, sizeofArray(1) + sizeof(void*)));
   }
 }

+ 0 - 2
extras/tests/JsonDocument/swap.cpp

@@ -19,9 +19,7 @@ TEST_CASE("std::swap") {
 
     swap(doc1, doc2);
 
-    CHECK(doc1.capacity() == 0x20);
     CHECK(doc1.as<string>() == "world");
-    CHECK(doc2.capacity() == 0x10);
     CHECK(doc2.as<string>() == "hello");
   }
 }

+ 6 - 11
src/ArduinoJson/Document/JsonDocument.hpp

@@ -28,7 +28,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
 
   // Copy-constructor
   JsonDocument(const JsonDocument& src)
-      : JsonDocument(src.capacity(), src.allocator()) {
+      : JsonDocument(src._pool.capacity(), src.allocator()) {
     set(src);
   }
 
@@ -41,6 +41,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
   // Construct from variant, array, or object
   template <typename T>
   JsonDocument(const T& src,
+               Allocator* alloc = detail::DefaultAllocator::instance(),
                typename detail::enable_if<
                    detail::is_same<T, JsonVariant>::value ||
                    detail::is_same<T, JsonVariantConst>::value ||
@@ -48,7 +49,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
                    detail::is_same<T, JsonArrayConst>::value ||
                    detail::is_same<T, JsonObject>::value ||
                    detail::is_same<T, JsonObjectConst>::value>::type* = 0)
-      : JsonDocument(src.memoryUsage()) {
+      : JsonDocument(src.memoryUsage(), alloc) {
     set(src);
   }
 
@@ -73,7 +74,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
   template <typename T>
   JsonDocument& operator=(const T& src) {
     size_t requiredSize = src.memoryUsage();
-    if (requiredSize > capacity())
+    if (requiredSize > _pool.capacity())
       _pool.reallocPool(requiredSize);
     set(src);
     return *this;
@@ -94,7 +95,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
   bool garbageCollect() {
     // make a temporary clone and move assign
     JsonDocument tmp(*this);
-    if (!tmp.capacity())
+    if (!tmp._pool.capacity())
       return false;
     tmp.set(*this);
     moveAssignFrom(tmp);
@@ -160,12 +161,6 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
     return variantNesting(&_data);
   }
 
-  // Returns the capacity of the memory pool.
-  // https://arduinojson.org/v6/api/jsondocument/capacity/
-  size_t capacity() const {
-    return _pool.capacity();
-  }
-
   // Returns the number of elements in the root array or object.
   // https://arduinojson.org/v6/api/jsondocument/size/
   size_t size() const {
@@ -364,7 +359,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
   }
 
   void copyAssignFrom(const JsonDocument& src) {
-    _pool.reallocPool(src.capacity());
+    _pool.reallocPool(src._pool.capacity());
     set(src);
   }