Skip to content

Commit c1a636c

Browse files
committed
Decouple VariantImpl from ArrayImpl and ObjectImpl
1 parent 5bc6a30 commit c1a636c

File tree

9 files changed

+117
-73
lines changed

9 files changed

+117
-73
lines changed

src/ArduinoJson/Array/JsonArray.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
2424

2525
// INTERNAL USE ONLY
2626
JsonArray(detail::VariantData* data, detail::ResourceManager* resources)
27-
: impl_(detail::VariantImpl(data, resources).asArray()) {}
27+
: impl_(data ? data->asArray() : nullptr, resources) {}
2828

2929
// INTERNAL USE ONLY
30-
JsonArray(const detail::ArrayImpl& impl) : impl_(impl) {}
30+
JsonArray(detail::CollectionData* data, detail::ResourceManager* resources)
31+
: impl_(data, resources) {}
3132

3233
// Returns a JsonVariant pointing to the array.
3334
// https://arduinojson.org/v7/api/jsonvariant/

src/ArduinoJson/Array/JsonArrayConst.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
3838

3939
// INTERNAL USE ONLY
4040
JsonArrayConst(detail::VariantData* data, detail::ResourceManager* resources)
41-
: impl_(detail::VariantImpl(data, resources).asArray()) {}
41+
: impl_(data ? data->asArray() : nullptr, resources) {}
4242

4343
// INTERNAL USE ONLY
4444
JsonArrayConst(const detail::ArrayImpl& impl) : impl_(impl) {}

src/ArduinoJson/Json/JsonDeserializer.hpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,22 @@ class JsonDeserializer {
6464
DeserializationOption::NestingLimit nestingLimit) {
6565
DeserializationError::Code err;
6666

67+
ARDUINOJSON_ASSERT(variant != nullptr);
68+
6769
err = skipSpacesAndComments();
6870
if (err)
6971
return err;
7072

7173
switch (current()) {
7274
case '[':
7375
if (filter.allowArray())
74-
return parseArray(VariantImpl(variant, resources_).toArray(), filter,
75-
nestingLimit);
76+
return parseArray(variant->toArray(), filter, nestingLimit);
7677
else
7778
return skipArray(nestingLimit);
7879

7980
case '{':
8081
if (filter.allowObject())
81-
return parseObject(VariantImpl(variant, resources_).toObject(),
82-
filter, nestingLimit);
82+
return parseObject(variant->toObject(), filter, nestingLimit);
8383
else
8484
return skipObject(nestingLimit);
8585

@@ -148,7 +148,7 @@ class JsonDeserializer {
148148

149149
template <typename TFilter>
150150
DeserializationError::Code parseArray(
151-
ArrayImpl array, TFilter filter,
151+
CollectionData* arrayData, TFilter filter,
152152
DeserializationOption::NestingLimit nestingLimit) {
153153
DeserializationError::Code err;
154154

@@ -173,6 +173,8 @@ class JsonDeserializer {
173173
// Read each value
174174
for (;;) {
175175
if (elementFilter.allow()) {
176+
ArrayImpl array(arrayData, resources_);
177+
176178
// Allocate slot in array
177179
VariantData* value = array.addElement();
178180
if (!value)
@@ -234,7 +236,7 @@ class JsonDeserializer {
234236

235237
template <typename TFilter>
236238
DeserializationError::Code parseObject(
237-
ObjectImpl object, TFilter filter,
239+
CollectionData* objectData, TFilter filter,
238240
DeserializationOption::NestingLimit nestingLimit) {
239241
DeserializationError::Code err;
240242

@@ -275,6 +277,7 @@ class JsonDeserializer {
275277
TFilter memberFilter = filter[key];
276278

277279
if (memberFilter.allow()) {
280+
ObjectImpl object(objectData, resources_);
278281
auto member = object.getMember(adaptString(key));
279282
if (!member) {
280283
auto keyVariant = object.addPair(&member);

src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ class MsgPackDeserializer {
352352
ArrayImpl array;
353353
if (allowArray) {
354354
ARDUINOJSON_ASSERT(variant != 0);
355-
array = VariantImpl(variant, resources_).toArray();
355+
array = ArrayImpl(variant->toArray(), resources_);
356356
}
357357

358358
TFilter elementFilter = filter[0U];
@@ -388,7 +388,7 @@ class MsgPackDeserializer {
388388
ObjectImpl object;
389389
if (filter.allowObject()) {
390390
ARDUINOJSON_ASSERT(variant != 0);
391-
object = VariantImpl(variant, resources_).toObject();
391+
object = ObjectImpl(variant->toObject(), resources_);
392392
}
393393

394394
for (; n; --n) {

src/ArduinoJson/Object/JsonObject.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
2323
JsonObject() {}
2424

2525
// INTERNAL USE ONLY
26-
JsonObject(const detail::ObjectImpl& impl) : impl_(impl) {}
26+
JsonObject(detail::CollectionData* data, detail::ResourceManager* resource)
27+
: impl_(data, resource) {}
2728

2829
// INTERNAL USE ONLY
2930
JsonObject(detail::VariantData* data, detail::ResourceManager* resource)
30-
: impl_(detail::VariantImpl(data, resource).asObject()) {}
31+
: impl_(data ? data->asObject() : nullptr, resource) {}
3132

3233
operator JsonVariant() const {
3334
return JsonVariant(getData(), getResourceManager());

src/ArduinoJson/Object/JsonObjectConst.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
2323

2424
// INTERNAL USE ONLY
2525
JsonObjectConst(detail::VariantData* data, detail::ResourceManager* resources)
26-
: impl_(detail::VariantImpl(data, resources).asObject()) {}
26+
: impl_(data ? data->asObject() : nullptr, resources) {}
2727

2828
// INTERNAL USE ONLY
2929
JsonObjectConst(const detail::ObjectImpl& impl) : impl_(impl) {}

src/ArduinoJson/Variant/VariantData.hpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ struct VariantData {
7171
content.asOwnedString = s;
7272
}
7373

74+
CollectionData* asCollection() {
75+
return type & VariantTypeBits::CollectionMask ? &content.asCollection
76+
: nullptr;
77+
}
78+
79+
CollectionData* asArray() {
80+
return type == VariantType::Array ? &content.asCollection : nullptr;
81+
}
82+
83+
CollectionData* asObject() {
84+
return type == VariantType::Object ? &content.asCollection : nullptr;
85+
}
86+
7487
bool isFloat() const {
7588
return type & VariantTypeBits::NumberBit;
7689
}
@@ -79,6 +92,40 @@ struct VariantData {
7992
return type == VariantType::LinkedString ||
8093
type == VariantType::OwnedString || type == VariantType::TinyString;
8194
}
95+
96+
CollectionData* toArray() {
97+
ARDUINOJSON_ASSERT(type == VariantType::Null);
98+
type = VariantType::Array;
99+
return new (&content.asCollection) CollectionData();
100+
}
101+
102+
CollectionData* toObject() {
103+
ARDUINOJSON_ASSERT(type == VariantType::Null);
104+
type = VariantType::Object;
105+
return new (&content.asCollection) CollectionData();
106+
}
107+
108+
CollectionData* getOrCreateArray() {
109+
switch (type) {
110+
case VariantType::Null:
111+
return toArray();
112+
case VariantType::Array:
113+
return &content.asCollection;
114+
default:
115+
return nullptr;
116+
}
117+
}
118+
119+
CollectionData* getOrCreateObject() {
120+
switch (type) {
121+
case VariantType::Null:
122+
return toObject();
123+
case VariantType::Object:
124+
return &content.asCollection;
125+
default:
126+
return nullptr;
127+
}
128+
}
82129
};
83130

84131
ARDUINOJSON_END_PRIVATE_NAMESPACE

src/ArduinoJson/Variant/VariantImpl.hpp

Lines changed: 39 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ class VariantImpl {
4646
#endif
4747

4848
case VariantType::Array:
49-
return visit.visit(asArray());
49+
return visit.visit(ArrayImpl(&data_->content.asCollection, resources_));
5050

5151
case VariantType::Object:
52-
return visit.visit(asObject());
52+
return visit.visit(
53+
ObjectImpl(&data_->content.asCollection, resources_));
5354

5455
case VariantType::TinyString:
5556
return visit.visit(JsonString(data_->content.asTinyString));
@@ -88,14 +89,16 @@ class VariantImpl {
8889
}
8990

9091
VariantData* addElement() {
91-
auto array = isNull() ? toArray() : asArray();
92-
return array.addElement();
92+
if (!data_)
93+
return nullptr;
94+
return ArrayImpl(data_->getOrCreateArray(), resources_).addElement();
9395
}
9496

9597
template <typename T>
9698
bool addValue(const T& value) {
97-
auto array = isNull() ? toArray() : asArray();
98-
return array.addValue(value);
99+
if (!data_)
100+
return false;
101+
return ArrayImpl(data_->getOrCreateArray(), resources_).addValue(value);
99102
}
100103

101104
bool asBoolean() const {
@@ -129,16 +132,6 @@ class VariantImpl {
129132
}
130133
}
131134

132-
ArrayImpl asArray() {
133-
return ArrayImpl(isArray() ? &data_->content.asCollection : nullptr,
134-
resources_);
135-
}
136-
137-
CollectionImpl asCollection() {
138-
return CollectionImpl(
139-
isCollection() ? &data_->content.asCollection : nullptr, resources_);
140-
}
141-
142135
template <typename T>
143136
T asFloat() const {
144137
if (!data_)
@@ -231,11 +224,6 @@ class VariantImpl {
231224
return parseNumber<T>(str);
232225
}
233226

234-
ObjectImpl asObject() {
235-
return ObjectImpl(isObject() ? &data_->content.asCollection : nullptr,
236-
resources_);
237-
}
238-
239227
JsonString asRawString() const {
240228
switch (type()) {
241229
case VariantType::RawString:
@@ -274,25 +262,33 @@ class VariantImpl {
274262
#endif
275263

276264
VariantData* getElement(size_t index) {
277-
return asArray().getElement(index);
265+
if (!data_)
266+
return nullptr;
267+
return ArrayImpl(data_->asArray(), resources_).getElement(index);
278268
}
279269

280270
template <typename TAdaptedString>
281271
VariantData* getMember(TAdaptedString key) {
282-
return asObject().getMember(key);
272+
if (!data_)
273+
return nullptr;
274+
return ObjectImpl(data_->asObject(), resources_).getMember(key);
283275
}
284276

285277
VariantData* getOrAddElement(size_t index) {
286-
auto array = isNull() ? toArray() : asArray();
287-
return array.getOrAddElement(index);
278+
if (!data_)
279+
return nullptr;
280+
return ArrayImpl(data_->getOrCreateArray(), resources_)
281+
.getOrAddElement(index);
288282
}
289283

290284
template <typename TAdaptedString>
291285
VariantData* getOrAddMember(TAdaptedString key) {
292286
if (key.isNull())
293287
return nullptr;
294-
auto obj = isNull() ? toObject() : asObject();
295-
return obj.getOrAddMember(key);
288+
if (!data_)
289+
return nullptr;
290+
return ObjectImpl(data_->getOrCreateObject(), resources_)
291+
.getOrAddMember(key);
296292
}
297293

298294
bool isArray() const {
@@ -352,16 +348,22 @@ class VariantImpl {
352348
}
353349

354350
size_t nesting() {
355-
return asCollection().nesting();
351+
if (!data_)
352+
return 0;
353+
return CollectionImpl(data_->asCollection(), resources_).nesting();
356354
}
357355

358356
void removeElement(size_t index) {
359-
asArray().removeElement(index);
357+
if (!data_)
358+
return;
359+
ArrayImpl(data_->asArray(), resources_).removeElement(index);
360360
}
361361

362362
template <typename TAdaptedString>
363363
void removeMember(TAdaptedString key) {
364-
asObject().removeMember(key);
364+
if (!data_)
365+
return;
366+
ObjectImpl(data_->asObject(), resources_).removeMember(key);
365367
}
366368

367369
bool setBoolean(bool value) {
@@ -466,31 +468,15 @@ class VariantImpl {
466468
bool setLinkedString(const char* s);
467469

468470
size_t size() {
469-
if (isObject())
470-
return asObject().size();
471-
472-
if (isArray())
473-
return asArray().size();
471+
if (!data_)
472+
return 0;
474473

475-
return 0;
476-
}
474+
auto size = CollectionImpl(data_->asCollection(), resources_).size();
477475

478-
ArrayImpl toArray() {
479-
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
480-
if (!data_)
481-
return ArrayImpl();
482-
data_->type = VariantType::Array;
483-
return ArrayImpl(new (&data_->content.asCollection) CollectionData(),
484-
resources_);
485-
}
476+
if (data_->type == VariantType::Object)
477+
size /= 2;
486478

487-
ObjectImpl toObject() {
488-
ARDUINOJSON_ASSERT(type() == VariantType::Null); // must call clear() first
489-
if (!data_)
490-
return ObjectImpl();
491-
data_->type = VariantType::Object;
492-
return ObjectImpl(new (&data_->content.asCollection) CollectionData(),
493-
resources_);
479+
return size;
494480
}
495481

496482
VariantType type() const {
@@ -566,7 +552,7 @@ inline void VariantImpl::clear() {
566552
resources_->freeEightByte(data_->content.asSlotId);
567553
#endif
568554

569-
asCollection().clear();
555+
CollectionImpl(data_->asCollection(), resources_).clear();
570556

571557
data_->type = VariantType::Null;
572558
}

src/ArduinoJson/Variant/VariantRefBaseImpl.hpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,17 +147,23 @@ inline bool VariantRefBase<TDerived>::doSet(const T& value, true_type) const {
147147
template <typename TDerived>
148148
template <typename T, enable_if_t<is_same<T, JsonArray>::value, int>>
149149
inline JsonArray VariantRefBase<TDerived>::to() const {
150-
auto variant = getOrCreateVariantImpl();
151-
variant.clear();
152-
return JsonArray(variant.toArray());
150+
auto data = getOrCreateData();
151+
if (!data)
152+
return JsonArray();
153+
auto resources = getResourceManager();
154+
VariantImpl(data, resources).clear();
155+
return JsonArray(data->toArray(), resources);
153156
}
154157

155158
template <typename TDerived>
156159
template <typename T, enable_if_t<is_same<T, JsonObject>::value, int>>
157160
JsonObject VariantRefBase<TDerived>::to() const {
158-
auto variant = getOrCreateVariantImpl();
159-
variant.clear();
160-
return JsonObject(variant.toObject());
161+
auto data = getOrCreateData();
162+
if (!data)
163+
return JsonObject();
164+
auto resources = getResourceManager();
165+
VariantImpl(data, resources).clear();
166+
return JsonObject(data->toObject(), resources);
161167
}
162168

163169
template <typename TDerived>

0 commit comments

Comments
 (0)