forked from bblanchon/ArduinoJson
Changed the array subscript to automatically add missing elements
This commit is contained in:
@ -9,7 +9,7 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
|
||||
return arr ? arr->add(pool) : 0;
|
||||
return arr ? arr->addElement(pool) : 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
|
@ -87,7 +87,7 @@ class ArrayConstRef : public ArrayRefBase<const CollectionData>,
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantConstRef getElement(size_t index) const {
|
||||
return VariantConstRef(_data ? _data->get(index) : 0);
|
||||
return VariantConstRef(_data ? _data->getElement(index) : 0);
|
||||
}
|
||||
};
|
||||
|
||||
@ -137,23 +137,28 @@ class ArrayRef : public ArrayRefBase<CollectionData>,
|
||||
return arrayEquals(_data, rhs._data);
|
||||
}
|
||||
|
||||
// Internal use
|
||||
FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
|
||||
return VariantRef(_pool, _data ? _data->getOrAddElement(index, _pool) : 0);
|
||||
}
|
||||
|
||||
// Gets the value at the specified index.
|
||||
FORCE_INLINE VariantRef getElement(size_t index) const {
|
||||
return VariantRef(_pool, _data ? _data->get(index) : 0);
|
||||
return VariantRef(_pool, _data ? _data->getElement(index) : 0);
|
||||
}
|
||||
|
||||
// Removes element at specified position.
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->remove(it.internal());
|
||||
_data->removeSlot(it.internal());
|
||||
}
|
||||
|
||||
// Removes element at specified index.
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->remove(index);
|
||||
_data->removeElement(index);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -28,7 +28,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
: _array(src._array), _index(src._index) {}
|
||||
|
||||
FORCE_INLINE this_type& operator=(const this_type& src) {
|
||||
getUpstreamElement().set(src.as<VariantConstRef>());
|
||||
getOrAddUpstreamElement().set(src.as<VariantConstRef>());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename T>
|
||||
FORCE_INLINE this_type& operator=(const T& src) {
|
||||
getUpstreamElement().set(src);
|
||||
getOrAddUpstreamElement().set(src);
|
||||
return *this;
|
||||
}
|
||||
//
|
||||
@ -47,7 +47,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename T>
|
||||
FORCE_INLINE this_type& operator=(T* src) {
|
||||
getUpstreamElement().set(src);
|
||||
getOrAddUpstreamElement().set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE typename VariantTo<T>::type to() const {
|
||||
return getUpstreamElement().template to<T>();
|
||||
return getOrAddUpstreamElement().template to<T>();
|
||||
}
|
||||
|
||||
// Replaces the value
|
||||
@ -89,14 +89,14 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
// std::string, String, ArrayRef, ObjectRef
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(const TValue& value) const {
|
||||
return getUpstreamElement().set(value);
|
||||
return getOrAddUpstreamElement().set(value);
|
||||
}
|
||||
//
|
||||
// bool set(TValue)
|
||||
// TValue = char*, const char*, const __FlashStringHelper*
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue* value) const {
|
||||
return getUpstreamElement().set(value);
|
||||
return getOrAddUpstreamElement().set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
@ -120,20 +120,20 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getOrAddMember(TNestedKey* key) const {
|
||||
return getUpstreamElement().getOrAddMember(key);
|
||||
return getOrAddUpstreamElement().getOrAddMember(key);
|
||||
}
|
||||
|
||||
template <typename TNestedKey>
|
||||
VariantRef getOrAddMember(const TNestedKey& key) const {
|
||||
return getUpstreamElement().getOrAddMember(key);
|
||||
return getOrAddUpstreamElement().getOrAddMember(key);
|
||||
}
|
||||
|
||||
VariantRef addElement() const {
|
||||
return getUpstreamElement().addElement();
|
||||
return getOrAddUpstreamElement().addElement();
|
||||
}
|
||||
|
||||
VariantRef getElement(size_t index) const {
|
||||
return getUpstreamElement().getElement(index);
|
||||
return getOrAddUpstreamElement().getElement(index);
|
||||
}
|
||||
|
||||
FORCE_INLINE void remove(size_t index) const {
|
||||
@ -160,6 +160,10 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
return _array.getElement(_index);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef getOrAddUpstreamElement() const {
|
||||
return _array.getOrAddElement(_index);
|
||||
}
|
||||
|
||||
TArray _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
@ -25,45 +25,56 @@ class CollectionData {
|
||||
// - no destructor
|
||||
// - no virtual
|
||||
// - no inheritance
|
||||
VariantSlot *addSlot(MemoryPool *);
|
||||
|
||||
VariantData *add(MemoryPool *pool);
|
||||
// Array only
|
||||
|
||||
VariantData *addElement(MemoryPool *pool);
|
||||
|
||||
VariantData *getElement(size_t index) const;
|
||||
|
||||
VariantData *getOrAddElement(size_t index, MemoryPool *pool);
|
||||
|
||||
void removeElement(size_t index);
|
||||
|
||||
bool equalsArray(const CollectionData &other) const;
|
||||
|
||||
// Object only
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *add(TAdaptedString key, MemoryPool *pool);
|
||||
VariantData *addMember(TAdaptedString key, MemoryPool *pool);
|
||||
|
||||
void clear();
|
||||
template <typename TAdaptedString>
|
||||
VariantData *getMember(TAdaptedString key) const;
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void removeMember(TAdaptedString key) {
|
||||
removeSlot(getSlot(key));
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
bool containsKey(const TAdaptedString &key) const;
|
||||
|
||||
bool copyFrom(const CollectionData &src, MemoryPool *pool);
|
||||
|
||||
bool equalsArray(const CollectionData &other) const;
|
||||
bool equalsObject(const CollectionData &other) const;
|
||||
|
||||
VariantData *get(size_t index) const;
|
||||
// Generic
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *get(TAdaptedString key) const;
|
||||
void clear();
|
||||
size_t memoryUsage() const;
|
||||
size_t nesting() const;
|
||||
size_t size() const;
|
||||
|
||||
VariantSlot *addSlot(MemoryPool *);
|
||||
void removeSlot(VariantSlot *slot);
|
||||
|
||||
bool copyFrom(const CollectionData &src, MemoryPool *pool);
|
||||
|
||||
VariantSlot *head() const {
|
||||
return _head;
|
||||
}
|
||||
|
||||
void remove(size_t index);
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void remove(TAdaptedString key) {
|
||||
remove(getSlot(key));
|
||||
}
|
||||
|
||||
void remove(VariantSlot *slot);
|
||||
|
||||
size_t memoryUsage() const;
|
||||
size_t nesting() const;
|
||||
size_t size() const;
|
||||
|
||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
|
||||
|
||||
private:
|
||||
|
@ -26,12 +26,13 @@ inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::add(MemoryPool* pool) {
|
||||
inline VariantData* CollectionData::addElement(MemoryPool* pool) {
|
||||
return slotData(addSlot(pool));
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
|
||||
inline VariantData* CollectionData::addMember(TAdaptedString key,
|
||||
MemoryPool* pool) {
|
||||
VariantSlot* slot = addSlot(pool);
|
||||
if (!slotSetKey(slot, key, pool))
|
||||
return 0;
|
||||
@ -55,11 +56,11 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
|
||||
VariantData* var;
|
||||
if (s->key() != 0) {
|
||||
if (s->ownsKey())
|
||||
var = add(RamStringAdapter(s->key()), pool);
|
||||
var = addMember(RamStringAdapter(s->key()), pool);
|
||||
else
|
||||
var = add(ConstRamStringAdapter(s->key()), pool);
|
||||
var = addMember(ConstRamStringAdapter(s->key()), pool);
|
||||
} else {
|
||||
var = add(pool);
|
||||
var = addElement(pool);
|
||||
}
|
||||
if (!var)
|
||||
return false;
|
||||
@ -73,7 +74,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(adaptString(slot->key()));
|
||||
VariantData* v2 = other.getMember(adaptString(slot->key()));
|
||||
if (!variantEquals(v1, v2))
|
||||
return false;
|
||||
count++;
|
||||
@ -123,17 +124,40 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* CollectionData::get(TAdaptedString key) const {
|
||||
inline VariantData* CollectionData::getMember(TAdaptedString key) const {
|
||||
VariantSlot* slot = getSlot(key);
|
||||
return slot ? slot->data() : 0;
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::get(size_t index) const {
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
|
||||
MemoryPool* pool) {
|
||||
VariantSlot* slot = getSlot(key);
|
||||
return slot ? slot->data() : addMember(key, pool);
|
||||
}
|
||||
|
||||
inline VariantData* CollectionData::getElement(size_t index) const {
|
||||
VariantSlot* slot = getSlot(index);
|
||||
return slot ? slot->data() : 0;
|
||||
}
|
||||
|
||||
inline void CollectionData::remove(VariantSlot* slot) {
|
||||
inline VariantData* CollectionData::getOrAddElement(size_t index,
|
||||
MemoryPool* pool) {
|
||||
VariantSlot* slot = _head;
|
||||
while (slot && index > 0) {
|
||||
slot = slot->next();
|
||||
index--;
|
||||
}
|
||||
if (!slot)
|
||||
index++;
|
||||
while (index > 0) {
|
||||
slot = addSlot(pool);
|
||||
index--;
|
||||
}
|
||||
return slotData(slot);
|
||||
}
|
||||
|
||||
inline void CollectionData::removeSlot(VariantSlot* slot) {
|
||||
if (!slot)
|
||||
return;
|
||||
VariantSlot* prev = getPreviousSlot(slot);
|
||||
@ -146,8 +170,8 @@ inline void CollectionData::remove(VariantSlot* slot) {
|
||||
_tail = prev;
|
||||
}
|
||||
|
||||
inline void CollectionData::remove(size_t index) {
|
||||
remove(getSlot(index));
|
||||
inline void CollectionData::removeElement(size_t index) {
|
||||
removeSlot(getSlot(index));
|
||||
}
|
||||
|
||||
inline size_t CollectionData::memoryUsage() const {
|
||||
|
@ -192,6 +192,10 @@ class JsonDocument : public Visitable {
|
||||
return VariantConstRef(_data.getElement(index));
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef getOrAddElement(size_t index) {
|
||||
return VariantRef(&_pool, _data.getOrAddElement(index, &_pool));
|
||||
}
|
||||
|
||||
// JsonVariantConst getMember(char*) const
|
||||
// JsonVariantConst getMember(const char*) const
|
||||
// JsonVariantConst getMember(const __FlashStringHelper*) const
|
||||
|
@ -139,7 +139,7 @@ class JsonDeserializer {
|
||||
for (;;) {
|
||||
if (memberFilter.allow()) {
|
||||
// Allocate slot in array
|
||||
VariantData *value = array.add(_pool);
|
||||
VariantData *value = array.addElement(_pool);
|
||||
if (!value)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
@ -231,7 +231,7 @@ class JsonDeserializer {
|
||||
TFilter memberFilter = filter[key];
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
VariantData *variant = object.get(adaptString(key));
|
||||
VariantData *variant = object.getMember(adaptString(key));
|
||||
if (!variant) {
|
||||
// Allocate slot in object
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
|
@ -269,7 +269,7 @@ class MsgPackDeserializer {
|
||||
return DeserializationError::TooDeep;
|
||||
|
||||
for (; n; --n) {
|
||||
VariantData *value = array.add(_pool);
|
||||
VariantData *value = array.addElement(_pool);
|
||||
if (!value)
|
||||
return DeserializationError::NoMemory;
|
||||
|
||||
|
@ -129,11 +129,14 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
|
||||
return getOrAddUpstreamMember().addElement();
|
||||
}
|
||||
|
||||
// getElement(size_t) const
|
||||
FORCE_INLINE VariantRef getElement(size_t index) const {
|
||||
return getUpstreamMember().getElement(index);
|
||||
}
|
||||
|
||||
FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
|
||||
return getOrAddUpstreamMember().getOrAddElement(index);
|
||||
}
|
||||
|
||||
// getMember(char*) const
|
||||
// getMember(const char*) const
|
||||
// getMember(const __FlashStringHelper*) const
|
||||
|
@ -28,14 +28,14 @@ template <typename TAdaptedString>
|
||||
inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) {
|
||||
if (!obj)
|
||||
return 0;
|
||||
return obj->get(key);
|
||||
return obj->getMember(key);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void objectRemove(CollectionData *obj, TAdaptedString key) {
|
||||
if (!obj)
|
||||
return;
|
||||
obj->remove(key);
|
||||
obj->removeMember(key);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
@ -49,10 +49,10 @@ inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key,
|
||||
return 0;
|
||||
|
||||
// search a matching key
|
||||
VariantData *var = obj->get(key);
|
||||
VariantData *var = obj->getMember(key);
|
||||
if (var)
|
||||
return var;
|
||||
|
||||
return obj->add(key, pool);
|
||||
return obj->addMember(key, pool);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -213,7 +213,7 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
|
||||
FORCE_INLINE void remove(iterator it) const {
|
||||
if (!_data)
|
||||
return;
|
||||
_data->remove(it.internal());
|
||||
_data->removeSlot(it.internal());
|
||||
}
|
||||
|
||||
// remove(const std::string&) const
|
||||
|
@ -186,13 +186,13 @@ class VariantData {
|
||||
|
||||
void remove(size_t index) {
|
||||
if (isArray())
|
||||
_content.asCollection.remove(index);
|
||||
_content.asCollection.removeElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void remove(TAdaptedString key) {
|
||||
if (isObject())
|
||||
_content.asCollection.remove(key);
|
||||
_content.asCollection.removeMember(key);
|
||||
}
|
||||
|
||||
void setBoolean(bool value) {
|
||||
@ -335,16 +335,24 @@ class VariantData {
|
||||
toArray();
|
||||
if (!isArray())
|
||||
return 0;
|
||||
return _content.asCollection.add(pool);
|
||||
return _content.asCollection.addElement(pool);
|
||||
}
|
||||
|
||||
VariantData *getElement(size_t index) const {
|
||||
return isArray() ? _content.asCollection.get(index) : 0;
|
||||
return isArray() ? _content.asCollection.getElement(index) : 0;
|
||||
}
|
||||
|
||||
VariantData *getOrAddElement(size_t index, MemoryPool *pool) {
|
||||
if (isNull())
|
||||
toArray();
|
||||
if (!isArray())
|
||||
return 0;
|
||||
return _content.asCollection.getOrAddElement(index, pool);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData *getMember(TAdaptedString key) const {
|
||||
return isObject() ? _content.asCollection.get(key) : 0;
|
||||
return isObject() ? _content.asCollection.getMember(key) : 0;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
@ -353,10 +361,7 @@ class VariantData {
|
||||
toObject();
|
||||
if (!isObject())
|
||||
return 0;
|
||||
VariantData *var = _content.asCollection.get(key);
|
||||
if (var)
|
||||
return var;
|
||||
return _content.asCollection.add(key, pool);
|
||||
return _content.asCollection.getOrAddMember(key, pool);
|
||||
}
|
||||
|
||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
||||
|
@ -160,19 +160,27 @@ inline CollectionData *variantToObject(VariantData *var) {
|
||||
return &var->toObject();
|
||||
}
|
||||
|
||||
inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) {
|
||||
inline NO_INLINE VariantData *variantAddElement(VariantData *var,
|
||||
MemoryPool *pool) {
|
||||
return var != 0 ? var->addElement(pool) : 0;
|
||||
}
|
||||
|
||||
inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var,
|
||||
size_t index,
|
||||
MemoryPool *pool) {
|
||||
return var != 0 ? var->getOrAddElement(index, pool) : 0;
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TChar *key,
|
||||
MemoryPool *pool) {
|
||||
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
|
||||
MemoryPool *pool) {
|
||||
return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TString &key,
|
||||
MemoryPool *pool) {
|
||||
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
|
||||
const TString &key,
|
||||
MemoryPool *pool) {
|
||||
return var != 0 ? var->getOrAddMember(adaptString(key), pool) : 0;
|
||||
}
|
||||
|
||||
|
@ -119,13 +119,17 @@ inline VariantConstRef VariantConstRef::getElement(size_t index) const {
|
||||
}
|
||||
|
||||
inline VariantRef VariantRef::addElement() const {
|
||||
return VariantRef(_pool, variantAdd(_data, _pool));
|
||||
return VariantRef(_pool, variantAddElement(_data, _pool));
|
||||
}
|
||||
|
||||
inline VariantRef VariantRef::getElement(size_t index) const {
|
||||
return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0);
|
||||
}
|
||||
|
||||
inline VariantRef VariantRef::getOrAddElement(size_t index) const {
|
||||
return VariantRef(_pool, variantGetOrAddElement(_data, index, _pool));
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline VariantRef VariantRef::getMember(TChar *key) const {
|
||||
return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
|
||||
@ -139,11 +143,11 @@ VariantRef::getMember(const TString &key) const {
|
||||
|
||||
template <typename TChar>
|
||||
inline VariantRef VariantRef::getOrAddMember(TChar *key) const {
|
||||
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
|
||||
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
|
||||
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
|
||||
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -301,6 +301,8 @@ class VariantRef : public VariantRefBase<VariantData>,
|
||||
|
||||
FORCE_INLINE VariantRef getElement(size_t) const;
|
||||
|
||||
FORCE_INLINE VariantRef getOrAddElement(size_t) const;
|
||||
|
||||
// getMember(const char*) const
|
||||
// getMember(const __FlashStringHelper*) const
|
||||
template <typename TChar>
|
||||
@ -391,7 +393,7 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
|
||||
template <typename TChar>
|
||||
FORCE_INLINE VariantConstRef getMember(TChar *key) const {
|
||||
const CollectionData *obj = variantAsObject(_data);
|
||||
return VariantConstRef(obj ? obj->get(adaptString(key)) : 0);
|
||||
return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0);
|
||||
}
|
||||
|
||||
// operator[](const std::string&) const
|
||||
|
Reference in New Issue
Block a user