diff --git a/extras/tests/MemoryPool/StringCopier.cpp b/extras/tests/MemoryPool/StringCopier.cpp index 7d6a192b..4d3fdba7 100644 --- a/extras/tests/MemoryPool/StringCopier.cpp +++ b/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") { diff --git a/extras/tests/Misc/Utf8.cpp b/extras/tests/Misc/Utf8.cpp index baff6222..56006c1a 100644 --- a/extras/tests/Misc/Utf8.cpp +++ b/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()") { diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index 1a07be86..d719e10e 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/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; } diff --git a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp index fbeb05df..f4bfe2aa 100644 --- a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp +++ b/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 { diff --git a/src/ArduinoJson/Polyfills/safe_strcmp.hpp b/src/ArduinoJson/Polyfills/safe_strcmp.hpp index e017b5dd..502fe527 100644 --- a/src/ArduinoJson/Polyfills/safe_strcmp.hpp +++ b/src/ArduinoJson/Polyfills/safe_strcmp.hpp @@ -7,6 +7,7 @@ #include #include // int8_t +#include // strcmp namespace ARDUINOJSON_NAMESPACE { diff --git a/src/ArduinoJson/StringStorage/StringCopier.hpp b/src/ArduinoJson/StringStorage/StringCopier.hpp index 80670aad..3666a98d 100644 --- a/src/ArduinoJson/StringStorage/StringCopier.hpp +++ b/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; diff --git a/src/ArduinoJson/StringStorage/StringMover.hpp b/src/ArduinoJson/StringStorage/StringMover.hpp index f727a7d8..b2b8da8a 100644 --- a/src/ArduinoJson/StringStorage/StringMover.hpp +++ b/src/ArduinoJson/StringStorage/StringMover.hpp @@ -5,19 +5,21 @@ #pragma once #include -#include +#include 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; diff --git a/src/ArduinoJson/Strings/StoredString.hpp b/src/ArduinoJson/Strings/StoredString.hpp new file mode 100644 index 00000000..3682a280 --- /dev/null +++ b/src/ArduinoJson/Strings/StoredString.hpp @@ -0,0 +1,32 @@ +// ArduinoJson - https://arduinojson.org +// Copyright Benoit Blanchon 2014-2021 +// MIT License + +#pragma once + +#include +#include + +namespace ARDUINOJSON_NAMESPACE { + +template +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 LinkedString; +typedef StoredString CopiedString; + +} // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Variant/ConverterImpl.hpp b/src/ArduinoJson/Variant/ConverterImpl.hpp index d282d8e2..fe7e3dcf 100644 --- a/src/ArduinoJson/Variant/ConverterImpl.hpp +++ b/src/ArduinoJson/Variant/ConverterImpl.hpp @@ -173,7 +173,7 @@ struct Converter, 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 diff --git a/src/ArduinoJson/Variant/SlotFunctions.hpp b/src/ArduinoJson/Variant/SlotFunctions.hpp index 74ac5a78..4b89c5b8 100644 --- a/src/ArduinoJson/Variant/SlotFunctions.hpp +++ b/src/ArduinoJson/Variant/SlotFunctions.hpp @@ -30,18 +30,18 @@ template 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 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; } diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index cd0b3277..a376d2b1 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/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(src._content.asString)), - pool); + return storeString( + adaptString(const_cast(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 - bool setOwnedRaw(SerializedValue value, MemoryPool *pool) { + bool storeOwnedRaw(SerializedValue 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 - 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; } }; diff --git a/src/ArduinoJson/Variant/VariantFunctions.hpp b/src/ArduinoJson/Variant/VariantFunctions.hpp index 3fc9cbbc..397a96bf 100644 --- a/src/ArduinoJson/Variant/VariantFunctions.hpp +++ b/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) { diff --git a/src/ArduinoJson/Variant/VariantSlot.hpp b/src/ArduinoJson/Variant/VariantSlot.hpp index a271c1ee..80c6b768 100644 --- a/src/ArduinoJson/Variant/VariantSlot.hpp +++ b/src/ArduinoJson/Variant/VariantSlot.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include 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 {