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

bblanchon / ArduinoJson / 4469075312

pending completion
4469075312

push

github

Benoit Blanchon
`MemoryPool` calls the `Allocator` directly

52 of 52 new or added lines in 3 files covered. (100.0%)

3283 of 3299 relevant lines covered (99.52%)

6203.28 hits per line

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

99.21
/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/MemoryPool.hpp>
10
#include <ArduinoJson/Object/JsonObject.hpp>
11
#include <ArduinoJson/Object/MemberProxy.hpp>
12
#include <ArduinoJson/Polyfills/utility.hpp>
13
#include <ArduinoJson/Strings/StoragePolicy.hpp>
14
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
15
#include <ArduinoJson/Variant/VariantTo.hpp>
16

17
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
18

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

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

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

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

41
  // Construct from variant, array, or object
42
  template <typename T>
43
  JsonDocument(const T& src,
2✔
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()) {
4✔
52
    set(src);
2✔
53
  }
2✔
54

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

61
  JsonDocument& operator=(const JsonDocument& src) {
5✔
62
    // TODO: use the copy and swap idiom
63
    copyAssignFrom(src);
5✔
64
    return *this;
5✔
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 > capacity())
5✔
77
      _pool.reallocPool(requiredSize);
×
78
    set(src);
5✔
79
    return *this;
5✔
80
  }
81

82
  Allocator* allocator() const {
7✔
83
    return _pool.allocator();
7✔
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() {
29✔
89
    _pool.shrinkToFit(_data);
29✔
90
  }
29✔
91

92
  // Reclaims the memory leaked when removing and replacing values.
93
  // https://arduinojson.org/v6/api/jsondocument/garbagecollect/
94
  bool garbageCollect() {
3✔
95
    // make a temporary clone and move assign
96
    JsonDocument tmp(*this);
6✔
97
    if (!tmp.capacity())
3✔
98
      return false;
1✔
99
    tmp.set(*this);
2✔
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() {
483✔
108
    return getVariant().template as<T>();
966✔
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 {
15✔
115
    return getVariant().template as<T>();
30✔
116
  }
117

118
  // Empties the document and resets the memory pool
119
  // https://arduinojson.org/v6/api/jsondocument/clear/
120
  void clear() {
1,779✔
121
    _pool.clear();
1,779✔
122
    _data.setNull();
1,779✔
123
  }
1,779✔
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() {
93✔
129
    return getVariant().template is<T>();
186✔
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 {
297✔
148
    return _pool.size();
297✔
149
  }
150

151
  // Returns trues if the memory pool was too small.
152
  // https://arduinojson.org/v6/api/jsondocument/overflowed/
153
  bool overflowed() const {
18✔
154
    return _pool.overflowed();
18✔
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 variantNesting(&_data);
4✔
161
  }
162

163
  // Returns the capacity of the memory pool.
164
  // https://arduinojson.org/v6/api/jsondocument/capacity/
165
  size_t capacity() const {
75✔
166
    return _pool.capacity();
75✔
167
  }
168

169
  // Returns the number of elements in the root array or object.
170
  // https://arduinojson.org/v6/api/jsondocument/size/
171
  size_t size() const {
11✔
172
    return _data.size();
11✔
173
  }
174

175
  // Copies the specified document.
176
  // https://arduinojson.org/v6/api/jsondocument/set/
177
  bool set(const JsonDocument& src) {
12✔
178
    return to<JsonVariant>().set(src.as<JsonVariantConst>());
24✔
179
  }
180

181
  // Replaces the root with the specified value.
182
  // https://arduinojson.org/v6/api/jsondocument/set/
183
  template <typename T>
184
  typename detail::enable_if<!detail::is_base_of<JsonDocument, T>::value,
185
                             bool>::type
186
  set(const T& src) {
43✔
187
    return to<JsonVariant>().set(src);
86✔
188
  }
189

190
  // Clears the document and converts it to the specified type.
191
  // https://arduinojson.org/v6/api/jsondocument/to/
192
  template <typename T>
193
  typename detail::VariantTo<T>::type to() {
723✔
194
    clear();
723✔
195
    return getVariant().template to<T>();
1,446✔
196
  }
197

198
  // Creates an array and appends it to the root array.
199
  // https://arduinojson.org/v6/api/jsondocument/createnestedarray/
200
  JsonArray createNestedArray() {
25✔
201
    return add().to<JsonArray>();
50✔
202
  }
203

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

211
  // Creates an array and adds it to the root object.
212
  // https://arduinojson.org/v6/api/jsondocument/createnestedarray/
213
  template <typename TString>
214
  JsonArray createNestedArray(const TString& key) {
1✔
215
    return operator[](key).template to<JsonArray>();
1✔
216
  }
217

218
  // Creates an object and appends it to the root array.
219
  // https://arduinojson.org/v6/api/jsondocument/createnestedobject/
220
  JsonObject createNestedObject() {
25✔
221
    return add().to<JsonObject>();
50✔
222
  }
223

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

231
  // Creates an object and adds it to the root object.
232
  // https://arduinojson.org/v6/api/jsondocument/createnestedobject/
233
  template <typename TString>
234
  JsonObject createNestedObject(const TString& key) {
1✔
235
    return operator[](key).template to<JsonObject>();
1✔
236
  }
237

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

245
  // Returns true if the root object contains the specified key.
246
  // https://arduinojson.org/v6/api/jsondocument/containskey/
247
  template <typename TString>
248
  bool containsKey(const TString& key) const {
1✔
249
    return _data.getMember(detail::adaptString(key)) != 0;
1✔
250
  }
251

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

262
  // Gets or sets a root object's member.
263
  // https://arduinojson.org/v6/api/jsondocument/subscript/
264
  template <typename TChar>
265
  FORCE_INLINE typename detail::enable_if<
266
      detail::IsString<TChar*>::value,
267
      detail::MemberProxy<JsonDocument&, TChar*>>::type
268
  operator[](TChar* key) {
269
    return {*this, key};
421✔
270
  }
271

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

281
  // Gets a root object's member.
282
  // https://arduinojson.org/v6/api/jsondocument/subscript/
283
  template <typename TChar>
284
  FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
285
                                          JsonVariantConst>::type
286
  operator[](TChar* key) const {
287
    return JsonVariantConst(_data.getMember(detail::adaptString(key)));
1✔
288
  }
289

290
  // Gets or sets a root array's element.
291
  // https://arduinojson.org/v6/api/jsondocument/subscript/
292
  FORCE_INLINE detail::ElementProxy<JsonDocument&> operator[](size_t index) {
293
    return {*this, index};
152✔
294
  }
295

296
  // Gets a root array's member.
297
  // https://arduinojson.org/v6/api/jsondocument/subscript/
298
  FORCE_INLINE JsonVariantConst operator[](size_t index) const {
299
    return JsonVariantConst(_data.getElement(index));
1✔
300
  }
301

302
  // Appends a new (null) element to the root array.
303
  // Returns a reference to the new element.
304
  // https://arduinojson.org/v6/api/jsondocument/add/
305
  FORCE_INLINE JsonVariant add() {
306
    return JsonVariant(&_pool, _data.addElement(&_pool));
176✔
307
  }
308

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

316
  // Appends a value to the root array.
317
  // https://arduinojson.org/v6/api/jsondocument/add/
318
  template <typename TChar>
319
  FORCE_INLINE bool add(TChar* value) {
320
    return add().set(value);
32✔
321
  }
322

323
  // Removes an element of the root array.
324
  // ⚠️ Doesn't release the memory associated with the removed element.
325
  // https://arduinojson.org/v6/api/jsondocument/remove/
326
  FORCE_INLINE void remove(size_t index) {
327
    _data.remove(index);
1✔
328
  }
1✔
329

330
  // Removes a member of the root object.
331
  // ⚠️ Doesn't release the memory associated with the removed element.
332
  // https://arduinojson.org/v6/api/jsondocument/remove/
333
  template <typename TChar>
334
  FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type
335
  remove(TChar* key) {
336
    _data.remove(detail::adaptString(key));
4✔
337
  }
4✔
338

339
  // Removes a member of the root object.
340
  // ⚠️ Doesn't release the memory associated with the removed element.
341
  // https://arduinojson.org/v6/api/jsondocument/remove/
342
  template <typename TString>
343
  FORCE_INLINE
344
      typename detail::enable_if<detail::IsString<TString>::value>::type
345
      remove(const TString& key) {
346
    _data.remove(detail::adaptString(key));
1✔
347
  }
1✔
348

349
  FORCE_INLINE operator JsonVariant() {
350
    return getVariant();
1✔
351
  }
352

353
  FORCE_INLINE operator JsonVariantConst() const {
354
    return getVariant();
335✔
355
  }
356

357
 private:
358
  JsonVariant getVariant() {
1,300✔
359
    return JsonVariant(&_pool, &_data);
1,300✔
360
  }
361

362
  JsonVariantConst getVariant() const {
362✔
363
    return JsonVariantConst(&_data);
362✔
364
  }
365

366
  void copyAssignFrom(const JsonDocument& src) {
5✔
367
    _pool.reallocPool(src.capacity());
5✔
368
    set(src);
5✔
369
  }
5✔
370

371
  void moveAssignFrom(JsonDocument& src) {
7✔
372
    _data = src._data;
7✔
373
    src._data.setNull();
7✔
374
    _pool = move(src._pool);
7✔
375
  }
7✔
376

377
  detail::MemoryPool* getPool() {
2,382✔
378
    return &_pool;
2,382✔
379
  }
380

381
  detail::VariantData* getData() {
1,316✔
382
    return &_data;
1,316✔
383
  }
384

385
  const detail::VariantData* getData() const {
6✔
386
    return &_data;
6✔
387
  }
388

389
  detail::VariantData* getOrCreateData() {
398✔
390
    return &_data;
398✔
391
  }
392

393
  detail::MemoryPool _pool;
394
  detail::VariantData _data;
395
};
396

397
inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
1✔
398
  dst.set(src.as<JsonVariantConst>());
1✔
399
}
1✔
400

401
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