Jelajahi Sumber

Add `CopiedString` and `LinkedString`

Benoit Blanchon 4 tahun lalu
induk
melakukan
62f9b94ab1

+ 3 - 2
extras/tests/MemoryPool/StringCopier.cpp

@@ -19,7 +19,8 @@ TEST_CASE("StringCopier") {
     str.append('\0');
 
     REQUIRE(str.isValid() == true);
-    REQUIRE(str.c_str() == std::string("hello"));
+    REQUIRE(std::string(str.str()) == "hello");
+    REQUIRE(pool.overflowed() == false);
   }
 
   SECTION("Returns null when too small") {
@@ -49,7 +50,7 @@ static const char* addStringToPool(MemoryPool& pool, const char* s) {
   str.startString();
   str.append(s);
   str.append('\0');
-  return str.save();
+  return str.save().c_str();
 }
 
 TEST_CASE("StringCopier::save() deduplicates strings") {

+ 1 - 1
extras/tests/Misc/Utf8.cpp

@@ -19,7 +19,7 @@ static void testCodepoint(uint32_t codepoint, std::string expected) {
   Utf8::encodeCodepoint(codepoint, str);
 
   str.append('\0');
-  REQUIRE(str.c_str() == expected);
+  REQUIRE(str.str().c_str() == expected);
 }
 
 TEST_CASE("Utf8::encodeCodepoint()") {

+ 5 - 6
src/ArduinoJson/Json/JsonDeserializer.hpp

@@ -231,12 +231,12 @@ class JsonDeserializer {
         return false;
       }
 
-      const char *key = _stringStorage.c_str();
+      typename TStringStorage::string_type key = _stringStorage.str();
 
-      TFilter memberFilter = filter[key];
+      TFilter memberFilter = filter[key.c_str()];
 
       if (memberFilter.allow()) {
-        VariantData *variant = object.getMember(adaptString(key));
+        VariantData *variant = object.getMember(adaptString(key.c_str()));
         if (!variant) {
           // Save key in memory pool.
           // This MUST be done before adding the slot.
@@ -249,7 +249,7 @@ class JsonDeserializer {
             return false;
           }
 
-          slot->setKey(key, typename TStringStorage::storage_policy());
+          slot->setKey(key);
 
           variant = slot->data();
         }
@@ -345,8 +345,7 @@ class JsonDeserializer {
     _stringStorage.startString();
     if (!parseQuotedString())
       return false;
-    const char *value = _stringStorage.save();
-    variant.setStringPointer(value, typename TStringStorage::storage_policy());
+    variant.setString(_stringStorage.save());
     return true;
   }
 

+ 4 - 5
src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp

@@ -331,8 +331,7 @@ class MsgPackDeserializer {
   bool readString(VariantData *variant, size_t n) {
     if (!readString(n))
       return false;
-    variant->setStringPointer(_stringStorage.save(),
-                              typename TStringStorage::storage_policy());
+    variant->setString(_stringStorage.save());
     return true;
   }
 
@@ -419,8 +418,8 @@ class MsgPackDeserializer {
       if (!readKey())
         return false;
 
-      const char *key = _stringStorage.c_str();
-      TFilter memberFilter = filter[key];
+      typename TStringStorage::string_type key = _stringStorage.str();
+      TFilter memberFilter = filter[key.c_str()];
       VariantData *member;
 
       if (memberFilter.allow()) {
@@ -434,7 +433,7 @@ class MsgPackDeserializer {
           return false;
         }
 
-        slot->setKey(key, typename TStringStorage::storage_policy());
+        slot->setKey(key);
 
         member = slot->data();
       } else {

+ 1 - 0
src/ArduinoJson/Polyfills/safe_strcmp.hpp

@@ -7,6 +7,7 @@
 #include <ArduinoJson/Namespace.hpp>
 
 #include <stdint.h>  // int8_t
+#include <string.h>  // strcmp
 
 namespace ARDUINOJSON_NAMESPACE {
 

+ 4 - 4
src/ArduinoJson/StringStorage/StringCopier.hpp

@@ -10,6 +10,8 @@ namespace ARDUINOJSON_NAMESPACE {
 
 class StringCopier {
  public:
+  typedef CopiedString string_type;
+
   StringCopier(MemoryPool& pool) : _pool(&pool) {}
 
   void startString() {
@@ -17,7 +19,7 @@ class StringCopier {
     _size = 0;
   }
 
-  const char* save() {
+  string_type save() {
     ARDUINOJSON_ASSERT(_ptr);
     return _pool->saveStringFromFreeZone(_size);
   }
@@ -47,12 +49,10 @@ class StringCopier {
     return _ptr != 0;
   }
 
-  const char* c_str() {
+  string_type str() const {
     return _ptr;
   }
 
-  typedef storage_policies::store_by_copy storage_policy;
-
  private:
   MemoryPool* _pool;
 

+ 6 - 6
src/ArduinoJson/StringStorage/StringMover.hpp

@@ -5,19 +5,21 @@
 #pragma once
 
 #include <ArduinoJson/Namespace.hpp>
-#include <ArduinoJson/Strings/StoragePolicy.hpp>
+#include <ArduinoJson/Strings/StoredString.hpp>
 
 namespace ARDUINOJSON_NAMESPACE {
 
 class StringMover {
  public:
+  typedef LinkedString string_type;
+
   StringMover(char* ptr) : _writePtr(ptr) {}
 
   void startString() {
     _startPtr = _writePtr;
   }
 
-  const char* save() const {
+  FORCE_INLINE string_type save() {
     return _startPtr;
   }
 
@@ -29,12 +31,10 @@ class StringMover {
     return true;
   }
 
-  const char* c_str() const {
-    return _startPtr;
+  string_type str() const {
+    return string_type(_startPtr);
   }
 
-  typedef storage_policies::store_by_address storage_policy;
-
  private:
   char* _writePtr;
   char* _startPtr;

+ 32 - 0
src/ArduinoJson/Strings/StoredString.hpp

@@ -0,0 +1,32 @@
+// ArduinoJson - https://arduinojson.org
+// Copyright Benoit Blanchon 2014-2021
+// MIT License
+
+#pragma once
+
+#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
+#include <ArduinoJson/Strings/StoragePolicy.hpp>
+
+namespace ARDUINOJSON_NAMESPACE {
+
+template <typename TStoragePolicy>
+class StoredString {
+ public:
+  StoredString(const char* p) : _data(p) {}
+
+  operator const char*() const {
+    return _data;
+  }
+
+  const char* c_str() const {
+    return _data;
+  }
+
+ private:
+  const char* _data;
+};
+
+typedef StoredString<storage_policies::store_by_address> LinkedString;
+typedef StoredString<storage_policies::store_by_copy> CopiedString;
+
+}  // namespace ARDUINOJSON_NAMESPACE

+ 3 - 3
src/ArduinoJson/Variant/ConverterImpl.hpp

@@ -173,7 +173,7 @@ struct Converter<SerializedValue<T>,
     VariantData* data = getData(dst);
     MemoryPool* pool = getPool(dst);
     if (data)
-      data->setOwnedRaw(src, pool);
+      data->storeOwnedRaw(src, pool);
   }
 };
 
@@ -203,7 +203,7 @@ class MemoryPoolPrint : public Print {
     pool->getFreeZone(&_string, &_capacity);
   }
 
-  const char* c_str() {
+  CopiedString str() {
     _string[_size++] = 0;
     ARDUINOJSON_ASSERT(_size <= _capacity);
     return _pool->saveStringFromFreeZone(_size);
@@ -250,7 +250,7 @@ inline void convertToJson(const ::Printable& src, VariantRef dst) {
     data->setNull();
     return;
   }
-  data->setStringPointer(print.c_str(), storage_policies::store_by_copy());
+  data->setString(print.str());
 }
 
 #endif

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

@@ -30,18 +30,18 @@ template <typename TAdaptedString>
 inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool*,
                        storage_policies::store_by_address) {
   ARDUINOJSON_ASSERT(var);
-  var->setKey(key.data(), storage_policies::store_by_address());
+  var->setKey(LinkedString(key.data()));
   return true;
 }
 
 template <typename TAdaptedString>
 inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
                        storage_policies::store_by_copy) {
-  const char* dup = pool->saveString(key);
+  CopiedString dup = pool->saveString(key);
   if (!dup)
     return false;
   ARDUINOJSON_ASSERT(var);
-  var->setKey(dup, storage_policies::store_by_copy());
+  var->setKey(dup);
   return true;
 }
 

+ 13 - 13
src/ArduinoJson/Variant/VariantData.hpp

@@ -104,10 +104,10 @@ class VariantData {
       case VALUE_IS_OBJECT:
         return toObject().copyFrom(src._content.asCollection, pool);
       case VALUE_IS_OWNED_STRING:
-        return setString(adaptString(const_cast<char *>(src._content.asString)),
-                         pool);
+        return storeString(
+            adaptString(const_cast<char *>(src._content.asString)), pool);
       case VALUE_IS_OWNED_RAW:
-        return setOwnedRaw(
+        return storeOwnedRaw(
             serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
       default:
         setType(src.type());
@@ -194,7 +194,7 @@ class VariantData {
   }
 
   template <typename T>
-  bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
+  bool storeOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
     const char *dup = pool->saveString(adaptString(value.data(), value.size()));
     if (dup) {
       setType(VALUE_IS_OWNED_RAW);
@@ -223,20 +223,20 @@ class VariantData {
     setType(VALUE_IS_NULL);
   }
 
-  void setStringPointer(const char *s, storage_policies::store_by_copy) {
-    ARDUINOJSON_ASSERT(s != 0);
+  void setString(CopiedString s) {
+    ARDUINOJSON_ASSERT(s);
     setType(VALUE_IS_OWNED_STRING);
-    _content.asString = s;
+    _content.asString = s.c_str();
   }
 
-  void setStringPointer(const char *s, storage_policies::store_by_address) {
-    ARDUINOJSON_ASSERT(s != 0);
+  void setString(LinkedString s) {
+    ARDUINOJSON_ASSERT(s);
     setType(VALUE_IS_LINKED_STRING);
-    _content.asString = s;
+    _content.asString = s.c_str();
   }
 
   template <typename TAdaptedString>
-  bool setString(TAdaptedString value, MemoryPool *pool) {
+  bool storeString(TAdaptedString value, MemoryPool *pool) {
     return storeString(value, pool, typename TAdaptedString::storage_policy());
   }
 
@@ -342,7 +342,7 @@ class VariantData {
     if (value.isNull())
       setNull();
     else
-      setStringPointer(value.data(), storage_policies::store_by_address());
+      setString(LinkedString(value.data()));
     return true;
   }
 
@@ -358,7 +358,7 @@ class VariantData {
       setNull();
       return false;
     }
-    setStringPointer(copy, storage_policies::store_by_copy());
+    setString(CopiedString(copy));
     return true;
   }
 };

+ 1 - 1
src/ArduinoJson/Variant/VariantFunctions.hpp

@@ -54,7 +54,7 @@ inline bool variantSetString(VariantData *var, TAdaptedString value,
                              MemoryPool *pool) {
   if (!var)
     return false;
-  return var->setString(value, pool);
+  return var->storeString(value, pool);
 }
 
 inline size_t variantSize(const VariantData *var) {

+ 7 - 6
src/ArduinoJson/Variant/VariantSlot.hpp

@@ -8,6 +8,7 @@
 #include <ArduinoJson/Polyfills/limits.hpp>
 #include <ArduinoJson/Polyfills/type_traits.hpp>
 #include <ArduinoJson/Strings/StoragePolicy.hpp>
+#include <ArduinoJson/Strings/StoredString.hpp>
 #include <ArduinoJson/Variant/VariantContent.hpp>
 
 namespace ARDUINOJSON_NAMESPACE {
@@ -77,16 +78,16 @@ class VariantSlot {
     _next = VariantSlotDiff(slot - this);
   }
 
-  void setKey(const char* k, storage_policies::store_by_copy) {
-    ARDUINOJSON_ASSERT(k != NULL);
+  void setKey(CopiedString k) {
+    ARDUINOJSON_ASSERT(k);
     _flags |= OWNED_KEY_BIT;
-    _key = k;
+    _key = k.c_str();
   }
 
-  void setKey(const char* k, storage_policies::store_by_address) {
-    ARDUINOJSON_ASSERT(k != NULL);
+  void setKey(LinkedString k) {
+    ARDUINOJSON_ASSERT(k);
     _flags &= VALUE_MASK;
-    _key = k;
+    _key = k.c_str();
   }
 
   const char* key() const {