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

bblanchon / ArduinoJson / 5489391768

pending completion
5489391768

push

github

bblanchon
`VariantSlot` stores a `StringNode*` for owned keys

18 of 18 new or added lines in 5 files covered. (100.0%)

3406 of 3429 relevant lines covered (99.33%)

6529.06 hits per line

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

99.17
/src/ArduinoJson/Document/JsonDocument.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2023, 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/v6/api/jsondocument/
20
class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
21
  friend class detail::VariantAttorney;
22

23
 public:
24
  explicit JsonDocument(size_t capa,
1,957✔
25
                        Allocator* alloc = detail::DefaultAllocator::instance())
26
      : resources_(capa, alloc) {}
1,957✔
27

28
  // Copy-constructor
29
  JsonDocument(const JsonDocument& src)
4✔
30
      : JsonDocument(src.resources_.capacity(), src.allocator()) {
4✔
31
    set(src);
4✔
32
  }
4✔
33

34
  // Move-constructor
35
  JsonDocument(JsonDocument&& src) : resources_(0, src.allocator()) {
2✔
36
    // TODO: use the copy and swap idiom
37
    moveAssignFrom(src);
2✔
38
  }
2✔
39

40
  // Construct from variant, array, or object
41
  template <typename T>
42
  JsonDocument(const T& src,
3✔
43
               Allocator* alloc = detail::DefaultAllocator::instance(),
44
               typename detail::enable_if<
45
                   detail::is_same<T, JsonVariant>::value ||
46
                   detail::is_same<T, JsonVariantConst>::value ||
47
                   detail::is_same<T, JsonArray>::value ||
48
                   detail::is_same<T, JsonArrayConst>::value ||
49
                   detail::is_same<T, JsonObject>::value ||
50
                   detail::is_same<T, JsonObjectConst>::value>::type* = 0)
51
      : JsonDocument(src.memoryUsage(), alloc) {
3✔
52
    set(src);
3✔
53
  }
3✔
54

55
  // disambiguate
56
  // TODO: still needed?
57
  JsonDocument(JsonVariant src) : JsonDocument(src.memoryUsage()) {
58
    set(src);
59
  }
60

61
  JsonDocument& operator=(const JsonDocument& src) {
3✔
62
    // TODO: use the copy and swap idiom
63
    copyAssignFrom(src);
3✔
64
    return *this;
3✔
65
  }
66

67
  JsonDocument& operator=(JsonDocument&& src) {
3✔
68
    // TODO: use the copy and swap idiom
69
    moveAssignFrom(src);
3✔
70
    return *this;
3✔
71
  }
72

73
  template <typename T>
74
  JsonDocument& operator=(const T& src) {
5✔
75
    size_t requiredSize = src.memoryUsage();
5✔
76
    if (requiredSize > resources_.capacity())
5✔
77
      resources_.reallocPool(requiredSize);
×
78
    set(src);
5✔
79
    return *this;
5✔
80
  }
81

82
  Allocator* allocator() const {
6✔
83
    return resources_.allocator();
6✔
84
  }
85

86
  // Reduces the capacity of the memory pool to match the current usage.
87
  // https://arduinojson.org/v6/api/JsonDocument/shrinktofit/
88
  void shrinkToFit() {
14✔
89
    auto offset = resources_.shrinkToFit();
14✔
90
    data_.movePointers(offset);
14✔
91
  }
14✔
92

93
  // Reclaims the memory leaked when removing and replacing values.
94
  // https://arduinojson.org/v6/api/jsondocument/garbagecollect/
95
  bool garbageCollect() {
3✔
96
    // make a temporary clone and move assign
97
    JsonDocument tmp(*this);
6✔
98
    if (!tmp.resources_.capacity())
3✔
99
      return false;
1✔
100
    moveAssignFrom(tmp);
2✔
101
    return true;
2✔
102
  }
103

104
  // Casts the root to the specified type.
105
  // https://arduinojson.org/v6/api/jsondocument/as/
106
  template <typename T>
107
  T as() {
502✔
108
    return getVariant().template as<T>();
1,004✔
109
  }
110

111
  // Casts the root to the specified type.
112
  // https://arduinojson.org/v6/api/jsondocument/as/
113
  template <typename T>
114
  T as() const {
10✔
115
    return getVariant().template as<T>();
20✔
116
  }
117

118
  // Empties the document and resets the memory pool
119
  // https://arduinojson.org/v6/api/jsondocument/clear/
120
  void clear() {
1,756✔
121
    resources_.clear();
1,756✔
122
    data_.reset();
1,756✔
123
  }
1,756✔
124

125
  // Returns true if the root is of the specified type.
126
  // https://arduinojson.org/v6/api/jsondocument/is/
127
  template <typename T>
128
  bool is() {
94✔
129
    return getVariant().template is<T>();
188✔
130
  }
131

132
  // Returns true if the root is of the specified type.
133
  // https://arduinojson.org/v6/api/jsondocument/is/
134
  template <typename T>
135
  bool is() const {
136
    return getVariant().template is<T>();
137
  }
138

139
  // Returns true if the root is null.
140
  // https://arduinojson.org/v6/api/jsondocument/isnull/
141
  bool isNull() const {
12✔
142
    return getVariant().isNull();
24✔
143
  }
144

145
  // Returns the number of used bytes in the memory pool.
146
  // https://arduinojson.org/v6/api/jsondocument/memoryusage/
147
  size_t memoryUsage() const {
283✔
148
    return resources_.size();
283✔
149
  }
150

151
  // Returns trues if the memory pool was too small.
152
  // https://arduinojson.org/v6/api/jsondocument/overflowed/
153
  bool overflowed() const {
21✔
154
    return resources_.overflowed();
21✔
155
  }
156

157
  // Returns the depth (nesting level) of the array.
158
  // https://arduinojson.org/v6/api/jsondocument/nesting/
159
  size_t nesting() const {
4✔
160
    return data_.nesting();
4✔
161
  }
162

163
  // Returns the number of elements in the root array or object.
164
  // https://arduinojson.org/v6/api/jsondocument/size/
165
  size_t size() const {
12✔
166
    return data_.size();
12✔
167
  }
168

169
  // Copies the specified document.
170
  // https://arduinojson.org/v6/api/jsondocument/set/
171
  bool set(const JsonDocument& src) {
7✔
172
    return to<JsonVariant>().set(src.as<JsonVariantConst>());
14✔
173
  }
174

175
  // Replaces the root with the specified value.
176
  // https://arduinojson.org/v6/api/jsondocument/set/
177
  template <typename T>
178
  typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
179
                             bool>::type
180
  set(const T& src) {
39✔
181
    return to<JsonVariant>().set(src);
78✔
182
  }
183

184
  // Clears the document and converts it to the specified type.
185
  // https://arduinojson.org/v6/api/jsondocument/to/
186
  template <typename T>
187
  typename detail::VariantTo<T>::type to() {
717✔
188
    clear();
717✔
189
    return getVariant().template to<T>();
1,434✔
190
  }
191

192
  // Creates an array and appends it to the root array.
193
  // https://arduinojson.org/v6/api/jsondocument/createnestedarray/
194
  JsonArray createNestedArray() {
25✔
195
    return add().to<JsonArray>();
50✔
196
  }
197

198
  // Creates an array and adds it to the root object.
199
  // https://arduinojson.org/v6/api/jsondocument/createnestedarray/
200
  template <typename TChar>
201
  JsonArray createNestedArray(TChar* key) {
1✔
202
    return operator[](key).template to<JsonArray>();
1✔
203
  }
204

205
  // Creates an array and adds it to the root object.
206
  // https://arduinojson.org/v6/api/jsondocument/createnestedarray/
207
  template <typename TString>
208
  JsonArray createNestedArray(const TString& key) {
1✔
209
    return operator[](key).template to<JsonArray>();
1✔
210
  }
211

212
  // Creates an object and appends it to the root array.
213
  // https://arduinojson.org/v6/api/jsondocument/createnestedobject/
214
  JsonObject createNestedObject() {
25✔
215
    return add().to<JsonObject>();
50✔
216
  }
217

218
  // Creates an object and adds it to the root object.
219
  // https://arduinojson.org/v6/api/jsondocument/createnestedobject/
220
  template <typename TChar>
221
  JsonObject createNestedObject(TChar* key) {
1✔
222
    return operator[](key).template to<JsonObject>();
1✔
223
  }
224

225
  // Creates an object and adds it to the root object.
226
  // https://arduinojson.org/v6/api/jsondocument/createnestedobject/
227
  template <typename TString>
228
  JsonObject createNestedObject(const TString& key) {
1✔
229
    return operator[](key).template to<JsonObject>();
1✔
230
  }
231

232
  // Returns true if the root object contains the specified key.
233
  // https://arduinojson.org/v6/api/jsondocument/containskey/
234
  template <typename TChar>
235
  bool containsKey(TChar* key) const {
5✔
236
    return data_.getMember(detail::adaptString(key)) != 0;
5✔
237
  }
238

239
  // Returns true if the root object contains the specified key.
240
  // https://arduinojson.org/v6/api/jsondocument/containskey/
241
  template <typename TString>
242
  bool containsKey(const TString& key) const {
1✔
243
    return data_.getMember(detail::adaptString(key)) != 0;
1✔
244
  }
245

246
  // Gets or sets a root object's member.
247
  // https://arduinojson.org/v6/api/jsondocument/subscript/
248
  template <typename TString>
249
  FORCE_INLINE typename detail::enable_if<
250
      detail::IsString<TString>::value,
251
      detail::MemberProxy<JsonDocument&, TString>>::type
252
  operator[](const TString& key) {
253
    return {*this, key};
18✔
254
  }
255

256
  // Gets or sets a root object's member.
257
  // https://arduinojson.org/v6/api/jsondocument/subscript/
258
  template <typename TChar>
259
  FORCE_INLINE typename detail::enable_if<
260
      detail::IsString<TChar*>::value,
261
      detail::MemberProxy<JsonDocument&, TChar*>>::type
262
  operator[](TChar* key) {
263
    return {*this, key};
431✔
264
  }
265

266
  // Gets a root object's member.
267
  // https://arduinojson.org/v6/api/jsondocument/subscript/
268
  template <typename TString>
269
  FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
270
                                          JsonVariantConst>::type
271
  operator[](const TString& key) const {
272
    return JsonVariantConst(data_.getMember(detail::adaptString(key)));
1✔
273
  }
274

275
  // Gets a root object's member.
276
  // https://arduinojson.org/v6/api/jsondocument/subscript/
277
  template <typename TChar>
278
  FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
279
                                          JsonVariantConst>::type
280
  operator[](TChar* key) const {
281
    return JsonVariantConst(data_.getMember(detail::adaptString(key)));
1✔
282
  }
283

284
  // Gets or sets a root array's element.
285
  // https://arduinojson.org/v6/api/jsondocument/subscript/
286
  FORCE_INLINE detail::ElementProxy<JsonDocument&> operator[](size_t index) {
287
    return {*this, index};
124✔
288
  }
289

290
  // Gets a root array's member.
291
  // https://arduinojson.org/v6/api/jsondocument/subscript/
292
  FORCE_INLINE JsonVariantConst operator[](size_t index) const {
293
    return JsonVariantConst(data_.getElement(index));
1✔
294
  }
295

296
  // Appends a new (null) element to the root array.
297
  // Returns a reference to the new element.
298
  // https://arduinojson.org/v6/api/jsondocument/add/
299
  FORCE_INLINE JsonVariant add() {
300
    return JsonVariant(data_.addElement(&resources_), &resources_);
170✔
301
  }
302

303
  // Appends a value to the root array.
304
  // https://arduinojson.org/v6/api/jsondocument/add/
305
  template <typename TValue>
306
  FORCE_INLINE bool add(const TValue& value) {
307
    return add().set(value);
92✔
308
  }
309

310
  // Appends a value to the root array.
311
  // https://arduinojson.org/v6/api/jsondocument/add/
312
  template <typename TChar>
313
  FORCE_INLINE bool add(TChar* value) {
314
    return add().set(value);
24✔
315
  }
316

317
  // Removes an element of the root array.
318
  // ⚠️ Doesn't release the memory associated with the removed element.
319
  // https://arduinojson.org/v6/api/jsondocument/remove/
320
  FORCE_INLINE void remove(size_t index) {
321
    detail::VariantData::removeElement(getData(), index, getResourceManager());
1✔
322
  }
1✔
323

324
  // Removes a member of the root object.
325
  // ⚠️ Doesn't release the memory associated with the removed element.
326
  // https://arduinojson.org/v6/api/jsondocument/remove/
327
  template <typename TChar>
328
  FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type
329
  remove(TChar* key) {
330
    detail::VariantData::removeMember(getData(), detail::adaptString(key),
4✔
331
                                      getResourceManager());
332
  }
4✔
333

334
  // Removes a member of the root object.
335
  // ⚠️ Doesn't release the memory associated with the removed element.
336
  // https://arduinojson.org/v6/api/jsondocument/remove/
337
  template <typename TString>
338
  FORCE_INLINE
339
      typename detail::enable_if<detail::IsString<TString>::value>::type
340
      remove(const TString& key) {
341
    detail::VariantData::removeMember(getData(), detail::adaptString(key),
1✔
342
                                      getResourceManager());
343
  }
1✔
344

345
  FORCE_INLINE operator JsonVariant() {
346
    return getVariant();
1✔
347
  }
348

349
  FORCE_INLINE operator JsonVariantConst() const {
350
    return getVariant();
297✔
351
  }
352

353
 private:
354
  JsonVariant getVariant() {
1,314✔
355
    return JsonVariant(&data_, &resources_);
1,314✔
356
  }
357

358
  JsonVariantConst getVariant() const {
319✔
359
    return JsonVariantConst(&data_);
319✔
360
  }
361

362
  void copyAssignFrom(const JsonDocument& src) {
3✔
363
    resources_.reallocPool(src.resources_.capacity());
3✔
364
    set(src);
3✔
365
  }
3✔
366

367
  void moveAssignFrom(JsonDocument& src) {
7✔
368
    data_ = src.data_;
7✔
369
    src.data_.reset();
7✔
370
    resources_ = move(src.resources_);
7✔
371
  }
7✔
372

373
  detail::ResourceManager* getResourceManager() {
2,382✔
374
    return &resources_;
2,382✔
375
  }
376

377
  detail::VariantData* getData() {
1,262✔
378
    return &data_;
1,262✔
379
  }
380

381
  const detail::VariantData* getData() const {
6✔
382
    return &data_;
6✔
383
  }
384

385
  detail::VariantData* getOrCreateData() {
401✔
386
    return &data_;
401✔
387
  }
388

389
  detail::ResourceManager resources_;
390
  detail::VariantData data_;
391
};
392

393
inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
1✔
394
  dst.set(src.as<JsonVariantConst>());
1✔
395
}
1✔
396

397
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

© 2025 Coveralls, Inc