Attach copy policy to string adapters

This commit is contained in:
Benoit Blanchon
2022-10-26 10:37:18 +02:00
parent 61c6f8ba59
commit b27990f780
12 changed files with 113 additions and 101 deletions

View File

@ -38,15 +38,14 @@ class CollectionData {
// Object only // Object only
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
VariantData* addMember(TAdaptedString key, MemoryPool* pool, TStoragePolicy); VariantData* addMember(TAdaptedString key, MemoryPool* pool);
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData* getMember(TAdaptedString key) const; VariantData* getMember(TAdaptedString key) const;
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool, VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool);
TStoragePolicy);
template <typename TAdaptedString> template <typename TAdaptedString>
void removeMember(TAdaptedString key) { void removeMember(TAdaptedString key) {

View File

@ -33,12 +33,11 @@ inline VariantData* CollectionData::addElement(MemoryPool* pool) {
return slotData(addSlot(pool)); return slotData(addSlot(pool));
} }
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
inline VariantData* CollectionData::addMember(TAdaptedString key, inline VariantData* CollectionData::addMember(TAdaptedString key,
MemoryPool* pool, MemoryPool* pool) {
TStoragePolicy storage) {
VariantSlot* slot = addSlot(pool); VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool, storage)) { if (!slotSetKey(slot, key, pool)) {
removeSlot(slot); removeSlot(slot);
return 0; return 0;
} }
@ -62,7 +61,7 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
VariantData* var; VariantData* var;
if (s->key() != 0) { if (s->key() != 0) {
String key(s->key(), s->ownsKey() ? String::Copied : String::Linked); String key(s->key(), s->ownsKey() ? String::Copied : String::Linked);
var = addMember(adaptString(key), pool, getStringStoragePolicy(key)); var = addMember(adaptString(key), pool);
} else { } else {
var = addElement(pool); var = addElement(pool);
} }
@ -110,9 +109,9 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const {
return slot ? slot->data() : 0; return slot ? slot->data() : 0;
} }
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
inline VariantData* CollectionData::getOrAddMember( inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
TAdaptedString key, MemoryPool* pool, TStoragePolicy storage_policy) { MemoryPool* pool) {
// ignore null key // ignore null key
if (key.isNull()) if (key.isNull())
return 0; return 0;
@ -122,7 +121,7 @@ inline VariantData* CollectionData::getOrAddMember(
if (slot) if (slot)
return slot->data(); return slot->data();
return addMember(key, pool, storage_policy); return addMember(key, pool);
} }
inline VariantData* CollectionData::getElement(size_t index) const { inline VariantData* CollectionData::getElement(size_t index) const {

View File

@ -208,4 +208,35 @@ class MemoryPool {
bool _overflowed; bool _overflowed;
}; };
template <typename TAdaptedString, typename TCallback>
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 <typename TAdaptedString, typename TCallback>
bool storeString(MemoryPool*, TAdaptedString str, LinkStringStoragePolicy,
TCallback callback) {
String storedString(str.data(), str.size(), String::Linked);
callback(storedString);
return !str.isNull();
}
template <typename TAdaptedString, typename TCallback>
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 <typename TAdaptedString, typename TCallback>
bool storeString(MemoryPool* pool, TAdaptedString str, TCallback callback) {
return storeString(pool, str, str.storagePolicy(), callback);
}
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@ -61,6 +61,10 @@ class FlashString {
::memcpy_P(p, s._str, n); ::memcpy_P(p, s._str, n);
} }
CopyStringStoragePolicy storagePolicy() {
return CopyStringStoragePolicy();
}
private: private:
const char* _str; const char* _str;
size_t _size; size_t _size;

View File

@ -10,8 +10,21 @@
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
inline SizedRamString adaptString(const String& s) { class JsonStringAdapter : public SizedRamString {
return SizedRamString(s.c_str(), s.size()); 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 <> template <>

View File

@ -9,6 +9,7 @@
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Strings/IsString.hpp> #include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
@ -48,6 +49,10 @@ class ZeroTerminatedRamString {
return stringCompare(a, b) == 0; return stringCompare(a, b) == 0;
} }
CopyStringStoragePolicy storagePolicy() {
return CopyStringStoragePolicy();
}
protected: protected:
const char* _str; const char* _str;
}; };
@ -55,7 +60,7 @@ class ZeroTerminatedRamString {
template <> template <>
struct IsString<char*> : true_type {}; struct IsString<char*> : true_type {};
inline ZeroTerminatedRamString adaptString(const char* s) { inline ZeroTerminatedRamString adaptString(char* s) {
return ZeroTerminatedRamString(s); return ZeroTerminatedRamString(s);
} }
@ -63,14 +68,27 @@ template <>
struct IsString<unsigned char*> : true_type {}; struct IsString<unsigned char*> : true_type {};
inline ZeroTerminatedRamString adaptString(const unsigned char* s) { inline ZeroTerminatedRamString adaptString(const unsigned char* s) {
return adaptString(reinterpret_cast<const char*>(s)); return ZeroTerminatedRamString(reinterpret_cast<const char*>(s));
} }
template <> template <>
struct IsString<signed char*> : true_type {}; struct IsString<signed char*> : true_type {};
inline ZeroTerminatedRamString adaptString(const signed char* s) { inline ZeroTerminatedRamString adaptString(const signed char* s) {
return adaptString(reinterpret_cast<const char*>(s)); return ZeroTerminatedRamString(reinterpret_cast<const char*>(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 { class SizedRamString {
@ -97,6 +115,10 @@ class SizedRamString {
return _str; return _str;
} }
CopyStringStoragePolicy storagePolicy() {
return CopyStringStoragePolicy();
}
protected: protected:
const char* _str; const char* _str;
size_t _size; size_t _size;

View File

@ -4,53 +4,16 @@
#pragma once #pragma once
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Strings/String.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
struct LinkStringStoragePolicy { struct LinkStringStoragePolicy {};
template <typename TAdaptedString, typename TCallback>
bool store(TAdaptedString str, MemoryPool*, TCallback callback) { struct CopyStringStoragePolicy {};
String storedString(str.data(), str.size(), String::Linked);
callback(storedString); struct LinkOrCopyStringStoragePolicy {
return !str.isNull(); LinkOrCopyStringStoragePolicy(bool l) : link(l) {}
}
bool link;
}; };
struct CopyStringStoragePolicy {
template <typename TAdaptedString, typename TCallback>
bool store(TAdaptedString str, MemoryPool* pool, TCallback callback);
};
class LinkOrCopyStringStoragePolicy : LinkStringStoragePolicy,
CopyStringStoragePolicy {
public:
LinkOrCopyStringStoragePolicy(bool link) : _link(link) {}
template <typename TAdaptedString, typename TCallback>
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 <typename T>
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 } // namespace ARDUINOJSON_NAMESPACE

View File

@ -118,8 +118,7 @@ struct Converter<T, typename enable_if<is_floating_point<T>::value>::type>
template <> template <>
struct Converter<const char*> : private VariantAttorney { struct Converter<const char*> : private VariantAttorney {
static void toJson(const char* src, VariantRef dst) { static void toJson(const char* src, VariantRef dst) {
variantSetString(getData(dst), adaptString(src), getPool(dst), variantSetString(getData(dst), adaptString(src), getPool(dst));
getStringStoragePolicy(src));
} }
static const char* fromJson(VariantConstRef src) { static const char* fromJson(VariantConstRef src) {
@ -136,8 +135,7 @@ struct Converter<const char*> : private VariantAttorney {
template <> template <>
struct Converter<String> : private VariantAttorney { struct Converter<String> : private VariantAttorney {
static void toJson(String src, VariantRef dst) { static void toJson(String src, VariantRef dst) {
variantSetString(getData(dst), adaptString(src), getPool(dst), variantSetString(getData(dst), adaptString(src), getPool(dst));
getStringStoragePolicy(src));
} }
static String fromJson(VariantConstRef src) { static String fromJson(VariantConstRef src) {
@ -156,8 +154,7 @@ inline typename enable_if<IsString<T>::value, bool>::type convertToJson(
const T& src, VariantRef dst) { const T& src, VariantRef dst) {
VariantData* data = VariantAttorney::getData(dst); VariantData* data = VariantAttorney::getData(dst);
MemoryPool* pool = VariantAttorney::getPool(dst); MemoryPool* pool = VariantAttorney::getPool(dst);
return variantSetString(data, adaptString(src), pool, return variantSetString(data, adaptString(src), pool);
getStringStoragePolicy(src));
} }
template <> template <>

View File

@ -23,12 +23,11 @@ struct SlotKeySetter {
VariantSlot* _instance; VariantSlot* _instance;
}; };
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool, inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
TStoragePolicy storage) {
if (!var) if (!var)
return false; return false;
return storage.store(key, pool, SlotKeySetter(var)); return storeString(pool, key, SlotKeySetter(var));
} }
inline size_t slotSize(const VariantSlot* var) { inline size_t slotSize(const VariantSlot* var) {

View File

@ -285,14 +285,13 @@ class VariantData {
return col ? col->getMember(key) : 0; return col ? col->getMember(key) : 0;
} }
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool, VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool) {
TStoragePolicy storage_policy) {
if (isNull()) if (isNull())
toObject(); toObject();
if (!isObject()) if (!isObject())
return 0; return 0;
return _content.asCollection.getOrAddMember(key, pool, storage_policy); return _content.asCollection.getOrAddMember(key, pool);
} }
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
@ -306,15 +305,14 @@ class VariantData {
return _flags & VALUE_MASK; return _flags & VALUE_MASK;
} }
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
inline bool storeString(TAdaptedString value, MemoryPool* pool, inline bool setString(TAdaptedString value, MemoryPool* pool) {
TStoragePolicy storage) {
if (value.isNull()) { if (value.isNull()) {
setNull(); setNull();
return true; return true;
} }
return storage.store(value, pool, VariantStringSetter(this)); return storeString(pool, value, VariantStringSetter(this));
} }
private: private:

View File

@ -37,10 +37,10 @@ inline void variantSetNull(VariantData* var) {
var->setNull(); var->setNull();
} }
template <typename TAdaptedString, typename TStoragePolicy> template <typename TAdaptedString>
inline bool variantSetString(VariantData* var, TAdaptedString value, inline bool variantSetString(VariantData* var, TAdaptedString value,
MemoryPool* pool, TStoragePolicy storage_policy) { MemoryPool* pool) {
return var != 0 ? var->storeString(value, pool, storage_policy) : 0; return var != 0 ? var->setString(value, pool) : 0;
} }
inline size_t variantSize(const VariantData* var) { inline size_t variantSize(const VariantData* var) {
@ -88,8 +88,7 @@ VariantData* variantGetOrAddMember(VariantData* var, TChar* key,
MemoryPool* pool) { MemoryPool* pool) {
if (!var) if (!var)
return 0; return 0;
return var->getOrAddMember(adaptString(key), pool, return var->getOrAddMember(adaptString(key), pool);
getStringStoragePolicy(key));
} }
template <typename TString> template <typename TString>
@ -97,8 +96,7 @@ VariantData* variantGetOrAddMember(VariantData* var, const TString& key,
MemoryPool* pool) { MemoryPool* pool) {
if (!var) if (!var)
return 0; return 0;
return var->getOrAddMember(adaptString(key), pool, return var->getOrAddMember(adaptString(key), pool);
getStringStoragePolicy(key));
} }
inline bool variantIsNull(const VariantData* var) { inline bool variantIsNull(const VariantData* var) {

View File

@ -91,8 +91,7 @@ inline bool VariantData::copyFrom(const VariantData& src, MemoryPool* pool) {
return toObject().copyFrom(src._content.asCollection, pool); return toObject().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OWNED_STRING: { case VALUE_IS_OWNED_STRING: {
String value = src.asString(); String value = src.asString();
return storeString(adaptString(value), pool, return setString(adaptString(value), pool);
getStringStoragePolicy(value));
} }
case VALUE_IS_OWNED_RAW: case VALUE_IS_OWNED_RAW:
return storeOwnedRaw( return storeOwnedRaw(
@ -154,14 +153,4 @@ inline void convertToJson(const VariantRefBase<TDataSource>& src,
dst.set(src.template as<VariantConstRef>()); dst.set(src.template as<VariantConstRef>());
} }
// TODO: move somewhere else
template <typename TAdaptedString, typename TCallback>
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 } // namespace ARDUINOJSON_NAMESPACE