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`. * `JsonDocument` now support the same operations as `JsonVariant`.
Calling `JsonDocument::as<T>()` is not required anymore. Calling `JsonDocument::as<T>()` is not required anymore.
* Fixed example `JsonHttpClient.ino` * Fixed example `JsonHttpClient.ino`
* User can now use a `JsonString` as a key or a value
> ### BREAKING CHANGES > ### BREAKING CHANGES
> >

View File

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

View File

@ -29,8 +29,8 @@ inline VariantData* CollectionData::add(MemoryPool* pool) {
return addSlot(pool)->data(); return addSlot(pool)->data();
} }
template <typename TKey> template <typename TAdaptedString>
inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) { inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
VariantSlot* slot = addSlot(pool); VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) return 0; if (!slotSetKey(slot, key, pool)) return 0;
return slot->data(); return slot->data();
@ -41,8 +41,8 @@ inline void CollectionData::clear() {
_tail = 0; _tail = 0;
} }
template <typename TKey> template <typename TAdaptedString>
inline bool CollectionData::containsKey(const TKey& key) const { inline bool CollectionData::containsKey(const TAdaptedString& key) const {
return getSlot(key) != 0; return getSlot(key) != 0;
} }
@ -53,9 +53,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
VariantData* var; VariantData* var;
if (s->key() != 0) { if (s->key() != 0) {
if (s->ownsKey()) if (s->ownsKey())
var = add(RamStringWrapper(s->key()), pool); var = add(RamStringAdapter(s->key()), pool);
else else
var = add(ConstRamStringWrapper(s->key()), pool); var = add(ConstRamStringAdapter(s->key()), pool);
} else { } else {
var = add(pool); var = add(pool);
} }
@ -69,7 +69,7 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const {
size_t count = 0; size_t count = 0;
for (VariantSlot* slot = _head; slot; slot = slot->next()) { for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data(); VariantData* v1 = slot->data();
VariantData* v2 = other.get(wrapString(slot->key())); VariantData* v2 = other.get(adaptString(slot->key()));
if (!variantEquals(v1, v2)) return false; if (!variantEquals(v1, v2)) return false;
count++; count++;
} }
@ -88,8 +88,8 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const {
} }
} }
template <typename TKey> template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TKey key) const { inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
VariantSlot* slot = _head; VariantSlot* slot = _head;
while (slot) { while (slot) {
if (key.equals(slot->key())) break; if (key.equals(slot->key())) break;
@ -112,8 +112,8 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
return 0; return 0;
} }
template <typename TKey> template <typename TAdaptedString>
inline VariantData* CollectionData::get(TKey key) const { inline VariantData* CollectionData::get(TAdaptedString key) const {
VariantSlot* slot = getSlot(key); VariantSlot* slot = getSlot(key);
return slot ? slot->data() : 0; 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); return TDeserializer<TReader, TWriter>(pool, reader, writer, nestingLimit);
} }
// DeserializationError deserialize(JsonDocument& doc, TString input); // deserialize(JsonDocument&, const std::string&);
// TString = const std::string&, const String& // deserialize(JsonDocument&, const String&);
template <template <typename, typename> class TDeserializer, typename TString> template <template <typename, typename> class TDeserializer, typename TString>
typename enable_if<!is_array<TString>::value, DeserializationError>::type typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(JsonDocument &doc, const TString &input, deserialize(JsonDocument &doc, const TString &input,
@ -36,8 +36,9 @@ deserialize(JsonDocument &doc, const TString &input,
.parse(doc.data()); .parse(doc.data());
} }
// //
// DeserializationError deserialize(JsonDocument& doc, TChar* input); // deserialize(JsonDocument&, char*);
// TChar* = char*, const char*, const __FlashStringHelper* // deserialize(JsonDocument&, const char*);
// deserialize(JsonDocument&, const __FlashStringHelper*);
template <template <typename, typename> class TDeserializer, typename TChar> template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input, DeserializationError deserialize(JsonDocument &doc, TChar *input,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
@ -48,9 +49,9 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
.parse(doc.data()); .parse(doc.data());
} }
// //
// DeserializationError deserialize(JsonDocument& doc, TChar* input, size_t // deserialize(JsonDocument&, char*, size_t);
// inputSize); // deserialize(JsonDocument&, const char*, size_t);
// TChar* = char*, const char*, const __FlashStringHelper* // deserialize(JsonDocument&, const __FlashStringHelper*, size_t);
template <template <typename, typename> class TDeserializer, typename TChar> template <template <typename, typename> class TDeserializer, typename TChar>
DeserializationError deserialize(JsonDocument &doc, TChar *input, DeserializationError deserialize(JsonDocument &doc, TChar *input,
size_t inputSize, NestingLimit nestingLimit) { size_t inputSize, NestingLimit nestingLimit) {
@ -61,8 +62,8 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
.parse(doc.data()); .parse(doc.data());
} }
// //
// DeserializationError deserialize(JsonDocument& doc, TStream input); // deserialize(JsonDocument&, std::istream&);
// TStream = std::istream&, Stream& // deserialize(JsonDocument&, Stream&);
template <template <typename, typename> class TDeserializer, typename TStream> template <template <typename, typename> class TDeserializer, typename TStream>
DeserializationError deserialize(JsonDocument &doc, TStream &input, DeserializationError deserialize(JsonDocument &doc, TStream &input,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -21,28 +21,28 @@ class VariantComparisons {
template <typename T> template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==( friend typename enable_if<IsString<T *>::value, bool>::type operator==(
T *lhs, TVariant rhs) { 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 // std::string == TVariant
template <typename T> template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==( friend typename enable_if<IsString<T>::value, bool>::type operator==(
const T &lhs, TVariant rhs) { 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* // TVariant == const char*
template <typename T> template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator==( friend typename enable_if<IsString<T *>::value, bool>::type operator==(
TVariant lhs, T *rhs) { 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 // TVariant == std::string
template <typename T> template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator==( friend typename enable_if<IsString<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) { 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 // bool/int/float == TVariant
@ -63,28 +63,28 @@ class VariantComparisons {
template <typename T> template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=( friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
T *lhs, TVariant rhs) { 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 // std::string != TVariant
template <typename T> template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=( friend typename enable_if<IsString<T>::value, bool>::type operator!=(
const T &lhs, TVariant rhs) { 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* // TVariant != const char*
template <typename T> template <typename T>
friend typename enable_if<IsString<T *>::value, bool>::type operator!=( friend typename enable_if<IsString<T *>::value, bool>::type operator!=(
TVariant lhs, T *rhs) { 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 // TVariant != std::string
template <typename T> template <typename T>
friend typename enable_if<IsString<T>::value, bool>::type operator!=( friend typename enable_if<IsString<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) { 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 // bool/int/float != TVariant

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,12 +4,15 @@
#pragma once #pragma once
#include "ConstRamStringAdapter.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class String { class String {
public: public:
String() : _data(0) {} String() : _data(0), _isStatic(true) {}
String(const char* slot) : _data(slot) {} String(const char* data, bool isStaticData = true)
: _data(data), _isStatic(isStaticData) {}
const char* c_str() const { const char* c_str() const {
return _data; return _data;
@ -19,6 +22,10 @@ class String {
return !_data; return !_data;
} }
bool isStatic() const {
return _isStatic;
}
friend bool operator==(String lhs, String rhs) { friend bool operator==(String lhs, String rhs) {
if (lhs._data == rhs._data) return true; if (lhs._data == rhs._data) return true;
if (!lhs._data) return false; if (!lhs._data) return false;
@ -28,5 +35,31 @@ class String {
private: private:
const char* _data; 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 } // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

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

View File

@ -89,7 +89,7 @@ class VariantData {
case VALUE_IS_OBJECT: case VALUE_IS_OBJECT:
return toObject().copyFrom(src._content.asCollection, pool); return toObject().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OWNED_STRING: case VALUE_IS_OWNED_STRING:
return setOwnedString(RamStringWrapper(src._content.asString), pool); return setOwnedString(RamStringAdapter(src._content.asString), pool);
case VALUE_IS_OWNED_RAW: case VALUE_IS_OWNED_RAW:
return setOwnedRaw( return setOwnedRaw(
serialized(src._content.asRaw.data, src._content.asRaw.size), pool); serialized(src._content.asRaw.data, src._content.asRaw.size), pool);
@ -186,7 +186,7 @@ class VariantData {
template <typename T> template <typename T>
bool setOwnedRaw(SerializedValue<T> value, MemoryPool *pool) { 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) { if (dup) {
setType(VALUE_IS_OWNED_RAW); setType(VALUE_IS_OWNED_RAW);
_content.asRaw.data = dup; _content.asRaw.data = dup;
@ -289,13 +289,13 @@ class VariantData {
return isArray() ? _content.asCollection.get(index) : 0; return isArray() ? _content.asCollection.get(index) : 0;
} }
template <typename TKey> template <typename TAdaptedString>
VariantData *get(TKey key) const { VariantData *get(TAdaptedString key) const {
return isObject() ? _content.asCollection.get(key) : 0; return isObject() ? _content.asCollection.get(key) : 0;
} }
template <typename TKey> template <typename TAdaptedString>
VariantData *getOrCreate(TKey key, MemoryPool *pool) { VariantData *getOrCreate(TAdaptedString key, MemoryPool *pool) {
if (isNull()) toObject(); if (isNull()) toObject();
if (!isObject()) return 0; if (!isObject()) return 0;
VariantData *var = _content.asCollection.get(key); 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; return var != 0 ? var->add(pool) : 0;
} }
template <typename TKey> template <typename TChar>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TKey *key, NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key,
MemoryPool *pool) { MemoryPool *pool) {
return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0; return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
} }
template <typename TKey> template <typename TString>
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TKey &key, NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key,
MemoryPool *pool) { MemoryPool *pool) {
return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0; return var != 0 ? var->getOrCreate(adaptString(key), pool) : 0;
} }
} // namespace ARDUINOJSON_NAMESPACE } // 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); return VariantRef(_pool, _data != 0 ? _data->get(index) : 0);
} }
template <typename TKey> template <typename TChar>
inline VariantRef VariantRef::get(TKey *key) const { inline VariantRef VariantRef::get(TChar *key) const {
return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0); return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
} }
template <typename TKey> template <typename TString>
inline typename enable_if<IsString<TKey>::value, VariantRef>::type inline typename enable_if<IsString<TString>::value, VariantRef>::type
VariantRef::get(const TKey &key) const { VariantRef::get(const TString &key) const {
return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0); return VariantRef(_pool, _data != 0 ? _data->get(adaptString(key)) : 0);
} }
template <typename TKey> template <typename TChar>
inline VariantRef VariantRef::getOrCreate(TKey *key) const { inline VariantRef VariantRef::getOrCreate(TChar *key) const {
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
} }
template <typename TKey> template <typename TString>
inline VariantRef VariantRef::getOrCreate(const TKey &key) const { inline VariantRef VariantRef::getOrCreate(const TString &key) const {
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool)); return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

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

View File

@ -71,6 +71,26 @@ TEST_CASE("JsonVariant and strings") {
REQUIRE(variant == "hello"); 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") { TEST_CASE("JsonVariant with not enough memory") {