Sfoglia il codice sorgente

Inverted dependency between MemoryPool and string adapters.
Inserted a null after each raw string in the pool.

Benoit Blanchon 5 anni fa
parent
commit
04c59985a1

+ 2 - 2
extras/tests/JsonArray/add.cpp

@@ -102,13 +102,13 @@ TEST_CASE("JsonArray::add()") {
 
   SECTION("should duplicate char*") {
     array.add(const_cast<char*>("world"));
-    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 
   SECTION("should duplicate std::string") {
     array.add(std::string("world"));
-    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 

+ 2 - 2
extras/tests/JsonArray/subscript.cpp

@@ -119,13 +119,13 @@ TEST_CASE("JsonArray::operator[]") {
 
   SECTION("should duplicate char*") {
     array[0] = const_cast<char*>("world");
-    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 
   SECTION("should duplicate std::string") {
     array[0] = std::string("world");
-    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 

+ 1 - 1
extras/tests/JsonDeserializer/array_static.cpp

@@ -56,7 +56,7 @@ TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
 
     deserializeJson(doc, "  [ \"1234567\" ] ");
 
-    REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(8) == doc.memoryUsage());
+    REQUIRE(JSON_ARRAY_SIZE(1) + JSON_STRING_SIZE(7) == doc.memoryUsage());
     // note: we use a string of 8 bytes to be sure that the StaticMemoryPool
     // will not insert bytes to enforce alignement
   }

+ 2 - 2
extras/tests/JsonDocument/shrinkToFit.cpp

@@ -94,8 +94,8 @@ TEST_CASE("BasicJsonDocument::shrinkToFit()") {
   }
 
   SECTION("owned raw") {
-    doc.set(serialized(std::string("[{},123]")));
-    testShrinkToFit(doc, "[{},123]", 8);
+    doc.set(serialized(std::string("[{},12]")));
+    testShrinkToFit(doc, "[{},12]", 8);
   }
 
   SECTION("linked key") {

+ 7 - 7
extras/tests/JsonObject/subscript.cpp

@@ -107,43 +107,43 @@ TEST_CASE("JsonObject::operator[]") {
 
   SECTION("should duplicate char* value") {
     obj["hello"] = const_cast<char*>("world");
-    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 
   SECTION("should duplicate char* key") {
     obj[const_cast<char*>("hello")] = "world";
-    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 
   SECTION("should duplicate char* key&value") {
     obj[const_cast<char*>("hello")] = const_cast<char*>("world");
-    const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(5);
     REQUIRE(expectedSize <= doc.memoryUsage());
   }
 
   SECTION("should duplicate std::string value") {
     obj["hello"] = std::string("world");
-    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 
   SECTION("should duplicate std::string key") {
     obj[std::string("hello")] = "world";
-    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 
   SECTION("should duplicate std::string key&value") {
     obj[std::string("hello")] = std::string("world");
-    const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_OBJECT_SIZE(1) + 2 * JSON_STRING_SIZE(5);
     REQUIRE(expectedSize <= doc.memoryUsage());
   }
 
   SECTION("should duplicate a non-static JsonString key") {
     obj[JsonString("hello", false)] = "world";
-    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(6);
+    const size_t expectedSize = JSON_OBJECT_SIZE(1) + JSON_STRING_SIZE(5);
     REQUIRE(expectedSize == doc.memoryUsage());
   }
 

+ 11 - 11
extras/tests/JsonVariant/copy.cpp

@@ -47,20 +47,20 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
     var1.set(str);
     var2.set(var1);
 
-    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
-    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
+    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
+    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
   }
 
   SECTION("stores std::string by copy") {
     var1.set(std::string("hello!!"));
     var2.set(var1);
 
-    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
-    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
+    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
+    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
   }
 
   SECTION("stores Serialized<const char*> by reference") {
-    var1.set(serialized("hello!!", JSON_STRING_SIZE(8)));
+    var1.set(serialized("hello!!", 8));
     var2.set(var1);
 
     REQUIRE(doc1.memoryUsage() == 0);
@@ -69,18 +69,18 @@ TEST_CASE("JsonVariant::set(JsonVariant)") {
 
   SECTION("stores Serialized<char*> by copy") {
     char str[] = "hello!!";
-    var1.set(serialized(str, 8));
+    var1.set(serialized(str, 7));
     var2.set(var1);
 
-    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
-    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
+    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
+    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
   }
 
   SECTION("stores Serialized<std::string> by copy") {
-    var1.set(serialized(std::string("hello!!!")));
+    var1.set(serialized(std::string("hello!!")));
     var2.set(var1);
 
-    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(8));
-    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(8));
+    REQUIRE(doc1.memoryUsage() == JSON_STRING_SIZE(7));
+    REQUIRE(doc2.memoryUsage() == JSON_STRING_SIZE(7));
   }
 }

+ 1 - 1
extras/tests/MemoryPool/StringBuilder.cpp

@@ -36,6 +36,6 @@ TEST_CASE("StringBuilder") {
     str.append('h');
     str.complete();
 
-    REQUIRE(JSON_STRING_SIZE(2) == pool.size());
+    REQUIRE(JSON_STRING_SIZE(1) == pool.size());
   }
 }

+ 6 - 6
extras/tests/MemoryPool/size.cpp

@@ -30,19 +30,19 @@ TEST_CASE("MemoryPool::size()") {
   SECTION("Decreases after freezeString()") {
     StringSlot a = pool.allocExpandableString();
     pool.freezeString(a, 1);
-    REQUIRE(pool.size() == JSON_STRING_SIZE(1));
+    REQUIRE(pool.size() == 1);
 
     StringSlot b = pool.allocExpandableString();
     pool.freezeString(b, 1);
-    REQUIRE(pool.size() == 2 * JSON_STRING_SIZE(1));
+    REQUIRE(pool.size() == 2);
   }
 
   SECTION("Increases after allocFrozenString()") {
-    pool.allocFrozenString(0);
-    REQUIRE(pool.size() == JSON_STRING_SIZE(0));
+    pool.allocFrozenString(1);
+    REQUIRE(pool.size() == 1);
 
-    pool.allocFrozenString(0);
-    REQUIRE(pool.size() == 2 * JSON_STRING_SIZE(0));
+    pool.allocFrozenString(2);
+    REQUIRE(pool.size() == 3);
   }
 
   SECTION("Doesn't grow when memory pool is full") {

+ 8 - 0
extras/tests/Misc/StringAdapters.cpp

@@ -145,4 +145,12 @@ TEST_CASE("IsString<T>") {
   SECTION("const __FlashStringHelper*") {
     CHECK(IsString<const __FlashStringHelper*>::value == true);
   }
+
+  SECTION("const char*") {
+    CHECK(IsString<const char*>::value == true);
+  }
+
+  SECTION("const char[]") {
+    CHECK(IsString<const char[8]>::value == true);
+  }
 }

+ 3 - 3
extras/tests/MsgPackDeserializer/deserializeStaticVariant.cpp

@@ -7,9 +7,9 @@
 
 template <size_t Capacity>
 static void check(const char* input, DeserializationError expected) {
-  StaticJsonDocument<Capacity> variant;
+  StaticJsonDocument<Capacity> doc;
 
-  DeserializationError error = deserializeMsgPack(variant, input);
+  DeserializationError error = deserializeMsgPack(doc, input);
 
   CAPTURE(input);
   REQUIRE(error == expected);
@@ -17,7 +17,7 @@ static void check(const char* input, DeserializationError expected) {
 
 template <size_t Size>
 static void checkString(const char* input, DeserializationError expected) {
-  check<JSON_STRING_SIZE(Size)>(input, expected);
+  check<Size>(input, expected);
 }
 
 TEST_CASE("deserializeMsgPack(StaticJsonDocument&)") {

+ 13 - 0
src/ArduinoJson/Memory/MemoryPool.hpp

@@ -60,6 +60,19 @@ class MemoryPool {
     return s;
   }
 
+  template <typename TAdaptedString>
+  char* saveString(const TAdaptedString& str) {
+    if (str.isNull())
+      return 0;
+    size_t n = str.size();
+    char* dup = allocFrozenString(n + 1);
+    if (dup) {
+      str.copyTo(dup, n);
+      dup[n] = 0;  // force null-terminator
+    }
+    return dup;
+  }
+
   StringSlot allocExpandableString() {
     StringSlot s;
     s.value = _left;

+ 1 - 1
src/ArduinoJson/Memory/StringSlot.hpp

@@ -8,7 +8,7 @@
 
 #include <ArduinoJson/Namespace.hpp>
 
-#define JSON_STRING_SIZE(SIZE) (SIZE)
+#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
 
 namespace ARDUINOJSON_NAMESPACE {
 

+ 3 - 9
src/ArduinoJson/Strings/ArduinoStringAdapter.hpp

@@ -16,14 +16,8 @@ class ArduinoStringAdapter {
  public:
   ArduinoStringAdapter(const ::String& str) : _str(&str) {}
 
-  char* save(MemoryPool* pool) const {
-    if (isNull())
-      return NULL;
-    size_t n = _str->length() + 1;
-    char* dup = pool->allocFrozenString(n);
-    if (dup)
-      memcpy(dup, _str->c_str(), n);
-    return dup;
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str->c_str(), n);
   }
 
   bool isNull() const {
@@ -45,7 +39,7 @@ class ArduinoStringAdapter {
     return _str->length();
   }
 
-  typedef storage_policy::store_by_copy storage_policy;
+  typedef storage_policies::store_by_copy storage_policy;
 
  private:
   const ::String* _str;

+ 7 - 1
src/ArduinoJson/Strings/ConstRamStringAdapter.hpp

@@ -39,12 +39,18 @@ class ConstRamStringAdapter {
     return _str;
   }
 
-  typedef storage_policy::store_by_address storage_policy;
+  typedef storage_policies::store_by_address storage_policy;
 
  protected:
   const char* _str;
 };
 
+template <>
+struct IsString<const char*> : true_type {};
+
+template <int N>
+struct IsString<const char[N]> : true_type {};
+
 inline ConstRamStringAdapter adaptString(const char* str) {
   return ConstRamStringAdapter(str);
 }

+ 3 - 10
src/ArduinoJson/Strings/FlashStringAdapter.hpp

@@ -4,7 +4,6 @@
 
 #pragma once
 
-#include <ArduinoJson/Memory/MemoryPool.hpp>
 #include <ArduinoJson/Polyfills/pgmspace.hpp>
 #include <ArduinoJson/Strings/IsString.hpp>
 #include <ArduinoJson/Strings/StoragePolicy.hpp>
@@ -33,14 +32,8 @@ class FlashStringAdapter {
     return !_str;
   }
 
-  char* save(MemoryPool* pool) const {
-    if (!_str)
-      return NULL;
-    size_t n = size() + 1;  // copy the terminator
-    char* dup = pool->allocFrozenString(n);
-    if (dup)
-      memcpy_P(dup, reinterpret_cast<const char*>(_str), n);
-    return dup;
+  void copyTo(char* p, size_t n) const {
+    memcpy_P(p, reinterpret_cast<const char*>(_str), n);
   }
 
   size_t size() const {
@@ -49,7 +42,7 @@ class FlashStringAdapter {
     return strlen_P(reinterpret_cast<const char*>(_str));
   }
 
-  typedef storage_policy::store_by_copy storage_policy;
+  typedef storage_policies::store_by_copy storage_policy;
 
  private:
   const __FlashStringHelper* _str;

+ 3 - 10
src/ArduinoJson/Strings/RamStringAdapter.hpp

@@ -4,7 +4,6 @@
 
 #pragma once
 
-#include <ArduinoJson/Memory/MemoryPool.hpp>
 #include <ArduinoJson/Strings/ConstRamStringAdapter.hpp>
 #include <ArduinoJson/Strings/IsString.hpp>
 #include <ArduinoJson/Strings/StoragePolicy.hpp>
@@ -15,17 +14,11 @@ class RamStringAdapter : public ConstRamStringAdapter {
  public:
   RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
 
-  char* save(MemoryPool* pool) const {
-    if (!_str)
-      return NULL;
-    size_t n = size() + 1;
-    char* dup = pool->allocFrozenString(n);
-    if (dup)
-      memcpy(dup, _str, n);
-    return dup;
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str, n);
   }
 
-  typedef ARDUINOJSON_NAMESPACE::storage_policy::store_by_copy storage_policy;
+  typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy;
 };
 
 template <typename TChar>

+ 3 - 8
src/ArduinoJson/Strings/SizedFlashStringAdapter.hpp

@@ -33,20 +33,15 @@ class SizedFlashStringAdapter {
     return !_str;
   }
 
-  char* save(MemoryPool* pool) const {
-    if (!_str)
-      return NULL;
-    char* dup = pool->allocFrozenString(_size);
-    if (dup)
-      memcpy_P(dup, reinterpret_cast<const char*>(_str), _size);
-    return dup;
+  void copyTo(char* p, size_t n) const {
+    memcpy_P(p, reinterpret_cast<const char*>(_str), n);
   }
 
   size_t size() const {
     return _size;
   }
 
-  typedef storage_policy::store_by_copy storage_policy;
+  typedef storage_policies::store_by_copy storage_policy;
 
  private:
   const __FlashStringHelper* _str;

+ 3 - 8
src/ArduinoJson/Strings/SizedRamStringAdapter.hpp

@@ -28,20 +28,15 @@ class SizedRamStringAdapter {
     return !_str;
   }
 
-  char* save(MemoryPool* pool) const {
-    if (!_str)
-      return NULL;
-    char* dup = pool->allocFrozenString(_size);
-    if (dup)
-      memcpy(dup, _str, _size);
-    return dup;
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str, n);
   }
 
   size_t size() const {
     return _size;
   }
 
-  typedef storage_policy::store_by_copy storage_policy;
+  typedef storage_policies::store_by_copy storage_policy;
 
  private:
   const char* _str;

+ 3 - 8
src/ArduinoJson/Strings/StlStringAdapter.hpp

@@ -4,7 +4,6 @@
 
 #pragma once
 
-#include <ArduinoJson/Memory/MemoryPool.hpp>
 #include <ArduinoJson/Namespace.hpp>
 #include <ArduinoJson/Strings/IsString.hpp>
 #include <ArduinoJson/Strings/StoragePolicy.hpp>
@@ -18,12 +17,8 @@ class StlStringAdapter {
  public:
   StlStringAdapter(const TString& str) : _str(&str) {}
 
-  char* save(MemoryPool* pool) const {
-    size_t n = _str->length() + 1;
-    char* dup = pool->allocFrozenString(n);
-    if (dup)
-      memcpy(dup, _str->c_str(), n);
-    return dup;
+  void copyTo(char* p, size_t n) const {
+    memcpy(p, _str->c_str(), n);
   }
 
   bool isNull() const {
@@ -46,7 +41,7 @@ class StlStringAdapter {
     return _str->size();
   }
 
-  typedef storage_policy::store_by_copy storage_policy;
+  typedef storage_policies::store_by_copy storage_policy;
 
  private:
   const TString* _str;

+ 2 - 2
src/ArduinoJson/Strings/StoragePolicy.hpp

@@ -6,10 +6,10 @@
 
 namespace ARDUINOJSON_NAMESPACE {
 
-namespace storage_policy {
+namespace storage_policies {
 struct store_by_address {};
 struct store_by_copy {};
 struct decide_at_runtime {};
-}  // namespace storage_policy
+}  // namespace storage_policies
 
 }  // namespace ARDUINOJSON_NAMESPACE

+ 1 - 7
src/ArduinoJson/Strings/String.hpp

@@ -38,8 +38,6 @@ class String {
     return strcmp(lhs._data, rhs._data) == 0;
   }
 
-  typedef storage_policy::decide_at_runtime storage_policy;
-
  private:
   const char* _data;
   bool _isStatic;
@@ -54,11 +52,7 @@ class StringAdapter : public RamStringAdapter {
     return _isStatic;
   }
 
-  const char* save(MemoryPool* pool) const {
-    if (_isStatic)
-      return data();
-    return RamStringAdapter::save(pool);
-  }
+  typedef storage_policies::decide_at_runtime storage_policy;
 
  private:
   bool _isStatic;

+ 6 - 6
src/ArduinoJson/Variant/SlotFunctions.hpp

@@ -18,17 +18,17 @@ inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
 
 template <typename TAdaptedString>
 inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
-                       storage_policy::decide_at_runtime) {
+                       storage_policies::decide_at_runtime) {
   if (key.isStatic()) {
-    return slotSetKey(var, key, pool, storage_policy::store_by_address());
+    return slotSetKey(var, key, pool, storage_policies::store_by_address());
   } else {
-    return slotSetKey(var, key, pool, storage_policy::store_by_copy());
+    return slotSetKey(var, key, pool, storage_policies::store_by_copy());
   }
 }
 
 template <typename TAdaptedString>
 inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
-                       storage_policy::store_by_address) {
+                       storage_policies::store_by_address) {
   ARDUINOJSON_ASSERT(var);
   var->setLinkedKey(make_not_null(key.data()));
   return true;
@@ -36,8 +36,8 @@ inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
 
 template <typename TAdaptedString>
 inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
-                       storage_policy::store_by_copy) {
-  const char* dup = key.save(pool);
+                       storage_policies::store_by_copy) {
+  const char* dup = pool->saveString(key);
   if (!dup)
     return false;
   ARDUINOJSON_ASSERT(var);

+ 5 - 4
src/ArduinoJson/Variant/VariantData.hpp

@@ -4,6 +4,7 @@
 
 #pragma once
 
+#include <ArduinoJson/Memory/MemoryPool.hpp>
 #include <ArduinoJson/Misc/SerializedValue.hpp>
 #include <ArduinoJson/Numbers/convertNumber.hpp>
 #include <ArduinoJson/Polyfills/gsl/not_null.hpp>
@@ -191,7 +192,7 @@ class VariantData {
 
   template <typename T>
   bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
-    char *dup = adaptString(value.data(), value.size()).save(pool);
+    char *dup = pool->saveString(adaptString(value.data(), value.size()));
     if (dup) {
       setType(VALUE_IS_OWNED_RAW);
       _content.asRaw.data = dup;
@@ -265,9 +266,9 @@ class VariantData {
     }
   }
 
-  template <typename T>
-  bool setOwnedString(T value, MemoryPool *pool) {
-    return setOwnedString(value.save(pool));
+  template <typename TAdaptedString>
+  bool setOwnedString(TAdaptedString value, MemoryPool *pool) {
+    return setOwnedString(pool->saveString(value));
   }
 
   CollectionData &toArray() {

+ 35 - 2
src/ArduinoJson/Variant/VariantFunctions.hpp

@@ -119,11 +119,44 @@ inline bool variantSetOwnedString(VariantData *var, char *value) {
   return true;
 }
 
-template <typename T>
-inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) {
+template <typename TAdaptedString>
+inline bool variantSetOwnedString(VariantData *var, TAdaptedString value,
+                                  MemoryPool *pool) {
   return var != 0 && var->setOwnedString(value, pool);
 }
 
+template <typename TAdaptedString>
+inline bool variantSetString(VariantData *var, TAdaptedString value,
+                             MemoryPool *pool,
+                             storage_policies::decide_at_runtime) {
+  if (value.isStatic())
+    return variantSetString(var, value, pool,
+                            storage_policies::store_by_address());
+  else
+    return variantSetString(var, value, pool,
+                            storage_policies::store_by_copy());
+}
+
+template <typename TAdaptedString>
+inline bool variantSetString(VariantData *var, TAdaptedString value,
+                             MemoryPool *pool) {
+  return variantSetString(var, value, pool,
+                          typename TAdaptedString::storage_policy());
+}
+
+template <typename TAdaptedString>
+inline bool variantSetString(VariantData *var, TAdaptedString value,
+                             MemoryPool *, storage_policies::store_by_address) {
+  return variantSetLinkedString(var, value.data());
+}
+
+template <typename TAdaptedString>
+inline bool variantSetString(VariantData *var, TAdaptedString value,
+                             MemoryPool *pool,
+                             storage_policies::store_by_copy) {
+  return variantSetOwnedString(var, value, pool);
+}
+
 template <typename T>
 inline bool variantSetInteger(VariantData *var, T value) {
   ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);

+ 12 - 8
src/ArduinoJson/Variant/VariantRef.hpp

@@ -10,6 +10,7 @@
 #include <ArduinoJson/Memory/MemoryPool.hpp>
 #include <ArduinoJson/Misc/Visitable.hpp>
 #include <ArduinoJson/Polyfills/type_traits.hpp>
+#include <ArduinoJson/Strings/StringAdapters.hpp>
 #include <ArduinoJson/Variant/VariantAs.hpp>
 #include <ArduinoJson/Variant/VariantFunctions.hpp>
 #include <ArduinoJson/Variant/VariantOperators.hpp>
@@ -213,20 +214,15 @@ class VariantRef : public VariantRefBase<VariantData>,
   FORCE_INLINE bool set(
       const T &value,
       typename enable_if<IsString<T>::value>::type * = 0) const {
-    return variantSetOwnedString(_data, adaptString(value), _pool);
+    return variantSetString(_data, adaptString(value), _pool);
   }
-
   // set(char*)
   // set(const __FlashStringHelper*)
+  // set(const char*)
   template <typename T>
   FORCE_INLINE bool set(
       T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
-    return variantSetOwnedString(_data, adaptString(value), _pool);
-  }
-
-  // set(const char*);
-  FORCE_INLINE bool set(const char *value) const {
-    return variantSetLinkedString(_data, value);
+    return variantSetString(_data, adaptString(value), _pool);
   }
 
   // set(VariantRef)
@@ -247,6 +243,14 @@ class VariantRef : public VariantRefBase<VariantData>,
     return variantSetInteger(_data, static_cast<Integer>(value));
   }
 
+#if ARDUINOJSON_HAS_NULLPTR
+  // set(nullptr_t)
+  FORCE_INLINE bool set(decltype(nullptr)) const {
+    variantSetNull(_data);
+    return true;
+  }
+#endif
+
   template <typename T>
   FORCE_INLINE typename VariantAs<T>::type as() const {
     return variantAs<typename VariantAs<T>::type>(_data, _pool);