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

bblanchon / ArduinoJson / 5059873495

pending completion
5059873495

push

github

Benoit Blanchon
Remove VariantImpl.hpp

2 of 2 new or added lines in 1 file covered. (100.0%)

3280 of 3299 relevant lines covered (99.42%)

6312.26 hits per line

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

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

5
#pragma once
6

7
#include <ArduinoJson/Memory/StringNode.hpp>
8
#include <ArduinoJson/Misc/SerializedValue.hpp>
9
#include <ArduinoJson/Numbers/convertNumber.hpp>
10
#include <ArduinoJson/Strings/JsonString.hpp>
11
#include <ArduinoJson/Strings/StringAdapters.hpp>
12
#include <ArduinoJson/Variant/VariantContent.hpp>
13
#include <ArduinoJson/Variant/VariantSlot.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
  uint8_t flags_;
23

24
 public:
25
  VariantData() : flags_(VALUE_IS_NULL) {}
2,082✔
26

27
  template <typename TVisitor>
28
  typename TVisitor::result_type accept(TVisitor& visitor) const {
137,781✔
29
    switch (type()) {
137,781✔
30
      case VALUE_IS_FLOAT:
135✔
31
        return visitor.visitFloat(content_.asFloat);
135✔
32

33
      case VALUE_IS_ARRAY:
897✔
34
        return visitor.visitArray(content_.asCollection);
1,107✔
35

36
      case VALUE_IS_OBJECT:
2,588✔
37
        return visitor.visitObject(content_.asCollection);
2,588✔
38

39
      case VALUE_IS_LINKED_STRING:
670✔
40
        return visitor.visitString(content_.asLinkedString,
670✔
41
                                   strlen(content_.asLinkedString));
670✔
42

43
      case VALUE_IS_OWNED_STRING:
282✔
44
        return visitor.visitString(content_.asOwnedString->data,
282✔
45
                                   content_.asOwnedString->length);
282✔
46

47
      case VALUE_IS_RAW_STRING:
55✔
48
        return visitor.visitRawString(content_.asOwnedString->data,
55✔
49
                                      content_.asOwnedString->length);
55✔
50

51
      case VALUE_IS_SIGNED_INTEGER:
1,041✔
52
        return visitor.visitSignedInteger(content_.asSignedInteger);
1,041✔
53

54
      case VALUE_IS_UNSIGNED_INTEGER:
257✔
55
        return visitor.visitUnsignedInteger(content_.asUnsignedInteger);
257✔
56

57
      case VALUE_IS_BOOLEAN:
616✔
58
        return visitor.visitBoolean(content_.asBoolean != 0);
616✔
59

60
      default:
131,240✔
61
        return visitor.visitNull();
131,240✔
62
    }
63
  }
64

65
  bool asBoolean() const {
554✔
66
    switch (type()) {
554✔
67
      case VALUE_IS_BOOLEAN:
307✔
68
        return content_.asBoolean;
307✔
69
      case VALUE_IS_SIGNED_INTEGER:
7✔
70
      case VALUE_IS_UNSIGNED_INTEGER:
71
        return content_.asUnsignedInteger != 0;
7✔
72
      case VALUE_IS_FLOAT:
5✔
73
        return content_.asFloat != 0;
5✔
74
      case VALUE_IS_NULL:
6✔
75
        return false;
6✔
76
      default:
229✔
77
        return true;
229✔
78
    }
79
  }
80

81
  CollectionData* asArray() {
706✔
82
    return isArray() ? &content_.asCollection : 0;
706✔
83
  }
84

85
  const CollectionData* asArray() const {
459✔
86
    return const_cast<VariantData*>(this)->asArray();
459✔
87
  }
88

89
  const CollectionData* asCollection() const {
67,849✔
90
    return isCollection() ? &content_.asCollection : 0;
67,849✔
91
  }
92

93
  template <typename T>
94
  T asFloat() const {
117✔
95
    static_assert(is_floating_point<T>::value, "T must be a floating point");
96
    switch (type()) {
117✔
97
      case VALUE_IS_BOOLEAN:
2✔
98
        return static_cast<T>(content_.asBoolean);
2✔
99
      case VALUE_IS_UNSIGNED_INTEGER:
3✔
100
        return static_cast<T>(content_.asUnsignedInteger);
3✔
101
      case VALUE_IS_SIGNED_INTEGER:
6✔
102
        return static_cast<T>(content_.asSignedInteger);
6✔
103
      case VALUE_IS_LINKED_STRING:
1✔
104
      case VALUE_IS_OWNED_STRING:
105
        return parseNumber<T>(content_.asOwnedString->data);
1✔
106
      case VALUE_IS_FLOAT:
103✔
107
        return static_cast<T>(content_.asFloat);
103✔
108
      default:
2✔
109
        return 0;
2✔
110
    }
111
  }
112

113
  template <typename T>
114
  T asIntegral() const {
210✔
115
    static_assert(is_integral<T>::value, "T must be an integral type");
116
    switch (type()) {
210✔
117
      case VALUE_IS_BOOLEAN:
2✔
118
        return content_.asBoolean;
2✔
119
      case VALUE_IS_UNSIGNED_INTEGER:
87✔
120
        return convertNumber<T>(content_.asUnsignedInteger);
87✔
121
      case VALUE_IS_SIGNED_INTEGER:
84✔
122
        return convertNumber<T>(content_.asSignedInteger);
84✔
123
      case VALUE_IS_LINKED_STRING:
6✔
124
        return parseNumber<T>(content_.asLinkedString);
6✔
125
      case VALUE_IS_OWNED_STRING:
2✔
126
        return parseNumber<T>(content_.asOwnedString->data);
2✔
127
      case VALUE_IS_FLOAT:
19✔
128
        return convertNumber<T>(content_.asFloat);
19✔
129
      default:
10✔
130
        return 0;
10✔
131
    }
132
  }
133

134
  CollectionData* asObject() {
2,744✔
135
    return isObject() ? &content_.asCollection : 0;
2,744✔
136
  }
137

138
  const CollectionData* asObject() const {
2,152✔
139
    return const_cast<VariantData*>(this)->asObject();
2,152✔
140
  }
141

142
  JsonString asRawString() const {
4✔
143
    switch (type()) {
4✔
144
      case VALUE_IS_RAW_STRING:
4✔
145
        return JsonString(content_.asOwnedString->data,
4✔
146
                          content_.asOwnedString->length, JsonString::Copied);
4✔
147
      default:
×
148
        return JsonString();
×
149
    }
150
  }
151

152
  JsonString asString() const {
444✔
153
    switch (type()) {
444✔
154
      case VALUE_IS_LINKED_STRING:
30✔
155
        return JsonString(content_.asLinkedString, JsonString::Linked);
30✔
156
      case VALUE_IS_OWNED_STRING:
76✔
157
        return JsonString(content_.asOwnedString->data,
76✔
158
                          content_.asOwnedString->length, JsonString::Copied);
76✔
159
      default:
338✔
160
        return JsonString();
338✔
161
    }
162
  }
163

164
  VariantData* getElement(size_t index) const {
424✔
165
    auto array = asArray();
424✔
166
    if (!array)
424✔
167
      return nullptr;
15✔
168
    return slotData(array->get(index));
409✔
169
  }
170

171
  template <typename TAdaptedString>
172
  VariantData* getMember(TAdaptedString key) const {
2,135✔
173
    auto object = asObject();
2,135✔
174
    if (!object)
2,135✔
175
      return nullptr;
44✔
176
    return slotData(object->get(key));
2,091✔
177
  }
178

179
  const char* getOwnedString() const {
67,828✔
180
    if (flags_ & OWNED_VALUE_BIT)
67,828✔
181
      return content_.asOwnedString->data;
11✔
182
    else
183
      return nullptr;
67,817✔
184
  }
185

186
  bool isArray() const {
802✔
187
    return (flags_ & VALUE_IS_ARRAY) != 0;
802✔
188
  }
189

190
  bool isBoolean() const {
35✔
191
    return type() == VALUE_IS_BOOLEAN;
35✔
192
  }
193

194
  bool isCollection() const {
67,888✔
195
    return (flags_ & COLLECTION_MASK) != 0;
67,888✔
196
  }
197

198
  bool isFloat() const {
402✔
199
    return (flags_ & NUMBER_BIT) != 0;
402✔
200
  }
201

202
  template <typename T>
203
  bool isInteger() const {
123✔
204
    switch (type()) {
123✔
205
      case VALUE_IS_UNSIGNED_INTEGER:
12✔
206
        return canConvertNumber<T>(content_.asUnsignedInteger);
12✔
207

208
      case VALUE_IS_SIGNED_INTEGER:
57✔
209
        return canConvertNumber<T>(content_.asSignedInteger);
57✔
210

211
      default:
54✔
212
        return false;
54✔
213
    }
214
  }
215

216
  bool isNull() const {
1,690✔
217
    return type() == VALUE_IS_NULL;
1,690✔
218
  }
219

220
  bool isObject() const {
3,094✔
221
    return (flags_ & VALUE_IS_OBJECT) != 0;
3,094✔
222
  }
223

224
  bool isString() const {
62✔
225
    return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
62✔
226
  }
227

228
  size_t memoryUsage() const {
34✔
229
    switch (type()) {
34✔
230
      case VALUE_IS_OWNED_STRING:
10✔
231
      case VALUE_IS_RAW_STRING:
232
        return sizeofString(content_.asOwnedString->length);
10✔
233
      case VALUE_IS_OBJECT:
6✔
234
      case VALUE_IS_ARRAY:
235
        return content_.asCollection.memoryUsage();
6✔
236
      default:
18✔
237
        return 0;
18✔
238
    }
239
  }
240

241
  void movePointers(ptrdiff_t variantDistance) {
22✔
242
    if (flags_ & COLLECTION_MASK)
22✔
243
      content_.asCollection.movePointers(variantDistance);
10✔
244
  }
22✔
245

246
  void operator=(const VariantData& src) {
39✔
247
    content_ = src.content_;
39✔
248
    flags_ = uint8_t((flags_ & OWNED_KEY_BIT) | (src.flags_ & ~OWNED_KEY_BIT));
39✔
249
  }
39✔
250

251
  void reset() {
1,763✔
252
    flags_ = VALUE_IS_NULL;
1,763✔
253
  }
1,763✔
254

255
  void setBoolean(bool value) {
337✔
256
    setType(VALUE_IS_BOOLEAN);
337✔
257
    content_.asBoolean = value;
337✔
258
  }
337✔
259

260
  void setFloat(JsonFloat value) {
231✔
261
    setType(VALUE_IS_FLOAT);
231✔
262
    content_.asFloat = value;
231✔
263
  }
231✔
264

265
  template <typename T>
266
  typename enable_if<is_signed<T>::value>::type setInteger(T value) {
723✔
267
    setType(VALUE_IS_SIGNED_INTEGER);
723✔
268
    content_.asSignedInteger = value;
723✔
269
  }
723✔
270

271
  template <typename T>
272
  typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
2,313✔
273
    setType(VALUE_IS_UNSIGNED_INTEGER);
2,313✔
274
    content_.asUnsignedInteger = static_cast<JsonUInt>(value);
2,313✔
275
  }
2,313✔
276

277
  void setNull() {
65,985✔
278
    setType(VALUE_IS_NULL);
65,985✔
279
  }
65,985✔
280

281
  void setRawString(StringNode* s) {
30✔
282
    ARDUINOJSON_ASSERT(s);
283
    setType(VALUE_IS_RAW_STRING);
30✔
284
    content_.asOwnedString = s;
30✔
285
  }
30✔
286

287
  void setString(const char* s) {
300✔
288
    ARDUINOJSON_ASSERT(s);
289
    setType(VALUE_IS_LINKED_STRING);
300✔
290
    content_.asLinkedString = s;
300✔
291
  }
300✔
292

293
  void setString(StringNode* s) {
469✔
294
    ARDUINOJSON_ASSERT(s);
295
    setType(VALUE_IS_OWNED_STRING);
469✔
296
    content_.asOwnedString = s;
469✔
297
  }
469✔
298

299
  size_t size() const {
39✔
300
    return isCollection() ? content_.asCollection.size() : 0;
39✔
301
  }
302

303
  CollectionData& toArray() {
1,217✔
304
    setType(VALUE_IS_ARRAY);
1,217✔
305
    content_.asCollection.clear();
1,217✔
306
    return content_.asCollection;
1,217✔
307
  }
308

309
  CollectionData& toObject() {
1,269✔
310
    setType(VALUE_IS_OBJECT);
1,269✔
311
    content_.asCollection.clear();
1,269✔
312
    return content_.asCollection;
1,269✔
313
  }
314

315
  uint8_t type() const {
141,172✔
316
    return flags_ & VALUE_MASK;
141,172✔
317
  }
318

319
 private:
320
  void setType(uint8_t t) {
72,874✔
321
    flags_ &= OWNED_KEY_BIT;
72,874✔
322
    flags_ |= t;
72,874✔
323
  }
72,874✔
324
};
325

326
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