JsonCpp project page | Classes | Namespace | JsonCpp home page

json_value.cpp
Go to the documentation of this file.
// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
#include <json/assertions.h>
#include <json/value.h>
#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <cstring>
#include <iostream>
#include <sstream>
#include <utility>
#ifdef JSONCPP_HAS_STRING_VIEW
#include <string_view>
#endif
// Provide implementation equivalent of std::snprintf for older _MSC compilers
#if defined(_MSC_VER) && _MSC_VER < 1900
#include <stdarg.h>
static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size,
const char* format, va_list ap) {
int count = -1;
if (size != 0)
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
if (count == -1)
count = _vscprintf(format, ap);
return count;
}
int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
const char* format, ...) {
va_list ap;
va_start(ap, format);
const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#endif
// Disable warning C4702 : unreachable code
#if defined(_MSC_VER)
#pragma warning(disable : 4702)
#endif
#define JSON_ASSERT_UNREACHABLE assert(false)
namespace Json {
template <typename T>
static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
std::unique_ptr<T> r;
if (p) {
r = std::unique_ptr<T>(new T(*p));
}
return r;
}
// This is a walkaround to avoid the static initialization of Value::null.
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
// 8 (instead of 4) as a bit of future-proofing.
#if defined(__ARMEL__)
#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
#else
#define ALIGNAS(byte_alignment)
#endif
// static
Value const& Value::nullSingleton() {
static Value const nullStatic;
return nullStatic;
}
#if JSON_USE_NULLREF
// for backwards compatibility, we'll leave these global references around, but
// DO NOT use them in JSONCPP library code any more!
// static
Value const& Value::null = Value::nullSingleton();
// static
Value const& Value::nullRef = Value::nullSingleton();
#endif
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
template <typename T, typename U>
static inline bool InRange(double d, T min, U max) {
// The casts can lose precision, but we are looking only for
// an approximate range. Might fail on edge cases though. ~cdunn
return d >= static_cast<double>(min) && d <= static_cast<double>(max) &&
!(static_cast<U>(d) == min && d != static_cast<double>(min));
}
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
static inline double integerToDouble(Json::UInt64 value) {
return static_cast<double>(Int64(value / 2)) * 2.0 +
static_cast<double>(Int64(value & 1));
}
template <typename T> static inline double integerToDouble(T value) {
return static_cast<double>(value);
}
template <typename T, typename U>
static inline bool InRange(double d, T min, U max) {
return d >= integerToDouble(min) && d <= integerToDouble(max) &&
!(static_cast<U>(d) == min && d != integerToDouble(min));
}
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
static inline char* duplicateStringValue(const char* value, size_t length) {
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
if (length >= static_cast<size_t>(Value::maxInt))
length = Value::maxInt - 1;
auto newString = static_cast<char*>(malloc(length + 1));
if (newString == nullptr) {
throwRuntimeError("in Json::Value::duplicateStringValue(): "
"Failed to allocate string value buffer");
}
memcpy(newString, value, length);
newString[length] = 0;
return newString;
}
/* Record the length as a prefix.
*/
static inline char* duplicateAndPrefixStringValue(const char* value,
unsigned int length) {
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
size_t actualLength = sizeof(length) + length + 1;
auto newString = static_cast<char*>(malloc(actualLength));
if (newString == nullptr) {
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
"Failed to allocate string value buffer");
}
*reinterpret_cast<unsigned*>(newString) = length;
memcpy(newString + sizeof(unsigned), value, length);
newString[actualLength - 1U] =
0; // to avoid buffer over-run accidents by users later
return newString;
}
inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
unsigned* length, char const** value) {
if (!isPrefixed) {
*length = static_cast<unsigned>(strlen(prefixed));
*value = prefixed;
} else {
*length = *reinterpret_cast<unsigned const*>(prefixed);
*value = prefixed + sizeof(unsigned);
}
}
#if JSONCPP_USE_SECURE_MEMORY
static inline void releasePrefixedStringValue(char* value) {
unsigned length = 0;
char const* valueDecoded;
decodePrefixedString(true, value, &length, &valueDecoded);
size_t const size = sizeof(unsigned) + length + 1U;
memset(value, 0, size);
free(value);
}
static inline void releaseStringValue(char* value, unsigned length) {
// length==0 => we allocated the strings memory
size_t size = (length == 0) ? strlen(value) : length;
memset(value, 0, size);
free(value);
}
#else // !JSONCPP_USE_SECURE_MEMORY
static inline void releasePrefixedStringValue(char* value) { free(value); }
static inline void releaseStringValue(char* value, unsigned) { free(value); }
#endif // JSONCPP_USE_SECURE_MEMORY
} // namespace Json
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// ValueInternals...
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
#if !defined(JSON_IS_AMALGAMATION)
#include "json_valueiterator.inl"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
#if JSON_USE_EXCEPTION
Exception::Exception(String msg) : msg_(std::move(msg)) {}
Exception::~Exception() noexcept = default;
char const* Exception::what() const noexcept { return msg_.c_str(); }
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
LogicError::LogicError(String const& msg) : Exception(msg) {}
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
throw RuntimeError(msg);
}
JSONCPP_NORETURN void throwLogicError(String const& msg) {
throw LogicError(msg);
}
#else // !JSON_USE_EXCEPTION
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
std::cerr << msg << std::endl;
abort();
}
JSONCPP_NORETURN void throwLogicError(String const& msg) {
std::cerr << msg << std::endl;
abort();
}
#endif
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::CZString
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// Notes: policy_ indicates if the string was allocated when
// a string is stored.
Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
Value::CZString::CZString(char const* str, unsigned length,
DuplicationPolicy allocate)
: cstr_(str) {
// allocate != duplicate
storage_.policy_ = allocate & 0x3;
storage_.length_ = length & 0x3FFFFFFF;
}
Value::CZString::CZString(const CZString& other) {
cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
? duplicateStringValue(other.cstr_, other.storage_.length_)
: other.cstr_);
if (other.cstr_) {
storage_.policy_ =
static_cast<unsigned>(
other.cstr_
? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
noDuplication
? noDuplication
: duplicate)
: static_cast<DuplicationPolicy>(other.storage_.policy_)) &
3U;
storage_.length_ = other.storage_.length_;
} else {
index_ = other.index_;
}
}
Value::CZString::CZString(CZString&& other) noexcept : cstr_(other.cstr_) {
if (other.cstr_) {
storage_.policy_ = other.storage_.policy_;
storage_.length_ = other.storage_.length_;
} else {
index_ = other.index_;
}
other.cstr_ = nullptr;
}
Value::CZString::~CZString() {
if (cstr_ && storage_.policy_ == duplicate) {
releaseStringValue(const_cast<char*>(cstr_),
storage_.length_ + 1U); // +1 for null terminating
// character for sake of
// completeness but not actually
// necessary
}
}
void Value::CZString::swap(CZString& other) {
std::swap(cstr_, other.cstr_);
std::swap(index_, other.index_);
}
Value::CZString& Value::CZString::operator=(const CZString& other) {
cstr_ = other.cstr_;
index_ = other.index_;
return *this;
}
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
if (cstr_ && storage_.policy_ == duplicate) {
releasePrefixedStringValue(const_cast<char*>(cstr_));
}
cstr_ = other.cstr_;
if (other.cstr_) {
storage_.policy_ = other.storage_.policy_;
storage_.length_ = other.storage_.length_;
} else {
index_ = other.index_;
}
other.cstr_ = nullptr;
return *this;
}
bool Value::CZString::operator<(const CZString& other) const {
if (!cstr_)
return index_ < other.index_;
// return strcmp(cstr_, other.cstr_) < 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
unsigned min_len = std::min<unsigned>(this_len, other_len);
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, min_len);
if (comp < 0)
return true;
if (comp > 0)
return false;
return (this_len < other_len);
}
bool Value::CZString::operator==(const CZString& other) const {
if (!cstr_)
return index_ == other.index_;
// return strcmp(cstr_, other.cstr_) == 0;
// Assume both are strings.
unsigned this_len = this->storage_.length_;
unsigned other_len = other.storage_.length_;
if (this_len != other_len)
return false;
JSON_ASSERT(this->cstr_ && other.cstr_);
int comp = memcmp(this->cstr_, other.cstr_, this_len);
return comp == 0;
}
ArrayIndex Value::CZString::index() const { return index_; }
// const char* Value::CZString::c_str() const { return cstr_; }
const char* Value::CZString::data() const { return cstr_; }
unsigned Value::CZString::length() const { return storage_.length_; }
bool Value::CZString::isStaticString() const {
return storage_.policy_ == noDuplication;
}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::Value
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
Value::Value(ValueType type) {
static char const emptyString[] = "";
initBasic(type);
switch (type) {
case nullValue:
break;
case intValue:
case uintValue:
value_.int_ = 0;
break;
case realValue:
value_.real_ = 0.0;
break;
case stringValue:
// allocated_ == false, so this is safe.
value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
break;
case arrayValue:
case objectValue:
value_.map_ = new ObjectValues();
break;
case booleanValue:
value_.bool_ = false;
break;
default:
JSON_ASSERT_UNREACHABLE;
}
}
Value::Value(Int value) {
initBasic(intValue);
value_.int_ = value;
}
Value::Value(UInt value) {
initBasic(uintValue);
value_.uint_ = value;
}
#if defined(JSON_HAS_INT64)
Value::Value(Int64 value) {
initBasic(intValue);
value_.int_ = value;
}
Value::Value(UInt64 value) {
initBasic(uintValue);
value_.uint_ = value;
}
#endif // defined(JSON_HAS_INT64)
Value::Value(double value) {
initBasic(realValue);
value_.real_ = value;
}
Value::Value(const char* value) {
initBasic(stringValue, true);
JSON_ASSERT_MESSAGE(value != nullptr,
"Null Value Passed to Value Constructor");
value_.string_ = duplicateAndPrefixStringValue(
value, static_cast<unsigned>(strlen(value)));
}
Value::Value(const char* begin, const char* end) {
initBasic(stringValue, true);
value_.string_ =
duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
}
Value::Value(const String& value) {
initBasic(stringValue, true);
value_.string_ = duplicateAndPrefixStringValue(
value.data(), static_cast<unsigned>(value.length()));
}
Value::Value(const StaticString& value) {
initBasic(stringValue);
value_.string_ = const_cast<char*>(value.c_str());
}
Value::Value(bool value) {
initBasic(booleanValue);
value_.bool_ = value;
}
Value::Value(const Value& other) {
dupPayload(other);
dupMeta(other);
}
Value::Value(Value&& other) noexcept {
initBasic(nullValue);
swap(other);
}
Value::~Value() {
releasePayload();
value_.uint_ = 0;
}
Value& Value::operator=(const Value& other) {
Value(other).swap(*this);
return *this;
}
Value& Value::operator=(Value&& other) noexcept {
other.swap(*this);
return *this;
}
void Value::swapPayload(Value& other) {
std::swap(bits_, other.bits_);
std::swap(value_, other.value_);
}
void Value::copyPayload(const Value& other) {
releasePayload();
dupPayload(other);
}
void Value::swap(Value& other) {
swapPayload(other);
std::swap(comments_, other.comments_);
std::swap(start_, other.start_);
std::swap(limit_, other.limit_);
}
void Value::copy(const Value& other) {
copyPayload(other);
dupMeta(other);
}
ValueType Value::type() const {
return static_cast<ValueType>(bits_.value_type_);
}
int Value::compare(const Value& other) const {
if (*this < other)
return -1;
if (*this > other)
return 1;
return 0;
}
bool Value::operator<(const Value& other) const {
int typeDelta = type() - other.type();
if (typeDelta)
return typeDelta < 0;
switch (type()) {
case nullValue:
return false;
case intValue:
return value_.int_ < other.value_.int_;
case uintValue:
return value_.uint_ < other.value_.uint_;
case realValue:
return value_.real_ < other.value_.real_;
case booleanValue:
return value_.bool_ < other.value_.bool_;
case stringValue: {
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
return other.value_.string_ != nullptr;
}
unsigned this_len;
unsigned other_len;
char const* this_str;
char const* other_str;
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
&this_str);
decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
&other_str);
unsigned min_len = std::min<unsigned>(this_len, other_len);
JSON_ASSERT(this_str && other_str);
int comp = memcmp(this_str, other_str, min_len);
if (comp < 0)
return true;
if (comp > 0)
return false;
return (this_len < other_len);
}
case arrayValue:
case objectValue: {
auto thisSize = value_.map_->size();
auto otherSize = other.value_.map_->size();
if (thisSize != otherSize)
return thisSize < otherSize;
return (*value_.map_) < (*other.value_.map_);
}
default:
JSON_ASSERT_UNREACHABLE;
}
return false; // unreachable
}
bool Value::operator<=(const Value& other) const { return !(other < *this); }
bool Value::operator>=(const Value& other) const { return !(*this < other); }
bool Value::operator>(const Value& other) const { return other < *this; }
bool Value::operator==(const Value& other) const {
if (type() != other.type())
return false;
switch (type()) {
case nullValue:
return true;
case intValue:
return value_.int_ == other.value_.int_;
case uintValue:
return value_.uint_ == other.value_.uint_;
case realValue:
return value_.real_ == other.value_.real_;
case booleanValue:
return value_.bool_ == other.value_.bool_;
case stringValue: {
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
return (value_.string_ == other.value_.string_);
}
unsigned this_len;
unsigned other_len;
char const* this_str;
char const* other_str;
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
&this_str);
decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
&other_str);
if (this_len != other_len)
return false;
JSON_ASSERT(this_str && other_str);
int comp = memcmp(this_str, other_str, this_len);
return comp == 0;
}
case arrayValue:
case objectValue:
return value_.map_->size() == other.value_.map_->size() &&
(*value_.map_) == (*other.value_.map_);
default:
JSON_ASSERT_UNREACHABLE;
}
return false; // unreachable
}
bool Value::operator!=(const Value& other) const { return !(*this == other); }
const char* Value::asCString() const {
JSON_ASSERT_MESSAGE(type() == stringValue,
"in Json::Value::asCString(): requires stringValue");
if (value_.string_ == nullptr)
return nullptr;
unsigned this_len;
char const* this_str;
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
&this_str);
return this_str;
}
#if JSONCPP_USE_SECURE_MEMORY
unsigned Value::getCStringLength() const {
JSON_ASSERT_MESSAGE(type() == stringValue,
"in Json::Value::asCString(): requires stringValue");
if (value_.string_ == 0)
return 0;
unsigned this_len;
char const* this_str;
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
&this_str);
return this_len;
}
#endif
bool Value::getString(char const** begin, char const** end) const {
if (type() != stringValue)
return false;
if (value_.string_ == nullptr)
return false;
unsigned length;
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
begin);
*end = *begin + length;
return true;
}
String Value::asString() const {
switch (type()) {
case nullValue:
return "";
case stringValue: {
if (value_.string_ == nullptr)
return "";
unsigned this_len;
char const* this_str;
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
&this_str);
return String(this_str, this_len);
}
case booleanValue:
return value_.bool_ ? "true" : "false";
case intValue:
return valueToString(value_.int_);
case uintValue:
return valueToString(value_.uint_);
case realValue:
return valueToString(value_.real_);
default:
JSON_FAIL_MESSAGE("Type is not convertible to string");
}
}
Value::Int Value::asInt() const {
switch (type()) {
case intValue:
JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
return Int(value_.int_);
case uintValue:
JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
return Int(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
"double out of Int range");
return Int(value_.real_);
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int.");
}
Value::UInt Value::asUInt() const {
switch (type()) {
case intValue:
JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
return UInt(value_.int_);
case uintValue:
JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
return UInt(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt),
"double out of UInt range");
return UInt(value_.real_);
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
}
JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
}
#if defined(JSON_HAS_INT64)
Value::Int64 Value::asInt64() const {
switch (type()) {
case intValue:
return Int64(value_.int_);
case uintValue:
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
return Int64(value_.uint_);
case realValue:
// If the double value is in proximity to minInt64, it will be rounded to
// minInt64. The correct value in this scenario is indeterminable
JSON_ASSERT_MESSAGE(
value_.real_ != minInt64,
"Double value is minInt64, precise value cannot be determined");
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
"double out of Int64 range");
return Int64(value_.real_);
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
}
JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
}
Value::UInt64 Value::asUInt64() const {
switch (type()) {
case intValue:
JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
return UInt64(value_.int_);
case uintValue:
return UInt64(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt64),
"double out of UInt64 range");
return UInt64(value_.real_);
case nullValue:
return 0;
case booleanValue:
return value_.bool_ ? 1 : 0;
default:
break;
}
JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
}
#endif // if defined(JSON_HAS_INT64)
LargestInt Value::asLargestInt() const {
#if defined(JSON_NO_INT64)
return asInt();
#else
return asInt64();
#endif
}
LargestUInt Value::asLargestUInt() const {
#if defined(JSON_NO_INT64)
return asUInt();
#else
return asUInt64();
#endif
}
double Value::asDouble() const {
switch (type()) {
case intValue:
return static_cast<double>(value_.int_);
case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
return static_cast<double>(value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
return integerToDouble(value_.uint_);
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
case realValue:
return value_.real_;
case nullValue:
return 0.0;
case booleanValue:
return value_.bool_ ? 1.0 : 0.0;
default:
break;
}
JSON_FAIL_MESSAGE("Value is not convertible to double.");
}
float Value::asFloat() const {
switch (type()) {
case intValue:
return static_cast<float>(value_.int_);
case uintValue:
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
return static_cast<float>(value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
// This can fail (silently?) if the value is bigger than MAX_FLOAT.
return static_cast<float>(integerToDouble(value_.uint_));
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
case realValue:
return static_cast<float>(value_.real_);
case nullValue:
return 0.0;
case booleanValue:
return value_.bool_ ? 1.0F : 0.0F;
default:
break;
}
JSON_FAIL_MESSAGE("Value is not convertible to float.");
}
bool Value::asBool() const {
switch (type()) {
case booleanValue:
return value_.bool_;
case nullValue:
return false;
case intValue:
return value_.int_ != 0;
case uintValue:
return value_.uint_ != 0;
case realValue: {
// According to JavaScript language zero or NaN is regarded as false
const auto value_classification = std::fpclassify(value_.real_);
return value_classification != FP_ZERO && value_classification != FP_NAN;
}
default:
break;
}
JSON_FAIL_MESSAGE("Value is not convertible to bool.");
}
bool Value::isConvertibleTo(ValueType other) const {
switch (other) {
case nullValue:
return (isNumeric() && asDouble() == 0.0) ||
(type() == booleanValue && !value_.bool_) ||
(type() == stringValue && asString().empty()) ||
(type() == arrayValue && value_.map_->empty()) ||
(type() == objectValue && value_.map_->empty()) ||
type() == nullValue;
case intValue:
return isInt() ||
(type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
type() == booleanValue || type() == nullValue;
case uintValue:
return isUInt() ||
(type() == realValue && InRange(value_.real_, 0u, maxUInt)) ||
type() == booleanValue || type() == nullValue;
case realValue:
return isNumeric() || type() == booleanValue || type() == nullValue;
case booleanValue:
return isNumeric() || type() == booleanValue || type() == nullValue;
case stringValue:
return isNumeric() || type() == booleanValue || type() == stringValue ||
type() == nullValue;
case arrayValue:
return type() == arrayValue || type() == nullValue;
case objectValue:
return type() == objectValue || type() == nullValue;
}
JSON_ASSERT_UNREACHABLE;
return false;
}
ArrayIndex Value::size() const {
switch (type()) {
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
case stringValue:
return 0;
case arrayValue: // size of the array is highest index + 1
if (!value_.map_->empty()) {
ObjectValues::const_iterator itLast = value_.map_->end();
--itLast;
return (*itLast).first.index() + 1;
}
return 0;
case objectValue:
return ArrayIndex(value_.map_->size());
}
JSON_ASSERT_UNREACHABLE;
return 0; // unreachable;
}
bool Value::empty() const {
if (isNull() || isArray() || isObject())
return size() == 0U;
return false;
}
Value::operator bool() const { return !isNull(); }
void Value::clear() {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue ||
type() == objectValue,
"in Json::Value::clear(): requires complex value");
start_ = 0;
limit_ = 0;
switch (type()) {
case arrayValue:
case objectValue:
value_.map_->clear();
break;
default:
break;
}
}
void Value::resize(ArrayIndex newSize) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::resize(): requires arrayValue");
if (type() == nullValue)
*this = Value(arrayValue);
ArrayIndex oldSize = size();
if (newSize == 0)
clear();
else if (newSize > oldSize)
for (ArrayIndex i = oldSize; i < newSize; ++i)
(*this)[i];
else {
for (ArrayIndex index = newSize; index < oldSize; ++index) {
value_.map_->erase(index);
}
JSON_ASSERT(size() == newSize);
}
}
Value& Value::operator[](ArrayIndex index) {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == arrayValue,
"in Json::Value::operator[](ArrayIndex): requires arrayValue");
if (type() == nullValue)
*this = Value(arrayValue);
CZString key(index);
auto it = value_.map_->lower_bound(key);
if (it != value_.map_->end() && (*it).first == key)
return (*it).second;
ObjectValues::value_type defaultValue(key, nullSingleton());
it = value_.map_->insert(it, defaultValue);
return (*it).second;
}
Value& Value::operator[](int index) {
JSON_ASSERT_MESSAGE(
index >= 0,
"in Json::Value::operator[](int index): index cannot be negative");
return (*this)[ArrayIndex(index)];
}
const Value& Value::operator[](ArrayIndex index) const {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == arrayValue,
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
if (type() == nullValue)
return nullSingleton();
CZString key(index);
ObjectValues::const_iterator it = value_.map_->find(key);
if (it == value_.map_->end())
return nullSingleton();
return (*it).second;
}
const Value& Value::operator[](int index) const {
JSON_ASSERT_MESSAGE(
index >= 0,
"in Json::Value::operator[](int index) const: index cannot be negative");
return (*this)[ArrayIndex(index)];
}
void Value::initBasic(ValueType type, bool allocated) {
setType(type);
setIsAllocated(allocated);
comments_ = Comments{};
start_ = 0;
limit_ = 0;
}
void Value::dupPayload(const Value& other) {
setType(other.type());
setIsAllocated(false);
switch (type()) {
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
value_ = other.value_;
break;
case stringValue:
if (other.value_.string_ && other.isAllocated()) {
unsigned len;
char const* str;
decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
&str);
value_.string_ = duplicateAndPrefixStringValue(str, len);
setIsAllocated(true);
} else {
value_.string_ = other.value_.string_;
}
break;
case arrayValue:
case objectValue:
value_.map_ = new ObjectValues(*other.value_.map_);
break;
default:
JSON_ASSERT_UNREACHABLE;
}
}
void Value::releasePayload() {
switch (type()) {
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
break;
case stringValue:
if (isAllocated())
releasePrefixedStringValue(value_.string_);
break;
case arrayValue:
case objectValue:
delete value_.map_;
break;
default:
JSON_ASSERT_UNREACHABLE;
}
}
void Value::dupMeta(const Value& other) {
comments_ = other.comments_;
start_ = other.start_;
limit_ = other.limit_;
}
// Access an object value by name, create a null member if it does not exist.
// @pre Type of '*this' is object or null.
// @param key is null-terminated.
Value& Value::resolveReference(const char* key) {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
"in Json::Value::resolveReference(): requires objectValue");
if (type() == nullValue)
*this = Value(objectValue);
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
CZString::noDuplication); // NOTE!
auto it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}
// @param key is not null-terminated.
Value& Value::resolveReference(char const* key, char const* end) {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
"in Json::Value::resolveReference(key, end): requires objectValue");
if (type() == nullValue)
*this = Value(objectValue);
CZString actualKey(key, static_cast<unsigned>(end - key),
CZString::duplicateOnCopy);
auto it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
it = value_.map_->insert(it, defaultValue);
Value& value = (*it).second;
return value;
}
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
const Value* value = &((*this)[index]);
return value == &nullSingleton() ? defaultValue : *value;
}
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
Value const* Value::find(char const* begin, char const* end) const {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
"in Json::Value::find(begin, end): requires "
"objectValue or nullValue");
if (type() == nullValue)
return nullptr;
CZString actualKey(begin, static_cast<unsigned>(end - begin),
CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return nullptr;
return &(*it).second;
}
Value const* Value::find(const String& key) const {
return find(key.data(), key.data() + key.length());
}
Value const* Value::findNull(const String& key) const {
return findValue<Value, &Value::isNull>(key);
}
Value const* Value::findBool(const String& key) const {
return findValue<Value, &Value::isBool>(key);
}
Value const* Value::findInt(const String& key) const {
return findValue<Value, &Value::isInt>(key);
}
Value const* Value::findInt64(const String& key) const {
return findValue<Value, &Value::isInt64>(key);
}
Value const* Value::findUInt(const String& key) const {
return findValue<Value, &Value::isUInt>(key);
}
Value const* Value::findUInt64(const String& key) const {
return findValue<Value, &Value::isUInt64>(key);
}
Value const* Value::findIntegral(const String& key) const {
return findValue<Value, &Value::isIntegral>(key);
}
Value const* Value::findDouble(const String& key) const {
return findValue<Value, &Value::isDouble>(key);
}
Value const* Value::findNumeric(const String& key) const {
return findValue<Value, &Value::isNumeric>(key);
}
Value const* Value::findString(const String& key) const {
return findValue<Value, &Value::isString>(key);
}
Value const* Value::findArray(const String& key) const {
return findValue<Value, &Value::isArray>(key);
}
Value const* Value::findObject(const String& key) const {
return findValue<Value, &Value::isObject>(key);
}
Value* Value::demand(char const* begin, char const* end) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
"in Json::Value::demand(begin, end): requires "
"objectValue or nullValue");
return &resolveReference(begin, end);
}
const Value& Value::operator[](const char* key) const {
Value const* found = find(key, key + strlen(key));
if (!found)
return nullSingleton();
return *found;
}
Value const& Value::operator[](const String& key) const {
Value const* found = find(key);
if (!found)
return nullSingleton();
return *found;
}
Value& Value::operator[](const char* key) {
return resolveReference(key, key + strlen(key));
}
Value& Value::operator[](const String& key) {
return resolveReference(key.data(), key.data() + key.length());
}
Value& Value::operator[](const StaticString& key) {
return resolveReference(key.c_str());
}
Value& Value::append(const Value& value) { return append(Value(value)); }
Value& Value::append(Value&& value) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::append: requires arrayValue");
if (type() == nullValue) {
*this = Value(arrayValue);
}
return this->value_.map_->emplace(size(), std::move(value)).first->second;
}
bool Value::insert(ArrayIndex index, const Value& newValue) {
return insert(index, Value(newValue));
}
bool Value::insert(ArrayIndex index, Value&& newValue) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::insert: requires arrayValue");
ArrayIndex length = size();
if (index > length) {
return false;
}
for (ArrayIndex i = length; i > index; i--) {
(*this)[i] = std::move((*this)[i - 1]);
}
(*this)[index] = std::move(newValue);
return true;
}
Value Value::get(char const* begin, char const* end,
Value const& defaultValue) const {
Value const* found = find(begin, end);
return !found ? defaultValue : *found;
}
Value Value::get(char const* key, Value const& defaultValue) const {
return get(key, key + strlen(key), defaultValue);
}
Value Value::get(String const& key, Value const& defaultValue) const {
return get(key.data(), key.data() + key.length(), defaultValue);
}
bool Value::removeMember(const char* begin, const char* end, Value* removed) {
if (type() != objectValue) {
return false;
}
CZString actualKey(begin, static_cast<unsigned>(end - begin),
CZString::noDuplication);
auto it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
if (removed)
*removed = std::move(it->second);
value_.map_->erase(it);
return true;
}
bool Value::removeMember(const char* key, Value* removed) {
return removeMember(key, key + strlen(key), removed);
}
bool Value::removeMember(String const& key, Value* removed) {
return removeMember(key.data(), key.data() + key.length(), removed);
}
void Value::removeMember(const char* key) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
"in Json::Value::removeMember(): requires objectValue");
if (type() == nullValue)
return;
CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
value_.map_->erase(actualKey);
}
void Value::removeMember(const String& key) { removeMember(key.c_str()); }
bool Value::removeIndex(ArrayIndex index, Value* removed) {
if (type() != arrayValue) {
return false;
}
CZString key(index);
auto it = value_.map_->find(key);
if (it == value_.map_->end()) {
return false;
}
if (removed)
*removed = std::move(it->second);
ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed"
for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
CZString keey(i);
(*value_.map_)[keey] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
auto itLast = value_.map_->find(keyLast);
value_.map_->erase(itLast);
return true;
}
bool Value::isMember(char const* begin, char const* end) const {
Value const* value = find(begin, end);
return nullptr != value;
}
bool Value::isMember(char const* key) const {
return isMember(key, key + strlen(key));
}
bool Value::isMember(String const& key) const {
return isMember(key.data(), key.data() + key.length());
}
Value::Members Value::getMemberNames() const {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
"in Json::Value::getMemberNames(), value must be objectValue");
if (type() == nullValue)
return Value::Members();
Members members;
members.reserve(value_.map_->size());
ObjectValues::const_iterator it = value_.map_->begin();
ObjectValues::const_iterator itEnd = value_.map_->end();
for (; it != itEnd; ++it) {
members.push_back(String((*it).first.data(), (*it).first.length()));
}
return members;
}
static bool IsIntegral(double d) {
double integral_part;
return modf(d, &integral_part) == 0.0;
}
bool Value::isNull() const { return type() == nullValue; }
bool Value::isBool() const { return type() == booleanValue; }
bool Value::isInt() const {
switch (type()) {
case intValue:
#if defined(JSON_HAS_INT64)
return value_.int_ >= minInt && value_.int_ <= maxInt;
#else
return true;
#endif
case uintValue:
return value_.uint_ <= UInt(maxInt);
case realValue:
return value_.real_ >= minInt && value_.real_ <= maxInt &&
IsIntegral(value_.real_);
default:
break;
}
return false;
}
bool Value::isUInt() const {
switch (type()) {
case intValue:
#if defined(JSON_HAS_INT64)
return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
#else
return value_.int_ >= 0;
#endif
case uintValue:
#if defined(JSON_HAS_INT64)
return value_.uint_ <= maxUInt;
#else
return true;
#endif
case realValue:
return value_.real_ >= 0 && value_.real_ <= maxUInt &&
IsIntegral(value_.real_);
default:
break;
}
return false;
}
bool Value::isInt64() const {
#if defined(JSON_HAS_INT64)
switch (type()) {
case intValue:
return true;
case uintValue:
return value_.uint_ <= UInt64(maxInt64);
case realValue:
// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
// double, so double(maxInt64) will be rounded up to 2^63. Therefore we
// require the value to be strictly less than the limit.
// minInt64 is -2^63 which can be represented as a double, but since double
// values in its proximity are also rounded to -2^63, we require the value
// to be strictly greater than the limit to avoid returning 'true' for
// values that are not in the range
return value_.real_ > double(minInt64) && value_.real_ < double(maxInt64) &&
IsIntegral(value_.real_);
default:
break;
}
#endif // JSON_HAS_INT64
return false;
}
bool Value::isUInt64() const {
#if defined(JSON_HAS_INT64)
switch (type()) {
case intValue:
return value_.int_ >= 0;
case uintValue:
return true;
case realValue:
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
// require the value to be strictly less than the limit.
return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
IsIntegral(value_.real_);
default:
break;
}
#endif // JSON_HAS_INT64
return false;
}
bool Value::isIntegral() const {
switch (type()) {
case intValue:
case uintValue:
return true;
case realValue:
#if defined(JSON_HAS_INT64)
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
// require the value to be strictly less than the limit.
// minInt64 is -2^63 which can be represented as a double, but since double
// values in its proximity are also rounded to -2^63, we require the value
// to be strictly greater than the limit to avoid returning 'true' for
// values that are not in the range
return value_.real_ > double(minInt64) &&
value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
#else
return value_.real_ >= minInt && value_.real_ <= maxUInt &&
IsIntegral(value_.real_);
#endif // JSON_HAS_INT64
default:
break;
}
return false;
}
bool Value::isDouble() const {
return type() == intValue || type() == uintValue || type() == realValue;
}
bool Value::isNumeric() const { return isDouble(); }
bool Value::isString() const { return type() == stringValue; }
bool Value::isArray() const { return type() == arrayValue; }
bool Value::isObject() const { return type() == objectValue; }
Value::Comments::Comments(const Comments& that)
: ptr_{cloneUnique(that.ptr_)} {}
Value::Comments::Comments(Comments&& that) noexcept
: ptr_{std::move(that.ptr_)} {}
Value::Comments& Value::Comments::operator=(const Comments& that) {
ptr_ = cloneUnique(that.ptr_);
return *this;
}
Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
ptr_ = std::move(that.ptr_);
return *this;
}
bool Value::Comments::has(CommentPlacement slot) const {
return ptr_ && !(*ptr_)[slot].empty();
}
String Value::Comments::get(CommentPlacement slot) const {
if (!ptr_)
return {};
return (*ptr_)[slot];
}
void Value::Comments::set(CommentPlacement slot, String comment) {
if (slot >= CommentPlacement::numberOfCommentPlacement)
return;
if (!ptr_)
ptr_ = std::unique_ptr<Array>(new Array());
(*ptr_)[slot] = std::move(comment);
}
void Value::setComment(String comment, CommentPlacement placement) {
if (!comment.empty() && (comment.back() == '\n')) {
// Always discard trailing newline, to aid indentation.
comment.pop_back();
}
JSON_ASSERT_MESSAGE(
comment.empty() || comment[0] == '/',
"in Json::Value::setComment(): Comments must start with /");
comments_.set(placement, std::move(comment));
}
bool Value::hasComment(CommentPlacement placement) const {
return comments_.has(placement);
}
String Value::getComment(CommentPlacement placement) const {
return comments_.get(placement);
}
void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
ptrdiff_t Value::getOffsetStart() const { return start_; }
ptrdiff_t Value::getOffsetLimit() const { return limit_; }
String Value::toStyledString() const {
StreamWriterBuilder builder;
String out = this->hasComment(commentBefore) ? "\n" : "";
out += Json::writeString(builder, *this);
out += '\n';
return out;
}
Value::const_iterator Value::begin() const {
switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
return const_iterator(value_.map_->begin());
break;
default:
break;
}
return {};
}
Value::const_iterator Value::end() const {
switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
return const_iterator(value_.map_->end());
break;
default:
break;
}
return {};
}
Value::iterator Value::begin() {
switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
return iterator(value_.map_->begin());
break;
default:
break;
}
return iterator();
}
Value::iterator Value::end() {
switch (type()) {
case arrayValue:
case objectValue:
if (value_.map_)
return iterator(value_.map_->end());
break;
default:
break;
}
return iterator();
}
// class PathArgument
// //////////////////////////////////////////////////////////////////
PathArgument::PathArgument() = default;
PathArgument::PathArgument(ArrayIndex index)
: index_(index), kind_(kindIndex) {}
PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
// class Path
// //////////////////////////////////////////////////////////////////
Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
const PathArgument& a3, const PathArgument& a4,
const PathArgument& a5) {
InArgs in;
in.reserve(5);
in.push_back(&a1);
in.push_back(&a2);
in.push_back(&a3);
in.push_back(&a4);
in.push_back(&a5);
makePath(path, in);
}
void Path::makePath(const String& path, const InArgs& in) {
const char* current = path.c_str();
const char* end = current + path.length();
auto itInArg = in.begin();
while (current != end) {
if (*current == '[') {
++current;
if (*current == '%')
addPathInArg(path, in, itInArg, PathArgument::kindIndex);
else {
ArrayIndex index = 0;
for (; current != end && *current >= '0' && *current <= '9'; ++current)
index = index * 10 + ArrayIndex(*current - '0');
args_.push_back(index);
}
if (current == end || *++current != ']')
invalidPath(path, int(current - path.c_str()));
} else if (*current == '%') {
addPathInArg(path, in, itInArg, PathArgument::kindKey);
++current;
} else if (*current == '.' || *current == ']') {
++current;
} else {
const char* beginName = current;
while (current != end && !strchr("[.", *current))
++current;
args_.push_back(String(beginName, current));
}
}
}
void Path::addPathInArg(const String& /*path*/, const InArgs& in,
InArgs::const_iterator& itInArg,
PathArgument::Kind kind) {
if (itInArg == in.end()) {
// Error: missing argument %d
} else if ((*itInArg)->kind_ != kind) {
// Error: bad argument type
} else {
args_.push_back(**itInArg++);
}
}
void Path::invalidPath(const String& /*path*/, int /*location*/) {
// Error: invalid path.
}
const Value& Path::resolve(const Value& root) const {
const Value* node = &root;
for (const auto& arg : args_) {
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
// Error: unable to resolve path (array value expected at position... )
return Value::nullSingleton();
}
node = &((*node)[arg.index_]);
} else if (arg.kind_ == PathArgument::kindKey) {
if (!node->isObject()) {
// Error: unable to resolve path (object value expected at position...)
return Value::nullSingleton();
}
node = &((*node)[arg.key_]);
if (node == &Value::nullSingleton()) {
// Error: unable to resolve path (object has no member named '' at
// position...)
return Value::nullSingleton();
}
}
}
return *node;
}
Value Path::resolve(const Value& root, const Value& defaultValue) const {
const Value* node = &root;
for (const auto& arg : args_) {
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray() || !node->isValidIndex(arg.index_))
return defaultValue;
node = &((*node)[arg.index_]);
} else if (arg.kind_ == PathArgument::kindKey) {
if (!node->isObject())
return defaultValue;
node = &((*node)[arg.key_]);
if (node == &Value::nullSingleton())
return defaultValue;
}
}
return *node;
}
Value& Path::make(Value& root) const {
Value* node = &root;
for (const auto& arg : args_) {
if (arg.kind_ == PathArgument::kindIndex) {
if (!node->isArray()) {
// Error: node is not an array at position ...
}
node = &((*node)[arg.index_]);
} else if (arg.kind_ == PathArgument::kindKey) {
if (!node->isObject()) {
// Error: node is not an object at position...
}
node = &((*node)[arg.key_]);
}
}
return *node;
}
} // namespace Json
assertions.h
JSON_ASSERT
#define JSON_ASSERT(condition)
It should not be possible for a maliciously designed file to cause an abort() or seg-fault,...
Definition assertions.h:23
JSON_FAIL_MESSAGE
#define JSON_FAIL_MESSAGE(message)
Definition assertions.h:30
JSON_ASSERT_MESSAGE
#define JSON_ASSERT_MESSAGE(condition, message)
Definition assertions.h:54
Json::Exception::what
char const * what() const noexcept override
Definition json_value.cpp:211
Json::Exception::~Exception
~Exception() noexcept override
Json::Exception::Exception
Exception(String msg)
Definition json_value.cpp:209
Json::Exception::msg_
String msg_
Definition value.h:88
Json::LogicError::LogicError
LogicError(String const &msg)
Definition json_value.cpp:213
Json::PathArgument
Experimental and untested: represents an element of the "path" to access a node.
Definition value.h:808
Json::PathArgument::PathArgument
PathArgument()
Json::Path::Path
Path(const String &path, const PathArgument &a1=PathArgument(), const PathArgument &a2=PathArgument(), const PathArgument &a3=PathArgument(), const PathArgument &a4=PathArgument(), const PathArgument &a5=PathArgument())
Definition json_value.cpp:1590
Json::Path::make
Value & make(Value &root) const
Creates the "path" to access the specified node and returns a reference on the node.
Definition json_value.cpp:1693
Json::Path::resolve
const Value & resolve(const Value &root) const
Definition json_value.cpp:1650
Json::RuntimeError
Exceptions which the user cannot easily avoid.
Definition value.h:97
Json::RuntimeError::RuntimeError
RuntimeError(String const &msg)
Definition json_value.cpp:212
Json::StaticString
Lightweight wrapper to tag static string.
Definition value.h:161
Json::StaticString::c_str
const char * c_str() const
Definition value.h:167
Json::StreamWriterBuilder
Build a StreamWriter implementation.
Definition writer.h:90
Json::Value
Represents a JSON value.
Definition value.h:207
Json::Value::begin
const_iterator begin() const
Definition json_value.cpp:1523
Json::Value::get
Value get(ArrayIndex index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
Definition json_value.cpp:1103
Json::Value::empty
bool empty() const
Return true if empty array, empty object, or null; otherwise, false.
Definition json_value.cpp:910
Json::Value::ArrayIndex
Json::ArrayIndex ArrayIndex
Definition value.h:223
Json::Value::asUInt64
UInt64 asUInt64() const
Definition json_value.cpp:749
Json::Value::size
ArrayIndex size() const
Number of values in array or object.
Definition json_value.cpp:887
Json::Value::UInt
Json::UInt UInt
Definition value.h:215
Json::Value::isArray
bool isArray() const
Definition json_value.cpp:1448
Json::Value::asCString
const char * asCString() const
Embedded zeroes could cause you trouble!
Definition json_value.cpp:613
Json::Value::operator==
bool operator==(const Value &other) const
Definition json_value.cpp:569
Json::Value::maxInt64
static constexpr Int64 maxInt64
Maximum signed 64 bits int value that can be stored in a Json::Value.
Definition value.h:256
Json::Value::copy
void copy(const Value &other)
copy everything.
Definition json_value.cpp:496
Json::Value::null
static const Value & null
Definition value.h:230
Json::Value::findDouble
Value const * findDouble(const String &key) const
Definition json_value.cpp:1148
Json::Value::~Value
~Value()
Definition json_value.cpp:464
Json::Value::setComment
void setComment(const char *comment, size_t len, CommentPlacement placement)
Comments must be //... or /* ... *‍/.
Definition value.h:668
Json::Value::getOffsetLimit
ptrdiff_t getOffsetLimit() const
Definition json_value.cpp:1511
Json::Value::getString
bool getString(char const **begin, char const **end) const
Get raw char* of string-value.
Definition json_value.cpp:639
Json::Value::findString
Value const * findString(const String &key) const
Definition json_value.cpp:1154
Json::Value::maxUInt64AsDouble
static constexpr double maxUInt64AsDouble
Definition value.h:265
Json::Value::Members
std::vector< String > Members
Definition value.h:212
Json::Value::end
const_iterator end() const
Definition json_value.cpp:1536
Json::Value::operator<=
bool operator<=(const Value &other) const
Definition json_value.cpp:563
Json::Value::getComment
String getComment(CommentPlacement placement) const
Include delimiters and embedded newlines.
Definition json_value.cpp:1501
Json::Value::operator>
bool operator>(const Value &other) const
Definition json_value.cpp:567
Json::Value::toStyledString
String toStyledString() const
Definition json_value.cpp:1513
Json::Value::isDouble
bool isDouble() const
Definition json_value.cpp:1440
Json::Value::isInt64
bool isInt64() const
Definition json_value.cpp:1370
Json::Value::clear
void clear()
Remove all object members and array elements.
Definition json_value.cpp:918
Json::Value::asString
String asString() const
Embedded zeroes are possible.
Definition json_value.cpp:651
Json::Value::swapPayload
void swapPayload(Value &other)
Swap values but leave comments and source offsets in place.
Definition json_value.cpp:479
Json::Value::placement
CommentPlacement placement
Definition value.h:664
Json::Value::setOffsetLimit
void setOffsetLimit(ptrdiff_t limit)
Definition json_value.cpp:1507
Json::Value::asInt
Int asInt() const
Definition json_value.cpp:677
Json::Value::removeIndex
bool removeIndex(ArrayIndex index, Value *removed)
Remove the indexed array element.
Definition json_value.cpp:1268
Json::Value::findArray
Value const * findArray(const String &key) const
Definition json_value.cpp:1157
Json::Value::hasComment
bool hasComment(CommentPlacement placement) const
Definition json_value.cpp:1497
Json::Value::iterator
ValueIterator iterator
Definition value.h:213
Json::Value::LargestInt
Json::LargestInt LargestInt
Definition value.h:221
Json::Value::LargestUInt
Json::LargestUInt LargestUInt
Definition value.h:222
Json::Value::const_iterator
ValueConstIterator const_iterator
Definition value.h:214
Json::Value::isString
bool isString() const
Definition json_value.cpp:1446
Json::Value::asUInt
UInt asUInt() const
Definition json_value.cpp:699
Json::Value::UInt64
Json::UInt64 UInt64
Definition value.h:218
Json::Value::getMemberNames
Members getMemberNames() const
Return a list of the member names.
Definition json_value.cpp:1303
Json::Value::resize
void resize(ArrayIndex newSize)
Resize the array to newSize elements.
Definition json_value.cpp:934
Json::Value::operator[]
Value & operator[](ArrayIndex index)
Definition json_value.cpp:953
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition json_value.cpp:1195
Json::Value::findBool
Value const * findBool(const String &key) const
Definition json_value.cpp:1130
Json::Value::operator!=
bool operator!=(const Value &other) const
Definition json_value.cpp:611
Json::Value::isUInt64
bool isUInt64() const
Definition json_value.cpp:1394
Json::Value::findValue
Value const * findValue(const String &key) const
Calls find and only returns a valid pointer if the type is found.
Definition value.h:576
Json::Value::type
ValueType type() const
Definition json_value.cpp:501
Json::Value::isObject
bool isObject() const
Definition json_value.cpp:1450
Json::Value::findInt64
Value const * findInt64(const String &key) const
Definition json_value.cpp:1136
Json::Value::removeMember
void removeMember(const char *key)
Remove and return the named member.
Definition json_value.cpp:1257
Json::Value::setOffsetStart
void setOffsetStart(ptrdiff_t start)
Definition json_value.cpp:1505
Json::Value::findNull
Value const * findNull(const String &key) const
Definition json_value.cpp:1127
Json::Value::findUInt
Value const * findUInt(const String &key) const
Definition json_value.cpp:1139
Json::Value::asInt64
Int64 asInt64() const
Definition json_value.cpp:723
Json::Value::demand
Value * demand(char const *begin, char const *end)
Most general and efficient version of object-mutators.
Definition json_value.cpp:1164
Json::Value::swap
void swap(Value &other)
Swap everything.
Definition json_value.cpp:489
Json::Value::operator<
bool operator<(const Value &other) const
Compare payload only, not comments etc.
Definition json_value.cpp:513
Json::Value::findInt
Value const * findInt(const String &key) const
Definition json_value.cpp:1133
Json::Value::Int
Json::Int Int
Definition value.h:216
Json::Value::nullRef
static const Value & nullRef
Definition value.h:231
Json::Value::asLargestInt
LargestInt asLargestInt() const
Definition json_value.cpp:771
Json::Value::isBool
bool isBool() const
Definition json_value.cpp:1326
Json::Value::copyPayload
void copyPayload(const Value &other)
copy values but leave comments and source offsets in place.
Definition json_value.cpp:484
Json::Value::findIntegral
Value const * findIntegral(const String &key) const
Definition json_value.cpp:1145
Json::Value::maxInt
static constexpr Int maxInt
Maximum signed int value that can be stored in a Json::Value.
Definition value.h:248
Json::Value::isIntegral
bool isIntegral() const
Definition json_value.cpp:1414
Json::Value::asBool
bool asBool() const
Definition json_value.cpp:832
Json::Value::findNumeric
Value const * findNumeric(const String &key) const
Definition json_value.cpp:1151
Json::Value::isUInt
bool isUInt() const
Definition json_value.cpp:1347
Json::Value::isNull
bool isNull() const
Definition json_value.cpp:1324
Json::Value::isValidIndex
bool isValidIndex(ArrayIndex index) const
Return true if index < size().
Definition json_value.cpp:1108
Json::Value::findUInt64
Value const * findUInt64(const String &key) const
Definition json_value.cpp:1142
Json::Value::asLargestUInt
LargestUInt asLargestUInt() const
Definition json_value.cpp:779
Json::Value::findObject
Value const * findObject(const String &key) const
Definition json_value.cpp:1160
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition json_value.cpp:1296
Json::Value::Int64
Json::Int64 Int64
Definition value.h:219
Json::Value::Value
Value(ValueType type=nullValue)
Create a default Value of the given type.
Definition json_value.cpp:370
Json::Value::maxUInt64
static constexpr UInt64 maxUInt64
Maximum unsigned 64 bits int value that can be stored in a Json::Value.
Definition value.h:258
Json::Value::operator=
Value & operator=(const Value &other)
Definition json_value.cpp:469
Json::Value::minInt
static constexpr Int minInt
Minimum signed int value that can be stored in a Json::Value.
Definition value.h:246
Json::Value::insert
bool insert(ArrayIndex index, const Value &newValue)
Insert value in array at specific index.
Definition json_value.cpp:1206
Json::Value::minInt64
static constexpr Int64 minInt64
Minimum signed 64 bits int value that can be stored in a Json::Value.
Definition value.h:254
Json::Value::compare
int compare(const Value &other) const
Definition json_value.cpp:505
Json::Value::isConvertibleTo
bool isConvertibleTo(ValueType other) const
Definition json_value.cpp:853
Json::Value::nullSingleton
static Value const & nullSingleton()
Definition json_value.cpp:74
Json::Value::asFloat
float asFloat() const
Definition json_value.cpp:809
Json::Value::isNumeric
bool isNumeric() const
Definition json_value.cpp:1444
Json::Value::getOffsetStart
ptrdiff_t getOffsetStart() const
Definition json_value.cpp:1509
Json::Value::find
Value const * find(char const *begin, char const *end) const
Most general and efficient version of isMember()const, get()const, and operator[]const.
Definition json_value.cpp:1110
Json::Value::asDouble
double asDouble() const
Definition json_value.cpp:787
Json::Value::operator>=
bool operator>=(const Value &other) const
Definition json_value.cpp:565
Json::Value::maxUInt
static constexpr UInt maxUInt
Maximum unsigned int value that can be stored in a Json::Value.
Definition value.h:250
Json::Value::isInt
bool isInt() const
Definition json_value.cpp:1328
JSON_API
#define JSON_API
If defined, indicates that the source file is amalgamated to prevent private header inclusion.
Definition config.h:50
msvc_pre1900_c99_snprintf
int msvc_pre1900_c99_snprintf(char *outBuf, size_t size, const char *format,...)
Definition json_value.cpp:37
JSON_ASSERT_UNREACHABLE
#define JSON_ASSERT_UNREACHABLE
Definition json_value.cpp:52
msvc_pre1900_c99_vsnprintf
static int msvc_pre1900_c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
Definition json_value.cpp:27
json_valueiterator.inl
Json
JSON (JavaScript Object Notation).
Definition allocator.h:16
Json::duplicateStringValue
static char * duplicateStringValue(const char *value, size_t length)
Duplicates the specified string value.
Definition json_value.cpp:121
Json::UInt64
unsigned __int64 UInt64
Definition config.h:118
Json::IsIntegral
static bool IsIntegral(double d)
Definition json_value.cpp:1319
Json::ArrayIndex
unsigned int ArrayIndex
Definition forwards.h:32
Json::Int64
__int64 Int64
Definition config.h:117
Json::releaseStringValue
static void releaseStringValue(char *value, unsigned)
Definition json_value.cpp:189
Json::releasePrefixedStringValue
static void releasePrefixedStringValue(char *value)
Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
Definition json_value.cpp:188
Json::writeString
String writeString(StreamWriter::Factory const &factory, Value const &root)
Write into stringstream, then return string, for convenience.
Definition json_writer.cpp:1187
Json::CommentPlacement
CommentPlacement
Definition value.h:132
Json::commentBefore
@ commentBefore
a comment placed on the line before a value
Definition value.h:133
Json::numberOfCommentPlacement
@ numberOfCommentPlacement
root value)
Definition value.h:137
Json::valueToString
String valueToString(Int value)
Definition json_writer.cpp:57
Json::ValueType
ValueType
Type of the value held by a Value object.
Definition value.h:121
Json::booleanValue
@ booleanValue
bool value
Definition value.h:127
Json::nullValue
@ nullValue
'null' value
Definition value.h:122
Json::stringValue
@ stringValue
UTF-8 string value.
Definition value.h:126
Json::realValue
@ realValue
double value
Definition value.h:125
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition value.h:128
Json::intValue
@ intValue
signed integer value
Definition value.h:123
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition value.h:129
Json::uintValue
@ uintValue
unsigned integer value
Definition value.h:124
Json::decodePrefixedString
static void decodePrefixedString(bool isPrefixed, char const *prefixed, unsigned *length, char const **value)
Definition json_value.cpp:159
Json::String
std::basic_string< char, std::char_traits< char >, Allocator< char > > String
Definition config.h:132
Json::cloneUnique
static std::unique_ptr< T > cloneUnique(const std::unique_ptr< T > &p)
Definition json_value.cpp:56
Json::duplicateAndPrefixStringValue
static char * duplicateAndPrefixStringValue(const char *value, unsigned int length)
Definition json_value.cpp:139
Json::InRange
static bool InRange(double d, T min, U max)
Definition json_value.cpp:91
value.h
JSONCPP_NORETURN
#define JSONCPP_NORETURN
Definition value.h:18
writer.h