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

open-source-parsers / jsoncpp / 13936668312

19 Mar 2025 01:11AM CUT coverage: 95.292%. Remained the same
13936668312

push

github

web-flow
Merge bb4ac3c6c into ca98c9845

5364 of 5629 relevant lines covered (95.29%)

11794.59 hits per line

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

93.71
/src/lib_json/json_value.cpp
1
// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
2
// Distributed under MIT license, or public domain if desired and
3
// recognized in your jurisdiction.
4
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5

6
#if !defined(JSON_IS_AMALGAMATION)
7
#include <json/assertions.h>
8
#include <json/value.h>
9
#include <json/writer.h>
10
#endif // if !defined(JSON_IS_AMALGAMATION)
11
#include <algorithm>
12
#include <cassert>
13
#include <cmath>
14
#include <cstddef>
15
#include <cstring>
16
#include <iostream>
17
#include <sstream>
18
#include <utility>
19

20
#ifdef JSONCPP_HAS_STRING_VIEW
21
#include <string_view>
22
#endif
23

24
// Provide implementation equivalent of std::snprintf for older _MSC compilers
25
#if defined(_MSC_VER) && _MSC_VER < 1900
26
#include <stdarg.h>
27
static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size,
28
                                      const char* format, va_list ap) {
29
  int count = -1;
30
  if (size != 0)
31
    count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
32
  if (count == -1)
33
    count = _vscprintf(format, ap);
34
  return count;
35
}
36

37
int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
38
                                       const char* format, ...) {
39
  va_list ap;
40
  va_start(ap, format);
41
  const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);
42
  va_end(ap);
43
  return count;
44
}
45
#endif
46

47
// Disable warning C4702 : unreachable code
48
#if defined(_MSC_VER)
49
#pragma warning(disable : 4702)
50
#endif
51

52
#define JSON_ASSERT_UNREACHABLE assert(false)
53

54
namespace Json {
55
template <typename T>
56
static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
253,265✔
57
  std::unique_ptr<T> r;
253,265✔
58
  if (p) {
253,265✔
59
    r = std::unique_ptr<T>(new T(*p));
6✔
60
  }
61
  return r;
253,265✔
62
}
63

64
// This is a walkaround to avoid the static initialization of Value::null.
65
// kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
66
// 8 (instead of 4) as a bit of future-proofing.
67
#if defined(__ARMEL__)
68
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
69
#else
70
#define ALIGNAS(byte_alignment)
71
#endif
72

73
// static
74
Value const& Value::nullSingleton() {
127,473✔
75
  static Value const nullStatic;
127,473✔
76
  return nullStatic;
127,473✔
77
}
78

79
#if JSON_USE_NULLREF
80
// for backwards compatibility, we'll leave these global references around, but
81
// DO NOT use them in JSONCPP library code any more!
82
// static
83
Value const& Value::null = Value::nullSingleton();
84

85
// static
86
Value const& Value::nullRef = Value::nullSingleton();
87
#endif
88

89
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
90
template <typename T, typename U>
91
static inline bool InRange(double d, T min, U max) {
92
  // The casts can lose precision, but we are looking only for
93
  // an approximate range. Might fail on edge cases though. ~cdunn
94
  return d >= static_cast<double>(min) && d <= static_cast<double>(max) &&
95
         !(static_cast<U>(d) == min && d != static_cast<double>(min));
96
}
97
#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
98
static inline double integerToDouble(Json::UInt64 value) {
99
  return static_cast<double>(Int64(value / 2)) * 2.0 +
21✔
100
         static_cast<double>(Int64(value & 1));
21✔
101
}
102

103
template <typename T> static inline double integerToDouble(T value) {
104
  return static_cast<double>(value);
105
}
106

107
template <typename T, typename U>
108
static inline bool InRange(double d, T min, U max) {
109
  return d >= integerToDouble(min) && d <= integerToDouble(max) &&
45✔
110
         !(static_cast<U>(d) == min && d != integerToDouble(min));
34✔
111
}
112
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
113

114
/** Duplicates the specified string value.
115
 * @param value Pointer to the string to duplicate. Must be zero-terminated if
116
 *              length is "unknown".
117
 * @param length Length of the value. if equals to unknown, then it will be
118
 *               computed using strlen(value).
119
 * @return Pointer on the duplicate instance of string.
120
 */
121
static inline char* duplicateStringValue(const char* value, size_t length) {
30,271✔
122
  // Avoid an integer overflow in the call to malloc below by limiting length
123
  // to a sane value.
124
  if (length >= static_cast<size_t>(Value::maxInt))
30,271✔
125
    length = Value::maxInt - 1;
126

127
  auto newString = static_cast<char*>(malloc(length + 1));
30,271✔
128
  if (newString == nullptr) {
30,271✔
129
    throwRuntimeError("in Json::Value::duplicateStringValue(): "
×
130
                      "Failed to allocate string value buffer");
131
  }
132
  memcpy(newString, value, length);
133
  newString[length] = 0;
30,271✔
134
  return newString;
30,271✔
135
}
136

137
/* Record the length as a prefix.
138
 */
139
static inline char* duplicateAndPrefixStringValue(const char* value,
2,623✔
140
                                                  unsigned int length) {
141
  // Avoid an integer overflow in the call to malloc below by limiting length
142
  // to a sane value.
143
  JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
2,623✔
144
                                    sizeof(unsigned) - 1U,
145
                      "in Json::Value::duplicateAndPrefixStringValue(): "
146
                      "length too big for prefixing");
147
  size_t actualLength = sizeof(length) + length + 1;
2,623✔
148
  auto newString = static_cast<char*>(malloc(actualLength));
2,623✔
149
  if (newString == nullptr) {
2,623✔
150
    throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
×
151
                      "Failed to allocate string value buffer");
152
  }
153
  *reinterpret_cast<unsigned*>(newString) = length;
2,623✔
154
  memcpy(newString + sizeof(unsigned), value, length);
2,623✔
155
  newString[actualLength - 1U] =
2,623✔
156
      0; // to avoid buffer over-run accidents by users later
157
  return newString;
2,623✔
158
}
159
inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
160
                                        unsigned* length, char const** value) {
161
  if (!isPrefixed) {
4,017✔
162
    *length = static_cast<unsigned>(strlen(prefixed));
3✔
163
    *value = prefixed;
×
164
  } else {
165
    *length = *reinterpret_cast<unsigned const*>(prefixed);
4,140✔
166
    *value = prefixed + sizeof(unsigned);
4,014✔
167
  }
168
}
169
/** Free the string duplicated by
170
 * duplicateStringValue()/duplicateAndPrefixStringValue().
171
 */
172
#if JSONCPP_USE_SECURE_MEMORY
173
static inline void releasePrefixedStringValue(char* value) {
174
  unsigned length = 0;
175
  char const* valueDecoded;
176
  decodePrefixedString(true, value, &length, &valueDecoded);
177
  size_t const size = sizeof(unsigned) + length + 1U;
178
  memset(value, 0, size);
179
  free(value);
180
}
181
static inline void releaseStringValue(char* value, unsigned length) {
182
  // length==0 => we allocated the strings memory
183
  size_t size = (length == 0) ? strlen(value) : length;
184
  memset(value, 0, size);
185
  free(value);
186
}
187
#else  // !JSONCPP_USE_SECURE_MEMORY
188
static inline void releasePrefixedStringValue(char* value) { free(value); }
2,623✔
189
static inline void releaseStringValue(char* value, unsigned) { free(value); }
30,271✔
190
#endif // JSONCPP_USE_SECURE_MEMORY
191

192
} // namespace Json
193

194
// //////////////////////////////////////////////////////////////////
195
// //////////////////////////////////////////////////////////////////
196
// //////////////////////////////////////////////////////////////////
197
// ValueInternals...
198
// //////////////////////////////////////////////////////////////////
199
// //////////////////////////////////////////////////////////////////
200
// //////////////////////////////////////////////////////////////////
201
#if !defined(JSON_IS_AMALGAMATION)
202

203
#include "json_valueiterator.inl"
204
#endif // if !defined(JSON_IS_AMALGAMATION)
205

206
namespace Json {
207

208
#if JSON_USE_EXCEPTION
209
Exception::Exception(String msg) : msg_(std::move(msg)) {}
48✔
210
Exception::~Exception() noexcept = default;
96✔
211
char const* Exception::what() const noexcept { return msg_.c_str(); }
6✔
212
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
16✔
213
LogicError::LogicError(String const& msg) : Exception(msg) {}
80✔
214
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
8✔
215
  throw RuntimeError(msg);
8✔
216
}
217
JSONCPP_NORETURN void throwLogicError(String const& msg) {
40✔
218
  throw LogicError(msg);
40✔
219
}
220
#else // !JSON_USE_EXCEPTION
221
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
222
  std::cerr << msg << std::endl;
223
  abort();
224
}
225
JSONCPP_NORETURN void throwLogicError(String const& msg) {
226
  std::cerr << msg << std::endl;
227
  abort();
228
}
229
#endif
230

231
// //////////////////////////////////////////////////////////////////
232
// //////////////////////////////////////////////////////////////////
233
// //////////////////////////////////////////////////////////////////
234
// class Value::CZString
235
// //////////////////////////////////////////////////////////////////
236
// //////////////////////////////////////////////////////////////////
237
// //////////////////////////////////////////////////////////////////
238

239
// Notes: policy_ indicates if the string was allocated when
240
// a string is stored.
241

242
Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
269,527✔
243

244
Value::CZString::CZString(char const* str, unsigned length,
36,406✔
245
                          DuplicationPolicy allocate)
36,406✔
246
    : cstr_(str) {
36,406✔
247
  // allocate != duplicate
248
  storage_.policy_ = allocate & 0x3;
36,406✔
249
  storage_.length_ = length & 0x3FFFFFFF;
36,406✔
250
}
36,406✔
251

252
Value::CZString::CZString(const CZString& other) {
252,970✔
253
  cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
187,751✔
254
               ? duplicateStringValue(other.cstr_, other.storage_.length_)
440,721✔
255
               : other.cstr_);
256
  storage_.policy_ =
252,970✔
257
      static_cast<unsigned>(
258
          other.cstr_
252,970✔
259
              ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
30,274✔
260
                         noDuplication
261
                     ? noDuplication
30,274✔
262
                     : duplicate)
263
              : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
252,970✔
264
      3U;
265
  storage_.length_ = other.storage_.length_;
252,970✔
266
}
252,970✔
267

268
Value::CZString::CZString(CZString&& other) noexcept
×
269
    : cstr_(other.cstr_), index_(other.index_) {
×
270
  other.cstr_ = nullptr;
×
271
}
×
272

273
Value::CZString::~CZString() {
558,903✔
274
  if (cstr_ && storage_.policy_ == duplicate) {
558,903✔
275
    releaseStringValue(const_cast<char*>(cstr_),
276
                       storage_.length_ + 1U); // +1 for null terminating
277
                                               // character for sake of
278
                                               // completeness but not actually
279
                                               // necessary
280
  }
281
}
558,903✔
282

283
void Value::CZString::swap(CZString& other) {
×
284
  std::swap(cstr_, other.cstr_);
285
  std::swap(index_, other.index_);
286
}
×
287

288
Value::CZString& Value::CZString::operator=(const CZString& other) {
×
289
  cstr_ = other.cstr_;
×
290
  index_ = other.index_;
×
291
  return *this;
×
292
}
293

294
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
×
295
  cstr_ = other.cstr_;
×
296
  index_ = other.index_;
×
297
  other.cstr_ = nullptr;
×
298
  return *this;
×
299
}
300

301
bool Value::CZString::operator<(const CZString& other) const {
3,940,902✔
302
  if (!cstr_)
3,940,902✔
303
    return index_ < other.index_;
3,782,636✔
304
  // return strcmp(cstr_, other.cstr_) < 0;
305
  // Assume both are strings.
306
  unsigned this_len = this->storage_.length_;
158,266✔
307
  unsigned other_len = other.storage_.length_;
158,266✔
308
  unsigned min_len = std::min<unsigned>(this_len, other_len);
158,266✔
309
  JSON_ASSERT(this->cstr_ && other.cstr_);
158,266✔
310
  int comp = memcmp(this->cstr_, other.cstr_, min_len);
158,266✔
311
  if (comp < 0)
158,266✔
312
    return true;
313
  if (comp > 0)
80,771✔
314
    return false;
315
  return (this_len < other_len);
40,411✔
316
}
317

318
bool Value::CZString::operator==(const CZString& other) const {
120,275✔
319
  if (!cstr_)
120,275✔
320
    return index_ == other.index_;
104,928✔
321
  // return strcmp(cstr_, other.cstr_) == 0;
322
  // Assume both are strings.
323
  unsigned this_len = this->storage_.length_;
15,347✔
324
  unsigned other_len = other.storage_.length_;
15,347✔
325
  if (this_len != other_len)
15,347✔
326
    return false;
327
  JSON_ASSERT(this->cstr_ && other.cstr_);
5,380✔
328
  int comp = memcmp(this->cstr_, other.cstr_, this_len);
5,380✔
329
  return comp == 0;
5,380✔
330
}
331

332
ArrayIndex Value::CZString::index() const { return index_; }
717✔
333

334
// const char* Value::CZString::c_str() const { return cstr_; }
335
const char* Value::CZString::data() const { return cstr_; }
1,727✔
336
unsigned Value::CZString::length() const { return storage_.length_; }
1,711✔
337
bool Value::CZString::isStaticString() const {
3✔
338
  return storage_.policy_ == noDuplication;
3✔
339
}
340

341
// //////////////////////////////////////////////////////////////////
342
// //////////////////////////////////////////////////////////////////
343
// //////////////////////////////////////////////////////////////////
344
// class Value::Value
345
// //////////////////////////////////////////////////////////////////
346
// //////////////////////////////////////////////////////////////////
347
// //////////////////////////////////////////////////////////////////
348

349
/*! \internal Default constructor initialization must be equivalent to:
350
 * memset( this, 0, sizeof(Value) )
351
 * This optimization is used in ValueInternalMap fast allocator.
352
 */
353
Value::Value(ValueType type) {
118,714✔
354
  static char const emptyString[] = "";
355
  initBasic(type);
118,714✔
356
  switch (type) {
118,714✔
357
  case nullValue:
358
    break;
359
  case intValue:
2✔
360
  case uintValue:
361
    value_.int_ = 0;
2✔
362
    break;
2✔
363
  case realValue:
1✔
364
    value_.real_ = 0.0;
1✔
365
    break;
1✔
366
  case stringValue:
×
367
    // allocated_ == false, so this is safe.
368
    value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
×
369
    break;
×
370
  case arrayValue:
9,118✔
371
  case objectValue:
372
    value_.map_ = new ObjectValues();
9,118✔
373
    break;
9,118✔
374
  case booleanValue:
×
375
    value_.bool_ = false;
×
376
    break;
×
377
  default:
×
378
    JSON_ASSERT_UNREACHABLE;
×
379
  }
380
}
118,714✔
381

382
Value::Value(Int value) {
1,486✔
383
  initBasic(intValue);
1,486✔
384
  value_.int_ = value;
1,486✔
385
}
1,486✔
386

387
Value::Value(UInt value) {
212✔
388
  initBasic(uintValue);
212✔
389
  value_.uint_ = value;
212✔
390
}
212✔
391
#if defined(JSON_HAS_INT64)
392
Value::Value(Int64 value) {
105,102✔
393
  initBasic(intValue);
105,102✔
394
  value_.int_ = value;
105,102✔
395
}
105,102✔
396
Value::Value(UInt64 value) {
124✔
397
  initBasic(uintValue);
124✔
398
  value_.uint_ = value;
124✔
399
}
124✔
400
#endif // defined(JSON_HAS_INT64)
401

402
Value::Value(double value) {
577✔
403
  initBasic(realValue);
577✔
404
  value_.real_ = value;
577✔
405
}
577✔
406

407
Value::Value(const char* value) {
1,233✔
408
  initBasic(stringValue, true);
1,233✔
409
  JSON_ASSERT_MESSAGE(value != nullptr,
1,233✔
410
                      "Null Value Passed to Value Constructor");
411
  value_.string_ = duplicateAndPrefixStringValue(
2,466✔
412
      value, static_cast<unsigned>(strlen(value)));
1,233✔
413
}
1,233✔
414

415
Value::Value(const char* begin, const char* end) {
2✔
416
  initBasic(stringValue, true);
2✔
417
  value_.string_ =
2✔
418
      duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
2✔
419
}
2✔
420

421
Value::Value(const String& value) {
1,259✔
422
  initBasic(stringValue, true);
1,259✔
423
  value_.string_ = duplicateAndPrefixStringValue(
1,259✔
424
      value.data(), static_cast<unsigned>(value.length()));
425
}
1,259✔
426

427
#ifdef JSONCPP_HAS_STRING_VIEW
428
Value::Value(std::string_view value) {
429
  initBasic(stringValue, true);
430
  value_.string_ = duplicateAndPrefixStringValue(
431
      value.data(), static_cast<unsigned>(value.length()));
432
}
433
#endif
434

435
Value::Value(const StaticString& value) {
2✔
436
  initBasic(stringValue);
2✔
437
  value_.string_ = const_cast<char*>(value.c_str());
2✔
438
}
2✔
439

440
Value::Value(bool value) {
14,600✔
441
  initBasic(booleanValue);
14,600✔
442
  value_.bool_ = value;
14,600✔
443
}
14,600✔
444

445
Value::Value(const Value& other) {
253,257✔
446
  dupPayload(other);
253,257✔
447
  dupMeta(other);
253,257✔
448
}
253,257✔
449

450
Value::Value(Value&& other) noexcept {
50✔
451
  initBasic(nullValue);
50✔
452
  swap(other);
50✔
453
}
50✔
454

455
Value::~Value() {
496,618✔
456
  releasePayload();
496,618✔
457
  value_.uint_ = 0;
496,618✔
458
}
496,618✔
459

460
Value& Value::operator=(const Value& other) {
18✔
461
  Value(other).swap(*this);
18✔
462
  return *this;
18✔
463
}
464

465
Value& Value::operator=(Value&& other) noexcept {
124,959✔
466
  other.swap(*this);
124,959✔
467
  return *this;
124,959✔
468
}
469

470
void Value::swapPayload(Value& other) {
238,804✔
471
  std::swap(bits_, other.bits_);
472
  std::swap(value_, other.value_);
473
}
238,804✔
474

475
void Value::copyPayload(const Value& other) {
8✔
476
  releasePayload();
8✔
477
  dupPayload(other);
8✔
478
}
8✔
479

480
void Value::swap(Value& other) {
125,028✔
481
  swapPayload(other);
125,028✔
482
  std::swap(comments_, other.comments_);
125,028✔
483
  std::swap(start_, other.start_);
484
  std::swap(limit_, other.limit_);
485
}
125,028✔
486

487
void Value::copy(const Value& other) {
8✔
488
  copyPayload(other);
8✔
489
  dupMeta(other);
8✔
490
}
8✔
491

492
ValueType Value::type() const {
2,269,811✔
493
  return static_cast<ValueType>(bits_.value_type_);
2,269,811✔
494
}
495

496
int Value::compare(const Value& other) const {
120✔
497
  if (*this < other)
120✔
498
    return -1;
499
  if (*this > other)
89✔
500
    return 1;
31✔
501
  return 0;
502
}
503

504
bool Value::operator<(const Value& other) const {
1,279✔
505
  int typeDelta = type() - other.type();
1,279✔
506
  if (typeDelta)
1,279✔
507
    return typeDelta < 0;
77✔
508
  switch (type()) {
1,202✔
509
  case nullValue:
510
    return false;
511
  case intValue:
564✔
512
    return value_.int_ < other.value_.int_;
564✔
513
  case uintValue:
34✔
514
    return value_.uint_ < other.value_.uint_;
34✔
515
  case realValue:
46✔
516
    return value_.real_ < other.value_.real_;
46✔
517
  case booleanValue:
35✔
518
    return value_.bool_ < other.value_.bool_;
35✔
519
  case stringValue: {
175✔
520
    if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
175✔
521
      return other.value_.string_ != nullptr;
×
522
    }
523
    unsigned this_len;
524
    unsigned other_len;
525
    char const* this_str;
526
    char const* other_str;
527
    decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
528
                         &this_str);
529
    decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
530
                         &other_str);
531
    unsigned min_len = std::min<unsigned>(this_len, other_len);
175✔
532
    JSON_ASSERT(this_str && other_str);
533
    int comp = memcmp(this_str, other_str, min_len);
175✔
534
    if (comp < 0)
175✔
535
      return true;
536
    if (comp > 0)
163✔
537
      return false;
538
    return (this_len < other_len);
153✔
539
  }
540
  case arrayValue:
312✔
541
  case objectValue: {
542
    auto thisSize = value_.map_->size();
312✔
543
    auto otherSize = other.value_.map_->size();
312✔
544
    if (thisSize != otherSize)
312✔
545
      return thisSize < otherSize;
66✔
546
    return (*value_.map_) < (*other.value_.map_);
246✔
547
  }
548
  default:
×
549
    JSON_ASSERT_UNREACHABLE;
×
550
  }
551
  return false; // unreachable
552
}
553

554
bool Value::operator<=(const Value& other) const { return !(other < *this); }
120✔
555

556
bool Value::operator>=(const Value& other) const { return !(*this < other); }
120✔
557

558
bool Value::operator>(const Value& other) const { return other < *this; }
209✔
559

560
bool Value::operator==(const Value& other) const {
313✔
561
  if (type() != other.type())
313✔
562
    return false;
563
  switch (type()) {
298✔
564
  case nullValue:
565
    return true;
566
  case intValue:
79✔
567
    return value_.int_ == other.value_.int_;
79✔
568
  case uintValue:
10✔
569
    return value_.uint_ == other.value_.uint_;
10✔
570
  case realValue:
14✔
571
    return value_.real_ == other.value_.real_;
14✔
572
  case booleanValue:
15✔
573
    return value_.bool_ == other.value_.bool_;
15✔
574
  case stringValue: {
87✔
575
    if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
87✔
576
      return (value_.string_ == other.value_.string_);
×
577
    }
578
    unsigned this_len;
579
    unsigned other_len;
580
    char const* this_str;
581
    char const* other_str;
582
    decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
583
                         &this_str);
584
    decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
585
                         &other_str);
586
    if (this_len != other_len)
87✔
587
      return false;
588
    JSON_ASSERT(this_str && other_str);
589
    int comp = memcmp(this_str, other_str, this_len);
80✔
590
    return comp == 0;
80✔
591
  }
592
  case arrayValue:
60✔
593
  case objectValue:
594
    return value_.map_->size() == other.value_.map_->size() &&
107✔
595
           (*value_.map_) == (*other.value_.map_);
596
  default:
×
597
    JSON_ASSERT_UNREACHABLE;
×
598
  }
599
  return false; // unreachable
600
}
601

602
bool Value::operator!=(const Value& other) const { return !(*this == other); }
131✔
603

604
const char* Value::asCString() const {
4✔
605
  JSON_ASSERT_MESSAGE(type() == stringValue,
6✔
606
                      "in Json::Value::asCString(): requires stringValue");
607
  if (value_.string_ == nullptr)
3✔
608
    return nullptr;
609
  unsigned this_len;
610
  char const* this_str;
611
  decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
612
                       &this_str);
613
  return this_str;
614
}
615

616
#if JSONCPP_USE_SECURE_MEMORY
617
unsigned Value::getCStringLength() const {
618
  JSON_ASSERT_MESSAGE(type() == stringValue,
619
                      "in Json::Value::asCString(): requires stringValue");
620
  if (value_.string_ == 0)
621
    return 0;
622
  unsigned this_len;
623
  char const* this_str;
624
  decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
625
                       &this_str);
626
  return this_len;
627
}
628
#endif
629

630
bool Value::getString(char const** begin, char const** end) const {
782✔
631
  if (type() != stringValue)
782✔
632
    return false;
633
  if (value_.string_ == nullptr)
782✔
634
    return false;
635
  unsigned length;
636
  decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
637
                       begin);
638
  *end = *begin + length;
782✔
639
  return true;
782✔
640
}
641

642
#ifdef JSONCPP_HAS_STRING_VIEW
643
bool Value::getString(std::string_view* str) const {
644
  if (type() != stringValue)
645
    return false;
646
  if (value_.string_ == nullptr)
647
    return false;
648
  const char* begin;
649
  unsigned length;
650
  decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
651
                       &begin);
652
  *str = std::string_view(begin, length);
653
  return true;
654
}
655
#endif
656

657
String Value::asString() const {
2,750✔
658
  switch (type()) {
2,750✔
659
  case nullValue:
660
    return "";
2✔
661
  case stringValue: {
2,708✔
662
    if (value_.string_ == nullptr)
2,708✔
663
      return "";
×
664
    unsigned this_len;
665
    char const* this_str;
666
    decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
667
                         &this_str);
668
    return String(this_str, this_len);
2,708✔
669
  }
670
  case booleanValue:
671
    return value_.bool_ ? "true" : "false";
×
672
  case intValue:
13✔
673
    return valueToString(value_.int_);
13✔
674
  case uintValue:
7✔
675
    return valueToString(value_.uint_);
7✔
676
  case realValue:
18✔
677
    return valueToString(value_.real_);
18✔
678
  default:
2✔
679
    JSON_FAIL_MESSAGE("Type is not convertible to string");
6✔
680
  }
681
}
682

683
Value::Int Value::asInt() const {
28✔
684
  switch (type()) {
28✔
685
  case intValue:
9✔
686
    JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
9✔
687
    return Int(value_.int_);
9✔
688
  case uintValue:
8✔
689
    JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
8✔
690
    return Int(value_.uint_);
8✔
691
  case realValue:
5✔
692
    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
5✔
693
                        "double out of Int range");
694
    return Int(value_.real_);
695
  case nullValue:
696
    return 0;
697
  case booleanValue:
2✔
698
    return value_.bool_ ? 1 : 0;
2✔
699
  default:
700
    break;
701
  }
702
  JSON_FAIL_MESSAGE("Value is not convertible to Int.");
9✔
703
}
704

705
Value::UInt Value::asUInt() const {
1,575✔
706
  switch (type()) {
1,575✔
707
  case intValue:
1,558✔
708
    JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
1,558✔
709
    return UInt(value_.int_);
1,558✔
710
  case uintValue:
6✔
711
    JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
6✔
712
    return UInt(value_.uint_);
6✔
713
  case realValue:
5✔
714
    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt),
5✔
715
                        "double out of UInt range");
716
    return UInt(value_.real_);
717
  case nullValue:
718
    return 0;
719
  case booleanValue:
2✔
720
    return value_.bool_ ? 1 : 0;
2✔
721
  default:
722
    break;
723
  }
724
  JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
9✔
725
}
726

727
#if defined(JSON_HAS_INT64)
728

729
Value::Int64 Value::asInt64() const {
157,460✔
730
  switch (type()) {
157,460✔
731
  case intValue:
157,438✔
732
    return Int64(value_.int_);
157,438✔
733
  case uintValue:
6✔
734
    JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
6✔
735
    return Int64(value_.uint_);
6✔
736
  case realValue:
10✔
737
    // If the double value is in proximity to minInt64, it will be rounded to
738
    // minInt64. The correct value in this scenario is indeterminable
739
    JSON_ASSERT_MESSAGE(
10✔
740
        value_.real_ != minInt64,
741
        "Double value is minInt64, precise value cannot be determined");
742
    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
×
743
                        "double out of Int64 range");
744
    return Int64(value_.real_);
745
  case nullValue:
746
    return 0;
747
  case booleanValue:
2✔
748
    return value_.bool_ ? 1 : 0;
2✔
749
  default:
750
    break;
751
  }
752
  JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
9✔
753
}
754

755
Value::UInt64 Value::asUInt64() const {
261✔
756
  switch (type()) {
261✔
757
  case intValue:
8✔
758
    JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
8✔
759
    return UInt64(value_.int_);
8✔
760
  case uintValue:
237✔
761
    return UInt64(value_.uint_);
237✔
762
  case realValue:
10✔
763
    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt64),
10✔
764
                        "double out of UInt64 range");
765
    return UInt64(value_.real_);
766
  case nullValue:
767
    return 0;
768
  case booleanValue:
2✔
769
    return value_.bool_ ? 1 : 0;
2✔
770
  default:
771
    break;
772
  }
773
  JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
9✔
774
}
775
#endif // if defined(JSON_HAS_INT64)
776

777
LargestInt Value::asLargestInt() const {
157,448✔
778
#if defined(JSON_NO_INT64)
779
  return asInt();
780
#else
781
  return asInt64();
157,448✔
782
#endif
783
}
784

785
LargestUInt Value::asLargestUInt() const {
248✔
786
#if defined(JSON_NO_INT64)
787
  return asUInt();
788
#else
789
  return asUInt64();
248✔
790
#endif
791
}
792

793
double Value::asDouble() const {
528✔
794
  switch (type()) {
528✔
795
  case intValue:
20✔
796
    return static_cast<double>(value_.int_);
20✔
797
  case uintValue:
14✔
798
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
799
    return static_cast<double>(value_.uint_);
800
#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
801
    return integerToDouble(value_.uint_);
14✔
802
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
803
  case realValue:
488✔
804
    return value_.real_;
488✔
805
  case nullValue:
806
    return 0.0;
807
  case booleanValue:
2✔
808
    return value_.bool_ ? 1.0 : 0.0;
2✔
809
  default:
810
    break;
811
  }
812
  JSON_FAIL_MESSAGE("Value is not convertible to double.");
9✔
813
}
814

815
float Value::asFloat() const {
40✔
816
  switch (type()) {
40✔
817
  case intValue:
10✔
818
    return static_cast<float>(value_.int_);
10✔
819
  case uintValue:
7✔
820
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
821
    return static_cast<float>(value_.uint_);
822
#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
823
    // This can fail (silently?) if the value is bigger than MAX_FLOAT.
824
    return static_cast<float>(integerToDouble(value_.uint_));
7✔
825
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
826
  case realValue:
17✔
827
    return static_cast<float>(value_.real_);
17✔
828
  case nullValue:
829
    return 0.0;
830
  case booleanValue:
2✔
831
    return value_.bool_ ? 1.0F : 0.0F;
2✔
832
  default:
833
    break;
834
  }
835
  JSON_FAIL_MESSAGE("Value is not convertible to float.");
9✔
836
}
837

838
bool Value::asBool() const {
12,669✔
839
  switch (type()) {
12,669✔
840
  case booleanValue:
12,636✔
841
    return value_.bool_;
12,636✔
842
  case nullValue:
843
    return false;
844
  case intValue:
10✔
845
    return value_.int_ != 0;
10✔
846
  case uintValue:
7✔
847
    return value_.uint_ != 0;
7✔
848
  case realValue: {
13✔
849
    // According to JavaScript language zero or NaN is regarded as false
850
    const auto value_classification = std::fpclassify(value_.real_);
13✔
851
    return value_classification != FP_ZERO && value_classification != FP_NAN;
13✔
852
  }
853
  default:
854
    break;
855
  }
856
  JSON_FAIL_MESSAGE("Value is not convertible to bool.");
9✔
857
}
858

859
bool Value::isConvertibleTo(ValueType other) const {
173✔
860
  switch (other) {
173✔
861
  case nullValue:
39✔
862
    return (isNumeric() && asDouble() == 0.0) ||
102✔
863
           (type() == booleanValue && !value_.bool_) ||
67✔
864
           (type() == stringValue && asString().empty()) ||
105✔
865
           (type() == arrayValue && value_.map_->empty()) ||
63✔
866
           (type() == objectValue && value_.map_->empty()) ||
100✔
867
           type() == nullValue;
29✔
868
  case intValue:
35✔
869
    return isInt() ||
58✔
870
           (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
54✔
871
           type() == booleanValue || type() == nullValue;
76✔
872
  case uintValue:
35✔
873
    return isUInt() ||
59✔
874
           (type() == realValue && InRange(value_.real_, 0u, maxUInt)) ||
56✔
875
           type() == booleanValue || type() == nullValue;
78✔
876
  case realValue:
13✔
877
    return isNumeric() || type() == booleanValue || type() == nullValue;
13✔
878
  case booleanValue:
12✔
879
    return isNumeric() || type() == booleanValue || type() == nullValue;
12✔
880
  case stringValue:
13✔
881
    return isNumeric() || type() == booleanValue || type() == stringValue ||
16✔
882
           type() == nullValue;
3✔
883
  case arrayValue:
13✔
884
    return type() == arrayValue || type() == nullValue;
13✔
885
  case objectValue:
13✔
886
    return type() == objectValue || type() == nullValue;
13✔
887
  }
888
  JSON_ASSERT_UNREACHABLE;
×
889
  return false;
890
}
891

892
/// Number of values in array or object
893
ArrayIndex Value::size() const {
838✔
894
  switch (type()) {
838✔
895
  case nullValue:
896
  case intValue:
897
  case uintValue:
898
  case realValue:
899
  case booleanValue:
900
  case stringValue:
901
    return 0;
902
  case arrayValue: // size of the array is highest index + 1
797✔
903
    if (!value_.map_->empty()) {
797✔
904
      ObjectValues::const_iterator itLast = value_.map_->end();
905
      --itLast;
906
      return (*itLast).first.index() + 1;
713✔
907
    }
908
    return 0;
909
  case objectValue:
28✔
910
    return ArrayIndex(value_.map_->size());
28✔
911
  }
912
  JSON_ASSERT_UNREACHABLE;
×
913
  return 0; // unreachable;
914
}
915

916
bool Value::empty() const {
36✔
917
  if (isNull() || isArray() || isObject())
36✔
918
    return size() == 0U;
36✔
919
  return false;
920
}
921

922
Value::operator bool() const { return !isNull(); }
4✔
923

924
void Value::clear() {
3✔
925
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue ||
5✔
926
                          type() == objectValue,
927
                      "in Json::Value::clear(): requires complex value");
928
  start_ = 0;
2✔
929
  limit_ = 0;
2✔
930
  switch (type()) {
2✔
931
  case arrayValue:
2✔
932
  case objectValue:
933
    value_.map_->clear();
2✔
934
    break;
935
  default:
936
    break;
937
  }
938
}
2✔
939

940
void Value::resize(ArrayIndex newSize) {
7✔
941
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
13✔
942
                      "in Json::Value::resize(): requires arrayValue");
943
  if (type() == nullValue)
4✔
944
    *this = Value(arrayValue);
1✔
945
  ArrayIndex oldSize = size();
4✔
946
  if (newSize == 0)
4✔
947
    clear();
1✔
948
  else if (newSize > oldSize)
3✔
949
    for (ArrayIndex i = oldSize; i < newSize; ++i)
17✔
950
      (*this)[i];
15✔
951
  else {
952
    for (ArrayIndex index = newSize; index < oldSize; ++index) {
11✔
953
      value_.map_->erase(index);
20✔
954
    }
955
    JSON_ASSERT(size() == newSize);
1✔
956
  }
957
}
4✔
958

959
Value& Value::operator[](ArrayIndex index) {
216,243✔
960
  JSON_ASSERT_MESSAGE(
216,249✔
961
      type() == nullValue || type() == arrayValue,
962
      "in Json::Value::operator[](ArrayIndex): requires arrayValue");
963
  if (type() == nullValue)
216,240✔
964
    *this = Value(arrayValue);
16✔
965
  CZString key(index);
216,240✔
966
  auto it = value_.map_->lower_bound(key);
216,240✔
967
  if (it != value_.map_->end() && (*it).first == key)
216,240✔
968
    return (*it).second;
104,903✔
969

970
  ObjectValues::value_type defaultValue(key, nullSingleton());
111,337✔
971
  it = value_.map_->insert(it, defaultValue);
111,337✔
972
  return (*it).second;
111,337✔
973
}
216,240✔
974

975
Value& Value::operator[](int index) {
111,235✔
976
  JSON_ASSERT_MESSAGE(
111,235✔
977
      index >= 0,
978
      "in Json::Value::operator[](int index): index cannot be negative");
979
  return (*this)[ArrayIndex(index)];
111,235✔
980
}
981

982
const Value& Value::operator[](ArrayIndex index) const {
53,225✔
983
  JSON_ASSERT_MESSAGE(
53,225✔
984
      type() == nullValue || type() == arrayValue,
985
      "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
986
  if (type() == nullValue)
53,225✔
987
    return nullSingleton();
×
988
  CZString key(index);
53,225✔
989
  ObjectValues::const_iterator it = value_.map_->find(key);
53,225✔
990
  if (it == value_.map_->end())
53,225✔
991
    return nullSingleton();
1✔
992
  return (*it).second;
53,224✔
993
}
53,225✔
994

995
const Value& Value::operator[](int index) const {
4✔
996
  JSON_ASSERT_MESSAGE(
4✔
997
      index >= 0,
998
      "in Json::Value::operator[](int index) const: index cannot be negative");
999
  return (*this)[ArrayIndex(index)];
4✔
1000
}
1001

1002
void Value::initBasic(ValueType type, bool allocated) {
243,361✔
1003
  setType(type);
1004
  setIsAllocated(allocated);
1005
  comments_ = Comments{};
243,361✔
1006
  start_ = 0;
243,361✔
1007
  limit_ = 0;
243,361✔
1008
}
243,361✔
1009

1010
void Value::dupPayload(const Value& other) {
253,265✔
1011
  setType(other.type());
253,265✔
1012
  setIsAllocated(false);
1013
  switch (type()) {
253,265✔
1014
  case nullValue:
253,082✔
1015
  case intValue:
1016
  case uintValue:
1017
  case realValue:
1018
  case booleanValue:
1019
    value_ = other.value_;
253,082✔
1020
    break;
253,082✔
1021
  case stringValue:
129✔
1022
    if (other.value_.string_ && other.isAllocated()) {
129✔
1023
      unsigned len;
1024
      char const* str;
1025
      decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
1026
                           &str);
1027
      value_.string_ = duplicateAndPrefixStringValue(str, len);
129✔
1028
      setIsAllocated(true);
1029
    } else {
1030
      value_.string_ = other.value_.string_;
×
1031
    }
1032
    break;
1033
  case arrayValue:
54✔
1034
  case objectValue:
1035
    value_.map_ = new ObjectValues(*other.value_.map_);
54✔
1036
    break;
54✔
1037
  default:
×
1038
    JSON_ASSERT_UNREACHABLE;
×
1039
  }
1040
}
253,265✔
1041

1042
void Value::releasePayload() {
496,626✔
1043
  switch (type()) {
496,626✔
1044
  case nullValue:
1045
  case intValue:
1046
  case uintValue:
1047
  case realValue:
1048
  case booleanValue:
1049
    break;
1050
  case stringValue:
1051
    if (isAllocated())
2,625✔
1052
      releasePrefixedStringValue(value_.string_);
2,623✔
1053
    break;
1054
  case arrayValue:
9,172✔
1055
  case objectValue:
1056
    delete value_.map_;
18,344✔
1057
    break;
1058
  default:
×
1059
    JSON_ASSERT_UNREACHABLE;
×
1060
  }
1061
}
496,626✔
1062

1063
void Value::dupMeta(const Value& other) {
253,265✔
1064
  comments_ = other.comments_;
253,265✔
1065
  start_ = other.start_;
253,265✔
1066
  limit_ = other.limit_;
253,265✔
1067
}
253,265✔
1068

1069
// Access an object value by name, create a null member if it does not exist.
1070
// @pre Type of '*this' is object or null.
1071
// @param key is null-terminated.
1072
Value& Value::resolveReference(const char* key) {
1✔
1073
  JSON_ASSERT_MESSAGE(
1✔
1074
      type() == nullValue || type() == objectValue,
1075
      "in Json::Value::resolveReference(): requires objectValue");
1076
  if (type() == nullValue)
1✔
1077
    *this = Value(objectValue);
1✔
1078
  CZString actualKey(key, static_cast<unsigned>(strlen(key)),
1✔
1079
                     CZString::noDuplication); // NOTE!
1✔
1080
  auto it = value_.map_->lower_bound(actualKey);
1✔
1081
  if (it != value_.map_->end() && (*it).first == actualKey)
1✔
1082
    return (*it).second;
×
1083

1084
  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1✔
1085
  it = value_.map_->insert(it, defaultValue);
1✔
1086
  Value& value = (*it).second;
1✔
1087
  return value;
1088
}
1✔
1089

1090
// @param key is not null-terminated.
1091
Value& Value::resolveReference(char const* key, char const* end) {
19,464✔
1092
  JSON_ASSERT_MESSAGE(
19,470✔
1093
      type() == nullValue || type() == objectValue,
1094
      "in Json::Value::resolveReference(key, end): requires objectValue");
1095
  if (type() == nullValue)
19,461✔
1096
    *this = Value(objectValue);
1,680✔
1097
  CZString actualKey(key, static_cast<unsigned>(end - key),
19,461✔
1098
                     CZString::duplicateOnCopy);
19,461✔
1099
  auto it = value_.map_->lower_bound(actualKey);
19,461✔
1100
  if (it != value_.map_->end() && (*it).first == actualKey)
19,461✔
1101
    return (*it).second;
4,345✔
1102

1103
  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
15,116✔
1104
  it = value_.map_->insert(it, defaultValue);
15,116✔
1105
  Value& value = (*it).second;
15,116✔
1106
  return value;
1107
}
19,461✔
1108

1109
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
6✔
1110
  const Value* value = &((*this)[index]);
6✔
1111
  return value == &nullSingleton() ? defaultValue : *value;
11✔
1112
}
1113

1114
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
7✔
1115

1116
Value const* Value::find(char const* begin, char const* end) const {
16,934✔
1117
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
16,934✔
1118
                      "in Json::Value::find(begin, end): requires "
1119
                      "objectValue or nullValue");
1120
  if (type() == nullValue)
16,934✔
1121
    return nullptr;
1122
  CZString actualKey(begin, static_cast<unsigned>(end - begin),
16,934✔
1123
                     CZString::noDuplication);
16,934✔
1124
  ObjectValues::const_iterator it = value_.map_->find(actualKey);
16,934✔
1125
  if (it == value_.map_->end())
16,934✔
1126
    return nullptr;
1127
  return &(*it).second;
16,919✔
1128
}
16,934✔
1129
Value const* Value::find(const String& key) const {
896✔
1130
  return find(key.data(), key.data() + key.length());
896✔
1131
}
1132

1133
Value const* Value::findNull(const String& key) const {
2✔
1134
  return findValue<Value, &Value::isNull>(key);
2✔
1135
}
1136
Value const* Value::findBool(const String& key) const {
2✔
1137
  return findValue<Value, &Value::isBool>(key);
2✔
1138
}
1139
Value const* Value::findInt(const String& key) const {
2✔
1140
  return findValue<Value, &Value::isInt>(key);
2✔
1141
}
1142
Value const* Value::findInt64(const String& key) const {
2✔
1143
  return findValue<Value, &Value::isInt64>(key);
2✔
1144
}
1145
Value const* Value::findUInt(const String& key) const {
2✔
1146
  return findValue<Value, &Value::isUInt>(key);
2✔
1147
}
1148
Value const* Value::findUInt64(const String& key) const {
2✔
1149
  return findValue<Value, &Value::isUInt64>(key);
2✔
1150
}
1151
Value const* Value::findIntegral(const String& key) const {
2✔
1152
  return findValue<Value, &Value::isIntegral>(key);
2✔
1153
}
1154
Value const* Value::findDouble(const String& key) const {
2✔
1155
  return findValue<Value, &Value::isDouble>(key);
2✔
1156
}
1157
Value const* Value::findNumeric(const String& key) const {
2✔
1158
  return findValue<Value, &Value::isNumeric>(key);
2✔
1159
}
1160
Value const* Value::findString(const String& key) const {
2✔
1161
  return findValue<Value, &Value::isString>(key);
2✔
1162
}
1163
Value const* Value::findArray(const String& key) const {
2✔
1164
  return findValue<Value, &Value::isArray>(key);
2✔
1165
}
1166
Value const* Value::findObject(const String& key) const {
×
1167
  return findValue<Value, &Value::isObject>(key);
×
1168
}
1169

1170
Value* Value::demand(char const* begin, char const* end) {
1✔
1171
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
1✔
1172
                      "in Json::Value::demand(begin, end): requires "
1173
                      "objectValue or nullValue");
1174
  return &resolveReference(begin, end);
1✔
1175
}
1176
#ifdef JSONCPP_HAS_STRING_VIEW
1177
const Value& Value::operator[](std::string_view key) const {
1178
  Value const* found = find(key.data(), key.data() + key.length());
1179
  if (!found)
1180
    return nullSingleton();
1181
  return *found;
1182
}
1183
Value& Value::operator[](std::string_view key) {
1184
  return resolveReference(key.data(), key.data() + key.length());
1185
}
1186
#else
1187
const Value& Value::operator[](const char* key) const {
16,010✔
1188
  Value const* found = find(key, key + strlen(key));
16,010✔
1189
  if (!found)
16,010✔
1190
    return nullSingleton();
1✔
1191
  return *found;
1192
}
1193
Value const& Value::operator[](const String& key) const {
872✔
1194
  Value const* found = find(key);
872✔
1195
  if (!found)
872✔
1196
    return nullSingleton();
3✔
1197
  return *found;
1198
}
1199

1200
Value& Value::operator[](const char* key) {
17,599✔
1201
  return resolveReference(key, key + strlen(key));
17,599✔
1202
}
1203

1204
Value& Value::operator[](const String& key) {
1,864✔
1205
  return resolveReference(key.data(), key.data() + key.length());
1,864✔
1206
}
1207
#endif
1208

1209
Value& Value::operator[](const StaticString& key) {
1✔
1210
  return resolveReference(key.c_str());
1✔
1211
}
1212

1213
Value& Value::append(const Value& value) { return append(Value(value)); }
1✔
1214

1215
Value& Value::append(Value&& value) {
49✔
1216
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
49✔
1217
                      "in Json::Value::append: requires arrayValue");
1218
  if (type() == nullValue) {
49✔
1219
    *this = Value(arrayValue);
40✔
1220
  }
1221
  return this->value_.map_->emplace(size(), std::move(value)).first->second;
49✔
1222
}
1223

1224
bool Value::insert(ArrayIndex index, const Value& newValue) {
1✔
1225
  return insert(index, Value(newValue));
1✔
1226
}
1227

1228
bool Value::insert(ArrayIndex index, Value&& newValue) {
4✔
1229
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
4✔
1230
                      "in Json::Value::insert: requires arrayValue");
1231
  ArrayIndex length = size();
4✔
1232
  if (index > length) {
4✔
1233
    return false;
1234
  }
1235
  for (ArrayIndex i = length; i > index; i--) {
8✔
1236
    (*this)[i] = std::move((*this)[i - 1]);
5✔
1237
  }
1238
  (*this)[index] = std::move(newValue);
3✔
1239
  return true;
3✔
1240
}
1241

1242
Value Value::get(char const* begin, char const* end,
15✔
1243
                 Value const& defaultValue) const {
1244
  Value const* found = find(begin, end);
15✔
1245
  return !found ? defaultValue : *found;
29✔
1246
}
1247
#ifdef JSONCPP_HAS_STRING_VIEW
1248
Value Value::get(std::string_view key, const Value& defaultValue) const {
1249
  return get(key.data(), key.data() + key.length(), defaultValue);
1250
}
1251
#else
1252
Value Value::get(char const* key, Value const& defaultValue) const {
10✔
1253
  return get(key, key + strlen(key), defaultValue);
10✔
1254
}
1255
Value Value::get(String const& key, Value const& defaultValue) const {
5✔
1256
  return get(key.data(), key.data() + key.length(), defaultValue);
5✔
1257
}
1258
#endif
1259

1260
bool Value::removeMember(const char* begin, const char* end, Value* removed) {
9✔
1261
  if (type() != objectValue) {
9✔
1262
    return false;
1263
  }
1264
  CZString actualKey(begin, static_cast<unsigned>(end - begin),
9✔
1265
                     CZString::noDuplication);
9✔
1266
  auto it = value_.map_->find(actualKey);
9✔
1267
  if (it == value_.map_->end())
9✔
1268
    return false;
1269
  if (removed)
5✔
1270
    *removed = std::move(it->second);
4✔
1271
  value_.map_->erase(it);
5✔
1272
  return true;
5✔
1273
}
9✔
1274
#ifdef JSONCPP_HAS_STRING_VIEW
1275
bool Value::removeMember(std::string_view key, Value* removed) {
1276
  return removeMember(key.data(), key.data() + key.length(), removed);
1277
}
1278
#else
1279
bool Value::removeMember(const char* key, Value* removed) {
3✔
1280
  return removeMember(key, key + strlen(key), removed);
3✔
1281
}
1282
bool Value::removeMember(String const& key, Value* removed) {
2✔
1283
  return removeMember(key.data(), key.data() + key.length(), removed);
2✔
1284
}
1285
#endif
1286

1287
#ifdef JSONCPP_HAS_STRING_VIEW
1288
void Value::removeMember(std::string_view key) {
1289
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
1290
                      "in Json::Value::removeMember(): requires objectValue");
1291
  if (type() == nullValue)
1292
    return;
1293

1294
  CZString actualKey(key.data(), unsigned(key.length()),
1295
                     CZString::noDuplication);
1296
  value_.map_->erase(actualKey);
1297
}
1298
#else
1299
void Value::removeMember(const char* key) {
4✔
1300
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
10✔
1301
                      "in Json::Value::removeMember(): requires objectValue");
1302
  if (type() == nullValue)
1✔
1303
    return;
×
1304

1305
  CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
1✔
1306
  value_.map_->erase(actualKey);
1✔
1307
}
1✔
1308
void Value::removeMember(const String& key) { removeMember(key.c_str()); }
1✔
1309
#endif
1310

1311
bool Value::removeIndex(ArrayIndex index, Value* removed) {
2✔
1312
  if (type() != arrayValue) {
2✔
1313
    return false;
1314
  }
1315
  CZString key(index);
2✔
1316
  auto it = value_.map_->find(key);
2✔
1317
  if (it == value_.map_->end()) {
2✔
1318
    return false;
1319
  }
1320
  if (removed)
1✔
1321
    *removed = std::move(it->second);
1✔
1322
  ArrayIndex oldSize = size();
1✔
1323
  // shift left all items left, into the place of the "removed"
1324
  for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
1✔
1325
    CZString keey(i);
×
1326
    (*value_.map_)[keey] = (*this)[i + 1];
×
1327
  }
×
1328
  // erase the last one ("leftover")
1329
  CZString keyLast(oldSize - 1);
1✔
1330
  auto itLast = value_.map_->find(keyLast);
1✔
1331
  value_.map_->erase(itLast);
1✔
1332
  return true;
1333
}
2✔
1334

1335
bool Value::isMember(char const* begin, char const* end) const {
10✔
1336
  Value const* value = find(begin, end);
10✔
1337
  return nullptr != value;
10✔
1338
}
1339
#ifdef JSONCPP_HAS_STRING_VIEW
1340
bool Value::isMember(std::string_view key) const {
1341
  return isMember(key.data(), key.data() + key.length());
1342
}
1343
#else
1344
bool Value::isMember(char const* key) const {
5✔
1345
  return isMember(key, key + strlen(key));
5✔
1346
}
1347
bool Value::isMember(String const& key) const {
5✔
1348
  return isMember(key.data(), key.data() + key.length());
5✔
1349
}
1350
#endif
1351

1352
Value::Members Value::getMemberNames() const {
1,130✔
1353
  JSON_ASSERT_MESSAGE(
1,136✔
1354
      type() == nullValue || type() == objectValue,
1355
      "in Json::Value::getMemberNames(), value must be objectValue");
1356
  if (type() == nullValue)
1,127✔
1357
    return Value::Members();
×
1358
  Members members;
1359
  members.reserve(value_.map_->size());
1,127✔
1360
  ObjectValues::const_iterator it = value_.map_->begin();
1,127✔
1361
  ObjectValues::const_iterator itEnd = value_.map_->end();
1362
  for (; it != itEnd; ++it) {
2,792✔
1363
    members.push_back(String((*it).first.data(), (*it).first.length()));
3,330✔
1364
  }
1365
  return members;
1366
}
1,127✔
1367

1368
static bool IsIntegral(double d) {
1369
  double integral_part;
1370
  return modf(d, &integral_part) == 0.0;
58✔
1371
}
1372

1373
bool Value::isNull() const { return type() == nullValue; }
82✔
1374

1375
bool Value::isBool() const { return type() == booleanValue; }
50✔
1376

1377
bool Value::isInt() const {
102✔
1378
  switch (type()) {
102✔
1379
  case intValue:
32✔
1380
#if defined(JSON_HAS_INT64)
1381
    return value_.int_ >= minInt && value_.int_ <= maxInt;
32✔
1382
#else
1383
    return true;
1384
#endif
1385
  case uintValue:
22✔
1386
    return value_.uint_ <= UInt(maxInt);
22✔
1387
  case realValue:
28✔
1388
    return value_.real_ >= minInt && value_.real_ <= maxInt &&
28✔
1389
           IsIntegral(value_.real_);
1390
  default:
1391
    break;
1392
  }
1393
  return false;
1394
}
1395

1396
bool Value::isUInt() const {
1,649✔
1397
  switch (type()) {
1,649✔
1398
  case intValue:
1,580✔
1399
#if defined(JSON_HAS_INT64)
1400
    return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
1,580✔
1401
#else
1402
    return value_.int_ >= 0;
1403
#endif
1404
  case uintValue:
21✔
1405
#if defined(JSON_HAS_INT64)
1406
    return value_.uint_ <= maxUInt;
21✔
1407
#else
1408
    return true;
1409
#endif
1410
  case realValue:
28✔
1411
    return value_.real_ >= 0 && value_.real_ <= maxUInt &&
28✔
1412
           IsIntegral(value_.real_);
1413
  default:
1414
    break;
1415
  }
1416
  return false;
1417
}
1418

1419
bool Value::isInt64() const {
56✔
1420
#if defined(JSON_HAS_INT64)
1421
  switch (type()) {
56✔
1422
  case intValue:
1423
    return true;
1424
  case uintValue:
13✔
1425
    return value_.uint_ <= UInt64(maxInt64);
13✔
1426
  case realValue:
15✔
1427
    // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
1428
    // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
1429
    // require the value to be strictly less than the limit.
1430
    // minInt64 is -2^63 which can be represented as a double, but since double
1431
    // values in its proximity are also rounded to -2^63, we require the value
1432
    // to be strictly greater than the limit to avoid returning 'true' for
1433
    // values that are not in the range
1434
    return value_.real_ > double(minInt64) && value_.real_ < double(maxInt64) &&
15✔
1435
           IsIntegral(value_.real_);
1436
  default:
1437
    break;
1438
  }
1439
#endif // JSON_HAS_INT64
1440
  return false;
1441
}
1442

1443
bool Value::isUInt64() const {
57✔
1444
#if defined(JSON_HAS_INT64)
1445
  switch (type()) {
57✔
1446
  case intValue:
20✔
1447
    return value_.int_ >= 0;
20✔
1448
  case uintValue:
1449
    return true;
1450
  case realValue:
15✔
1451
    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1452
    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1453
    // require the value to be strictly less than the limit.
1454
    return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
15✔
1455
           IsIntegral(value_.real_);
1456
  default:
1457
    break;
1458
  }
1459
#endif // JSON_HAS_INT64
1460
  return false;
1461
}
1462

1463
bool Value::isIntegral() const {
42✔
1464
  switch (type()) {
42✔
1465
  case intValue:
1466
  case uintValue:
1467
    return true;
1468
  case realValue:
14✔
1469
#if defined(JSON_HAS_INT64)
1470
    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1471
    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1472
    // require the value to be strictly less than the limit.
1473
    // minInt64 is -2^63 which can be represented as a double, but since double
1474
    // values in its proximity are also rounded to -2^63, we require the value
1475
    // to be strictly greater than the limit to avoid returning 'true' for
1476
    // values that are not in the range
1477
    return value_.real_ > double(minInt64) &&
13✔
1478
           value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
26✔
1479
#else
1480
    return value_.real_ >= minInt && value_.real_ <= maxUInt &&
1481
           IsIntegral(value_.real_);
1482
#endif // JSON_HAS_INT64
1483
  default:
1484
    break;
1485
  }
1486
  return false;
1487
}
1488

1489
bool Value::isDouble() const {
169✔
1490
  return type() == intValue || type() == uintValue || type() == realValue;
169✔
1491
}
1492

1493
bool Value::isNumeric() const { return isDouble(); }
119✔
1494

1495
bool Value::isString() const { return type() == stringValue; }
52✔
1496

1497
bool Value::isArray() const { return type() == arrayValue; }
501✔
1498

1499
bool Value::isObject() const { return type() == objectValue; }
432✔
1500

1501
Value::Comments::Comments(const Comments& that)
×
1502
    : ptr_{cloneUnique(that.ptr_)} {}
×
1503

1504
Value::Comments::Comments(Comments&& that) noexcept
125,028✔
1505
    : ptr_{std::move(that.ptr_)} {}
125,028✔
1506

1507
Value::Comments& Value::Comments::operator=(const Comments& that) {
253,265✔
1508
  ptr_ = cloneUnique(that.ptr_);
253,265✔
1509
  return *this;
253,265✔
1510
}
1511

1512
Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
493,417✔
1513
  ptr_ = std::move(that.ptr_);
1514
  return *this;
493,417✔
1515
}
1516

1517
bool Value::Comments::has(CommentPlacement slot) const {
377,785✔
1518
  return ptr_ && !(*ptr_)[slot].empty();
377,785✔
1519
}
1520

1521
String Value::Comments::get(CommentPlacement slot) const {
1,282✔
1522
  if (!ptr_)
1,282✔
1523
    return {};
1524
  return (*ptr_)[slot];
1,282✔
1525
}
1526

1527
void Value::Comments::set(CommentPlacement slot, String comment) {
955✔
1528
  if (slot >= CommentPlacement::numberOfCommentPlacement)
955✔
1529
    return;
1530
  if (!ptr_)
955✔
1531
    ptr_ = std::unique_ptr<Array>(new Array());
893✔
1532
  (*ptr_)[slot] = std::move(comment);
1,910✔
1533
}
1534

1535
void Value::setComment(String comment, CommentPlacement placement) {
955✔
1536
  if (!comment.empty() && (comment.back() == '\n')) {
955✔
1537
    // Always discard trailing newline, to aid indentation.
1538
    comment.pop_back();
790✔
1539
  }
1540
  JSON_ASSERT_MESSAGE(
955✔
1541
      comment.empty() || comment[0] == '/',
1542
      "in Json::Value::setComment(): Comments must start with /");
1543
  comments_.set(placement, std::move(comment));
955✔
1544
}
955✔
1545

1546
bool Value::hasComment(CommentPlacement placement) const {
377,785✔
1547
  return comments_.has(placement);
377,785✔
1548
}
1549

1550
String Value::getComment(CommentPlacement placement) const {
1,282✔
1551
  return comments_.get(placement);
1,282✔
1552
}
1553

1554
void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
113,818✔
1555

1556
void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
107,817✔
1557

1558
ptrdiff_t Value::getOffsetStart() const { return start_; }
19✔
1559

1560
ptrdiff_t Value::getOffsetLimit() const { return limit_; }
19✔
1561

1562
String Value::toStyledString() const {
5✔
1563
  StreamWriterBuilder builder;
5✔
1564

1565
  String out = this->hasComment(commentBefore) ? "\n" : "";
8✔
1566
  out += Json::writeString(builder, *this);
10✔
1567
  out += '\n';
1568

1569
  return out;
5✔
1570
}
5✔
1571

1572
Value::const_iterator Value::begin() const {
22✔
1573
  switch (type()) {
22✔
1574
  case arrayValue:
9✔
1575
  case objectValue:
1576
    if (value_.map_)
9✔
1577
      return const_iterator(value_.map_->begin());
9✔
1578
    break;
1579
  default:
1580
    break;
1581
  }
1582
  return {};
13✔
1583
}
1584

1585
Value::const_iterator Value::end() const {
63✔
1586
  switch (type()) {
63✔
1587
  case arrayValue:
51✔
1588
  case objectValue:
1589
    if (value_.map_)
51✔
1590
      return const_iterator(value_.map_->end());
51✔
1591
    break;
1592
  default:
1593
    break;
1594
  }
1595
  return {};
12✔
1596
}
1597

1598
Value::iterator Value::begin() {
37✔
1599
  switch (type()) {
37✔
1600
  case arrayValue:
24✔
1601
  case objectValue:
1602
    if (value_.map_)
24✔
1603
      return iterator(value_.map_->begin());
24✔
1604
    break;
1605
  default:
1606
    break;
1607
  }
1608
  return iterator();
13✔
1609
}
1610

1611
Value::iterator Value::end() {
42✔
1612
  switch (type()) {
42✔
1613
  case arrayValue:
27✔
1614
  case objectValue:
1615
    if (value_.map_)
27✔
1616
      return iterator(value_.map_->end());
27✔
1617
    break;
1618
  default:
1619
    break;
1620
  }
1621
  return iterator();
15✔
1622
}
1623

1624
// class PathArgument
1625
// //////////////////////////////////////////////////////////////////
1626

1627
PathArgument::PathArgument() = default;
36✔
1628

1629
PathArgument::PathArgument(ArrayIndex index)
4✔
1630
    : index_(index), kind_(kindIndex) {}
4✔
1631

1632
PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
2✔
1633

1634
PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
10✔
1635

1636
// class Path
1637
// //////////////////////////////////////////////////////////////////
1638

1639
Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
8✔
1640
           const PathArgument& a3, const PathArgument& a4,
1641
           const PathArgument& a5) {
1642
  InArgs in;
1643
  in.reserve(5);
8✔
1644
  in.push_back(&a1);
8✔
1645
  in.push_back(&a2);
8✔
1646
  in.push_back(&a3);
8✔
1647
  in.push_back(&a4);
8✔
1648
  in.push_back(&a5);
8✔
1649
  makePath(path, in);
8✔
1650
}
8✔
1651

1652
void Path::makePath(const String& path, const InArgs& in) {
8✔
1653
  const char* current = path.c_str();
1654
  const char* end = current + path.length();
8✔
1655
  auto itInArg = in.begin();
8✔
1656
  while (current != end) {
42✔
1657
    if (*current == '[') {
34✔
1658
      ++current;
4✔
1659
      if (*current == '%')
4✔
1660
        addPathInArg(path, in, itInArg, PathArgument::kindIndex);
2✔
1661
      else {
1662
        ArrayIndex index = 0;
1663
        for (; current != end && *current >= '0' && *current <= '9'; ++current)
4✔
1664
          index = index * 10 + ArrayIndex(*current - '0');
2✔
1665
        args_.push_back(index);
4✔
1666
      }
1667
      if (current == end || *++current != ']')
4✔
1668
        invalidPath(path, int(current - path.c_str()));
2✔
1669
    } else if (*current == '%') {
30✔
1670
      addPathInArg(path, in, itInArg, PathArgument::kindKey);
2✔
1671
      ++current;
2✔
1672
    } else if (*current == '.' || *current == ']') {
28✔
1673
      ++current;
18✔
1674
    } else {
1675
      const char* beginName = current;
1676
      while (current != end && !strchr("[.", *current))
88✔
1677
        ++current;
78✔
1678
      args_.push_back(String(beginName, current));
20✔
1679
    }
1680
  }
1681
}
8✔
1682

1683
void Path::addPathInArg(const String& /*path*/, const InArgs& in,
4✔
1684
                        InArgs::const_iterator& itInArg,
1685
                        PathArgument::Kind kind) {
1686
  if (itInArg == in.end()) {
4✔
1687
    // Error: missing argument %d
1688
  } else if ((*itInArg)->kind_ != kind) {
4✔
1689
    // Error: bad argument type
1690
  } else {
1691
    args_.push_back(**itInArg++);
4✔
1692
  }
1693
}
4✔
1694

1695
void Path::invalidPath(const String& /*path*/, int /*location*/) {
2✔
1696
  // Error: invalid path.
1697
}
2✔
1698

1699
const Value& Path::resolve(const Value& root) const {
6✔
1700
  const Value* node = &root;
1701
  for (const auto& arg : args_) {
14✔
1702
    if (arg.kind_ == PathArgument::kindIndex) {
12✔
1703
      if (!node->isArray() || !node->isValidIndex(arg.index_)) {
2✔
1704
        // Error: unable to resolve path (array value expected at position... )
1705
        return Value::nullSingleton();
1✔
1706
      }
1707
      node = &((*node)[arg.index_]);
1✔
1708
    } else if (arg.kind_ == PathArgument::kindKey) {
10✔
1709
      if (!node->isObject()) {
10✔
1710
        // Error: unable to resolve path (object value expected at position...)
1711
        return Value::nullSingleton();
1✔
1712
      }
1713
      node = &((*node)[arg.key_]);
9✔
1714
      if (node == &Value::nullSingleton()) {
9✔
1715
        // Error: unable to resolve path (object has no member named '' at
1716
        // position...)
1717
        return Value::nullSingleton();
2✔
1718
      }
1719
    }
1720
  }
1721
  return *node;
1722
}
1723

1724
Value Path::resolve(const Value& root, const Value& defaultValue) const {
6✔
1725
  const Value* node = &root;
1726
  for (const auto& arg : args_) {
14✔
1727
    if (arg.kind_ == PathArgument::kindIndex) {
12✔
1728
      if (!node->isArray() || !node->isValidIndex(arg.index_))
3✔
1729
        return defaultValue;
2✔
1730
      node = &((*node)[arg.index_]);
1✔
1731
    } else if (arg.kind_ == PathArgument::kindKey) {
9✔
1732
      if (!node->isObject())
9✔
1733
        return defaultValue;
1✔
1734
      node = &((*node)[arg.key_]);
8✔
1735
      if (node == &Value::nullSingleton())
8✔
1736
        return defaultValue;
1✔
1737
    }
1738
  }
1739
  return *node;
2✔
1740
}
1741

1742
Value& Path::make(Value& root) const {
2✔
1743
  Value* node = &root;
1744
  for (const auto& arg : args_) {
6✔
1745
    if (arg.kind_ == PathArgument::kindIndex) {
4✔
1746
      if (!node->isArray()) {
1✔
1747
        // Error: node is not an array at position ...
1748
      }
1749
      node = &((*node)[arg.index_]);
1✔
1750
    } else if (arg.kind_ == PathArgument::kindKey) {
3✔
1751
      if (!node->isObject()) {
3✔
1752
        // Error: node is not an object at position...
1753
      }
1754
      node = &((*node)[arg.key_]);
3✔
1755
    }
1756
  }
1757
  return *node;
2✔
1758
}
1759

1760
} // namespace Json
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