• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bblanchon / ArduinoJson / 11738795103

08 Nov 2024 08:37AM UTC coverage: 99.302%. Remained the same
11738795103

push

github

bblanchon
Add more tests with VLAs

3984 of 4012 relevant lines covered (99.3%)

10788.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.27
/src/ArduinoJson/Document/JsonDocument.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2024, Benoit BLANCHON
3
// MIT License
4

5
#pragma once
6

7
#include <ArduinoJson/Array/ElementProxy.hpp>
8
#include <ArduinoJson/Memory/Allocator.hpp>
9
#include <ArduinoJson/Memory/ResourceManager.hpp>
10
#include <ArduinoJson/Object/JsonObject.hpp>
11
#include <ArduinoJson/Object/MemberProxy.hpp>
12
#include <ArduinoJson/Polyfills/utility.hpp>
13
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
14
#include <ArduinoJson/Variant/VariantTo.hpp>
15

16
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
17

18
// A JSON document.
19
// https://arduinojson.org/v7/api/jsondocument/
20
class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
21
  friend class detail::VariantAttorney;
22

23
 public:
24
  explicit JsonDocument(Allocator* alloc = detail::DefaultAllocator::instance())
2,023✔
25
      : resources_(alloc) {}
2,023✔
26

27
  // Copy-constructor
28
  JsonDocument(const JsonDocument& src) : JsonDocument(src.allocator()) {
7✔
29
    set(src);
7✔
30
  }
7✔
31

32
  // Move-constructor
33
  JsonDocument(JsonDocument&& src)
2✔
34
      : JsonDocument(detail::DefaultAllocator::instance()) {
2✔
35
    swap(*this, src);
2✔
36
  }
2✔
37

38
  // Construct from variant, array, or object
39
  template <typename T>
40
  JsonDocument(
9✔
41
      const T& src, Allocator* alloc = detail::DefaultAllocator::instance(),
42
      detail::enable_if_t<detail::IsVariant<T>::value ||
43
                          detail::is_same<T, JsonArray>::value ||
44
                          detail::is_same<T, JsonArrayConst>::value ||
45
                          detail::is_same<T, JsonObject>::value ||
46
                          detail::is_same<T, JsonObjectConst>::value>* = 0)
47
      : JsonDocument(alloc) {
9✔
48
    set(src);
9✔
49
  }
9✔
50

51
  JsonDocument& operator=(JsonDocument src) {
4✔
52
    swap(*this, src);
4✔
53
    return *this;
4✔
54
  }
55

56
  template <typename T>
57
  JsonDocument& operator=(const T& src) {
5✔
58
    set(src);
5✔
59
    return *this;
5✔
60
  }
61

62
  Allocator* allocator() const {
7✔
63
    return resources_.allocator();
7✔
64
  }
65

66
  // Reduces the capacity of the memory pool to match the current usage.
67
  // https://arduinojson.org/v7/api/jsondocument/shrinktofit/
68
  void shrinkToFit() {
1,347✔
69
    resources_.shrinkToFit();
1,347✔
70
  }
1,347✔
71

72
  // Casts the root to the specified type.
73
  // https://arduinojson.org/v7/api/jsondocument/as/
74
  template <typename T>
75
  T as() {
614✔
76
    return getVariant().template as<T>();
1,177✔
77
  }
78

79
  // Casts the root to the specified type.
80
  // https://arduinojson.org/v7/api/jsondocument/as/
81
  template <typename T>
82
  T as() const {
10✔
83
    return getVariant().template as<T>();
20✔
84
  }
85

86
  // Empties the document and resets the memory pool
87
  // https://arduinojson.org/v7/api/jsondocument/clear/
88
  void clear() {
1,929✔
89
    resources_.clear();
1,929✔
90
    data_.reset();
1,929✔
91
  }
1,929✔
92

93
  // Returns true if the root is of the specified type.
94
  // https://arduinojson.org/v7/api/jsondocument/is/
95
  template <typename T>
96
  bool is() {
102✔
97
    return getVariant().template is<T>();
204✔
98
  }
99

100
  // Returns true if the root is of the specified type.
101
  // https://arduinojson.org/v7/api/jsondocument/is/
102
  template <typename T>
103
  bool is() const {
104
    return getVariant().template is<T>();
105
  }
106

107
  // Returns true if the root is null.
108
  // https://arduinojson.org/v7/api/jsondocument/isnull/
109
  bool isNull() const {
15✔
110
    return getVariant().isNull();
15✔
111
  }
112

113
  // Returns trues if the memory pool was too small.
114
  // https://arduinojson.org/v7/api/jsondocument/overflowed/
115
  bool overflowed() const {
40✔
116
    return resources_.overflowed();
40✔
117
  }
118

119
  // Returns the depth (nesting level) of the array.
120
  // https://arduinojson.org/v7/api/jsondocument/nesting/
121
  size_t nesting() const {
4✔
122
    return data_.nesting(&resources_);
4✔
123
  }
124

125
  // Returns the number of elements in the root array or object.
126
  // https://arduinojson.org/v7/api/jsondocument/size/
127
  size_t size() const {
15✔
128
    return data_.size(&resources_);
15✔
129
  }
130

131
  // Copies the specified document.
132
  // https://arduinojson.org/v7/api/jsondocument/set/
133
  bool set(const JsonDocument& src) {
7✔
134
    return to<JsonVariant>().set(src.as<JsonVariantConst>());
7✔
135
  }
136

137
  // Replaces the root with the specified value.
138
  // https://arduinojson.org/v7/api/jsondocument/set/
139
  template <typename T>
140
  detail::enable_if_t<!detail::is_base_of<JsonDocument, T>::value, bool> set(
68✔
141
      const T& src) {
142
    return to<JsonVariant>().set(src);
68✔
143
  }
144

145
  // Replaces the root with the specified value.
146
  // https://arduinojson.org/v7/api/jsondocument/set/
147
  template <typename TChar>
148
  bool set(TChar* src) {
12✔
149
    return to<JsonVariant>().set(src);
12✔
150
  }
151

152
  // Clears the document and converts it to the specified type.
153
  // https://arduinojson.org/v7/api/jsondocument/to/
154
  template <typename T>
155
  typename detail::VariantTo<T>::type to() {
859✔
156
    clear();
859✔
157
    return getVariant().template to<T>();
1,718✔
158
  }
159

160
  // DEPRECATED: use obj["key"].is<T>() instead
161
  // https://arduinojson.org/v7/api/jsondocument/containskey/
162
  template <typename TChar>
163
  ARDUINOJSON_DEPRECATED("use doc[\"key\"].is<T>() instead")
164
  bool containsKey(TChar* key) const {
8✔
165
    return data_.getMember(detail::adaptString(key), &resources_) != 0;
8✔
166
  }
167

168
  // DEPRECATED: use obj[key].is<T>() instead
169
  // https://arduinojson.org/v7/api/jsondocument/containskey/
170
  template <typename TString>
171
  ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
172
  detail::enable_if_t<detail::IsString<TString>::value, bool> containsKey(
1✔
173
      const TString& key) const {
174
    return data_.getMember(detail::adaptString(key), &resources_) != 0;
1✔
175
  }
176

177
  // DEPRECATED: use obj[key].is<T>() instead
178
  // https://arduinojson.org/v7/api/jsondocument/containskey/
179
  template <typename TVariant>
180
  ARDUINOJSON_DEPRECATED("use doc[key].is<T>() instead")
181
  detail::enable_if_t<detail::IsVariant<TVariant>::value, bool> containsKey(
2✔
182
      const TVariant& key) const {
183
    return containsKey(key.template as<const char*>());
2✔
184
  }
185

186
  // Gets or sets a root object's member.
187
  // https://arduinojson.org/v7/api/jsondocument/subscript/
188
  template <typename TString>
189
  detail::enable_if_t<detail::IsString<TString>::value,
190
                      detail::MemberProxy<JsonDocument&, TString>>
191
  operator[](const TString& key) {
26✔
192
    return {*this, key};
26✔
193
  }
194

195
  // Gets or sets a root object's member.
196
  // https://arduinojson.org/v7/api/jsondocument/subscript/
197
  template <typename TChar>
198
  detail::enable_if_t<detail::IsString<TChar*>::value,
199
                      detail::MemberProxy<JsonDocument&, TChar*>>
200
  operator[](TChar* key) {
486✔
201
    return {*this, key};
486✔
202
  }
203

204
  // Gets a root object's member.
205
  // https://arduinojson.org/v7/api/jsondocument/subscript/
206
  template <typename TString>
207
  detail::enable_if_t<detail::IsString<TString>::value, JsonVariantConst>
208
  operator[](const TString& key) const {
1✔
209
    return JsonVariantConst(
1✔
210
        data_.getMember(detail::adaptString(key), &resources_), &resources_);
2✔
211
  }
212

213
  // Gets a root object's member.
214
  // https://arduinojson.org/v7/api/jsondocument/subscript/
215
  template <typename TChar>
216
  detail::enable_if_t<detail::IsString<TChar*>::value, JsonVariantConst>
217
  operator[](TChar* key) const {
5✔
218
    return JsonVariantConst(
5✔
219
        data_.getMember(detail::adaptString(key), &resources_), &resources_);
10✔
220
  }
221

222
  // Gets or sets a root array's element.
223
  // https://arduinojson.org/v7/api/jsondocument/subscript/
224
  template <typename T>
225
  detail::enable_if_t<detail::is_integral<T>::value,
226
                      detail::ElementProxy<JsonDocument&>>
227
  operator[](T index) {
140✔
228
    return {*this, size_t(index)};
140✔
229
  }
230

231
  // Gets a root array's member.
232
  // https://arduinojson.org/v7/api/jsondocument/subscript/
233
  JsonVariantConst operator[](size_t index) const {
3✔
234
    return JsonVariantConst(data_.getElement(index, &resources_), &resources_);
3✔
235
  }
236

237
  // Gets or sets a root object's member.
238
  // https://arduinojson.org/v7/api/jsondocument/subscript/
239
  template <typename TVariant>
240
  detail::enable_if_t<detail::IsVariant<TVariant>::value, JsonVariantConst>
241
  operator[](const TVariant& key) const {
4✔
242
    if (key.template is<const char*>())
4✔
243
      return operator[](key.template as<const char*>());
2✔
244
    if (key.template is<size_t>())
2✔
245
      return operator[](key.template as<size_t>());
2✔
246
    return {};
×
247
  }
248

249
  // Appends a new (empty) element to the root array.
250
  // Returns a reference to the new element.
251
  // https://arduinojson.org/v7/api/jsondocument/add/
252
  template <typename T>
253
  detail::enable_if_t<!detail::is_same<T, JsonVariant>::value, T> add() {
53✔
254
    return add<JsonVariant>().to<T>();
106✔
255
  }
256

257
  // Appends a new (null) element to the root array.
258
  // Returns a reference to the new element.
259
  // https://arduinojson.org/v7/api/jsondocument/add/
260
  template <typename T>
261
  detail::enable_if_t<detail::is_same<T, JsonVariant>::value, T> add() {
123✔
262
    return JsonVariant(data_.addElement(&resources_), &resources_);
123✔
263
  }
264

265
  // Appends a value to the root array.
266
  // https://arduinojson.org/v7/api/jsondocument/add/
267
  template <typename TValue>
268
  bool add(const TValue& value) {
69✔
269
    return data_.addValue(value, &resources_);
69✔
270
  }
271

272
  // Appends a value to the root array.
273
  // https://arduinojson.org/v7/api/jsondocument/add/
274
  template <typename TChar>
275
  bool add(TChar* value) {
20✔
276
    return data_.addValue(value, &resources_);
20✔
277
  }
278

279
  // Removes an element of the root array.
280
  // https://arduinojson.org/v7/api/jsondocument/remove/
281
  template <typename T>
282
  detail::enable_if_t<detail::is_integral<T>::value> remove(T index) {
2✔
283
    detail::VariantData::removeElement(getData(), size_t(index),
2✔
284
                                       getResourceManager());
285
  }
2✔
286

287
  // Removes a member of the root object.
288
  // https://arduinojson.org/v7/api/jsondocument/remove/
289
  template <typename TChar>
290
  detail::enable_if_t<detail::IsString<TChar*>::value> remove(TChar* key) {
3✔
291
    detail::VariantData::removeMember(getData(), detail::adaptString(key),
3✔
292
                                      getResourceManager());
293
  }
3✔
294

295
  // Removes a member of the root object.
296
  // https://arduinojson.org/v7/api/jsondocument/remove/
297
  template <typename TString>
298
  detail::enable_if_t<detail::IsString<TString>::value> remove(
1✔
299
      const TString& key) {
300
    detail::VariantData::removeMember(getData(), detail::adaptString(key),
1✔
301
                                      getResourceManager());
302
  }
1✔
303

304
  // Removes a member of the root object or an element of the root array.
305
  // https://arduinojson.org/v7/api/jsondocument/remove/
306
  template <typename TVariant>
307
  detail::enable_if_t<detail::IsVariant<TVariant>::value> remove(
3✔
308
      const TVariant& key) {
309
    if (key.template is<const char*>())
3✔
310
      remove(key.template as<const char*>());
1✔
311
    if (key.template is<size_t>())
3✔
312
      remove(key.template as<size_t>());
1✔
313
  }
3✔
314

315
  operator JsonVariant() {
1✔
316
    return getVariant();
1✔
317
  }
318

319
  operator JsonVariantConst() const {
282✔
320
    return getVariant();
282✔
321
  }
322

323
  friend void swap(JsonDocument& a, JsonDocument& b) {
7✔
324
    swap(a.resources_, b.resources_);
7✔
325
    swap_(a.data_, b.data_);
7✔
326
  }
7✔
327

328
  // DEPRECATED: use add<JsonVariant>() instead
329
  ARDUINOJSON_DEPRECATED("use add<JsonVariant>() instead")
330
  JsonVariant add() {
2✔
331
    return add<JsonVariant>();
2✔
332
  }
333

334
  // DEPRECATED: use add<JsonArray>() instead
335
  ARDUINOJSON_DEPRECATED("use add<JsonArray>() instead")
336
  JsonArray createNestedArray() {
1✔
337
    return add<JsonArray>();
1✔
338
  }
339

340
  // DEPRECATED: use doc[key].to<JsonArray>() instead
341
  template <typename TChar>
342
  ARDUINOJSON_DEPRECATED("use doc[key].to<JsonArray>() instead")
343
  JsonArray createNestedArray(TChar* key) {
2✔
344
    return operator[](key).template to<JsonArray>();
2✔
345
  }
346

347
  // DEPRECATED: use doc[key].to<JsonArray>() instead
348
  template <typename TString>
349
  ARDUINOJSON_DEPRECATED("use doc[key].to<JsonArray>() instead")
350
  JsonArray createNestedArray(const TString& key) {
1✔
351
    return operator[](key).template to<JsonArray>();
1✔
352
  }
353

354
  // DEPRECATED: use add<JsonObject>() instead
355
  ARDUINOJSON_DEPRECATED("use add<JsonObject>() instead")
356
  JsonObject createNestedObject() {
1✔
357
    return add<JsonObject>();
1✔
358
  }
359

360
  // DEPRECATED: use doc[key].to<JsonObject>() instead
361
  template <typename TChar>
362
  ARDUINOJSON_DEPRECATED("use doc[key].to<JsonObject>() instead")
363
  JsonObject createNestedObject(TChar* key) {
2✔
364
    return operator[](key).template to<JsonObject>();
2✔
365
  }
366

367
  // DEPRECATED: use doc[key].to<JsonObject>() instead
368
  template <typename TString>
369
  ARDUINOJSON_DEPRECATED("use doc[key].to<JsonObject>() instead")
370
  JsonObject createNestedObject(const TString& key) {
1✔
371
    return operator[](key).template to<JsonObject>();
1✔
372
  }
373

374
  // DEPRECATED: always returns zero
375
  ARDUINOJSON_DEPRECATED("always returns zero")
376
  size_t memoryUsage() const {
1✔
377
    return 0;
1✔
378
  }
379

380
 private:
381
  JsonVariant getVariant() {
1,576✔
382
    return JsonVariant(&data_, &resources_);
1,576✔
383
  }
384

385
  JsonVariantConst getVariant() const {
307✔
386
    return JsonVariantConst(&data_, &resources_);
307✔
387
  }
388

389
  detail::ResourceManager* getResourceManager() {
2,790✔
390
    return &resources_;
2,790✔
391
  }
392

393
  detail::VariantData* getData() {
243✔
394
    return &data_;
243✔
395
  }
396

397
  const detail::VariantData* getData() const {
398
    return &data_;
399
  }
400

401
  detail::VariantData* getOrCreateData() {
1,547✔
402
    return &data_;
1,547✔
403
  }
404

405
  detail::ResourceManager resources_;
406
  detail::VariantData data_;
407
};
408

409
inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
1✔
410
  dst.set(src.as<JsonVariantConst>());
1✔
411
}
1✔
412

413
ARDUINOJSON_END_PUBLIC_NAMESPACE
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc