User can now use a JsonString as a key or a value

This commit is contained in:
Benoit Blanchon
2019-01-29 17:00:11 +01:00
parent 6f55d1e58f
commit b184af6d00
29 changed files with 500 additions and 376 deletions

View File

@ -28,6 +28,7 @@ HEAD
* `JsonDocument` now support the same operations as `JsonVariant`.
Calling `JsonDocument::as<T>()` is not required anymore.
* Fixed example `JsonHttpClient.ino`
* User can now use a `JsonString` as a key or a value
> ### BREAKING CHANGES
>

View File

@ -24,13 +24,13 @@ class CollectionData {
VariantData *add(MemoryPool *pool);
template <typename TKey>
VariantData *add(TKey key, MemoryPool *pool);
template <typename TAdaptedString>
VariantData *add(TAdaptedString key, MemoryPool *pool);
void clear();
template <typename TKey>
bool containsKey(const TKey &key) const;
template <typename TAdaptedString>
bool containsKey(const TAdaptedString &key) const;
bool copyFrom(const CollectionData &src, MemoryPool *pool);
@ -39,8 +39,8 @@ class CollectionData {
VariantData *get(size_t index) const;
template <typename TKey>
VariantData *get(TKey key) const;
template <typename TAdaptedString>
VariantData *get(TAdaptedString key) const;
VariantSlot *head() const {
return _head;
@ -48,8 +48,8 @@ class CollectionData {
void remove(size_t index);
template <typename TKey>
void remove(TKey key) {
template <typename TAdaptedString>
void remove(TAdaptedString key) {
remove(getSlot(key));
}
@ -62,8 +62,8 @@ class CollectionData {
private:
VariantSlot *getSlot(size_t index) const;
template <typename TKey>
VariantSlot *getSlot(TKey key) const;
template <typename TAdaptedString>
VariantSlot *getSlot(TAdaptedString key) const;
VariantSlot *getPreviousSlot(VariantSlot *) const;
};

View File

@ -29,8 +29,8 @@ inline VariantData* CollectionData::add(MemoryPool* pool) {
return addSlot(pool)->data();
}
template <typename TKey>
inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) {
template <typename TAdaptedString>
inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) return 0;
return slot->data();
@ -41,8 +41,8 @@ inline void CollectionData::clear() {
_tail = 0;
}
template <typename TKey>
inline bool CollectionData::containsKey(const TKey& key) const {
template <typename TAdaptedString>
inline bool CollectionData::containsKey(const TAdaptedString& key) const {
return getSlot(key) != 0;
}
@ -53,9 +53,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
VariantData* var;
if (s->key() != 0) {
if (s->ownsKey())
var = add(RamStringWrapper(s->key()), pool);
var = add(RamStringAdapter(s->key()), pool);
else
var = add(ConstRamStringWrapper(s->key()), pool);
var = add(ConstRamStringAdapter(s->key()), pool);
} else {
var = add(pool);
}
@ -69,7 +69,7 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const {
size_t count = 0;
for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data();
VariantData* v2 = other.get(wrapString(slot->key()));
VariantData* v2 = other.get(adaptString(slot->key()));
if (!variantEquals(v1, v2)) return false;
count++;
}
@ -88,8 +88,8 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const {
}
}
template <typename TKey>
inline VariantSlot* CollectionData::getSlot(TKey key) const {
template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
VariantSlot* slot = _head;
while (slot) {
if (key.equals(slot->key())) break;
@ -112,8 +112,8 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
return 0;
}
template <typename TKey>
inline VariantData* CollectionData::get(TKey key) const {
template <typename TAdaptedString>
inline VariantData* CollectionData::get(TAdaptedString key) const {
VariantSlot* slot = getSlot(key);
return slot ? slot->data() : 0;
}

View File

@ -23,8 +23,8 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
}
// DeserializationError deserialize(JsonDocument& doc, TString input);
// TString = const std::string&, const String&
// deserialize(JsonDocument&, const std::string&);
// deserialize(JsonDocument&, const String&);
template <template <typename, typename> class TDeserializer, typename TString>
typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(JsonDocument &doc, const TString &input,
@ -36,8 +36,9 @@ deserialize(JsonDocument &doc, const TString &input,
.parse(doc.data());
}
//
// DeserializationError deserialize(JsonDocument& doc, TChar* input);
// TChar* = char*, const char*, const __FlashStringHelper*
// deserialize(JsonDocument&, char*);
// deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
NestingLimit nestingLimit) {
@ -48,9 +49,9 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
.parse(doc.data());
}
//
// DeserializationError deserialize(JsonDocument& doc, TChar* input, size_t
// inputSize);
// TChar* = char*, const char*, const __FlashStringHelper*
// deserialize(JsonDocument&, char*, size_t);
// deserialize(JsonDocument&, const char*, size_t);
// deserialize(JsonDocument&, const __FlashStringHelper*, size_t);
template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
size_t inputSize, NestingLimit nestingLimit) {
@ -61,8 +62,8 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
.parse(doc.data());
}
//
// DeserializationError deserialize(JsonDocument& doc, TStream input);
// TStream = std::istream&, Stream&
// deserialize(JsonDocument&, std::istream&);
// deserialize(JsonDocument&, Stream&);
template <template <typename, typename> class TDeserializer, typename TStream>
DeserializationError deserialize(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit) {

View File

@ -86,13 +86,18 @@ class JsonDocument : public Visitable {
return add().to<ArrayRef>();
}
template <typename TKey>
ArrayRef createNestedArray(TKey* key) {
// createNestedArray(char*)
// createNestedArray(const char*)
// createNestedArray(const __FlashStringHelper*)
template <typename TChar>
ArrayRef createNestedArray(TChar* key) {
return getOrCreate(key).template to<ArrayRef>();
}
template <typename TKey>
ArrayRef createNestedArray(const TKey& key) {
// createNestedArray(const std::string&)
// createNestedArray(const String&)
template <typename TString>
ArrayRef createNestedArray(const TString& key) {
return getOrCreate(key).template to<ArrayRef>();
}
@ -100,48 +105,57 @@ class JsonDocument : public Visitable {
return add().to<ObjectRef>();
}
template <typename TKey>
ObjectRef createNestedObject(TKey* key) {
// createNestedObject(char*)
// createNestedObject(const char*)
// createNestedObject(const __FlashStringHelper*)
template <typename TChar>
ObjectRef createNestedObject(TChar* key) {
return getOrCreate(key).template to<ObjectRef>();
}
template <typename TKey>
ObjectRef createNestedObject(const TKey& key) {
// createNestedObject(const std::string&)
// createNestedObject(const String&)
template <typename TString>
ObjectRef createNestedObject(const TString& key) {
return getOrCreate(key).template to<ObjectRef>();
}
// MemberProxy operator[](TKey)
// TKey = const std::string&, const String&
template <typename TKey>
// operator[](const std::string&)
// operator[](const String&)
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TKey>::value,
MemberProxy<JsonDocument&, const TKey&> >::type
operator[](const TKey& key) {
return MemberProxy<JsonDocument&, const TKey&>(*this, key);
typename enable_if<IsString<TString>::value,
MemberProxy<JsonDocument&, const TString&> >::type
operator[](const TString& key) {
return MemberProxy<JsonDocument&, const TString&>(*this, key);
}
// MemberProxy operator[](TKey);
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey*>::value,
MemberProxy<JsonDocument&, TKey*> >::type
operator[](TKey* key) {
return MemberProxy<JsonDocument&, TKey*>(*this, key);
// operator[](char*)
// operator[](const char*)
// operator[](const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<JsonDocument&, TChar*> >::type
operator[](TChar* key) {
return MemberProxy<JsonDocument&, TChar*>(*this, key);
}
// VariantConstRef operator[](TKey) const
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type
operator[](const TKey& key) const {
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const {
return getVariant()[key];
}
// VariantConstRef operator[](TKey) const;
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type
operator[](TKey* key) const {
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
operator[](TChar* key) const {
return getVariant()[key];
}
@ -157,43 +171,51 @@ class JsonDocument : public Visitable {
return VariantRef(&_pool, _data.get(index));
}
template <typename TKey>
FORCE_INLINE VariantRef get(TKey* key) {
return VariantRef(&_pool, _data.get(wrapString(key)));
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar* key) {
return VariantRef(&_pool, _data.get(adaptString(key)));
}
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get(
const TKey& key) {
return VariantRef(&_pool, _data.get(wrapString(key)));
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
get(const TString& key) {
return VariantRef(&_pool, _data.get(adaptString(key)));
}
template <typename TKey>
FORCE_INLINE VariantRef getOrCreate(TKey* key) {
return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool));
// getOrCreate(char*)
// getOrCreate(const char*)
// getOrCreate(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar* key) {
return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool));
}
template <typename TKey>
FORCE_INLINE VariantRef getOrCreate(const TKey& key) {
return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool));
// getOrCreate(const std::string&)
// getOrCreate(const String&)
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString& key) {
return VariantRef(&_pool, _data.getOrCreate(adaptString(key), &_pool));
}
FORCE_INLINE VariantRef add() {
return VariantRef(&_pool, _data.add(&_pool));
}
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ObjectRef
template <typename T>
FORCE_INLINE bool add(const T& value) {
template <typename TValue>
FORCE_INLINE bool add(const TValue& value) {
return add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE bool add(T* value) {
// add(char*) const
// add(const char*) const
// add(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool add(TChar* value) {
return add().set(value);
}

View File

@ -4,7 +4,7 @@
#pragma once
#include "../Strings/StringWrappers.hpp"
#include "../Strings/StringAdapters.hpp"
namespace ARDUINOJSON_NAMESPACE {
@ -58,7 +58,7 @@ inline SerializedValue<T> serialized(T str) {
template <typename TChar>
inline SerializedValue<TChar*> serialized(TChar* p) {
return SerializedValue<TChar*>(p, wrapString(p).size());
return SerializedValue<TChar*>(p, adaptString(p).size());
}
template <typename TChar>

View File

@ -15,13 +15,13 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TObject, typename TString>
class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
template <typename TObject, typename TStringRef>
class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
public Visitable {
typedef MemberProxy<TObject, TString> this_type;
typedef MemberProxy<TObject, TStringRef> this_type;
public:
FORCE_INLINE MemberProxy(TObject variant, TString key)
FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
: _object(variant), _key(key) {}
FORCE_INLINE operator VariantConstRef() const {
@ -33,22 +33,18 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
return *this;
}
// Set the specified value
//
// operator=(const TValue&);
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
getOrCreateMember().set(src);
return *this;
}
//
// operator=(TValue);
// TValue = char*, const char*, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE this_type &operator=(TValue *src) {
// operator=(char*) const
// operator=(const char*) const
// operator=(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE this_type &operator=(TChar *src) {
getOrCreateMember().set(src);
return *this;
}
@ -72,22 +68,17 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
return getOrCreateMember().template to<TValue>();
}
// Sets the specified value.
//
// bool set(const TValue&);
// TValue = bool, char, long, int, short, float, double, serialized,
// VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
const TValue &value) {
return getOrCreateMember().set(value);
}
//
// bool set(TValue);
// TValue = char*, const char, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(const TValue *value) {
// set(char*) const
// set(const char*) const
// set(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool set(const TChar *value) {
return getOrCreateMember().set(value);
}
@ -101,23 +92,33 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
return getOrCreateMember().add();
}
template <typename TNestedKey>
FORCE_INLINE VariantRef get(TNestedKey *key) const {
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar *key) const {
return getMember().get(key);
}
template <typename TNestedKey>
FORCE_INLINE VariantRef get(const TNestedKey &key) const {
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE VariantRef get(const TString &key) const {
return getMember().get(key);
}
template <typename TNestedKey>
FORCE_INLINE VariantRef getOrCreate(TNestedKey *key) const {
// getOrCreate(char*) const
// getOrCreate(const char*) const
// getOrCreate(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar *key) const {
return getOrCreateMember().getOrCreate(key);
}
template <typename TNestedKey>
FORCE_INLINE VariantRef getOrCreate(const TNestedKey &key) const {
// getOrCreate(const std::string&) const
// getOrCreate(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString &key) const {
return getOrCreateMember().getOrCreate(key);
}
@ -131,7 +132,7 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
}
TObject _object;
TString _key;
TStringRef _key;
};
template <typename TObject>

View File

@ -16,8 +16,8 @@ void objectAccept(const CollectionData *obj, Visitor &visitor) {
visitor.visitNull();
}
template <typename TKey>
inline bool objectContainsKey(const CollectionData *obj, TKey key) {
template <typename TAdaptedString>
inline bool objectContainsKey(const CollectionData *obj, TAdaptedString key) {
return obj && obj->containsKey(key);
}
@ -27,20 +27,20 @@ inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
return lhs->equalsObject(*rhs);
}
template <typename TKey>
inline VariantData *objectGet(const CollectionData *obj, TKey key) {
template <typename TAdaptedString>
inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) {
if (!obj) return 0;
return obj->get(key);
}
template <typename TKey>
void objectRemove(CollectionData *obj, TKey key) {
template <typename TAdaptedString>
void objectRemove(CollectionData *obj, TAdaptedString key) {
if (!obj) return;
obj->remove(key);
}
template <typename TKey>
inline VariantData *objectGetOrCreate(CollectionData *obj, TKey key,
template <typename TAdaptedString>
inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key,
MemoryPool *pool) {
if (!obj) return 0;

View File

@ -17,23 +17,22 @@ inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
}
template <typename TObject>
template <typename TString>
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
TString* key) const {
template <typename TChar>
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const {
return impl()->getOrCreate(key).template to<ArrayRef>();
}
template <typename TObject>
template <typename TKey>
ObjectRef ObjectShortcuts<TObject>::createNestedObject(const TKey& key) const {
template <typename TString>
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
const TString& key) const {
return impl()->getOrCreate(key).template to<ObjectRef>();
}
//
// ObjectRef createNestedObject(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TObject>
template <typename TKey>
ObjectRef ObjectShortcuts<TObject>::createNestedObject(TKey* key) const {
template <typename TChar>
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
TChar* key) const {
return impl()->getOrCreate(key).template to<ObjectRef>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -26,20 +26,19 @@ class ObjectRefBase {
objectAccept(_data, visitor);
}
// Tells weither the specified key is present and associated with a value.
//
// bool containsKey(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE bool containsKey(const TKey& key) const {
return objectContainsKey(_data, wrapString(key));
// containsKey(const std::string&) const
// containsKey(const String&) const
template <typename TString>
FORCE_INLINE bool containsKey(const TString& key) const {
return objectContainsKey(_data, adaptString(key));
}
//
// bool containsKey(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE bool containsKey(TKey* key) const {
return objectContainsKey(_data, wrapString(key));
// containsKey(char*) const
// containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool containsKey(TChar* key) const {
return objectContainsKey(_data, adaptString(key));
}
FORCE_INLINE bool isNull() const {
@ -83,41 +82,38 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
return iterator();
}
// Gets the value associated with the specified key.
//
// TValue get<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayConstRef, ObjectConstRef
template <typename TKey>
FORCE_INLINE VariantConstRef get(const TKey& key) const {
return get_impl(wrapString(key));
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const __FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, ArrayConstRef, ObjectConstRef
template <typename TKey>
FORCE_INLINE VariantConstRef get(TKey* key) const {
return get_impl(wrapString(key));
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE VariantConstRef get(const TString& key) const {
return get_impl(adaptString(key));
}
//
// VariantConstRef operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantConstRef>::type
operator[](const TKey& key) const {
return get_impl(wrapString(key));
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantConstRef get(TChar* key) const {
return get_impl(adaptString(key));
}
//
// VariantConstRef operator[](TKey) const;
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey*>::value, VariantConstRef>::type
operator[](TKey* key) const {
return get_impl(wrapString(key));
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const {
return get_impl(adaptString(key));
}
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
operator[](TChar* key) const {
return get_impl(adaptString(key));
}
FORCE_INLINE bool operator==(ObjectConstRef rhs) const {
@ -125,8 +121,8 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
}
private:
template <typename TKey>
FORCE_INLINE VariantConstRef get_impl(TKey key) const {
template <typename TAdaptedString>
FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
return VariantConstRef(objectGet(_data, key));
}
};
@ -170,30 +166,34 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
return _data->copyFrom(*src._data, _pool);
}
// Gets the value associated with the specified key.
//
// VariantRef get<TValue>(TKey) const;
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE VariantRef get(const TKey& key) const {
return get_impl(wrapString(key));
}
//
// VariantRef get<TValue>(TKey) const;
// TKey = char*, const char*, const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE VariantRef get(TKey* key) const {
return get_impl(wrapString(key));
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE VariantRef get(const TString& key) const {
return get_impl(adaptString(key));
}
template <typename TKey>
FORCE_INLINE VariantRef getOrCreate(TKey* key) const {
return getOrCreate_impl(wrapString(key));
// get(char*) const
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar* key) const {
return get_impl(adaptString(key));
}
template <typename TKey>
FORCE_INLINE VariantRef getOrCreate(const TKey& key) const {
return getOrCreate_impl(wrapString(key));
// getOrCreate(const std::string&) const
// getOrCreate(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString& key) const {
return getOrCreate_impl(adaptString(key));
}
// getOrCreate(char*) const
// getOrCreate(const char*) const
// getOrCreate(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar* key) const {
return getOrCreate_impl(adaptString(key));
}
FORCE_INLINE bool operator==(ObjectRef rhs) const {
@ -205,30 +205,29 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
_data->remove(it.internal());
}
// Removes the specified key and the associated value.
//
// void remove(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE void remove(const TKey& key) const {
objectRemove(_data, wrapString(key));
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE void remove(const TString& key) const {
objectRemove(_data, adaptString(key));
}
//
// void remove(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE void remove(TKey* key) const {
objectRemove(_data, wrapString(key));
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE void remove(TChar* key) const {
objectRemove(_data, adaptString(key));
}
private:
template <typename TKey>
FORCE_INLINE VariantRef get_impl(TKey key) const {
template <typename TAdaptedString>
FORCE_INLINE VariantRef get_impl(TAdaptedString key) const {
return VariantRef(_pool, objectGet(_data, key));
}
template <typename TKey>
FORCE_INLINE VariantRef getOrCreate_impl(TKey key) const {
template <typename TAdaptedString>
FORCE_INLINE VariantRef getOrCreate_impl(TAdaptedString key) const {
return VariantRef(_pool, objectGetOrCreate(_data, key, _pool));
}

View File

@ -6,52 +6,52 @@
#include "../Polyfills/attributes.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Strings/StringWrappers.hpp"
#include "../Strings/StringAdapters.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TParent, typename TKey>
template <typename TParent, typename TStringRef>
class MemberProxy;
template <typename TObject>
class ObjectShortcuts {
public:
// MemberProxy operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TKey>
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TKey>::value,
MemberProxy<const TObject &, const TKey &> >::type
operator[](const TKey &key) const;
//
// MemberProxy operator[](TKey) const;
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey *>::value,
MemberProxy<const TObject &, TKey *> >::type
operator[](TKey *key) const;
typename enable_if<IsString<TString>::value,
MemberProxy<const TObject &, const TString &> >::type
operator[](const TString &key) const;
// Creates and adds a ArrayRef.
//
// ArrayRef createNestedArray(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
FORCE_INLINE ArrayRef createNestedArray(const TKey &key) const;
// ArrayRef createNestedArray(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
FORCE_INLINE ArrayRef createNestedArray(TKey *key) const;
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value,
MemberProxy<const TObject &, TChar *> >::type
operator[](TChar *key) const;
// Creates and adds a ObjectRef.
//
// ObjectRef createNestedObject(TKey);
// TKey = const std::string&, const String&
template <typename TKey>
ObjectRef createNestedObject(const TKey &key) const;
//
// ObjectRef createNestedObject(TKey);
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
template <typename TKey>
ObjectRef createNestedObject(TKey *key) const;
// createNestedArray(const std::string&) const
// createNestedArray(const String&) const
template <typename TString>
FORCE_INLINE ArrayRef createNestedArray(const TString &key) const;
// createNestedArray(char*) const
// createNestedArray(const char*) const
// createNestedArray(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE ArrayRef createNestedArray(TChar *key) const;
// createNestedObject(const std::string&) const
// createNestedObject(const String&) const
template <typename TString>
ObjectRef createNestedObject(const TString &key) const;
// createNestedObject(char*) const
// createNestedObject(const char*) const
// createNestedObject(const __FlashStringHelper*) const
template <typename TChar>
ObjectRef createNestedObject(TChar *key) const;
private:
const TObject *impl() const {

View File

@ -13,7 +13,7 @@ class Pair {
public:
Pair(MemoryPool* pool, VariantSlot* slot) {
if (slot) {
_key = slot->key();
_key = String(slot->key(), !slot->ownsKey());
_value = VariantRef(pool, slot->data());
}
}
@ -35,7 +35,7 @@ class PairConst {
public:
PairConst(const VariantSlot* slot) {
if (slot) {
_key = slot->key();
_key = String(slot->key(), !slot->ownsKey());
_value = VariantConstRef(slot->data());
}
}

View File

@ -21,28 +21,28 @@ class VariantComparisons {
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
T *lhs, TVariant rhs) {
return wrapString(lhs).equals(rhs.template as<const char *>());
return adaptString(lhs).equals(rhs.template as<const char *>());
}
// std::string == TVariant
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==(
const T &lhs, TVariant rhs) {
return wrapString(lhs).equals(rhs.template as<const char *>());
return adaptString(lhs).equals(rhs.template as<const char *>());
}
// TVariant == const char*
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==(
TVariant lhs, T *rhs) {
return wrapString(rhs).equals(lhs.template as<const char *>());
return adaptString(rhs).equals(lhs.template as<const char *>());
}
// TVariant == std::string
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
return wrapString(rhs).equals(lhs.template as<const char *>());
return adaptString(rhs).equals(lhs.template as<const char *>());
}
// bool/int/float == TVariant
@ -63,28 +63,28 @@ class VariantComparisons {
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
T *lhs, TVariant rhs) {
return !wrapString(lhs).equals(rhs.template as<const char *>());
return !adaptString(lhs).equals(rhs.template as<const char *>());
}
// std::string != TVariant
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
const T &lhs, TVariant rhs) {
return !wrapString(lhs).equals(rhs.template as<const char *>());
return !adaptString(lhs).equals(rhs.template as<const char *>());
}
// TVariant != const char*
template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
TVariant lhs, T *rhs) {
return !wrapString(rhs).equals(lhs.template as<const char *>());
return !adaptString(rhs).equals(lhs.template as<const char *>());
}
// TVariant != std::string
template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
return !wrapString(rhs).equals(lhs.template as<const char *>());
return !adaptString(rhs).equals(lhs.template as<const char *>());
}
// bool/int/float != TVariant

View File

@ -8,9 +8,9 @@
namespace ARDUINOJSON_NAMESPACE {
class ArduinoStringWrapper {
class ArduinoStringAdapter {
public:
ArduinoStringWrapper(const ::String& str) : _str(&str) {}
ArduinoStringAdapter(const ::String& str) : _str(&str) {}
char* save(MemoryPool* pool) const {
if (isNull()) return NULL;
@ -40,6 +40,10 @@ class ArduinoStringWrapper {
return _str->length();
}
bool isStatic() const {
return false;
}
private:
const ::String* _str;
};
@ -50,8 +54,8 @@ struct IsString< ::String> : true_type {};
template <>
struct IsString< ::StringSumHelper> : true_type {};
inline ArduinoStringWrapper wrapString(const ::String& str) {
return ArduinoStringWrapper(str);
inline ArduinoStringAdapter adaptString(const ::String& str) {
return ArduinoStringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -9,9 +9,9 @@
namespace ARDUINOJSON_NAMESPACE {
class ConstRamStringWrapper {
class ConstRamStringAdapter {
public:
ConstRamStringWrapper(const char* str = 0) : _str(str) {}
ConstRamStringAdapter(const char* str = 0) : _str(str) {}
bool equals(const char* expected) const {
const char* actual = _str;
@ -23,25 +23,29 @@ class ConstRamStringWrapper {
return !_str;
}
// template <typename TMemoryPool>
// const char* save(TMemoryPool*) const {
// return _str;
// }
template <typename TMemoryPool>
char* save(TMemoryPool*) const {
return 0;
}
size_t size() const {
return strlen(_str);
}
const char* c_str() const {
const char* data() const {
return _str;
}
bool isStatic() const {
return true;
}
protected:
const char* _str;
};
inline ConstRamStringWrapper wrapString(const char* str) {
return ConstRamStringWrapper(str);
inline ConstRamStringAdapter adaptString(const char* str) {
return ConstRamStringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -6,9 +6,9 @@
namespace ARDUINOJSON_NAMESPACE {
class FlashStringWrapper {
class FlashStringAdapter {
public:
FlashStringWrapper(const __FlashStringHelper* str) : _str(str) {}
FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {}
bool equals(const char* expected) const {
const char* actual = reinterpret_cast<const char*>(_str);
@ -28,16 +28,24 @@ class FlashStringWrapper {
return dup;
}
const char* data() const {
return 0;
}
size_t size() const {
return strlen_P(reinterpret_cast<const char*>(_str));
}
bool isStatic() const {
return false;
}
private:
const __FlashStringHelper* _str;
};
inline FlashStringWrapper wrapString(const __FlashStringHelper* str) {
return FlashStringWrapper(str);
inline FlashStringAdapter adaptString(const __FlashStringHelper* str) {
return FlashStringAdapter(str);
}
template <>

View File

@ -4,13 +4,13 @@
#pragma once
#include "ConstRamStringWrapper.hpp"
#include "ConstRamStringAdapter.hpp"
namespace ARDUINOJSON_NAMESPACE {
class RamStringWrapper : public ConstRamStringWrapper {
class RamStringAdapter : public ConstRamStringAdapter {
public:
RamStringWrapper(const char* str) : ConstRamStringWrapper(str) {}
RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
char* save(MemoryPool* pool) const {
if (!_str) return NULL;
@ -19,15 +19,19 @@ class RamStringWrapper : public ConstRamStringWrapper {
if (dup) memcpy(dup, _str, n);
return dup;
}
bool isStatic() const {
return false;
}
};
template <typename TChar>
inline RamStringWrapper wrapString(const TChar* str) {
return RamStringWrapper(reinterpret_cast<const char*>(str));
inline RamStringAdapter adaptString(const TChar* str) {
return RamStringAdapter(reinterpret_cast<const char*>(str));
}
inline RamStringWrapper wrapString(char* str) {
return RamStringWrapper(str);
inline RamStringAdapter adaptString(char* str) {
return RamStringAdapter(str);
}
template <typename TChar>

View File

@ -6,9 +6,9 @@
namespace ARDUINOJSON_NAMESPACE {
class SizedFlashStringWrapper {
class SizedFlashStringAdapter {
public:
SizedFlashStringWrapper(const __FlashStringHelper* str, size_t sz)
SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz)
: _str(str), _size(sz) {}
bool equals(const char* expected) const {
@ -32,13 +32,17 @@ class SizedFlashStringWrapper {
return strlen_P(reinterpret_cast<const char*>(_str));
}
bool isStatic() const {
return false;
}
private:
const __FlashStringHelper* _str;
size_t _size;
};
inline SizedFlashStringWrapper wrapString(const __FlashStringHelper* str,
inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str,
size_t sz) {
return SizedFlashStringWrapper(str, sz);
return SizedFlashStringAdapter(str, sz);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,9 +8,9 @@
namespace ARDUINOJSON_NAMESPACE {
class SizedRamStringWrapper {
class SizedRamStringAdapter {
public:
SizedRamStringWrapper(const char* str, size_t n) : _str(str), _size(n) {}
SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {}
bool equals(const char* expected) const {
const char* actual = reinterpret_cast<const char*>(_str);
@ -33,14 +33,18 @@ class SizedRamStringWrapper {
return strlen(reinterpret_cast<const char*>(_str));
}
bool isStatic() const {
return false;
}
private:
const char* _str;
size_t _size;
};
template <typename TChar>
inline SizedRamStringWrapper wrapString(const TChar* str, size_t size) {
return SizedRamStringWrapper(reinterpret_cast<const char*>(str), size);
inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) {
return SizedRamStringAdapter(reinterpret_cast<const char*>(str), size);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -8,9 +8,9 @@
namespace ARDUINOJSON_NAMESPACE {
class StlStringWrapper {
class StlStringAdapter {
public:
StlStringWrapper(const std::string& str) : _str(&str) {}
StlStringAdapter(const std::string& str) : _str(&str) {}
char* save(MemoryPool* pool) const {
size_t n = _str->length() + 1;
@ -36,6 +36,10 @@ class StlStringWrapper {
return _str->size();
}
bool isStatic() const {
return false;
}
private:
const std::string* _str;
};
@ -43,8 +47,8 @@ class StlStringWrapper {
template <>
struct IsString<std::string> : true_type {};
inline StlStringWrapper wrapString(const std::string& str) {
return StlStringWrapper(str);
inline StlStringAdapter adaptString(const std::string& str) {
return StlStringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,12 +4,15 @@
#pragma once
#include "ConstRamStringAdapter.hpp"
namespace ARDUINOJSON_NAMESPACE {
class String {
public:
String() : _data(0) {}
String(const char* slot) : _data(slot) {}
String() : _data(0), _isStatic(true) {}
String(const char* data, bool isStaticData = true)
: _data(data), _isStatic(isStaticData) {}
const char* c_str() const {
return _data;
@ -19,6 +22,10 @@ class String {
return !_data;
}
bool isStatic() const {
return _isStatic;
}
friend bool operator==(String lhs, String rhs) {
if (lhs._data == rhs._data) return true;
if (!lhs._data) return false;
@ -28,5 +35,31 @@ class String {
private:
const char* _data;
bool _isStatic;
};
class StringAdapter : public RamStringAdapter {
public:
StringAdapter(const String& str)
: RamStringAdapter(str.c_str()), _isStatic(str.isStatic()) {}
bool isStatic() const {
return _isStatic;
}
/* const char* save(MemoryPool* pool) const {
if (_isStatic) return c_str();
return RamStringAdapter::save(pool);
}*/
private:
bool _isStatic;
};
template <>
struct IsString<String> : true_type {};
inline StringAdapter adaptString(const String& str) {
return StringAdapter(str);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -18,19 +18,19 @@ template <typename T>
struct IsString<T&> : IsString<T> {};
} // namespace ARDUINOJSON_NAMESPACE
#include "ConstRamStringWrapper.hpp"
#include "RamStringWrapper.hpp"
#include "SizedRamStringWrapper.hpp"
#include "ConstRamStringAdapter.hpp"
#include "RamStringAdapter.hpp"
#include "SizedRamStringAdapter.hpp"
#if ARDUINOJSON_ENABLE_STD_STRING
#include "StlStringWrapper.hpp"
#include "StlStringAdapter.hpp"
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include "ArduinoStringWrapper.hpp"
#include "ArduinoStringAdapter.hpp"
#endif
#if ARDUINOJSON_ENABLE_PROGMEM
#include "FlashStringWrapper.hpp"
#include "SizedFlashStringWrapper.hpp"
#include "FlashStringAdapter.hpp"
#include "SizedFlashStringAdapter.hpp"
#endif

View File

@ -6,24 +6,21 @@
#include "../Memory/MemoryPool.hpp"
#include "../Polyfills/assert.hpp"
#include "../Strings/StringWrappers.hpp"
#include "../Strings/StringAdapters.hpp"
#include "VariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
if (!var) return false;
if (key.isStatic()) {
var->setLinkedKey(key.data());
} else {
char* dup = key.save(pool);
if (!dup) return false;
var->setOwnedKey(dup);
return true;
}
inline bool slotSetKey(VariantSlot* var, ConstRamStringWrapper key,
MemoryPool*) {
if (!var) return false;
var->setLinkedKey(key.c_str());
return true;
}

View File

@ -89,7 +89,7 @@ class VariantData {
case VALUE_IS_OBJECT:
return toObject().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OWNED_STRING:
return setOwnedString(RamStringWrapper(src._content.asString), pool);
return setOwnedString(RamStringAdapter(src._content.asString), pool);
case VALUE_IS_OWNED_RAW:
return setOwnedRaw(
serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
@ -186,7 +186,7 @@ class VariantData {
template <typename T>
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
char *dup = wrapString(value.data(), value.size()).save(pool);
char *dup = adaptString(value.data(), value.size()).save(pool);
if (dup) {
setType(VALUE_IS_OWNED_RAW);
_content.asRaw.data = dup;
@ -289,13 +289,13 @@ class VariantData {
return isArray() ? _content.asCollection.get(index) : 0;
}
template <typename TKey>
VariantData *get(TKey key) const {
template <typename TAdaptedString>
VariantData *get(TAdaptedString key) const {
return isObject() ? _content.asCollection.get(key) : 0;
}
template <typename TKey>
VariantData *getOrCreate(TKey key, MemoryPool *pool) {
template <typename TAdaptedString>
VariantData *getOrCreate(TAdaptedString key, MemoryPool *pool) {
if (isNull()) toObject();
if (!isObject()) return 0;
VariantData *var = _content.asCollection.get(key);

View File

@ -150,16 +150,16 @@ inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) {
return var != 0 ? var->add(pool) : 0;
}
template <typename TKey>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TKey *key,
template <typename TChar>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key,
MemoryPool *pool) {
return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0;
return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
}
template <typename TKey>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TKey &key,
template <typename TString>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key,
MemoryPool *pool) {
return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0;
return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -110,24 +110,24 @@ inline VariantRef VariantRef::get(size_t index) const {
return VariantRef(_pool, _data != 0 ? _data->get(index) : 0);
}
template <typename TKey>
inline VariantRef VariantRef::get(TKey *key) const {
return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0);
template <typename TChar>
inline VariantRef VariantRef::get(TChar *key) const {
return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
}
template <typename TKey>
inline typename enable_if<IsString<TKey>::value, VariantRef>::type
VariantRef::get(const TKey &key) const {
return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0);
template <typename TString>
inline typename enable_if<IsString<TString>::value, VariantRef>::type
VariantRef::get(const TString &key) const {
return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
}
template <typename TKey>
inline VariantRef VariantRef::getOrCreate(TKey *key) const {
template <typename TChar>
inline VariantRef VariantRef::getOrCreate(TChar *key) const {
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
}
template <typename TKey>
inline VariantRef VariantRef::getOrCreate(const TKey &key) const {
template <typename TString>
inline VariantRef VariantRef::getOrCreate(const TString &key) const {
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -194,7 +194,7 @@ class VariantRef : public VariantRefBase<VariantData>,
FORCE_INLINE bool set(
const T &value,
typename enable_if<IsString<T>::value>::type * = 0) const {
return variantSetOwnedString(_data, wrapString(value), _pool);
return variantSetOwnedString(_data, adaptString(value), _pool);
}
// set(char*)
@ -202,7 +202,7 @@ class VariantRef : public VariantRefBase<VariantData>,
template <typename T>
FORCE_INLINE bool set(
T *value, typename enable_if<IsString<T *>::value>::type * = 0) const {
return variantSetOwnedString(_data, wrapString(value), _pool);
return variantSetOwnedString(_data, adaptString(value), _pool);
}
// set(const char*);
@ -285,20 +285,27 @@ class VariantRef : public VariantRefBase<VariantData>,
FORCE_INLINE VariantRef get(size_t) const;
template <typename TKey>
FORCE_INLINE VariantRef get(TKey *) const;
// get(const char*) const
// get(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef get(TChar *) const;
// get(const char*)
// get(const __FlashStringHelper*)
template <typename TKey>
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get(
const TKey &) const;
// get(const std::string&) const
// get(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
get(const TString &) const;
template <typename TKey>
FORCE_INLINE VariantRef getOrCreate(TKey *) const;
// getOrCreate(char*) const
// getOrCreate(const char*) const
// getOrCreate(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrCreate(TChar *) const;
template <typename TKey>
FORCE_INLINE VariantRef getOrCreate(const TKey &) const;
// getOrCreate(const std::string&) const
// getOrCreate(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrCreate(const TString &) const;
private:
MemoryPool *_pool;
@ -329,24 +336,24 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
FORCE_INLINE VariantConstRef operator[](size_t index) const;
//
// const VariantConstRef operator[](TKey) const;
// TKey = const std::string&, const String&
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString &key) const {
return VariantConstRef(objectGet(variantAsObject(_data), wrapString(key)));
return VariantConstRef(objectGet(variantAsObject(_data), adaptString(key)));
}
//
// VariantConstRef operator[](TKey);
// TKey = const char*, const char[N], const __FlashStringHelper*
template <typename TString>
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TString *>::value, VariantConstRef>::type
operator[](TString *key) const {
typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
operator[](TChar *key) const {
const CollectionData *obj = variantAsObject(_data);
return VariantConstRef(obj ? obj->get(wrapString(key)) : 0);
return VariantConstRef(obj ? obj->get(adaptString(key)) : 0);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -141,6 +141,18 @@ TEST_CASE("JsonObject::operator[]") {
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);
REQUIRE(expectedSize == doc.memoryUsage());
}
SECTION("should not duplicate a static JsonString key") {
obj[JsonString("hello", true)] = "world";
const size_t expectedSize = JSON_OBJECT_SIZE(1);
REQUIRE(expectedSize == doc.memoryUsage());
}
SECTION("should ignore null key") {
// object must have a value to make a call to strcmp()
obj["dummy"] = 42;

View File

@ -71,6 +71,26 @@ TEST_CASE("JsonVariant and strings") {
REQUIRE(variant == "hello");
}
SECTION("stores static JsonString by reference") {
char str[16];
strcpy(str, "hello");
variant.set(JsonString(str, true));
strcpy(str, "world");
REQUIRE(variant == "hello");
}
SECTION("stores non-static JsonString by copy") {
char str[16];
strcpy(str, "hello");
variant.set(JsonString(str, false));
strcpy(str, "world");
REQUIRE(variant == "hello");
}
}
TEST_CASE("JsonVariant with not enough memory") {