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

bblanchon / ArduinoJson / 12035063111

26 Nov 2024 01:32PM UTC coverage: 99.323% (-0.001%) from 99.324%
12035063111

push

github

bblanchon
Rename undocumented `JsonString::isLinked()` to `isStatic()`

8 of 8 new or added lines in 4 files covered. (100.0%)

3 existing lines in 1 file now uncovered.

3964 of 3991 relevant lines covered (99.32%)

10923.54 hits per line

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

98.96
/src/ArduinoJson/Variant/VariantData.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2024, Benoit BLANCHON
3
// MIT License
4

5
#pragma once
6

7
#include <ArduinoJson/Memory/MemoryPool.hpp>
8
#include <ArduinoJson/Memory/StringNode.hpp>
9
#include <ArduinoJson/Misc/SerializedValue.hpp>
10
#include <ArduinoJson/Numbers/convertNumber.hpp>
11
#include <ArduinoJson/Strings/JsonString.hpp>
12
#include <ArduinoJson/Strings/StringAdapters.hpp>
13
#include <ArduinoJson/Variant/VariantContent.hpp>
14

15
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
16

17
template <typename T>
18
T parseNumber(const char* s);
19

20
class VariantData {
21
  VariantContent content_;  // must be first to allow cast from array to variant
22
  VariantType type_;
23
  SlotId next_;
24

25
 public:
26
  // Placement new
27
  static void* operator new(size_t, void* p) noexcept {
74,798✔
28
    return p;
74,798✔
29
  }
30

31
  static void operator delete(void*, void*) noexcept {}
32

33
  VariantData() : type_(VariantType::Null), next_(NULL_SLOT) {}
76,852✔
34

35
  SlotId next() const {
292,498✔
36
    return next_;
292,498✔
37
  }
38

39
  void setNext(SlotId slot) {
71,927✔
40
    next_ = slot;
71,927✔
41
  }
71,927✔
42

43
  template <typename TVisitor>
44
  typename TVisitor::result_type accept(
139,338✔
45
      TVisitor& visit, const ResourceManager* resources) const {
46
#if ARDUINOJSON_USE_EXTENSIONS
47
    auto extension = getExtension(resources);
139,338✔
48
#else
49
    (void)resources;  // silence warning
50
#endif
51
    switch (type_) {
139,338✔
52
      case VariantType::Float:
121✔
53
        return visit.visit(content_.asFloat);
121✔
54

55
#if ARDUINOJSON_USE_DOUBLE
56
      case VariantType::Double:
16✔
57
        return visit.visit(extension->asDouble);
16✔
58
#endif
59

60
      case VariantType::Array:
983✔
61
        return visit.visit(content_.asArray);
983✔
62

63
      case VariantType::Object:
2,677✔
64
        return visit.visit(content_.asObject);
2,677✔
65

66
      case VariantType::LinkedString:
1,158✔
67
        return visit.visit(JsonString(content_.asLinkedString, true));
1,158✔
68

69
      case VariantType::OwnedString:
966✔
70
        return visit.visit(JsonString(content_.asOwnedString->data,
966✔
71
                                      content_.asOwnedString->length));
966✔
72

73
      case VariantType::RawString:
129✔
74
        return visit.visit(RawString(content_.asOwnedString->data,
129✔
75
                                     content_.asOwnedString->length));
129✔
76

77
      case VariantType::Int32:
1,183✔
78
        return visit.visit(static_cast<JsonInteger>(content_.asInt32));
1,183✔
79

80
      case VariantType::Uint32:
256✔
81
        return visit.visit(static_cast<JsonUInt>(content_.asUint32));
256✔
82

83
#if ARDUINOJSON_USE_LONG_LONG
84
      case VariantType::Int64:
7✔
85
        return visit.visit(extension->asInt64);
7✔
86

87
      case VariantType::Uint64:
8✔
88
        return visit.visit(extension->asUint64);
8✔
89
#endif
90

91
      case VariantType::Boolean:
607✔
92
        return visit.visit(content_.asBoolean != 0);
607✔
93

94
      default:
131,227✔
95
        return visit.visit(nullptr);
131,227✔
96
    }
97
  }
98

99
  template <typename TVisitor>
100
  static typename TVisitor::result_type accept(const VariantData* var,
726✔
101
                                               const ResourceManager* resources,
102
                                               TVisitor& visit) {
103
    if (var != 0)
726✔
104
      return var->accept(visit, resources);
723✔
105
    else
106
      return visit.visit(nullptr);
3✔
107
  }
108

109
  VariantData* addElement(ResourceManager* resources) {
159✔
110
    auto array = isNull() ? &toArray() : asArray();
159✔
111
    return detail::ArrayData::addElement(array, resources);
159✔
112
  }
113

114
  static VariantData* addElement(VariantData* var, ResourceManager* resources) {
41✔
115
    if (!var)
41✔
116
      return nullptr;
6✔
117
    return var->addElement(resources);
35✔
118
  }
119

120
  template <typename T>
121
  bool addValue(const T& value, ResourceManager* resources) {
133✔
122
    auto array = isNull() ? &toArray() : asArray();
133✔
123
    return detail::ArrayData::addValue(array, value, resources);
133✔
124
  }
125

126
  template <typename T>
127
  static bool addValue(VariantData* var, const T& value,
49✔
128
                       ResourceManager* resources) {
129
    if (!var)
49✔
130
      return false;
6✔
131
    return var->addValue(value, resources);
43✔
132
  }
133

134
  bool asBoolean(const ResourceManager* resources) const {
554✔
135
#if ARDUINOJSON_USE_EXTENSIONS
136
    auto extension = getExtension(resources);
554✔
137
#else
138
    (void)resources;  // silence warning
139
#endif
140
    switch (type_) {
554✔
141
      case VariantType::Boolean:
305✔
142
        return content_.asBoolean;
305✔
143
      case VariantType::Uint32:
6✔
144
      case VariantType::Int32:
145
        return content_.asUint32 != 0;
6✔
146
      case VariantType::Float:
2✔
147
        return content_.asFloat != 0;
2✔
148
#if ARDUINOJSON_USE_DOUBLE
149
      case VariantType::Double:
4✔
150
        return extension->asDouble != 0;
4✔
151
#endif
152
      case VariantType::Null:
6✔
153
        return false;
6✔
154
#if ARDUINOJSON_USE_LONG_LONG
155
      case VariantType::Uint64:
2✔
156
      case VariantType::Int64:
157
        return extension->asUint64 != 0;
2✔
158
#endif
159
      default:
229✔
160
        return true;
229✔
161
    }
162
  }
163

164
  ArrayData* asArray() {
776✔
165
    return isArray() ? &content_.asArray : 0;
776✔
166
  }
167

168
  const ArrayData* asArray() const {
496✔
169
    return const_cast<VariantData*>(this)->asArray();
496✔
170
  }
171

172
  CollectionData* asCollection() {
69,466✔
173
    return isCollection() ? &content_.asCollection : 0;
69,466✔
174
  }
175

176
  const CollectionData* asCollection() const {
44✔
177
    return const_cast<VariantData*>(this)->asCollection();
44✔
178
  }
179

180
  template <typename T>
181
  T asFloat(const ResourceManager* resources) const {
52✔
182
    static_assert(is_floating_point<T>::value, "T must be a floating point");
183
#if ARDUINOJSON_USE_EXTENSIONS
184
    auto extension = getExtension(resources);
52✔
185
#else
186
    (void)resources;  // silence warning
187
#endif
188
    switch (type_) {
52✔
189
      case VariantType::Boolean:
2✔
190
        return static_cast<T>(content_.asBoolean);
2✔
191
      case VariantType::Uint32:
2✔
192
        return static_cast<T>(content_.asUint32);
2✔
193
      case VariantType::Int32:
4✔
194
        return static_cast<T>(content_.asInt32);
4✔
195
#if ARDUINOJSON_USE_LONG_LONG
196
      case VariantType::Uint64:
1✔
197
        return static_cast<T>(extension->asUint64);
1✔
198
      case VariantType::Int64:
1✔
199
        return static_cast<T>(extension->asInt64);
1✔
200
#endif
201
      case VariantType::LinkedString:
1✔
202
      case VariantType::OwnedString:
203
        return parseNumber<T>(content_.asOwnedString->data);
1✔
204
      case VariantType::Float:
18✔
205
        return static_cast<T>(content_.asFloat);
18✔
206
#if ARDUINOJSON_USE_DOUBLE
207
      case VariantType::Double:
21✔
208
        return static_cast<T>(extension->asDouble);
21✔
209
#endif
210
      default:
2✔
211
        return 0;
2✔
212
    }
213
  }
214

215
  template <typename T>
216
  T asIntegral(const ResourceManager* resources) const {
197✔
217
    static_assert(is_integral<T>::value, "T must be an integral type");
218
#if ARDUINOJSON_USE_EXTENSIONS
219
    auto extension = getExtension(resources);
197✔
220
#else
221
    (void)resources;  // silence warning
222
#endif
223
    switch (type_) {
197✔
224
      case VariantType::Boolean:
2✔
225
        return content_.asBoolean;
2✔
226
      case VariantType::Uint32:
66✔
227
        return convertNumber<T>(content_.asUint32);
66✔
228
      case VariantType::Int32:
83✔
229
        return convertNumber<T>(content_.asInt32);
83✔
230
#if ARDUINOJSON_USE_LONG_LONG
231
      case VariantType::Uint64:
10✔
232
        return convertNumber<T>(extension->asUint64);
10✔
233
      case VariantType::Int64:
11✔
234
        return convertNumber<T>(extension->asInt64);
11✔
235
#endif
236
      case VariantType::LinkedString:
6✔
237
        return parseNumber<T>(content_.asLinkedString);
6✔
238
      case VariantType::OwnedString:
2✔
239
        return parseNumber<T>(content_.asOwnedString->data);
2✔
240
      case VariantType::Float:
5✔
241
        return convertNumber<T>(content_.asFloat);
5✔
242
#if ARDUINOJSON_USE_DOUBLE
243
      case VariantType::Double:
10✔
244
        return convertNumber<T>(extension->asDouble);
10✔
245
#endif
246
      default:
2✔
247
        return 0;
2✔
248
    }
249
  }
250

251
  ObjectData* asObject() {
2,941✔
252
    return isObject() ? &content_.asObject : 0;
2,941✔
253
  }
254

255
  const ObjectData* asObject() const {
2,233✔
256
    return const_cast<VariantData*>(this)->asObject();
2,233✔
257
  }
258

259
  JsonString asRawString() const {
46✔
260
    switch (type_) {
46✔
261
      case VariantType::RawString:
26✔
262
        return JsonString(content_.asOwnedString->data,
26✔
263
                          content_.asOwnedString->length);
26✔
264
      default:
20✔
265
        return JsonString();
20✔
266
    }
267
  }
268

269
  JsonString asString() const {
12,753✔
270
    switch (type_) {
12,753✔
271
      case VariantType::LinkedString:
4,663✔
272
        return JsonString(content_.asLinkedString, true);
4,663✔
273
      case VariantType::OwnedString:
7,660✔
274
        return JsonString(content_.asOwnedString->data,
7,660✔
275
                          content_.asOwnedString->length);
7,660✔
276
      default:
430✔
277
        return JsonString();
430✔
278
    }
279
  }
280

281
#if ARDUINOJSON_USE_EXTENSIONS
282
  const VariantExtension* getExtension(const ResourceManager* resources) const;
283
#endif
284

285
  VariantData* getElement(size_t index,
463✔
286
                          const ResourceManager* resources) const {
287
    return ArrayData::getElement(asArray(), index, resources);
463✔
288
  }
289

290
  static VariantData* getElement(const VariantData* var, size_t index,
466✔
291
                                 const ResourceManager* resources) {
292
    return var != 0 ? var->getElement(index, resources) : 0;
466✔
293
  }
294

295
  template <typename TAdaptedString>
296
  VariantData* getMember(TAdaptedString key,
2,199✔
297
                         const ResourceManager* resources) const {
298
    return ObjectData::getMember(asObject(), key, resources);
2,199✔
299
  }
300

301
  template <typename TAdaptedString>
302
  static VariantData* getMember(const VariantData* var, TAdaptedString key,
2,187✔
303
                                const ResourceManager* resources) {
304
    if (!var)
2,187✔
305
      return 0;
13✔
306
    return var->getMember(key, resources);
2,174✔
307
  }
308

309
  VariantData* getOrAddElement(size_t index, ResourceManager* resources) {
152✔
310
    auto array = isNull() ? &toArray() : asArray();
152✔
311
    if (!array)
152✔
312
      return nullptr;
1✔
313
    return array->getOrAddElement(index, resources);
151✔
314
  }
315

316
  template <typename TAdaptedString>
317
  VariantData* getOrAddMember(TAdaptedString key, ResourceManager* resources) {
958✔
318
    if (key.isNull())
958✔
319
      return nullptr;
1✔
320
    auto obj = isNull() ? &toObject() : asObject();
957✔
321
    if (!obj)
957✔
UNCOV
322
      return nullptr;
×
323
    return obj->getOrAddMember(key, resources);
957✔
324
  }
325

326
  bool isArray() const {
893✔
327
    return type_ == VariantType::Array;
893✔
328
  }
329

330
  bool isBoolean() const {
35✔
331
    return type_ == VariantType::Boolean;
35✔
332
  }
333

334
  bool isCollection() const {
69,466✔
335
    return type_ & VariantTypeBits::CollectionMask;
69,466✔
336
  }
337

338
  bool isFloat() const {
405✔
339
    return type_ & VariantTypeBits::NumberBit;
405✔
340
  }
341

342
  template <typename T>
343
  bool isInteger(const ResourceManager* resources) const {
151✔
344
#if ARDUINOJSON_USE_LONG_LONG
345
    auto extension = getExtension(resources);
148✔
346
#else
347
    (void)resources;  // silence warning
348
#endif
349
    switch (type_) {
151✔
350
      case VariantType::Uint32:
11✔
351
        return canConvertNumber<T>(content_.asUint32);
11✔
352

353
      case VariantType::Int32:
65✔
354
        return canConvertNumber<T>(content_.asInt32);
65✔
355

356
#if ARDUINOJSON_USE_LONG_LONG
357
      case VariantType::Uint64:
3✔
358
        return canConvertNumber<T>(extension->asUint64);
3✔
359

360
      case VariantType::Int64:
4✔
361
        return canConvertNumber<T>(extension->asInt64);
4✔
362
#endif
363

364
      default:
68✔
365
        return false;
68✔
366
    }
367
  }
368

369
  bool isNull() const {
1,955✔
370
    return type_ == VariantType::Null;
1,955✔
371
  }
372

373
  static bool isNull(const VariantData* var) {
1,288✔
374
    if (!var)
1,288✔
375
      return true;
737✔
376
    return var->isNull();
551✔
377
  }
378

379
  bool isObject() const {
3,328✔
380
    return type_ == VariantType::Object;
3,328✔
381
  }
382

383
  bool isString() const {
80✔
384
    return type_ == VariantType::LinkedString ||
136✔
385
           type_ == VariantType::OwnedString;
136✔
386
  }
387

388
  size_t nesting(const ResourceManager* resources) const {
44✔
389
    auto collection = asCollection();
44✔
390
    if (collection)
44✔
391
      return collection->nesting(resources);
30✔
392
    else
393
      return 0;
14✔
394
  }
395

396
  static size_t nesting(const VariantData* var,
28✔
397
                        const ResourceManager* resources) {
398
    if (!var)
28✔
399
      return 0;
6✔
400
    return var->nesting(resources);
22✔
401
  }
402

403
  void removeElement(size_t index, ResourceManager* resources) {
9✔
404
    ArrayData::removeElement(asArray(), index, resources);
9✔
405
  }
9✔
406

407
  static void removeElement(VariantData* var, size_t index,
10✔
408
                            ResourceManager* resources) {
409
    if (!var)
10✔
410
      return;
1✔
411
    var->removeElement(index, resources);
9✔
412
  }
413

414
  template <typename TAdaptedString>
415
  void removeMember(TAdaptedString key, ResourceManager* resources) {
16✔
416
    ObjectData::removeMember(asObject(), key, resources);
16✔
417
  }
16✔
418

419
  template <typename TAdaptedString>
420
  static void removeMember(VariantData* var, TAdaptedString key,
17✔
421
                           ResourceManager* resources) {
422
    if (!var)
17✔
423
      return;
1✔
424
    var->removeMember(key, resources);
16✔
425
  }
426

427
  void reset() {  // TODO: remove
1,945✔
428
    type_ = VariantType::Null;
1,945✔
429
  }
1,945✔
430

431
  void setBoolean(bool value) {
330✔
432
    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  // must call clear() first
433
    type_ = VariantType::Boolean;
330✔
434
    content_.asBoolean = value;
330✔
435
  }
330✔
436

437
  template <typename T>
438
  enable_if_t<sizeof(T) == 4, bool> setFloat(T value, ResourceManager*) {
89✔
439
    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  // must call clear() first
440
    type_ = VariantType::Float;
89✔
441
    content_.asFloat = value;
89✔
442
    return true;
89✔
443
  }
444

445
  template <typename T>
446
  enable_if_t<sizeof(T) == 8, bool> setFloat(T value, ResourceManager*);
447

448
  template <typename T>
449
  enable_if_t<is_signed<T>::value, bool> setInteger(T value,
450
                                                    ResourceManager* resources);
451

452
  template <typename T>
453
  enable_if_t<is_unsigned<T>::value, bool> setInteger(
454
      T value, ResourceManager* resources);
455

456
  void setRawString(StringNode* s) {
87✔
457
    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  // must call clear() first
458
    ARDUINOJSON_ASSERT(s);
459
    type_ = VariantType::RawString;
87✔
460
    content_.asOwnedString = s;
87✔
461
  }
87✔
462

463
  template <typename T>
464
  void setRawString(SerializedValue<T> value, ResourceManager* resources);
465

466
  template <typename T>
467
  static void setRawString(VariantData* var, SerializedValue<T> value,
36✔
468
                           ResourceManager* resources) {
469
    if (!var)
36✔
470
      return;
2✔
471
    var->clear(resources);
34✔
472
    var->setRawString(value, resources);
34✔
473
  }
474

475
  template <typename TAdaptedString>
476
  bool setString(TAdaptedString value, ResourceManager* resources);
477

478
  bool setString(StringNode* s, ResourceManager*) {
1,331✔
479
    setOwnedString(s);
1,331✔
480
    return true;
1,331✔
481
  }
482

483
  template <typename TAdaptedString>
484
  static void setString(VariantData* var, TAdaptedString value,
66,133✔
485
                        ResourceManager* resources) {
486
    if (!var)
66,133✔
487
      return;
5✔
488
    var->clear(resources);
66,128✔
489
    var->setString(value, resources);
66,128✔
490
  }
491

492
  void setLinkedString(const char* s) {
1,165✔
493
    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  // must call clear() first
494
    ARDUINOJSON_ASSERT(s);
495
    type_ = VariantType::LinkedString;
1,165✔
496
    content_.asLinkedString = s;
1,165✔
497
  }
1,165✔
498

499
  void setOwnedString(StringNode* s) {
2,024✔
500
    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  // must call clear() first
501
    ARDUINOJSON_ASSERT(s);
502
    type_ = VariantType::OwnedString;
2,024✔
503
    content_.asOwnedString = s;
2,024✔
504
  }
2,024✔
505

506
  size_t size(const ResourceManager* resources) const {
42✔
507
    if (isObject())
42✔
508
      return content_.asObject.size(resources);
14✔
509

510
    if (isArray())
28✔
511
      return content_.asArray.size(resources);
15✔
512

513
    return 0;
13✔
514
  }
515

516
  static size_t size(const VariantData* var, const ResourceManager* resources) {
30✔
517
    return var != 0 ? var->size(resources) : 0;
30✔
518
  }
519

520
  ArrayData& toArray() {
1,269✔
521
    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  // must call clear() first
522
    type_ = VariantType::Array;
1,269✔
523
    new (&content_.asArray) ArrayData();
2,538✔
524
    return content_.asArray;
1,269✔
525
  }
526

527
  static ArrayData* toArray(VariantData* var, ResourceManager* resources) {
256✔
528
    if (!var)
256✔
UNCOV
529
      return 0;
×
530
    var->clear(resources);
256✔
531
    return &var->toArray();
256✔
532
  }
533

534
  ObjectData& toObject() {
1,346✔
535
    ARDUINOJSON_ASSERT(type_ == VariantType::Null);  // must call clear() first
536
    type_ = VariantType::Object;
1,346✔
537
    new (&content_.asObject) ObjectData();
2,692✔
538
    return content_.asObject;
1,346✔
539
  }
540

541
  static ObjectData* toObject(VariantData* var, ResourceManager* resources) {
318✔
542
    if (!var)
318✔
UNCOV
543
      return 0;
×
544
    var->clear(resources);
318✔
545
    return &var->toObject();
318✔
546
  }
547

548
  VariantType type() const {
549
    return type_;
550
  }
551

552
  // Release the resources used by this variant and set it to null.
553
  void clear(ResourceManager* resources);
554

555
  static void clear(VariantData* var, ResourceManager* resources) {
539✔
556
    if (!var)
539✔
557
      return;
1✔
558
    var->clear(resources);
538✔
559
  }
560
};
561

562
ARDUINOJSON_END_PRIVATE_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