From b27990f780eaf3583e7f36aecb6d1ef573a1057e Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 26 Oct 2022 10:37:18 +0200 Subject: [PATCH] Attach copy policy to string adapters --- src/ArduinoJson/Collection/CollectionData.hpp | 9 ++-- src/ArduinoJson/Collection/CollectionImpl.hpp | 17 +++--- src/ArduinoJson/Memory/MemoryPool.hpp | 31 +++++++++++ .../Strings/Adapters/FlashString.hpp | 4 ++ .../Strings/Adapters/JsonString.hpp | 17 +++++- .../Strings/Adapters/RamString.hpp | 28 ++++++++-- src/ArduinoJson/Strings/StoragePolicy.hpp | 53 +++---------------- src/ArduinoJson/Variant/ConverterImpl.hpp | 9 ++-- src/ArduinoJson/Variant/SlotFunctions.hpp | 7 ++- src/ArduinoJson/Variant/VariantData.hpp | 14 +++-- src/ArduinoJson/Variant/VariantFunctions.hpp | 12 ++--- src/ArduinoJson/Variant/VariantImpl.hpp | 13 +---- 12 files changed, 113 insertions(+), 101 deletions(-) diff --git a/src/ArduinoJson/Collection/CollectionData.hpp b/src/ArduinoJson/Collection/CollectionData.hpp index 37bb055b..560e7e33 100644 --- a/src/ArduinoJson/Collection/CollectionData.hpp +++ b/src/ArduinoJson/Collection/CollectionData.hpp @@ -38,15 +38,14 @@ class CollectionData { // Object only - template - VariantData* addMember(TAdaptedString key, MemoryPool* pool, TStoragePolicy); + template + VariantData* addMember(TAdaptedString key, MemoryPool* pool); template VariantData* getMember(TAdaptedString key) const; - template - VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool, - TStoragePolicy); + template + VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool); template void removeMember(TAdaptedString key) { diff --git a/src/ArduinoJson/Collection/CollectionImpl.hpp b/src/ArduinoJson/Collection/CollectionImpl.hpp index da9835e3..634ab594 100644 --- a/src/ArduinoJson/Collection/CollectionImpl.hpp +++ b/src/ArduinoJson/Collection/CollectionImpl.hpp @@ -33,12 +33,11 @@ inline VariantData* CollectionData::addElement(MemoryPool* pool) { return slotData(addSlot(pool)); } -template +template inline VariantData* CollectionData::addMember(TAdaptedString key, - MemoryPool* pool, - TStoragePolicy storage) { + MemoryPool* pool) { VariantSlot* slot = addSlot(pool); - if (!slotSetKey(slot, key, pool, storage)) { + if (!slotSetKey(slot, key, pool)) { removeSlot(slot); return 0; } @@ -62,7 +61,7 @@ inline bool CollectionData::copyFrom(const CollectionData& src, VariantData* var; if (s->key() != 0) { String key(s->key(), s->ownsKey() ? String::Copied : String::Linked); - var = addMember(adaptString(key), pool, getStringStoragePolicy(key)); + var = addMember(adaptString(key), pool); } else { var = addElement(pool); } @@ -110,9 +109,9 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const { return slot ? slot->data() : 0; } -template -inline VariantData* CollectionData::getOrAddMember( - TAdaptedString key, MemoryPool* pool, TStoragePolicy storage_policy) { +template +inline VariantData* CollectionData::getOrAddMember(TAdaptedString key, + MemoryPool* pool) { // ignore null key if (key.isNull()) return 0; @@ -122,7 +121,7 @@ inline VariantData* CollectionData::getOrAddMember( if (slot) return slot->data(); - return addMember(key, pool, storage_policy); + return addMember(key, pool); } inline VariantData* CollectionData::getElement(size_t index) const { diff --git a/src/ArduinoJson/Memory/MemoryPool.hpp b/src/ArduinoJson/Memory/MemoryPool.hpp index 3745bfda..a4b2035a 100644 --- a/src/ArduinoJson/Memory/MemoryPool.hpp +++ b/src/ArduinoJson/Memory/MemoryPool.hpp @@ -208,4 +208,35 @@ class MemoryPool { bool _overflowed; }; +template +bool storeString(MemoryPool* pool, TAdaptedString str, CopyStringStoragePolicy, + TCallback callback) { + const char* copy = pool->saveString(str); + String storedString(copy, str.size(), String::Copied); + callback(storedString); + return copy != 0; +} + +template +bool storeString(MemoryPool*, TAdaptedString str, LinkStringStoragePolicy, + TCallback callback) { + String storedString(str.data(), str.size(), String::Linked); + callback(storedString); + return !str.isNull(); +} + +template +bool storeString(MemoryPool* pool, TAdaptedString str, + LinkOrCopyStringStoragePolicy policy, TCallback callback) { + if (policy.link) + return storeString(pool, str, LinkStringStoragePolicy(), callback); + else + return storeString(pool, str, CopyStringStoragePolicy(), callback); +} + +template +bool storeString(MemoryPool* pool, TAdaptedString str, TCallback callback) { + return storeString(pool, str, str.storagePolicy(), callback); +} + } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Strings/Adapters/FlashString.hpp b/src/ArduinoJson/Strings/Adapters/FlashString.hpp index 048d7c18..36ac6327 100644 --- a/src/ArduinoJson/Strings/Adapters/FlashString.hpp +++ b/src/ArduinoJson/Strings/Adapters/FlashString.hpp @@ -61,6 +61,10 @@ class FlashString { ::memcpy_P(p, s._str, n); } + CopyStringStoragePolicy storagePolicy() { + return CopyStringStoragePolicy(); + } + private: const char* _str; size_t _size; diff --git a/src/ArduinoJson/Strings/Adapters/JsonString.hpp b/src/ArduinoJson/Strings/Adapters/JsonString.hpp index fac729f6..f7e52c24 100644 --- a/src/ArduinoJson/Strings/Adapters/JsonString.hpp +++ b/src/ArduinoJson/Strings/Adapters/JsonString.hpp @@ -10,8 +10,21 @@ namespace ARDUINOJSON_NAMESPACE { -inline SizedRamString adaptString(const String& s) { - return SizedRamString(s.c_str(), s.size()); +class JsonStringAdapter : public SizedRamString { + public: + JsonStringAdapter(const String& s) + : SizedRamString(s.c_str(), s.size()), _linked(s.isLinked()) {} + + LinkOrCopyStringStoragePolicy storagePolicy() { + return LinkOrCopyStringStoragePolicy(_linked); + } + + private: + bool _linked; +}; + +inline JsonStringAdapter adaptString(const String& s) { + return JsonStringAdapter(s); } template <> diff --git a/src/ArduinoJson/Strings/Adapters/RamString.hpp b/src/ArduinoJson/Strings/Adapters/RamString.hpp index 5a55552a..50493d54 100644 --- a/src/ArduinoJson/Strings/Adapters/RamString.hpp +++ b/src/ArduinoJson/Strings/Adapters/RamString.hpp @@ -9,6 +9,7 @@ #include #include +#include namespace ARDUINOJSON_NAMESPACE { @@ -48,6 +49,10 @@ class ZeroTerminatedRamString { return stringCompare(a, b) == 0; } + CopyStringStoragePolicy storagePolicy() { + return CopyStringStoragePolicy(); + } + protected: const char* _str; }; @@ -55,7 +60,7 @@ class ZeroTerminatedRamString { template <> struct IsString : true_type {}; -inline ZeroTerminatedRamString adaptString(const char* s) { +inline ZeroTerminatedRamString adaptString(char* s) { return ZeroTerminatedRamString(s); } @@ -63,14 +68,27 @@ template <> struct IsString : true_type {}; inline ZeroTerminatedRamString adaptString(const unsigned char* s) { - return adaptString(reinterpret_cast(s)); + return ZeroTerminatedRamString(reinterpret_cast(s)); } template <> struct IsString : true_type {}; inline ZeroTerminatedRamString adaptString(const signed char* s) { - return adaptString(reinterpret_cast(s)); + return ZeroTerminatedRamString(reinterpret_cast(s)); +} + +class StaticStringAdapter : public ZeroTerminatedRamString { + public: + StaticStringAdapter(const char* str) : ZeroTerminatedRamString(str) {} + + LinkStringStoragePolicy storagePolicy() { + return LinkStringStoragePolicy(); + } +}; + +inline StaticStringAdapter adaptString(const char* s) { + return StaticStringAdapter(s); } class SizedRamString { @@ -97,6 +115,10 @@ class SizedRamString { return _str; } + CopyStringStoragePolicy storagePolicy() { + return CopyStringStoragePolicy(); + } + protected: const char* _str; size_t _size; diff --git a/src/ArduinoJson/Strings/StoragePolicy.hpp b/src/ArduinoJson/Strings/StoragePolicy.hpp index 284c70c2..d2fd9c37 100644 --- a/src/ArduinoJson/Strings/StoragePolicy.hpp +++ b/src/ArduinoJson/Strings/StoragePolicy.hpp @@ -4,53 +4,16 @@ #pragma once -#include -#include - namespace ARDUINOJSON_NAMESPACE { -struct LinkStringStoragePolicy { - template - bool store(TAdaptedString str, MemoryPool*, TCallback callback) { - String storedString(str.data(), str.size(), String::Linked); - callback(storedString); - return !str.isNull(); - } +struct LinkStringStoragePolicy {}; + +struct CopyStringStoragePolicy {}; + +struct LinkOrCopyStringStoragePolicy { + LinkOrCopyStringStoragePolicy(bool l) : link(l) {} + + bool link; }; -struct CopyStringStoragePolicy { - template - bool store(TAdaptedString str, MemoryPool* pool, TCallback callback); -}; - -class LinkOrCopyStringStoragePolicy : LinkStringStoragePolicy, - CopyStringStoragePolicy { - public: - LinkOrCopyStringStoragePolicy(bool link) : _link(link) {} - - template - bool store(TAdaptedString str, MemoryPool* pool, TCallback callback) { - if (_link) - return LinkStringStoragePolicy::store(str, pool, callback); - else - return CopyStringStoragePolicy::store(str, pool, callback); - } - - private: - bool _link; -}; - -template -inline CopyStringStoragePolicy getStringStoragePolicy(const T&) { - return CopyStringStoragePolicy(); -} - -inline LinkStringStoragePolicy getStringStoragePolicy(const char*) { - return LinkStringStoragePolicy(); -} - -inline LinkOrCopyStringStoragePolicy getStringStoragePolicy(const String& s) { - return LinkOrCopyStringStoragePolicy(s.isLinked()); -} - } // namespace ARDUINOJSON_NAMESPACE diff --git a/src/ArduinoJson/Variant/ConverterImpl.hpp b/src/ArduinoJson/Variant/ConverterImpl.hpp index 62fef3c9..60d3ea4c 100644 --- a/src/ArduinoJson/Variant/ConverterImpl.hpp +++ b/src/ArduinoJson/Variant/ConverterImpl.hpp @@ -118,8 +118,7 @@ struct Converter::value>::type> template <> struct Converter : private VariantAttorney { static void toJson(const char* src, VariantRef dst) { - variantSetString(getData(dst), adaptString(src), getPool(dst), - getStringStoragePolicy(src)); + variantSetString(getData(dst), adaptString(src), getPool(dst)); } static const char* fromJson(VariantConstRef src) { @@ -136,8 +135,7 @@ struct Converter : private VariantAttorney { template <> struct Converter : private VariantAttorney { static void toJson(String src, VariantRef dst) { - variantSetString(getData(dst), adaptString(src), getPool(dst), - getStringStoragePolicy(src)); + variantSetString(getData(dst), adaptString(src), getPool(dst)); } static String fromJson(VariantConstRef src) { @@ -156,8 +154,7 @@ inline typename enable_if::value, bool>::type convertToJson( const T& src, VariantRef dst) { VariantData* data = VariantAttorney::getData(dst); MemoryPool* pool = VariantAttorney::getPool(dst); - return variantSetString(data, adaptString(src), pool, - getStringStoragePolicy(src)); + return variantSetString(data, adaptString(src), pool); } template <> diff --git a/src/ArduinoJson/Variant/SlotFunctions.hpp b/src/ArduinoJson/Variant/SlotFunctions.hpp index 9119a460..1b5b5228 100644 --- a/src/ArduinoJson/Variant/SlotFunctions.hpp +++ b/src/ArduinoJson/Variant/SlotFunctions.hpp @@ -23,12 +23,11 @@ struct SlotKeySetter { VariantSlot* _instance; }; -template -inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool, - TStoragePolicy storage) { +template +inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) { if (!var) return false; - return storage.store(key, pool, SlotKeySetter(var)); + return storeString(pool, key, SlotKeySetter(var)); } inline size_t slotSize(const VariantSlot* var) { diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index 6e9ba394..6b037fa3 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -285,14 +285,13 @@ class VariantData { return col ? col->getMember(key) : 0; } - template - VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool, - TStoragePolicy storage_policy) { + template + VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool) { if (isNull()) toObject(); if (!isObject()) return 0; - return _content.asCollection.getOrAddMember(key, pool, storage_policy); + return _content.asCollection.getOrAddMember(key, pool); } void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { @@ -306,15 +305,14 @@ class VariantData { return _flags & VALUE_MASK; } - template - inline bool storeString(TAdaptedString value, MemoryPool* pool, - TStoragePolicy storage) { + template + inline bool setString(TAdaptedString value, MemoryPool* pool) { if (value.isNull()) { setNull(); return true; } - return storage.store(value, pool, VariantStringSetter(this)); + return storeString(pool, value, VariantStringSetter(this)); } private: diff --git a/src/ArduinoJson/Variant/VariantFunctions.hpp b/src/ArduinoJson/Variant/VariantFunctions.hpp index ccdec2b8..2673b7cd 100644 --- a/src/ArduinoJson/Variant/VariantFunctions.hpp +++ b/src/ArduinoJson/Variant/VariantFunctions.hpp @@ -37,10 +37,10 @@ inline void variantSetNull(VariantData* var) { var->setNull(); } -template +template inline bool variantSetString(VariantData* var, TAdaptedString value, - MemoryPool* pool, TStoragePolicy storage_policy) { - return var != 0 ? var->storeString(value, pool, storage_policy) : 0; + MemoryPool* pool) { + return var != 0 ? var->setString(value, pool) : 0; } inline size_t variantSize(const VariantData* var) { @@ -88,8 +88,7 @@ VariantData* variantGetOrAddMember(VariantData* var, TChar* key, MemoryPool* pool) { if (!var) return 0; - return var->getOrAddMember(adaptString(key), pool, - getStringStoragePolicy(key)); + return var->getOrAddMember(adaptString(key), pool); } template @@ -97,8 +96,7 @@ VariantData* variantGetOrAddMember(VariantData* var, const TString& key, MemoryPool* pool) { if (!var) return 0; - return var->getOrAddMember(adaptString(key), pool, - getStringStoragePolicy(key)); + return var->getOrAddMember(adaptString(key), pool); } inline bool variantIsNull(const VariantData* var) { diff --git a/src/ArduinoJson/Variant/VariantImpl.hpp b/src/ArduinoJson/Variant/VariantImpl.hpp index 9b52006d..511fc274 100644 --- a/src/ArduinoJson/Variant/VariantImpl.hpp +++ b/src/ArduinoJson/Variant/VariantImpl.hpp @@ -91,8 +91,7 @@ inline bool VariantData::copyFrom(const VariantData& src, MemoryPool* pool) { return toObject().copyFrom(src._content.asCollection, pool); case VALUE_IS_OWNED_STRING: { String value = src.asString(); - return storeString(adaptString(value), pool, - getStringStoragePolicy(value)); + return setString(adaptString(value), pool); } case VALUE_IS_OWNED_RAW: return storeOwnedRaw( @@ -154,14 +153,4 @@ inline void convertToJson(const VariantRefBase& src, dst.set(src.template as()); } -// TODO: move somewhere else -template -bool CopyStringStoragePolicy::store(TAdaptedString str, MemoryPool* pool, - TCallback callback) { - const char* copy = pool->saveString(str); - String storedString(copy, str.size(), String::Copied); - callback(storedString); - return copy != 0; -} - } // namespace ARDUINOJSON_NAMESPACE