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

open-source-parsers / jsoncpp / 12134745591

03 Dec 2024 07:16AM CUT coverage: 95.295%. Remained the same
12134745591

push

github

web-flow
Merge d350f8286 into 2b3815c90

5306 of 5568 relevant lines covered (95.29%)

11935.1 hits per line

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

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

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

43
// Disable warning C4702 : unreachable code
44
#if defined(_MSC_VER)
45
#pragma warning(disable : 4702)
46
#endif
47

48
#define JSON_ASSERT_UNREACHABLE assert(false)
49

50
namespace Json {
51
template <typename T>
52
static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
251,622✔
53
  std::unique_ptr<T> r;
251,622✔
54
  if (p) {
251,622✔
55
    r = std::unique_ptr<T>(new T(*p));
6✔
56
  }
57
  return r;
251,622✔
58
}
59

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

69
// static
70
Value const& Value::nullSingleton() {
126,657✔
71
  static Value const nullStatic;
126,657✔
72
  return nullStatic;
126,657✔
73
}
74

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

81
// static
82
Value const& Value::nullRef = Value::nullSingleton();
83
#endif
84

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

99
template <typename T> static inline double integerToDouble(T value) {
100
  return static_cast<double>(value);
101
}
102

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

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

123
  auto newString = static_cast<char*>(malloc(length + 1));
28,639✔
124
  if (newString == nullptr) {
28,639✔
125
    throwRuntimeError("in Json::Value::duplicateStringValue(): "
×
126
                      "Failed to allocate string value buffer");
127
  }
128
  memcpy(newString, value, length);
129
  newString[length] = 0;
28,639✔
130
  return newString;
28,639✔
131
}
132

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

188
} // namespace Json
189

190
// //////////////////////////////////////////////////////////////////
191
// //////////////////////////////////////////////////////////////////
192
// //////////////////////////////////////////////////////////////////
193
// ValueInternals...
194
// //////////////////////////////////////////////////////////////////
195
// //////////////////////////////////////////////////////////////////
196
// //////////////////////////////////////////////////////////////////
197
#if !defined(JSON_IS_AMALGAMATION)
198

199
#include "json_valueiterator.inl"
200
#endif // if !defined(JSON_IS_AMALGAMATION)
201

202
namespace Json {
203

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

227
// //////////////////////////////////////////////////////////////////
228
// //////////////////////////////////////////////////////////////////
229
// //////////////////////////////////////////////////////////////////
230
// class Value::CZString
231
// //////////////////////////////////////////////////////////////////
232
// //////////////////////////////////////////////////////////////////
233
// //////////////////////////////////////////////////////////////////
234

235
// Notes: policy_ indicates if the string was allocated when
236
// a string is stored.
237

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

240
Value::CZString::CZString(char const* str, unsigned length,
35,568✔
241
                          DuplicationPolicy allocate)
35,568✔
242
    : cstr_(str) {
35,568✔
243
  // allocate != duplicate
244
  storage_.policy_ = allocate & 0x3;
35,568✔
245
  storage_.length_ = length & 0x3FFFFFFF;
35,568✔
246
}
35,568✔
247

248
Value::CZString::CZString(const CZString& other) {
251,338✔
249
  cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
186,119✔
250
               ? duplicateStringValue(other.cstr_, other.storage_.length_)
437,457✔
251
               : other.cstr_);
252
  storage_.policy_ =
251,338✔
253
      static_cast<unsigned>(
254
          other.cstr_
251,338✔
255
              ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
28,642✔
256
                         noDuplication
257
                     ? noDuplication
28,642✔
258
                     : duplicate)
259
              : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
251,338✔
260
      3U;
261
  storage_.length_ = other.storage_.length_;
251,338✔
262
}
251,338✔
263

264
Value::CZString::CZString(CZString&& other) noexcept
×
265
    : cstr_(other.cstr_), index_(other.index_) {
×
266
  other.cstr_ = nullptr;
×
267
}
×
268

269
Value::CZString::~CZString() {
556,433✔
270
  if (cstr_ && storage_.policy_ == duplicate) {
556,433✔
271
    releaseStringValue(const_cast<char*>(cstr_),
272
                       storage_.length_ + 1U); // +1 for null terminating
273
                                               // character for sake of
274
                                               // completeness but not actually
275
                                               // necessary
276
  }
277
}
556,433✔
278

279
void Value::CZString::swap(CZString& other) {
×
280
  std::swap(cstr_, other.cstr_);
281
  std::swap(index_, other.index_);
282
}
×
283

284
Value::CZString& Value::CZString::operator=(const CZString& other) {
×
285
  cstr_ = other.cstr_;
×
286
  index_ = other.index_;
×
287
  return *this;
×
288
}
289

290
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
×
291
  cstr_ = other.cstr_;
×
292
  index_ = other.index_;
×
293
  other.cstr_ = nullptr;
×
294
  return *this;
×
295
}
296

297
bool Value::CZString::operator<(const CZString& other) const {
3,937,228✔
298
  if (!cstr_)
3,937,228✔
299
    return index_ < other.index_;
3,782,636✔
300
  // return strcmp(cstr_, other.cstr_) < 0;
301
  // Assume both are strings.
302
  unsigned this_len = this->storage_.length_;
154,592✔
303
  unsigned other_len = other.storage_.length_;
154,592✔
304
  unsigned min_len = std::min<unsigned>(this_len, other_len);
154,592✔
305
  JSON_ASSERT(this->cstr_ && other.cstr_);
154,592✔
306
  int comp = memcmp(this->cstr_, other.cstr_, min_len);
154,592✔
307
  if (comp < 0)
154,592✔
308
    return true;
309
  if (comp > 0)
79,099✔
310
    return false;
311
  return (this_len < other_len);
40,023✔
312
}
313

314
bool Value::CZString::operator==(const CZString& other) const {
119,629✔
315
  if (!cstr_)
119,629✔
316
    return index_ == other.index_;
104,928✔
317
  // return strcmp(cstr_, other.cstr_) == 0;
318
  // Assume both are strings.
319
  unsigned this_len = this->storage_.length_;
14,701✔
320
  unsigned other_len = other.storage_.length_;
14,701✔
321
  if (this_len != other_len)
14,701✔
322
    return false;
323
  JSON_ASSERT(this->cstr_ && other.cstr_);
5,278✔
324
  int comp = memcmp(this->cstr_, other.cstr_, this_len);
5,278✔
325
  return comp == 0;
5,278✔
326
}
327

328
ArrayIndex Value::CZString::index() const { return index_; }
717✔
329

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

337
// //////////////////////////////////////////////////////////////////
338
// //////////////////////////////////////////////////////////////////
339
// //////////////////////////////////////////////////////////////////
340
// class Value::Value
341
// //////////////////////////////////////////////////////////////////
342
// //////////////////////////////////////////////////////////////////
343
// //////////////////////////////////////////////////////////////////
344

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

378
Value::Value(Int value) {
1,382✔
379
  initBasic(intValue);
1,382✔
380
  value_.int_ = value;
1,382✔
381
}
1,382✔
382

383
Value::Value(UInt value) {
177✔
384
  initBasic(uintValue);
177✔
385
  value_.uint_ = value;
177✔
386
}
177✔
387
#if defined(JSON_HAS_INT64)
388
Value::Value(Int64 value) {
105,067✔
389
  initBasic(intValue);
105,067✔
390
  value_.int_ = value;
105,067✔
391
}
105,067✔
392
Value::Value(UInt64 value) {
89✔
393
  initBasic(uintValue);
89✔
394
  value_.uint_ = value;
89✔
395
}
89✔
396
#endif // defined(JSON_HAS_INT64)
397

398
Value::Value(double value) {
473✔
399
  initBasic(realValue);
473✔
400
  value_.real_ = value;
473✔
401
}
473✔
402

403
Value::Value(const char* value) {
1,029✔
404
  initBasic(stringValue, true);
1,029✔
405
  JSON_ASSERT_MESSAGE(value != nullptr,
1,029✔
406
                      "Null Value Passed to Value Constructor");
407
  value_.string_ = duplicateAndPrefixStringValue(
2,058✔
408
      value, static_cast<unsigned>(strlen(value)));
1,029✔
409
}
1,029✔
410

411
Value::Value(const char* begin, const char* end) {
2✔
412
  initBasic(stringValue, true);
2✔
413
  value_.string_ =
2✔
414
      duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
2✔
415
}
2✔
416

417
Value::Value(const String& value) {
1,258✔
418
  initBasic(stringValue, true);
1,258✔
419
  value_.string_ = duplicateAndPrefixStringValue(
1,258✔
420
      value.data(), static_cast<unsigned>(value.length()));
421
}
1,258✔
422

423
Value::Value(const StaticString& value) {
2✔
424
  initBasic(stringValue);
2✔
425
  value_.string_ = const_cast<char*>(value.c_str());
2✔
426
}
2✔
427

428
Value::Value(bool value) {
14,497✔
429
  initBasic(booleanValue);
14,497✔
430
  value_.bool_ = value;
14,497✔
431
}
14,497✔
432

433
Value::Value(const Value& other) {
251,614✔
434
  dupPayload(other);
251,614✔
435
  dupMeta(other);
251,614✔
436
}
251,614✔
437

438
Value::Value(Value&& other) noexcept {
50✔
439
  initBasic(nullValue);
50✔
440
  swap(other);
50✔
441
}
50✔
442

443
Value::~Value() {
494,012✔
444
  releasePayload();
494,012✔
445
  value_.uint_ = 0;
494,012✔
446
}
494,012✔
447

448
Value& Value::operator=(const Value& other) {
18✔
449
  Value(other).swap(*this);
18✔
450
  return *this;
18✔
451
}
452

453
Value& Value::operator=(Value&& other) noexcept {
124,075✔
454
  other.swap(*this);
124,075✔
455
  return *this;
124,075✔
456
}
457

458
void Value::swapPayload(Value& other) {
237,920✔
459
  std::swap(bits_, other.bits_);
460
  std::swap(value_, other.value_);
461
}
237,920✔
462

463
void Value::copyPayload(const Value& other) {
8✔
464
  releasePayload();
8✔
465
  dupPayload(other);
8✔
466
}
8✔
467

468
void Value::swap(Value& other) {
124,144✔
469
  swapPayload(other);
124,144✔
470
  std::swap(comments_, other.comments_);
124,144✔
471
  std::swap(start_, other.start_);
472
  std::swap(limit_, other.limit_);
473
}
124,144✔
474

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

480
ValueType Value::type() const {
2,261,411✔
481
  return static_cast<ValueType>(bits_.value_type_);
2,261,411✔
482
}
483

484
int Value::compare(const Value& other) const {
120✔
485
  if (*this < other)
120✔
486
    return -1;
487
  if (*this > other)
89✔
488
    return 1;
31✔
489
  return 0;
490
}
491

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

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

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

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

548
bool Value::operator==(const Value& other) const {
302✔
549
  if (type() != other.type())
302✔
550
    return false;
551
  switch (type()) {
287✔
552
  case nullValue:
553
    return true;
554
  case intValue:
76✔
555
    return value_.int_ == other.value_.int_;
76✔
556
  case uintValue:
8✔
557
    return value_.uint_ == other.value_.uint_;
8✔
558
  case realValue:
12✔
559
    return value_.real_ == other.value_.real_;
12✔
560
  case booleanValue:
14✔
561
    return value_.bool_ == other.value_.bool_;
14✔
562
  case stringValue: {
86✔
563
    if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
86✔
564
      return (value_.string_ == other.value_.string_);
×
565
    }
566
    unsigned this_len;
567
    unsigned other_len;
568
    char const* this_str;
569
    char const* other_str;
570
    decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
571
                         &this_str);
572
    decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
573
                         &other_str);
574
    if (this_len != other_len)
86✔
575
      return false;
576
    JSON_ASSERT(this_str && other_str);
577
    int comp = memcmp(this_str, other_str, this_len);
79✔
578
    return comp == 0;
79✔
579
  }
580
  case arrayValue:
59✔
581
  case objectValue:
582
    return value_.map_->size() == other.value_.map_->size() &&
105✔
583
           (*value_.map_) == (*other.value_.map_);
584
  default:
×
585
    JSON_ASSERT_UNREACHABLE;
×
586
  }
587
  return false; // unreachable
588
}
589

590
bool Value::operator!=(const Value& other) const { return !(*this == other); }
120✔
591

592
const char* Value::asCString() const {
4✔
593
  JSON_ASSERT_MESSAGE(type() == stringValue,
6✔
594
                      "in Json::Value::asCString(): requires stringValue");
595
  if (value_.string_ == nullptr)
3✔
596
    return nullptr;
597
  unsigned this_len;
598
  char const* this_str;
599
  decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
600
                       &this_str);
601
  return this_str;
602
}
603

604
#if JSONCPP_USE_SECURE_MEMORY
605
unsigned Value::getCStringLength() const {
606
  JSON_ASSERT_MESSAGE(type() == stringValue,
607
                      "in Json::Value::asCString(): requires stringValue");
608
  if (value_.string_ == 0)
609
    return 0;
610
  unsigned this_len;
611
  char const* this_str;
612
  decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
613
                       &this_str);
614
  return this_len;
615
}
616
#endif
617

618
bool Value::getString(char const** begin, char const** end) const {
782✔
619
  if (type() != stringValue)
782✔
620
    return false;
621
  if (value_.string_ == nullptr)
782✔
622
    return false;
623
  unsigned length;
624
  decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
625
                       begin);
626
  *end = *begin + length;
782✔
627
  return true;
782✔
628
}
629

630
String Value::asString() const {
2,750✔
631
  switch (type()) {
2,750✔
632
  case nullValue:
633
    return "";
2✔
634
  case stringValue: {
2,708✔
635
    if (value_.string_ == nullptr)
2,708✔
636
      return "";
×
637
    unsigned this_len;
638
    char const* this_str;
639
    decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
640
                         &this_str);
641
    return String(this_str, this_len);
2,708✔
642
  }
643
  case booleanValue:
644
    return value_.bool_ ? "true" : "false";
×
645
  case intValue:
13✔
646
    return valueToString(value_.int_);
13✔
647
  case uintValue:
7✔
648
    return valueToString(value_.uint_);
7✔
649
  case realValue:
18✔
650
    return valueToString(value_.real_);
18✔
651
  default:
2✔
652
    JSON_FAIL_MESSAGE("Type is not convertible to string");
6✔
653
  }
654
}
655

656
Value::Int Value::asInt() const {
28✔
657
  switch (type()) {
28✔
658
  case intValue:
9✔
659
    JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
9✔
660
    return Int(value_.int_);
9✔
661
  case uintValue:
8✔
662
    JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
8✔
663
    return Int(value_.uint_);
8✔
664
  case realValue:
5✔
665
    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
5✔
666
                        "double out of Int range");
667
    return Int(value_.real_);
668
  case nullValue:
669
    return 0;
670
  case booleanValue:
2✔
671
    return value_.bool_ ? 1 : 0;
2✔
672
  default:
673
    break;
674
  }
675
  JSON_FAIL_MESSAGE("Value is not convertible to Int.");
9✔
676
}
677

678
Value::UInt Value::asUInt() const {
1,575✔
679
  switch (type()) {
1,575✔
680
  case intValue:
1,558✔
681
    JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
1,558✔
682
    return UInt(value_.int_);
1,558✔
683
  case uintValue:
6✔
684
    JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
6✔
685
    return UInt(value_.uint_);
6✔
686
  case realValue:
5✔
687
    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
5✔
688
                        "double out of UInt range");
689
    return UInt(value_.real_);
690
  case nullValue:
691
    return 0;
692
  case booleanValue:
2✔
693
    return value_.bool_ ? 1 : 0;
2✔
694
  default:
695
    break;
696
  }
697
  JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
9✔
698
}
699

700
#if defined(JSON_HAS_INT64)
701

702
Value::Int64 Value::asInt64() const {
157,460✔
703
  switch (type()) {
157,460✔
704
  case intValue:
157,438✔
705
    return Int64(value_.int_);
157,438✔
706
  case uintValue:
6✔
707
    JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
6✔
708
    return Int64(value_.uint_);
6✔
709
  case realValue:
10✔
710
    // If the double value is in proximity to minInt64, it will be rounded to
711
    // minInt64. The correct value in this scenario is indeterminable
712
    JSON_ASSERT_MESSAGE(
10✔
713
        value_.real_ != minInt64,
714
        "Double value is minInt64, precise value cannot be determined");
715
    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
×
716
                        "double out of Int64 range");
717
    return Int64(value_.real_);
718
  case nullValue:
719
    return 0;
720
  case booleanValue:
2✔
721
    return value_.bool_ ? 1 : 0;
2✔
722
  default:
723
    break;
724
  }
725
  JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
9✔
726
}
727

728
Value::UInt64 Value::asUInt64() const {
261✔
729
  switch (type()) {
261✔
730
  case intValue:
8✔
731
    JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
8✔
732
    return UInt64(value_.int_);
8✔
733
  case uintValue:
237✔
734
    return UInt64(value_.uint_);
237✔
735
  case realValue:
10✔
736
    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
10✔
737
                        "double out of UInt64 range");
738
    return UInt64(value_.real_);
739
  case nullValue:
740
    return 0;
741
  case booleanValue:
2✔
742
    return value_.bool_ ? 1 : 0;
2✔
743
  default:
744
    break;
745
  }
746
  JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
9✔
747
}
748
#endif // if defined(JSON_HAS_INT64)
749

750
LargestInt Value::asLargestInt() const {
157,448✔
751
#if defined(JSON_NO_INT64)
752
  return asInt();
753
#else
754
  return asInt64();
157,448✔
755
#endif
756
}
757

758
LargestUInt Value::asLargestUInt() const {
248✔
759
#if defined(JSON_NO_INT64)
760
  return asUInt();
761
#else
762
  return asUInt64();
248✔
763
#endif
764
}
765

766
double Value::asDouble() const {
528✔
767
  switch (type()) {
528✔
768
  case intValue:
20✔
769
    return static_cast<double>(value_.int_);
20✔
770
  case uintValue:
14✔
771
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
772
    return static_cast<double>(value_.uint_);
773
#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
774
    return integerToDouble(value_.uint_);
14✔
775
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
776
  case realValue:
488✔
777
    return value_.real_;
488✔
778
  case nullValue:
779
    return 0.0;
780
  case booleanValue:
2✔
781
    return value_.bool_ ? 1.0 : 0.0;
2✔
782
  default:
783
    break;
784
  }
785
  JSON_FAIL_MESSAGE("Value is not convertible to double.");
9✔
786
}
787

788
float Value::asFloat() const {
40✔
789
  switch (type()) {
40✔
790
  case intValue:
10✔
791
    return static_cast<float>(value_.int_);
10✔
792
  case uintValue:
7✔
793
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
794
    return static_cast<float>(value_.uint_);
795
#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
796
    // This can fail (silently?) if the value is bigger than MAX_FLOAT.
797
    return static_cast<float>(integerToDouble(value_.uint_));
7✔
798
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
799
  case realValue:
17✔
800
    return static_cast<float>(value_.real_);
17✔
801
  case nullValue:
802
    return 0.0;
803
  case booleanValue:
2✔
804
    return value_.bool_ ? 1.0F : 0.0F;
2✔
805
  default:
806
    break;
807
  }
808
  JSON_FAIL_MESSAGE("Value is not convertible to float.");
9✔
809
}
810

811
bool Value::asBool() const {
12,669✔
812
  switch (type()) {
12,669✔
813
  case booleanValue:
12,636✔
814
    return value_.bool_;
12,636✔
815
  case nullValue:
816
    return false;
817
  case intValue:
10✔
818
    return value_.int_ != 0;
10✔
819
  case uintValue:
7✔
820
    return value_.uint_ != 0;
7✔
821
  case realValue: {
13✔
822
    // According to JavaScript language zero or NaN is regarded as false
823
    const auto value_classification = std::fpclassify(value_.real_);
13✔
824
    return value_classification != FP_ZERO && value_classification != FP_NAN;
13✔
825
  }
826
  default:
827
    break;
828
  }
829
  JSON_FAIL_MESSAGE("Value is not convertible to bool.");
9✔
830
}
831

832
bool Value::isConvertibleTo(ValueType other) const {
173✔
833
  switch (other) {
173✔
834
  case nullValue:
39✔
835
    return (isNumeric() && asDouble() == 0.0) ||
102✔
836
           (type() == booleanValue && !value_.bool_) ||
67✔
837
           (type() == stringValue && asString().empty()) ||
105✔
838
           (type() == arrayValue && value_.map_->empty()) ||
63✔
839
           (type() == objectValue && value_.map_->empty()) ||
100✔
840
           type() == nullValue;
29✔
841
  case intValue:
35✔
842
    return isInt() ||
58✔
843
           (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
54✔
844
           type() == booleanValue || type() == nullValue;
76✔
845
  case uintValue:
35✔
846
    return isUInt() ||
59✔
847
           (type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
56✔
848
           type() == booleanValue || type() == nullValue;
78✔
849
  case realValue:
13✔
850
    return isNumeric() || type() == booleanValue || type() == nullValue;
13✔
851
  case booleanValue:
12✔
852
    return isNumeric() || type() == booleanValue || type() == nullValue;
12✔
853
  case stringValue:
13✔
854
    return isNumeric() || type() == booleanValue || type() == stringValue ||
16✔
855
           type() == nullValue;
3✔
856
  case arrayValue:
13✔
857
    return type() == arrayValue || type() == nullValue;
13✔
858
  case objectValue:
13✔
859
    return type() == objectValue || type() == nullValue;
13✔
860
  }
861
  JSON_ASSERT_UNREACHABLE;
×
862
  return false;
863
}
864

865
/// Number of values in array or object
866
ArrayIndex Value::size() const {
838✔
867
  switch (type()) {
838✔
868
  case nullValue:
869
  case intValue:
870
  case uintValue:
871
  case realValue:
872
  case booleanValue:
873
  case stringValue:
874
    return 0;
875
  case arrayValue: // size of the array is highest index + 1
797✔
876
    if (!value_.map_->empty()) {
797✔
877
      ObjectValues::const_iterator itLast = value_.map_->end();
878
      --itLast;
879
      return (*itLast).first.index() + 1;
713✔
880
    }
881
    return 0;
882
  case objectValue:
28✔
883
    return ArrayIndex(value_.map_->size());
28✔
884
  }
885
  JSON_ASSERT_UNREACHABLE;
×
886
  return 0; // unreachable;
887
}
888

889
bool Value::empty() const {
36✔
890
  if (isNull() || isArray() || isObject())
36✔
891
    return size() == 0U;
36✔
892
  return false;
893
}
894

895
Value::operator bool() const { return !isNull(); }
4✔
896

897
void Value::clear() {
3✔
898
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue ||
5✔
899
                          type() == objectValue,
900
                      "in Json::Value::clear(): requires complex value");
901
  start_ = 0;
2✔
902
  limit_ = 0;
2✔
903
  switch (type()) {
2✔
904
  case arrayValue:
2✔
905
  case objectValue:
906
    value_.map_->clear();
2✔
907
    break;
908
  default:
909
    break;
910
  }
911
}
2✔
912

913
void Value::resize(ArrayIndex newSize) {
7✔
914
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
13✔
915
                      "in Json::Value::resize(): requires arrayValue");
916
  if (type() == nullValue)
4✔
917
    *this = Value(arrayValue);
1✔
918
  ArrayIndex oldSize = size();
4✔
919
  if (newSize == 0)
4✔
920
    clear();
1✔
921
  else if (newSize > oldSize)
3✔
922
    for (ArrayIndex i = oldSize; i < newSize; ++i)
17✔
923
      (*this)[i];
15✔
924
  else {
925
    for (ArrayIndex index = newSize; index < oldSize; ++index) {
11✔
926
      value_.map_->erase(index);
20✔
927
    }
928
    JSON_ASSERT(size() == newSize);
1✔
929
  }
930
}
4✔
931

932
Value& Value::operator[](ArrayIndex index) {
216,243✔
933
  JSON_ASSERT_MESSAGE(
216,249✔
934
      type() == nullValue || type() == arrayValue,
935
      "in Json::Value::operator[](ArrayIndex): requires arrayValue");
936
  if (type() == nullValue)
216,240✔
937
    *this = Value(arrayValue);
16✔
938
  CZString key(index);
216,240✔
939
  auto it = value_.map_->lower_bound(key);
216,240✔
940
  if (it != value_.map_->end() && (*it).first == key)
216,240✔
941
    return (*it).second;
104,903✔
942

943
  ObjectValues::value_type defaultValue(key, nullSingleton());
111,337✔
944
  it = value_.map_->insert(it, defaultValue);
111,337✔
945
  return (*it).second;
111,337✔
946
}
216,240✔
947

948
Value& Value::operator[](int index) {
111,235✔
949
  JSON_ASSERT_MESSAGE(
111,235✔
950
      index >= 0,
951
      "in Json::Value::operator[](int index): index cannot be negative");
952
  return (*this)[ArrayIndex(index)];
111,235✔
953
}
954

955
const Value& Value::operator[](ArrayIndex index) const {
53,225✔
956
  JSON_ASSERT_MESSAGE(
53,225✔
957
      type() == nullValue || type() == arrayValue,
958
      "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
959
  if (type() == nullValue)
53,225✔
960
    return nullSingleton();
×
961
  CZString key(index);
53,225✔
962
  ObjectValues::const_iterator it = value_.map_->find(key);
53,225✔
963
  if (it == value_.map_->end())
53,225✔
964
    return nullSingleton();
1✔
965
  return (*it).second;
53,224✔
966
}
53,225✔
967

968
const Value& Value::operator[](int index) const {
4✔
969
  JSON_ASSERT_MESSAGE(
4✔
970
      index >= 0,
971
      "in Json::Value::operator[](int index) const: index cannot be negative");
972
  return (*this)[ArrayIndex(index)];
4✔
973
}
974

975
void Value::initBasic(ValueType type, bool allocated) {
242,398✔
976
  setType(type);
977
  setIsAllocated(allocated);
978
  comments_ = Comments{};
242,398✔
979
  start_ = 0;
242,398✔
980
  limit_ = 0;
242,398✔
981
}
242,398✔
982

983
void Value::dupPayload(const Value& other) {
251,622✔
984
  setType(other.type());
251,622✔
985
  setIsAllocated(false);
986
  switch (type()) {
251,622✔
987
  case nullValue:
251,441✔
988
  case intValue:
989
  case uintValue:
990
  case realValue:
991
  case booleanValue:
992
    value_ = other.value_;
251,441✔
993
    break;
251,441✔
994
  case stringValue:
128✔
995
    if (other.value_.string_ && other.isAllocated()) {
128✔
996
      unsigned len;
997
      char const* str;
998
      decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
999
                           &str);
1000
      value_.string_ = duplicateAndPrefixStringValue(str, len);
128✔
1001
      setIsAllocated(true);
1002
    } else {
1003
      value_.string_ = other.value_.string_;
×
1004
    }
1005
    break;
1006
  case arrayValue:
53✔
1007
  case objectValue:
1008
    value_.map_ = new ObjectValues(*other.value_.map_);
53✔
1009
    break;
53✔
1010
  default:
×
1011
    JSON_ASSERT_UNREACHABLE;
×
1012
  }
1013
}
251,622✔
1014

1015
void Value::releasePayload() {
494,020✔
1016
  switch (type()) {
494,020✔
1017
  case nullValue:
1018
  case intValue:
1019
  case uintValue:
1020
  case realValue:
1021
  case booleanValue:
1022
    break;
1023
  case stringValue:
1024
    if (isAllocated())
2,419✔
1025
      releasePrefixedStringValue(value_.string_);
2,417✔
1026
    break;
1027
  case arrayValue:
8,966✔
1028
  case objectValue:
1029
    delete value_.map_;
17,932✔
1030
    break;
1031
  default:
×
1032
    JSON_ASSERT_UNREACHABLE;
×
1033
  }
1034
}
494,020✔
1035

1036
void Value::dupMeta(const Value& other) {
251,622✔
1037
  comments_ = other.comments_;
251,622✔
1038
  start_ = other.start_;
251,622✔
1039
  limit_ = other.limit_;
251,622✔
1040
}
251,622✔
1041

1042
// Access an object value by name, create a null member if it does not exist.
1043
// @pre Type of '*this' is object or null.
1044
// @param key is null-terminated.
1045
Value& Value::resolveReference(const char* key) {
1✔
1046
  JSON_ASSERT_MESSAGE(
1✔
1047
      type() == nullValue || type() == objectValue,
1048
      "in Json::Value::resolveReference(): requires objectValue");
1049
  if (type() == nullValue)
1✔
1050
    *this = Value(objectValue);
1✔
1051
  CZString actualKey(key, static_cast<unsigned>(strlen(key)),
1✔
1052
                     CZString::noDuplication); // NOTE!
1✔
1053
  auto it = value_.map_->lower_bound(actualKey);
1✔
1054
  if (it != value_.map_->end() && (*it).first == actualKey)
1✔
1055
    return (*it).second;
×
1056

1057
  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
1✔
1058
  it = value_.map_->insert(it, defaultValue);
1✔
1059
  Value& value = (*it).second;
1✔
1060
  return value;
1061
}
1✔
1062

1063
// @param key is not null-terminated.
1064
Value& Value::resolveReference(char const* key, char const* end) {
18,648✔
1065
  JSON_ASSERT_MESSAGE(
18,654✔
1066
      type() == nullValue || type() == objectValue,
1067
      "in Json::Value::resolveReference(key, end): requires objectValue");
1068
  if (type() == nullValue)
18,645✔
1069
    *this = Value(objectValue);
1,612✔
1070
  CZString actualKey(key, static_cast<unsigned>(end - key),
18,645✔
1071
                     CZString::duplicateOnCopy);
18,645✔
1072
  auto it = value_.map_->lower_bound(actualKey);
18,645✔
1073
  if (it != value_.map_->end() && (*it).first == actualKey)
18,645✔
1074
    return (*it).second;
4,345✔
1075

1076
  ObjectValues::value_type defaultValue(actualKey, nullSingleton());
14,300✔
1077
  it = value_.map_->insert(it, defaultValue);
14,300✔
1078
  Value& value = (*it).second;
14,300✔
1079
  return value;
1080
}
18,645✔
1081

1082
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
6✔
1083
  const Value* value = &((*this)[index]);
6✔
1084
  return value == &nullSingleton() ? defaultValue : *value;
11✔
1085
}
1086

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

1089
Value const* Value::find(char const* begin, char const* end) const {
16,912✔
1090
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
16,912✔
1091
                      "in Json::Value::find(begin, end): requires "
1092
                      "objectValue or nullValue");
1093
  if (type() == nullValue)
16,912✔
1094
    return nullptr;
1095
  CZString actualKey(begin, static_cast<unsigned>(end - begin),
16,912✔
1096
                     CZString::noDuplication);
16,912✔
1097
  ObjectValues::const_iterator it = value_.map_->find(actualKey);
16,912✔
1098
  if (it == value_.map_->end())
16,912✔
1099
    return nullptr;
1100
  return &(*it).second;
16,898✔
1101
}
16,912✔
1102
Value const* Value::find(const String& key) const {
874✔
1103
  return find(key.data(), key.data() + key.length());
874✔
1104
}
1105
Value* Value::demand(char const* begin, char const* end) {
1✔
1106
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
1✔
1107
                      "in Json::Value::demand(begin, end): requires "
1108
                      "objectValue or nullValue");
1109
  return &resolveReference(begin, end);
1✔
1110
}
1111
const Value& Value::operator[](const char* key) const {
16,010✔
1112
  Value const* found = find(key, key + strlen(key));
16,010✔
1113
  if (!found)
16,010✔
1114
    return nullSingleton();
1✔
1115
  return *found;
1116
}
1117
Value const& Value::operator[](const String& key) const {
872✔
1118
  Value const* found = find(key);
872✔
1119
  if (!found)
872✔
1120
    return nullSingleton();
3✔
1121
  return *found;
1122
}
1123

1124
Value& Value::operator[](const char* key) {
16,783✔
1125
  return resolveReference(key, key + strlen(key));
16,783✔
1126
}
1127

1128
Value& Value::operator[](const String& key) {
1,864✔
1129
  return resolveReference(key.data(), key.data() + key.length());
1,864✔
1130
}
1131

1132
Value& Value::operator[](const StaticString& key) {
1✔
1133
  return resolveReference(key.c_str());
1✔
1134
}
1135

1136
Value& Value::append(const Value& value) { return append(Value(value)); }
1✔
1137

1138
Value& Value::append(Value&& value) {
49✔
1139
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
49✔
1140
                      "in Json::Value::append: requires arrayValue");
1141
  if (type() == nullValue) {
49✔
1142
    *this = Value(arrayValue);
40✔
1143
  }
1144
  return this->value_.map_->emplace(size(), std::move(value)).first->second;
49✔
1145
}
1146

1147
bool Value::insert(ArrayIndex index, const Value& newValue) {
1✔
1148
  return insert(index, Value(newValue));
1✔
1149
}
1150

1151
bool Value::insert(ArrayIndex index, Value&& newValue) {
4✔
1152
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
4✔
1153
                      "in Json::Value::insert: requires arrayValue");
1154
  ArrayIndex length = size();
4✔
1155
  if (index > length) {
4✔
1156
    return false;
1157
  }
1158
  for (ArrayIndex i = length; i > index; i--) {
8✔
1159
    (*this)[i] = std::move((*this)[i - 1]);
5✔
1160
  }
1161
  (*this)[index] = std::move(newValue);
3✔
1162
  return true;
3✔
1163
}
1164

1165
Value Value::get(char const* begin, char const* end,
15✔
1166
                 Value const& defaultValue) const {
1167
  Value const* found = find(begin, end);
15✔
1168
  return !found ? defaultValue : *found;
29✔
1169
}
1170
Value Value::get(char const* key, Value const& defaultValue) const {
10✔
1171
  return get(key, key + strlen(key), defaultValue);
10✔
1172
}
1173
Value Value::get(String const& key, Value const& defaultValue) const {
5✔
1174
  return get(key.data(), key.data() + key.length(), defaultValue);
5✔
1175
}
1176

1177
bool Value::removeMember(const char* begin, const char* end, Value* removed) {
9✔
1178
  if (type() != objectValue) {
9✔
1179
    return false;
1180
  }
1181
  CZString actualKey(begin, static_cast<unsigned>(end - begin),
9✔
1182
                     CZString::noDuplication);
9✔
1183
  auto it = value_.map_->find(actualKey);
9✔
1184
  if (it == value_.map_->end())
9✔
1185
    return false;
1186
  if (removed)
5✔
1187
    *removed = std::move(it->second);
4✔
1188
  value_.map_->erase(it);
5✔
1189
  return true;
5✔
1190
}
9✔
1191
bool Value::removeMember(const char* key, Value* removed) {
3✔
1192
  return removeMember(key, key + strlen(key), removed);
3✔
1193
}
1194
bool Value::removeMember(String const& key, Value* removed) {
2✔
1195
  return removeMember(key.data(), key.data() + key.length(), removed);
2✔
1196
}
1197
void Value::removeMember(const char* key) {
4✔
1198
  JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
10✔
1199
                      "in Json::Value::removeMember(): requires objectValue");
1200
  if (type() == nullValue)
1✔
1201
    return;
×
1202

1203
  CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
1✔
1204
  value_.map_->erase(actualKey);
1✔
1205
}
1✔
1206
void Value::removeMember(const String& key) { removeMember(key.c_str()); }
1✔
1207

1208
bool Value::removeIndex(ArrayIndex index, Value* removed) {
2✔
1209
  if (type() != arrayValue) {
2✔
1210
    return false;
1211
  }
1212
  CZString key(index);
2✔
1213
  auto it = value_.map_->find(key);
2✔
1214
  if (it == value_.map_->end()) {
2✔
1215
    return false;
1216
  }
1217
  if (removed)
1✔
1218
    *removed = std::move(it->second);
1✔
1219
  ArrayIndex oldSize = size();
1✔
1220
  // shift left all items left, into the place of the "removed"
1221
  for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
1✔
1222
    CZString keey(i);
×
1223
    (*value_.map_)[keey] = (*this)[i + 1];
×
1224
  }
×
1225
  // erase the last one ("leftover")
1226
  CZString keyLast(oldSize - 1);
1✔
1227
  auto itLast = value_.map_->find(keyLast);
1✔
1228
  value_.map_->erase(itLast);
1✔
1229
  return true;
1230
}
2✔
1231

1232
bool Value::isMember(char const* begin, char const* end) const {
10✔
1233
  Value const* value = find(begin, end);
10✔
1234
  return nullptr != value;
10✔
1235
}
1236
bool Value::isMember(char const* key) const {
5✔
1237
  return isMember(key, key + strlen(key));
5✔
1238
}
1239
bool Value::isMember(String const& key) const {
5✔
1240
  return isMember(key.data(), key.data() + key.length());
5✔
1241
}
1242

1243
Value::Members Value::getMemberNames() const {
1,130✔
1244
  JSON_ASSERT_MESSAGE(
1,136✔
1245
      type() == nullValue || type() == objectValue,
1246
      "in Json::Value::getMemberNames(), value must be objectValue");
1247
  if (type() == nullValue)
1,127✔
1248
    return Value::Members();
×
1249
  Members members;
1250
  members.reserve(value_.map_->size());
1,127✔
1251
  ObjectValues::const_iterator it = value_.map_->begin();
1,127✔
1252
  ObjectValues::const_iterator itEnd = value_.map_->end();
1253
  for (; it != itEnd; ++it) {
2,792✔
1254
    members.push_back(String((*it).first.data(), (*it).first.length()));
3,330✔
1255
  }
1256
  return members;
1257
}
1,127✔
1258

1259
static bool IsIntegral(double d) {
1260
  double integral_part;
1261
  return modf(d, &integral_part) == 0.0;
57✔
1262
}
1263

1264
bool Value::isNull() const { return type() == nullValue; }
80✔
1265

1266
bool Value::isBool() const { return type() == booleanValue; }
48✔
1267

1268
bool Value::isInt() const {
100✔
1269
  switch (type()) {
100✔
1270
  case intValue:
31✔
1271
#if defined(JSON_HAS_INT64)
1272
    return value_.int_ >= minInt && value_.int_ <= maxInt;
31✔
1273
#else
1274
    return true;
1275
#endif
1276
  case uintValue:
22✔
1277
    return value_.uint_ <= UInt(maxInt);
22✔
1278
  case realValue:
28✔
1279
    return value_.real_ >= minInt && value_.real_ <= maxInt &&
28✔
1280
           IsIntegral(value_.real_);
1281
  default:
1282
    break;
1283
  }
1284
  return false;
1285
}
1286

1287
bool Value::isUInt() const {
1,647✔
1288
  switch (type()) {
1,647✔
1289
  case intValue:
1,580✔
1290
#if defined(JSON_HAS_INT64)
1291
    return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
1,580✔
1292
#else
1293
    return value_.int_ >= 0;
1294
#endif
1295
  case uintValue:
20✔
1296
#if defined(JSON_HAS_INT64)
1297
    return value_.uint_ <= maxUInt;
20✔
1298
#else
1299
    return true;
1300
#endif
1301
  case realValue:
28✔
1302
    return value_.real_ >= 0 && value_.real_ <= maxUInt &&
28✔
1303
           IsIntegral(value_.real_);
1304
  default:
1305
    break;
1306
  }
1307
  return false;
1308
}
1309

1310
bool Value::isInt64() const {
54✔
1311
#if defined(JSON_HAS_INT64)
1312
  switch (type()) {
54✔
1313
  case intValue:
1314
    return true;
1315
  case uintValue:
13✔
1316
    return value_.uint_ <= UInt64(maxInt64);
13✔
1317
  case realValue:
15✔
1318
    // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
1319
    // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
1320
    // require the value to be strictly less than the limit.
1321
    // minInt64 is -2^63 which can be represented as a double, but since double
1322
    // values in its proximity are also rounded to -2^63, we require the value
1323
    // to be strictly greater than the limit to avoid returning 'true' for
1324
    // values that are not in the range
1325
    return value_.real_ > double(minInt64) && value_.real_ < double(maxInt64) &&
15✔
1326
           IsIntegral(value_.real_);
1327
  default:
1328
    break;
1329
  }
1330
#endif // JSON_HAS_INT64
1331
  return false;
14✔
1332
}
1333

1334
bool Value::isUInt64() const {
56✔
1335
#if defined(JSON_HAS_INT64)
1336
  switch (type()) {
56✔
1337
  case intValue:
20✔
1338
    return value_.int_ >= 0;
20✔
1339
  case uintValue:
1340
    return true;
1341
  case realValue:
15✔
1342
    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1343
    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1344
    // require the value to be strictly less than the limit.
1345
    return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
15✔
1346
           IsIntegral(value_.real_);
1347
  default:
1348
    break;
1349
  }
1350
#endif // JSON_HAS_INT64
1351
  return false;
14✔
1352
}
1353

1354
bool Value::isIntegral() const {
40✔
1355
  switch (type()) {
40✔
1356
  case intValue:
1357
  case uintValue:
1358
    return true;
1359
  case realValue:
13✔
1360
#if defined(JSON_HAS_INT64)
1361
    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
1362
    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
1363
    // require the value to be strictly less than the limit.
1364
    // minInt64 is -2^63 which can be represented as a double, but since double
1365
    // values in its proximity are also rounded to -2^63, we require the value
1366
    // to be strictly greater than the limit to avoid returning 'true' for
1367
    // values that are not in the range
1368
    return value_.real_ > double(minInt64) &&
12✔
1369
           value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
24✔
1370
#else
1371
    return value_.real_ >= minInt && value_.real_ <= maxUInt &&
1372
           IsIntegral(value_.real_);
1373
#endif // JSON_HAS_INT64
1374
  default:
1375
    break;
1376
  }
1377
  return false;
10✔
1378
}
1379

1380
bool Value::isDouble() const {
165✔
1381
  return type() == intValue || type() == uintValue || type() == realValue;
165✔
1382
}
1383

1384
bool Value::isNumeric() const { return isDouble(); }
117✔
1385

1386
bool Value::isString() const { return type() == stringValue; }
50✔
1387

1388
bool Value::isArray() const { return type() == arrayValue; }
499✔
1389

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

1392
Value::Comments::Comments(const Comments& that)
×
1393
    : ptr_{cloneUnique(that.ptr_)} {}
×
1394

1395
Value::Comments::Comments(Comments&& that) noexcept
124,144✔
1396
    : ptr_{std::move(that.ptr_)} {}
124,144✔
1397

1398
Value::Comments& Value::Comments::operator=(const Comments& that) {
251,622✔
1399
  ptr_ = cloneUnique(that.ptr_);
251,622✔
1400
  return *this;
251,622✔
1401
}
1402

1403
Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
490,686✔
1404
  ptr_ = std::move(that.ptr_);
1405
  return *this;
490,686✔
1406
}
1407

1408
bool Value::Comments::has(CommentPlacement slot) const {
377,785✔
1409
  return ptr_ && !(*ptr_)[slot].empty();
377,785✔
1410
}
1411

1412
String Value::Comments::get(CommentPlacement slot) const {
1,282✔
1413
  if (!ptr_)
1,282✔
1414
    return {};
1415
  return (*ptr_)[slot];
1,282✔
1416
}
1417

1418
void Value::Comments::set(CommentPlacement slot, String comment) {
955✔
1419
  if (slot >= CommentPlacement::numberOfCommentPlacement)
955✔
1420
    return;
1421
  if (!ptr_)
955✔
1422
    ptr_ = std::unique_ptr<Array>(new Array());
1,786✔
1423
  (*ptr_)[slot] = std::move(comment);
1,910✔
1424
}
1425

1426
void Value::setComment(String comment, CommentPlacement placement) {
955✔
1427
  if (!comment.empty() && (comment.back() == '\n')) {
955✔
1428
    // Always discard trailing newline, to aid indentation.
1429
    comment.pop_back();
790✔
1430
  }
1431
  JSON_ASSERT_MESSAGE(
955✔
1432
      comment.empty() || comment[0] == '/',
1433
      "in Json::Value::setComment(): Comments must start with /");
1434
  comments_.set(placement, std::move(comment));
1,910✔
1435
}
955✔
1436

1437
bool Value::hasComment(CommentPlacement placement) const {
377,785✔
1438
  return comments_.has(placement);
377,785✔
1439
}
1440

1441
String Value::getComment(CommentPlacement placement) const {
1,282✔
1442
  return comments_.get(placement);
1,282✔
1443
}
1444

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

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

1449
ptrdiff_t Value::getOffsetStart() const { return start_; }
19✔
1450

1451
ptrdiff_t Value::getOffsetLimit() const { return limit_; }
19✔
1452

1453
String Value::toStyledString() const {
5✔
1454
  StreamWriterBuilder builder;
5✔
1455

1456
  String out = this->hasComment(commentBefore) ? "\n" : "";
8✔
1457
  out += Json::writeString(builder, *this);
10✔
1458
  out += '\n';
1459

1460
  return out;
5✔
1461
}
5✔
1462

1463
Value::const_iterator Value::begin() const {
22✔
1464
  switch (type()) {
22✔
1465
  case arrayValue:
9✔
1466
  case objectValue:
1467
    if (value_.map_)
9✔
1468
      return const_iterator(value_.map_->begin());
9✔
1469
    break;
1470
  default:
1471
    break;
1472
  }
1473
  return {};
13✔
1474
}
1475

1476
Value::const_iterator Value::end() const {
63✔
1477
  switch (type()) {
63✔
1478
  case arrayValue:
51✔
1479
  case objectValue:
1480
    if (value_.map_)
51✔
1481
      return const_iterator(value_.map_->end());
51✔
1482
    break;
1483
  default:
1484
    break;
1485
  }
1486
  return {};
12✔
1487
}
1488

1489
Value::iterator Value::begin() {
37✔
1490
  switch (type()) {
37✔
1491
  case arrayValue:
24✔
1492
  case objectValue:
1493
    if (value_.map_)
24✔
1494
      return iterator(value_.map_->begin());
24✔
1495
    break;
1496
  default:
1497
    break;
1498
  }
1499
  return iterator();
13✔
1500
}
1501

1502
Value::iterator Value::end() {
42✔
1503
  switch (type()) {
42✔
1504
  case arrayValue:
27✔
1505
  case objectValue:
1506
    if (value_.map_)
27✔
1507
      return iterator(value_.map_->end());
27✔
1508
    break;
1509
  default:
1510
    break;
1511
  }
1512
  return iterator();
15✔
1513
}
1514

1515
// class PathArgument
1516
// //////////////////////////////////////////////////////////////////
1517

1518
PathArgument::PathArgument() = default;
36✔
1519

1520
PathArgument::PathArgument(ArrayIndex index)
4✔
1521
    : index_(index), kind_(kindIndex) {}
4✔
1522

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

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

1527
// class Path
1528
// //////////////////////////////////////////////////////////////////
1529

1530
Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
8✔
1531
           const PathArgument& a3, const PathArgument& a4,
1532
           const PathArgument& a5) {
8✔
1533
  InArgs in;
1534
  in.reserve(5);
8✔
1535
  in.push_back(&a1);
8✔
1536
  in.push_back(&a2);
8✔
1537
  in.push_back(&a3);
8✔
1538
  in.push_back(&a4);
8✔
1539
  in.push_back(&a5);
8✔
1540
  makePath(path, in);
8✔
1541
}
8✔
1542

1543
void Path::makePath(const String& path, const InArgs& in) {
8✔
1544
  const char* current = path.c_str();
1545
  const char* end = current + path.length();
8✔
1546
  auto itInArg = in.begin();
8✔
1547
  while (current != end) {
42✔
1548
    if (*current == '[') {
34✔
1549
      ++current;
4✔
1550
      if (*current == '%')
4✔
1551
        addPathInArg(path, in, itInArg, PathArgument::kindIndex);
2✔
1552
      else {
1553
        ArrayIndex index = 0;
1554
        for (; current != end && *current >= '0' && *current <= '9'; ++current)
4✔
1555
          index = index * 10 + ArrayIndex(*current - '0');
2✔
1556
        args_.push_back(index);
4✔
1557
      }
1558
      if (current == end || *++current != ']')
4✔
1559
        invalidPath(path, int(current - path.c_str()));
2✔
1560
    } else if (*current == '%') {
30✔
1561
      addPathInArg(path, in, itInArg, PathArgument::kindKey);
2✔
1562
      ++current;
2✔
1563
    } else if (*current == '.' || *current == ']') {
28✔
1564
      ++current;
18✔
1565
    } else {
1566
      const char* beginName = current;
1567
      while (current != end && !strchr("[.", *current))
88✔
1568
        ++current;
78✔
1569
      args_.push_back(String(beginName, current));
20✔
1570
    }
1571
  }
1572
}
8✔
1573

1574
void Path::addPathInArg(const String& /*path*/, const InArgs& in,
4✔
1575
                        InArgs::const_iterator& itInArg,
1576
                        PathArgument::Kind kind) {
1577
  if (itInArg == in.end()) {
4✔
1578
    // Error: missing argument %d
1579
  } else if ((*itInArg)->kind_ != kind) {
4✔
1580
    // Error: bad argument type
1581
  } else {
1582
    args_.push_back(**itInArg++);
4✔
1583
  }
1584
}
4✔
1585

1586
void Path::invalidPath(const String& /*path*/, int /*location*/) {
2✔
1587
  // Error: invalid path.
1588
}
2✔
1589

1590
const Value& Path::resolve(const Value& root) const {
6✔
1591
  const Value* node = &root;
1592
  for (const auto& arg : args_) {
14✔
1593
    if (arg.kind_ == PathArgument::kindIndex) {
12✔
1594
      if (!node->isArray() || !node->isValidIndex(arg.index_)) {
2✔
1595
        // Error: unable to resolve path (array value expected at position... )
1596
        return Value::nullSingleton();
1✔
1597
      }
1598
      node = &((*node)[arg.index_]);
1✔
1599
    } else if (arg.kind_ == PathArgument::kindKey) {
10✔
1600
      if (!node->isObject()) {
10✔
1601
        // Error: unable to resolve path (object value expected at position...)
1602
        return Value::nullSingleton();
1✔
1603
      }
1604
      node = &((*node)[arg.key_]);
9✔
1605
      if (node == &Value::nullSingleton()) {
9✔
1606
        // Error: unable to resolve path (object has no member named '' at
1607
        // position...)
1608
        return Value::nullSingleton();
2✔
1609
      }
1610
    }
1611
  }
1612
  return *node;
1613
}
1614

1615
Value Path::resolve(const Value& root, const Value& defaultValue) const {
6✔
1616
  const Value* node = &root;
1617
  for (const auto& arg : args_) {
14✔
1618
    if (arg.kind_ == PathArgument::kindIndex) {
12✔
1619
      if (!node->isArray() || !node->isValidIndex(arg.index_))
3✔
1620
        return defaultValue;
2✔
1621
      node = &((*node)[arg.index_]);
1✔
1622
    } else if (arg.kind_ == PathArgument::kindKey) {
9✔
1623
      if (!node->isObject())
9✔
1624
        return defaultValue;
1✔
1625
      node = &((*node)[arg.key_]);
8✔
1626
      if (node == &Value::nullSingleton())
8✔
1627
        return defaultValue;
1✔
1628
    }
1629
  }
1630
  return *node;
2✔
1631
}
1632

1633
Value& Path::make(Value& root) const {
2✔
1634
  Value* node = &root;
1635
  for (const auto& arg : args_) {
6✔
1636
    if (arg.kind_ == PathArgument::kindIndex) {
4✔
1637
      if (!node->isArray()) {
1✔
1638
        // Error: node is not an array at position ...
1639
      }
1640
      node = &((*node)[arg.index_]);
1✔
1641
    } else if (arg.kind_ == PathArgument::kindKey) {
3✔
1642
      if (!node->isObject()) {
3✔
1643
        // Error: node is not an object at position...
1644
      }
1645
      node = &((*node)[arg.key_]);
3✔
1646
    }
1647
  }
1648
  return *node;
2✔
1649
}
1650

1651
} // 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