mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-03 13:46:46 +02:00
Compare commits
5 Commits
7.5
...
merge-impl
Author | SHA1 | Date | |
---|---|---|---|
485078abcb | |||
9a26c04e39 | |||
2de9a56681 | |||
e02fbe1195 | |||
c1a636c77e |
@ -12,9 +12,13 @@ class ArrayImpl : public CollectionImpl {
|
||||
public:
|
||||
ArrayImpl() {}
|
||||
|
||||
ArrayImpl(CollectionData* data, ResourceManager* resources)
|
||||
ArrayImpl(VariantData* data, ResourceManager* resources)
|
||||
: CollectionImpl(data, resources) {}
|
||||
|
||||
bool isNull() const {
|
||||
return !data_ || data_->type != VariantType::Array;
|
||||
}
|
||||
|
||||
VariantData* addElement();
|
||||
|
||||
template <typename T>
|
||||
|
@ -11,6 +11,9 @@
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
inline ArrayImpl::iterator ArrayImpl::at(size_t index) const {
|
||||
if (isNull())
|
||||
return iterator();
|
||||
|
||||
auto it = createIterator();
|
||||
while (!it.done() && index) {
|
||||
it.next(resources_);
|
||||
@ -20,10 +23,9 @@ inline ArrayImpl::iterator ArrayImpl::at(size_t index) const {
|
||||
}
|
||||
|
||||
inline VariantData* ArrayImpl::addElement() {
|
||||
if (!data_)
|
||||
if (isNull())
|
||||
return nullptr;
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
auto slot = resources_->allocVariant();
|
||||
auto slot = allocVariant();
|
||||
if (!slot)
|
||||
return nullptr;
|
||||
CollectionImpl::appendOne(slot);
|
||||
@ -58,15 +60,14 @@ inline void ArrayImpl::removeElement(size_t index) {
|
||||
|
||||
template <typename T>
|
||||
inline bool ArrayImpl::addValue(const T& value) {
|
||||
if (!data_)
|
||||
if (isNull())
|
||||
return false;
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
auto slot = resources_->allocVariant();
|
||||
auto slot = allocVariant();
|
||||
if (!slot)
|
||||
return false;
|
||||
JsonVariant variant(slot.ptr(), resources_);
|
||||
if (!variant.set(value)) {
|
||||
resources_->freeVariant(slot);
|
||||
freeVariant(slot);
|
||||
return false;
|
||||
}
|
||||
CollectionImpl::appendOne(slot);
|
||||
|
@ -24,10 +24,7 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonArray(detail::VariantData* data, detail::ResourceManager* resources)
|
||||
: impl_(detail::VariantImpl(data, resources).asArray()) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonArray(const detail::ArrayImpl& impl) : impl_(impl) {}
|
||||
: impl_(data, resources) {}
|
||||
|
||||
// Returns a JsonVariant pointing to the array.
|
||||
// https://arduinojson.org/v7/api/jsonvariant/
|
||||
|
@ -38,7 +38,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonArrayConst(detail::VariantData* data, detail::ResourceManager* resources)
|
||||
: impl_(detail::VariantImpl(data, resources).asArray()) {}
|
||||
: impl_(data, resources) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonArrayConst(const detail::ArrayImpl& impl) : impl_(impl) {}
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Namespace.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
|
||||
@ -65,21 +64,9 @@ class CollectionIterator {
|
||||
SlotId currentId_, nextId_;
|
||||
};
|
||||
|
||||
struct CollectionData {
|
||||
SlotId head = NULL_SLOT;
|
||||
SlotId tail = NULL_SLOT;
|
||||
|
||||
// Placement new
|
||||
static void* operator new(size_t, void* p) noexcept {
|
||||
return p;
|
||||
}
|
||||
|
||||
static void operator delete(void*, void*) noexcept {}
|
||||
};
|
||||
|
||||
class CollectionImpl {
|
||||
protected:
|
||||
CollectionData* data_;
|
||||
VariantData* data_;
|
||||
ResourceManager* resources_;
|
||||
|
||||
public:
|
||||
@ -87,20 +74,19 @@ class CollectionImpl {
|
||||
|
||||
CollectionImpl() : data_(nullptr), resources_(nullptr) {}
|
||||
|
||||
CollectionImpl(CollectionData* data, ResourceManager* resources)
|
||||
CollectionImpl(VariantData* data, ResourceManager* resources)
|
||||
: data_(data), resources_(resources) {}
|
||||
|
||||
explicit operator bool() const {
|
||||
return data_ != nullptr;
|
||||
return data_ && data_->isCollection();
|
||||
}
|
||||
|
||||
bool isNull() const {
|
||||
return data_ == nullptr;
|
||||
return !operator bool();
|
||||
}
|
||||
|
||||
VariantData* getData() const {
|
||||
void* data = data_; // prevent warning cast-align
|
||||
return reinterpret_cast<VariantData*>(data);
|
||||
return data_;
|
||||
}
|
||||
|
||||
ResourceManager* getResourceManager() const {
|
||||
@ -115,7 +101,7 @@ class CollectionImpl {
|
||||
void clear();
|
||||
|
||||
SlotId head() const {
|
||||
return data_->head;
|
||||
return getCollectionData()->head;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -125,8 +111,29 @@ class CollectionImpl {
|
||||
void removeOne(iterator it);
|
||||
void removePair(iterator it);
|
||||
|
||||
VariantData* getVariant(SlotId id) const {
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
return resources_->getVariant(id);
|
||||
}
|
||||
|
||||
void freeVariant(Slot<VariantData> slot) {
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
resources_->freeVariant(slot);
|
||||
}
|
||||
|
||||
Slot<VariantData> allocVariant() {
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
return resources_->allocVariant();
|
||||
}
|
||||
|
||||
private:
|
||||
Slot<VariantData> getPreviousSlot(VariantData*) const;
|
||||
|
||||
CollectionData* getCollectionData() const {
|
||||
ARDUINOJSON_ASSERT(data_ != nullptr);
|
||||
ARDUINOJSON_ASSERT(data_->isCollection());
|
||||
return &data_->content.asCollection;
|
||||
}
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
@ -26,63 +26,66 @@ inline void CollectionIterator::next(const ResourceManager* resources) {
|
||||
}
|
||||
|
||||
inline CollectionImpl::iterator CollectionImpl::createIterator() const {
|
||||
if (!data_)
|
||||
if (!data_ || !data_->isCollection())
|
||||
return iterator();
|
||||
return iterator(resources_->getVariant(data_->head), data_->head);
|
||||
auto coll = getCollectionData();
|
||||
return iterator(getVariant(coll->head), coll->head);
|
||||
}
|
||||
|
||||
inline void CollectionImpl::appendOne(Slot<VariantData> slot) {
|
||||
ARDUINOJSON_ASSERT(data_ != nullptr);
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
auto coll = getCollectionData();
|
||||
|
||||
if (data_->tail != NULL_SLOT) {
|
||||
auto tail = resources_->getVariant(data_->tail);
|
||||
if (coll->tail != NULL_SLOT) {
|
||||
auto tail = getVariant(coll->tail);
|
||||
tail->next = slot.id();
|
||||
data_->tail = slot.id();
|
||||
coll->tail = slot.id();
|
||||
} else {
|
||||
data_->head = slot.id();
|
||||
data_->tail = slot.id();
|
||||
coll->head = slot.id();
|
||||
coll->tail = slot.id();
|
||||
}
|
||||
}
|
||||
|
||||
inline void CollectionImpl::appendPair(Slot<VariantData> key,
|
||||
Slot<VariantData> value) {
|
||||
ARDUINOJSON_ASSERT(data_ != nullptr);
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
auto coll = getCollectionData();
|
||||
|
||||
key->next = value.id();
|
||||
|
||||
if (data_->tail != NULL_SLOT) {
|
||||
auto tail = resources_->getVariant(data_->tail);
|
||||
if (coll->tail != NULL_SLOT) {
|
||||
auto tail = getVariant(coll->tail);
|
||||
tail->next = key.id();
|
||||
data_->tail = value.id();
|
||||
coll->tail = value.id();
|
||||
} else {
|
||||
data_->head = key.id();
|
||||
data_->tail = value.id();
|
||||
coll->head = key.id();
|
||||
coll->tail = value.id();
|
||||
}
|
||||
}
|
||||
|
||||
inline void CollectionImpl::clear() {
|
||||
if (!data_)
|
||||
if (!data_ || !data_->isCollection())
|
||||
return;
|
||||
auto next = data_->head;
|
||||
|
||||
auto coll = getCollectionData();
|
||||
|
||||
auto next = coll->head;
|
||||
while (next != NULL_SLOT) {
|
||||
auto currId = next;
|
||||
auto slot = resources_->getVariant(next);
|
||||
auto slot = getVariant(next);
|
||||
next = slot->next;
|
||||
resources_->freeVariant({slot, currId});
|
||||
freeVariant({slot, currId});
|
||||
}
|
||||
|
||||
data_->head = NULL_SLOT;
|
||||
data_->tail = NULL_SLOT;
|
||||
coll->head = NULL_SLOT;
|
||||
coll->tail = NULL_SLOT;
|
||||
}
|
||||
|
||||
inline Slot<VariantData> CollectionImpl::getPreviousSlot(
|
||||
VariantData* target) const {
|
||||
auto coll = getCollectionData();
|
||||
auto prev = Slot<VariantData>();
|
||||
auto currentId = data_->head;
|
||||
auto currentId = coll->head;
|
||||
while (currentId != NULL_SLOT) {
|
||||
auto currentSlot = resources_->getVariant(currentId);
|
||||
auto currentSlot = getVariant(currentId);
|
||||
if (currentSlot == target)
|
||||
break;
|
||||
prev = Slot<VariantData>(currentSlot, currentId);
|
||||
@ -94,16 +97,17 @@ inline Slot<VariantData> CollectionImpl::getPreviousSlot(
|
||||
inline void CollectionImpl::removeOne(iterator it) {
|
||||
if (it.done())
|
||||
return;
|
||||
auto coll = getCollectionData();
|
||||
auto curr = it.slot_;
|
||||
auto prev = getPreviousSlot(curr);
|
||||
auto next = curr->next;
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
data_->head = next;
|
||||
coll->head = next;
|
||||
if (next == NULL_SLOT)
|
||||
data_->tail = prev.id();
|
||||
resources_->freeVariant({it.slot_, it.currentId_});
|
||||
coll->tail = prev.id();
|
||||
freeVariant({it.slot_, it.currentId_});
|
||||
}
|
||||
|
||||
inline void CollectionImpl::removePair(ObjectImpl::iterator it) {
|
||||
@ -113,18 +117,18 @@ inline void CollectionImpl::removePair(ObjectImpl::iterator it) {
|
||||
auto keySlot = it.slot_;
|
||||
|
||||
auto valueId = it.nextId_;
|
||||
auto valueSlot = resources_->getVariant(valueId);
|
||||
auto valueSlot = getVariant(valueId);
|
||||
|
||||
// remove value slot
|
||||
keySlot->next = valueSlot->next;
|
||||
resources_->freeVariant({valueSlot, valueId});
|
||||
freeVariant({valueSlot, valueId});
|
||||
|
||||
// remove key slot
|
||||
removeOne(it);
|
||||
}
|
||||
|
||||
inline size_t CollectionImpl::nesting() const {
|
||||
if (!data_)
|
||||
if (!data_ || !data_->isCollection())
|
||||
return 0;
|
||||
size_t maxChildNesting = 0;
|
||||
for (auto it = createIterator(); !it.done(); it.next(resources_)) {
|
||||
|
@ -64,6 +64,8 @@ class JsonDeserializer {
|
||||
DeserializationOption::NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
ARDUINOJSON_ASSERT(variant != nullptr);
|
||||
|
||||
err = skipSpacesAndComments();
|
||||
if (err)
|
||||
return err;
|
||||
@ -71,15 +73,13 @@ class JsonDeserializer {
|
||||
switch (current()) {
|
||||
case '[':
|
||||
if (filter.allowArray())
|
||||
return parseArray(VariantImpl(variant, resources_).toArray(), filter,
|
||||
nestingLimit);
|
||||
return parseArray(variant->toArray(), filter, nestingLimit);
|
||||
else
|
||||
return skipArray(nestingLimit);
|
||||
|
||||
case '{':
|
||||
if (filter.allowObject())
|
||||
return parseObject(VariantImpl(variant, resources_).toObject(),
|
||||
filter, nestingLimit);
|
||||
return parseObject(variant->toObject(), filter, nestingLimit);
|
||||
else
|
||||
return skipObject(nestingLimit);
|
||||
|
||||
@ -148,7 +148,7 @@ class JsonDeserializer {
|
||||
|
||||
template <typename TFilter>
|
||||
DeserializationError::Code parseArray(
|
||||
ArrayImpl array, TFilter filter,
|
||||
VariantData* arrayData, TFilter filter,
|
||||
DeserializationOption::NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
@ -173,6 +173,8 @@ class JsonDeserializer {
|
||||
// Read each value
|
||||
for (;;) {
|
||||
if (elementFilter.allow()) {
|
||||
ArrayImpl array(arrayData, resources_);
|
||||
|
||||
// Allocate slot in array
|
||||
VariantData* value = array.addElement();
|
||||
if (!value)
|
||||
@ -234,7 +236,7 @@ class JsonDeserializer {
|
||||
|
||||
template <typename TFilter>
|
||||
DeserializationError::Code parseObject(
|
||||
ObjectImpl object, TFilter filter,
|
||||
VariantData* objectData, TFilter filter,
|
||||
DeserializationOption::NestingLimit nestingLimit) {
|
||||
DeserializationError::Code err;
|
||||
|
||||
@ -275,6 +277,7 @@ class JsonDeserializer {
|
||||
TFilter memberFilter = filter[key];
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
ObjectImpl object(objectData, resources_);
|
||||
auto member = object.getMember(adaptString(key));
|
||||
if (!member) {
|
||||
auto keyVariant = object.addPair(&member);
|
||||
|
@ -352,7 +352,7 @@ class MsgPackDeserializer {
|
||||
ArrayImpl array;
|
||||
if (allowArray) {
|
||||
ARDUINOJSON_ASSERT(variant != 0);
|
||||
array = VariantImpl(variant, resources_).toArray();
|
||||
array = ArrayImpl(variant->toArray(), resources_);
|
||||
}
|
||||
|
||||
TFilter elementFilter = filter[0U];
|
||||
@ -388,7 +388,7 @@ class MsgPackDeserializer {
|
||||
ObjectImpl object;
|
||||
if (filter.allowObject()) {
|
||||
ARDUINOJSON_ASSERT(variant != 0);
|
||||
object = VariantImpl(variant, resources_).toObject();
|
||||
object = ObjectImpl(variant->toObject(), resources_);
|
||||
}
|
||||
|
||||
for (; n; --n) {
|
||||
|
@ -22,12 +22,9 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
||||
// Creates an unbound reference.
|
||||
JsonObject() {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonObject(const detail::ObjectImpl& impl) : impl_(impl) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonObject(detail::VariantData* data, detail::ResourceManager* resource)
|
||||
: impl_(detail::VariantImpl(data, resource).asObject()) {}
|
||||
: impl_(data, resource) {}
|
||||
|
||||
operator JsonVariant() const {
|
||||
return JsonVariant(getData(), getResourceManager());
|
||||
|
@ -23,7 +23,7 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonObjectConst(detail::VariantData* data, detail::ResourceManager* resources)
|
||||
: impl_(detail::VariantImpl(data, resources).asObject()) {}
|
||||
: impl_(data, resources) {}
|
||||
|
||||
// INTERNAL USE ONLY
|
||||
JsonObjectConst(const detail::ObjectImpl& impl) : impl_(impl) {}
|
||||
|
@ -14,9 +14,13 @@ class ObjectImpl : public CollectionImpl {
|
||||
public:
|
||||
ObjectImpl() {}
|
||||
|
||||
ObjectImpl(CollectionData* data, ResourceManager* resources)
|
||||
ObjectImpl(VariantData* data, ResourceManager* resources)
|
||||
: CollectionImpl(data, resources) {}
|
||||
|
||||
bool isNull() const {
|
||||
return !data_ || data_->type != VariantType::Object;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* addMember(TAdaptedString key);
|
||||
|
||||
|
@ -29,6 +29,8 @@ VariantData* ObjectImpl::getOrAddMember(TAdaptedString key) {
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline ObjectImpl::iterator ObjectImpl::findKey(TAdaptedString key) const {
|
||||
if (isNull())
|
||||
return iterator();
|
||||
if (key.isNull())
|
||||
return iterator();
|
||||
bool isKey = true;
|
||||
@ -48,15 +50,14 @@ inline void ObjectImpl::removeMember(TAdaptedString key) {
|
||||
|
||||
template <typename TAdaptedString>
|
||||
inline VariantData* ObjectImpl::addMember(TAdaptedString key) {
|
||||
if (!data_)
|
||||
if (isNull())
|
||||
return nullptr;
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
|
||||
auto keySlot = resources_->allocVariant();
|
||||
auto keySlot = allocVariant();
|
||||
if (!keySlot)
|
||||
return nullptr;
|
||||
|
||||
auto valueSlot = resources_->allocVariant();
|
||||
auto valueSlot = allocVariant();
|
||||
if (!valueSlot)
|
||||
return nullptr;
|
||||
|
||||
@ -70,15 +71,13 @@ inline VariantData* ObjectImpl::addMember(TAdaptedString key) {
|
||||
}
|
||||
|
||||
inline VariantData* ObjectImpl::addPair(VariantData** value) {
|
||||
if (!data_)
|
||||
return nullptr;
|
||||
ARDUINOJSON_ASSERT(resources_ != nullptr);
|
||||
ARDUINOJSON_ASSERT(!isNull());
|
||||
|
||||
auto keySlot = resources_->allocVariant();
|
||||
auto keySlot = allocVariant();
|
||||
if (!keySlot)
|
||||
return nullptr;
|
||||
|
||||
auto valueSlot = resources_->allocVariant();
|
||||
auto valueSlot = allocVariant();
|
||||
if (!valueSlot)
|
||||
return nullptr;
|
||||
*value = valueSlot.ptr();
|
||||
|
@ -6,10 +6,8 @@
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include <ArduinoJson/Array/ArrayData.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonFloat.hpp>
|
||||
#include <ArduinoJson/Numbers/JsonInteger.hpp>
|
||||
#include <ArduinoJson/Object/ObjectData.hpp>
|
||||
|
||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||
|
||||
@ -47,6 +45,18 @@ inline bool operator&(VariantType type, VariantTypeBits bit) {
|
||||
return (uint8_t(type) & uint8_t(bit)) != 0;
|
||||
}
|
||||
|
||||
struct CollectionData {
|
||||
SlotId head = NULL_SLOT;
|
||||
SlotId tail = NULL_SLOT;
|
||||
|
||||
// Placement new
|
||||
static void* operator new(size_t, void* p) noexcept {
|
||||
return p;
|
||||
}
|
||||
|
||||
static void operator delete(void*, void*) noexcept {}
|
||||
};
|
||||
|
||||
const size_t tinyStringMaxLength = 3;
|
||||
|
||||
union VariantContent {
|
||||
|
@ -71,6 +71,10 @@ struct VariantData {
|
||||
content.asOwnedString = s;
|
||||
}
|
||||
|
||||
bool isCollection() const {
|
||||
return type & VariantTypeBits::CollectionMask;
|
||||
}
|
||||
|
||||
bool isFloat() const {
|
||||
return type & VariantTypeBits::NumberBit;
|
||||
}
|
||||
@ -79,6 +83,42 @@ struct VariantData {
|
||||
return type == VariantType::LinkedString ||
|
||||
type == VariantType::OwnedString || type == VariantType::TinyString;
|
||||
}
|
||||
|
||||
VariantData* toArray() {
|
||||
ARDUINOJSON_ASSERT(type == VariantType::Null);
|
||||
type = VariantType::Array;
|
||||
new (&content.asCollection) CollectionData();
|
||||
return this;
|
||||
}
|
||||
|
||||
VariantData* toObject() {
|
||||
ARDUINOJSON_ASSERT(type == VariantType::Null);
|
||||
type = VariantType::Object;
|
||||
new (&content.asCollection) CollectionData();
|
||||
return this;
|
||||
}
|
||||
|
||||
VariantData* getOrCreateArray() {
|
||||
switch (type) {
|
||||
case VariantType::Null:
|
||||
return toArray();
|
||||
case VariantType::Array:
|
||||
return this;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
VariantData* getOrCreateObject() {
|
||||
switch (type) {
|
||||
case VariantType::Null:
|
||||
return toObject();
|
||||
case VariantType::Object:
|
||||
return this;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/ArrayData.hpp>
|
||||
#include <ArduinoJson/Memory/ResourceManager.hpp>
|
||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Object/ObjectData.hpp>
|
||||
#include <ArduinoJson/Strings/JsonString.hpp>
|
||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
@ -46,10 +48,10 @@ class VariantImpl {
|
||||
#endif
|
||||
|
||||
case VariantType::Array:
|
||||
return visit.visit(asArray());
|
||||
return visit.visit(ArrayImpl(data_, resources_));
|
||||
|
||||
case VariantType::Object:
|
||||
return visit.visit(asObject());
|
||||
return visit.visit(ObjectImpl(data_, resources_));
|
||||
|
||||
case VariantType::TinyString:
|
||||
return visit.visit(JsonString(data_->content.asTinyString));
|
||||
@ -88,14 +90,16 @@ class VariantImpl {
|
||||
}
|
||||
|
||||
VariantData* addElement() {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.addElement();
|
||||
if (!data_)
|
||||
return nullptr;
|
||||
return ArrayImpl(data_->getOrCreateArray(), resources_).addElement();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool addValue(const T& value) {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.addValue(value);
|
||||
if (!data_)
|
||||
return false;
|
||||
return ArrayImpl(data_->getOrCreateArray(), resources_).addValue(value);
|
||||
}
|
||||
|
||||
bool asBoolean() const {
|
||||
@ -129,16 +133,6 @@ class VariantImpl {
|
||||
}
|
||||
}
|
||||
|
||||
ArrayImpl asArray() {
|
||||
return ArrayImpl(isArray() ? &data_->content.asCollection : nullptr,
|
||||
resources_);
|
||||
}
|
||||
|
||||
CollectionImpl asCollection() {
|
||||
return CollectionImpl(
|
||||
isCollection() ? &data_->content.asCollection : nullptr, resources_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T asFloat() const {
|
||||
if (!data_)
|
||||
@ -231,11 +225,6 @@ class VariantImpl {
|
||||
return parseNumber<T>(str);
|
||||
}
|
||||
|
||||
ObjectImpl asObject() {
|
||||
return ObjectImpl(isObject() ? &data_->content.asCollection : nullptr,
|
||||
resources_);
|
||||
}
|
||||
|
||||
JsonString asRawString() const {
|
||||
switch (type()) {
|
||||
case VariantType::RawString:
|
||||
@ -274,25 +263,29 @@ class VariantImpl {
|
||||
#endif
|
||||
|
||||
VariantData* getElement(size_t index) {
|
||||
return asArray().getElement(index);
|
||||
return ArrayImpl(data_, resources_).getElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getMember(TAdaptedString key) {
|
||||
return asObject().getMember(key);
|
||||
return ObjectImpl(data_, resources_).getMember(key);
|
||||
}
|
||||
|
||||
VariantData* getOrAddElement(size_t index) {
|
||||
auto array = isNull() ? toArray() : asArray();
|
||||
return array.getOrAddElement(index);
|
||||
if (!data_)
|
||||
return nullptr;
|
||||
return ArrayImpl(data_->getOrCreateArray(), resources_)
|
||||
.getOrAddElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
VariantData* getOrAddMember(TAdaptedString key) {
|
||||
if (key.isNull())
|
||||
return nullptr;
|
||||
auto obj = isNull() ? toObject() : asObject();
|
||||
return obj.getOrAddMember(key);
|
||||
if (!data_)
|
||||
return nullptr;
|
||||
return ObjectImpl(data_->getOrCreateObject(), resources_)
|
||||
.getOrAddMember(key);
|
||||
}
|
||||
|
||||
bool isArray() const {
|
||||
@ -303,10 +296,6 @@ class VariantImpl {
|
||||
return type() == VariantType::Boolean;
|
||||
}
|
||||
|
||||
bool isCollection() const {
|
||||
return type() & VariantTypeBits::CollectionMask;
|
||||
}
|
||||
|
||||
bool isFloat() const {
|
||||
return data_ && data_->isFloat();
|
||||
}
|
||||
@ -352,16 +341,16 @@ class VariantImpl {
|
||||
}
|
||||
|
||||
size_t nesting() {
|
||||
return asCollection().nesting();
|
||||
return CollectionImpl(data_, resources_).nesting();
|
||||
}
|
||||
|
||||
void removeElement(size_t index) {
|
||||
asArray().removeElement(index);
|
||||
ArrayImpl(data_, resources_).removeElement(index);
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
void removeMember(TAdaptedString key) {
|
||||
asObject().removeMember(key);
|
||||
ObjectImpl(data_, resources_).removeMember(key);
|
||||
}
|
||||
|
||||
bool setBoolean(bool value) {
|
||||
@ -466,31 +455,12 @@ class VariantImpl {
|
||||
bool setLinkedString(const char* s);
|
||||
|
||||
size_t size() {
|
||||
if (isObject())
|
||||
return asObject().size();
|
||||
auto size = CollectionImpl(data_, resources_).size();
|
||||
|
||||
if (isArray())
|
||||
return asArray().size();
|
||||
if (data_ && data_->type == VariantType::Object)
|
||||
size /= 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ArrayImpl toArray() {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return ArrayImpl();
|
||||
data_->type = VariantType::Array;
|
||||
return ArrayImpl(new (&data_->content.asCollection) CollectionData(),
|
||||
resources_);
|
||||
}
|
||||
|
||||
ObjectImpl toObject() {
|
||||
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
|
||||
if (!data_)
|
||||
return ObjectImpl();
|
||||
data_->type = VariantType::Object;
|
||||
return ObjectImpl(new (&data_->content.asCollection) CollectionData(),
|
||||
resources_);
|
||||
return size;
|
||||
}
|
||||
|
||||
VariantType type() const {
|
||||
@ -566,7 +536,7 @@ inline void VariantImpl::clear() {
|
||||
resources_->freeEightByte(data_->content.asSlotId);
|
||||
#endif
|
||||
|
||||
asCollection().clear();
|
||||
CollectionImpl(data_, resources_).clear();
|
||||
|
||||
data_->type = VariantType::Null;
|
||||
}
|
||||
|
@ -147,17 +147,23 @@ inline bool VariantRefBase<TDerived>::doSet(const T& value, true_type) const {
|
||||
template <typename TDerived>
|
||||
template <typename T, enable_if_t<is_same<T, JsonArray>::value, int>>
|
||||
inline JsonArray VariantRefBase<TDerived>::to() const {
|
||||
auto variant = getOrCreateVariantImpl();
|
||||
variant.clear();
|
||||
return JsonArray(variant.toArray());
|
||||
auto data = getOrCreateData();
|
||||
if (!data)
|
||||
return JsonArray();
|
||||
auto resources = getResourceManager();
|
||||
VariantImpl(data, resources).clear();
|
||||
return JsonArray(data->toArray(), resources);
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
template <typename T, enable_if_t<is_same<T, JsonObject>::value, int>>
|
||||
JsonObject VariantRefBase<TDerived>::to() const {
|
||||
auto variant = getOrCreateVariantImpl();
|
||||
variant.clear();
|
||||
return JsonObject(variant.toObject());
|
||||
auto data = getOrCreateData();
|
||||
if (!data)
|
||||
return JsonObject();
|
||||
auto resources = getResourceManager();
|
||||
VariantImpl(data, resources).clear();
|
||||
return JsonObject(data->toObject(), resources);
|
||||
}
|
||||
|
||||
template <typename TDerived>
|
||||
|
Reference in New Issue
Block a user