2011-06-22 06:08:49 +08:00
// Copyright 2011 Baptiste Lepilleur
2010-04-21 05:35:19 +08:00
// 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
2011-05-03 05:09:30 +08:00
# if !defined(JSON_IS_AMALGAMATION)
2014-07-01 06:48:54 +08:00
# include <json/assertions.h>
# include <json/value.h>
# include <json/writer.h>
2011-05-03 05:09:30 +08:00
# endif // if !defined(JSON_IS_AMALGAMATION)
2011-05-25 12:19:17 +08:00
# include <math.h>
2011-05-26 10:46:28 +08:00
# include <sstream>
2007-06-13 23:48:30 +08:00
# include <utility>
2009-05-12 04:04:10 +08:00
# include <cstring>
# include <cassert>
2007-06-13 23:48:30 +08:00
# ifdef JSON_USE_CPPTL
2014-07-01 06:48:54 +08:00
# include <cpptl/conststring.h>
2007-06-13 23:48:30 +08:00
# endif
2014-07-01 06:48:54 +08:00
# include <cstddef> // size_t
2015-03-05 23:15:08 +08:00
# include <algorithm> // min()
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
# define JSON_ASSERT_UNREACHABLE assert(false)
2007-06-13 23:48:30 +08:00
namespace Json {
2014-07-06 04:52:19 +08:00
// 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
2016-06-27 07:47:43 +08:00
//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
//const unsigned char& kNullRef = kNull[0];
//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
//const Value& Value::nullRef = null;
// static
Value const & Value : : nullSingleton ( )
{
2016-07-21 02:31:41 +08:00
static Value const nullStatic ;
return nullStatic ;
2016-06-27 07:47:43 +08:00
}
// for backwards compatibility, we'll leave these global references around, but DO NOT
// use them in JSONCPP library code any more!
Value const & Value : : null = Value : : nullSingleton ( ) ;
Value const & Value : : nullRef = Value : : nullSingleton ( ) ;
2014-07-06 04:52:19 +08:00
2014-07-01 06:48:54 +08:00
const Int Value : : minInt = Int ( ~ ( UInt ( - 1 ) / 2 ) ) ;
const Int Value : : maxInt = Int ( UInt ( - 1 ) / 2 ) ;
2010-02-21 22:08:17 +08:00
const UInt Value : : maxUInt = UInt ( - 1 ) ;
2014-07-01 06:48:54 +08:00
# if defined(JSON_HAS_INT64)
const Int64 Value : : minInt64 = Int64 ( ~ ( UInt64 ( - 1 ) / 2 ) ) ;
const Int64 Value : : maxInt64 = Int64 ( UInt64 ( - 1 ) / 2 ) ;
2010-12-28 01:45:23 +08:00
const UInt64 Value : : maxUInt64 = UInt64 ( - 1 ) ;
2011-05-27 01:14:26 +08:00
// The constant is hard-coded because some compiler have trouble
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
// Assumes that UInt64 is a 64 bits integer.
static const double maxUInt64AsDouble = 18446744073709551615.0 ;
2011-05-24 11:18:02 +08:00
# endif // defined(JSON_HAS_INT64)
2014-07-01 06:48:54 +08:00
const LargestInt Value : : minLargestInt = LargestInt ( ~ ( LargestUInt ( - 1 ) / 2 ) ) ;
const LargestInt Value : : maxLargestInt = LargestInt ( LargestUInt ( - 1 ) / 2 ) ;
2010-12-28 01:45:23 +08:00
const LargestUInt Value : : maxLargestUInt = LargestUInt ( - 1 ) ;
2011-05-27 06:55:24 +08:00
# if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
template < typename T , typename U >
static inline bool InRange ( double d , T min , U max ) {
2016-02-06 23:25:20 +08:00
// 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);
2014-07-01 06:48:54 +08:00
return d > = min & & d < = max ;
2011-05-27 06:55:24 +08:00
}
2014-07-01 06:48:54 +08:00
# else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
static inline double integerToDouble ( Json : : UInt64 value ) {
2016-03-15 21:01:44 +08:00
return static_cast < double > ( Int64 ( value / 2 ) ) * 2.0 + static_cast < double > ( Int64 ( value & 1 ) ) ;
2011-05-27 06:55:24 +08:00
}
2014-07-01 06:48:54 +08:00
template < typename T > static inline double integerToDouble ( T value ) {
return static_cast < double > ( value ) ;
2011-05-27 06:55:24 +08:00
}
2011-05-26 10:46:28 +08:00
template < typename T , typename U >
static inline bool InRange ( double d , T min , U max ) {
2014-07-01 06:48:54 +08:00
return d > = integerToDouble ( min ) & & d < = integerToDouble ( max ) ;
2011-05-26 10:46:28 +08:00
}
2011-05-27 06:55:24 +08:00
# endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2011-05-26 10:46:28 +08:00
2010-03-13 21:10:27 +08:00
/** Duplicates the specified string value.
* @ param value Pointer to the string to duplicate . Must be zero - terminated if
* length is " unknown " .
* @ param length Length of the value . if equals to unknown , then it will be
* computed using strlen ( value ) .
* @ return Pointer on the duplicate instance of string .
*/
2014-09-15 08:15:29 +08:00
static inline char * duplicateStringValue ( const char * value ,
2016-03-07 16:29:59 +08:00
size_t length )
{
2014-07-01 06:48:54 +08:00
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
2016-02-28 19:56:04 +08:00
if ( length > = static_cast < size_t > ( Value : : maxInt ) )
2014-07-01 06:48:54 +08:00
length = Value : : maxInt - 1 ;
2011-05-24 08:43:59 +08:00
2014-09-15 08:15:29 +08:00
char * newString = static_cast < char * > ( malloc ( length + 1 ) ) ;
2015-03-09 01:05:28 +08:00
if ( newString = = NULL ) {
2015-03-09 01:43:18 +08:00
throwRuntimeError (
2015-03-09 01:05:28 +08:00
" in Json::Value::duplicateStringValue(): "
" Failed to allocate string value buffer " ) ;
}
2014-07-01 06:48:54 +08:00
memcpy ( newString , value , length ) ;
newString [ length ] = 0 ;
return newString ;
2010-03-13 21:10:27 +08:00
}
2007-06-13 23:48:30 +08:00
2015-02-22 00:54:38 +08:00
/* Record the length as a prefix.
*/
2015-02-22 01:44:16 +08:00
static inline char * duplicateAndPrefixStringValue (
2015-02-22 00:54:38 +08:00
const char * value ,
2015-02-22 01:44:16 +08:00
unsigned int length )
2015-02-22 00:54:38 +08:00
{
// Avoid an integer overflow in the call to malloc below by limiting length
// to a sane value.
2016-02-28 19:56:04 +08:00
JSON_ASSERT_MESSAGE ( length < = static_cast < unsigned > ( Value : : maxInt ) - sizeof ( unsigned ) - 1U ,
2015-02-22 01:44:16 +08:00
" in Json::Value::duplicateAndPrefixStringValue(): "
" length too big for prefixing " ) ;
2015-07-13 01:55:18 +08:00
unsigned actualLength = length + static_cast < unsigned > ( sizeof ( unsigned ) ) + 1U ;
2015-02-22 01:44:16 +08:00
char * newString = static_cast < char * > ( malloc ( actualLength ) ) ;
2015-03-09 01:05:28 +08:00
if ( newString = = 0 ) {
2015-03-09 01:43:18 +08:00
throwRuntimeError (
2015-03-09 01:05:28 +08:00
" in Json::Value::duplicateAndPrefixStringValue(): "
" Failed to allocate string value buffer " ) ;
}
2015-02-22 01:44:16 +08:00
* reinterpret_cast < unsigned * > ( newString ) = length ;
memcpy ( newString + sizeof ( unsigned ) , value , length ) ;
newString [ actualLength - 1U ] = 0 ; // to avoid buffer over-run accidents by users later
2015-02-22 00:54:38 +08:00
return newString ;
}
2015-02-22 01:44:16 +08:00
inline static void decodePrefixedString (
bool isPrefixed , char const * prefixed ,
unsigned * length , char const * * value )
{
if ( ! isPrefixed ) {
2015-07-02 05:18:15 +08:00
* length = static_cast < unsigned > ( strlen ( prefixed ) ) ;
2015-02-22 01:44:16 +08:00
* value = prefixed ;
} else {
* length = * reinterpret_cast < unsigned const * > ( prefixed ) ;
* value = prefixed + sizeof ( unsigned ) ;
}
}
/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
2010-03-13 21:10:27 +08:00
*/
2016-03-15 08:11:02 +08:00
# if JSONCPP_USING_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_USING_SECURE_MEMORY
static inline void releasePrefixedStringValue ( char * value ) {
free ( value ) ;
}
2016-03-27 02:41:46 +08:00
static inline void releaseStringValue ( char * value , unsigned ) {
2016-03-15 08:11:02 +08:00
free ( value ) ;
}
# endif // JSONCPP_USING_SECURE_MEMORY
2007-06-13 23:48:30 +08:00
2011-05-02 04:13:40 +08:00
} // namespace Json
2007-06-13 23:48:30 +08:00
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// ValueInternals...
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
2011-05-03 05:09:30 +08:00
# if !defined(JSON_IS_AMALGAMATION)
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
# include "json_valueiterator.inl"
2011-05-03 05:09:30 +08:00
# endif // if !defined(JSON_IS_AMALGAMATION)
2007-06-13 23:48:30 +08:00
2011-05-02 04:13:40 +08:00
namespace Json {
2007-06-13 23:48:30 +08:00
2016-03-07 01:19:46 +08:00
Exception : : Exception ( JSONCPP_STRING const & msg )
2015-03-09 01:20:06 +08:00
: msg_ ( msg )
2015-03-09 01:31:00 +08:00
{ }
2016-11-08 02:57:00 +08:00
Exception : : ~ Exception ( ) JSONCPP_NOEXCEPT
2015-03-09 01:20:06 +08:00
{ }
2016-11-08 02:57:00 +08:00
char const * Exception : : what ( ) const JSONCPP_NOEXCEPT
2015-03-09 01:20:06 +08:00
{
return msg_ . c_str ( ) ;
}
2016-03-07 01:19:46 +08:00
RuntimeError : : RuntimeError ( JSONCPP_STRING const & msg )
2015-03-09 01:31:00 +08:00
: Exception ( msg )
{ }
2016-03-07 01:19:46 +08:00
LogicError : : LogicError ( JSONCPP_STRING const & msg )
2015-03-09 01:31:00 +08:00
: Exception ( msg )
{ }
2016-03-16 13:47:21 +08:00
JSONCPP_NORETURN void throwRuntimeError ( JSONCPP_STRING const & msg )
2015-03-09 01:31:00 +08:00
{
throw RuntimeError ( msg ) ;
}
2016-03-16 13:47:21 +08:00
JSONCPP_NORETURN void throwLogicError ( JSONCPP_STRING const & msg )
2015-03-09 01:31:00 +08:00
{
throw LogicError ( msg ) ;
}
2015-03-09 01:20:06 +08:00
2007-06-13 23:48:30 +08:00
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::CommentInfo
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
2016-03-07 16:29:59 +08:00
Value : : CommentInfo : : CommentInfo ( ) : comment_ ( 0 )
{ }
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
Value : : CommentInfo : : ~ CommentInfo ( ) {
if ( comment_ )
2016-03-15 08:11:02 +08:00
releaseStringValue ( comment_ , 0u ) ;
2007-06-13 23:48:30 +08:00
}
2015-01-26 04:16:13 +08:00
void Value : : CommentInfo : : setComment ( const char * text , size_t len ) {
2015-01-25 18:01:22 +08:00
if ( comment_ ) {
2016-03-15 08:11:02 +08:00
releaseStringValue ( comment_ , 0u ) ;
2015-01-25 18:01:22 +08:00
comment_ = 0 ;
}
2014-07-01 06:48:54 +08:00
JSON_ASSERT ( text ! = 0 ) ;
JSON_ASSERT_MESSAGE (
text [ 0 ] = = ' \0 ' | | text [ 0 ] = = ' / ' ,
" in Json::Value::setComment(): Comments must start with / " ) ;
// It seems that /**/ style comments are acceptable as well.
2015-01-26 04:16:13 +08:00
comment_ = duplicateStringValue ( text , len ) ;
2007-06-13 23:48:30 +08:00
}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::CZString
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
2015-03-03 02:10:35 +08:00
// Notes: policy_ indicates if the string was allocated when
2007-06-13 23:48:30 +08:00
// a string is stored.
2015-07-13 01:55:18 +08:00
Value : : CZString : : CZString ( ArrayIndex aindex ) : cstr_ ( 0 ) , index_ ( aindex ) { }
2007-06-13 23:48:30 +08:00
2015-07-13 01:55:18 +08:00
Value : : CZString : : CZString ( char const * str , unsigned ulength , DuplicationPolicy allocate )
2015-10-20 12:49:07 +08:00
: cstr_ ( str ) {
2015-03-08 04:42:52 +08:00
// allocate != duplicate
2015-07-13 01:55:18 +08:00
storage_ . policy_ = allocate & 0x3 ;
storage_ . length_ = ulength & 0x3FFFFFFF ;
2015-03-03 15:22:13 +08:00
}
2007-06-13 23:48:30 +08:00
2016-03-15 08:11:02 +08:00
Value : : CZString : : CZString ( const CZString & other ) {
cstr_ = ( other . storage_ . policy_ ! = noDuplication & & other . cstr_ ! = 0
? duplicateStringValue ( other . cstr_ , other . storage_ . length_ )
: other . cstr_ ) ;
2016-02-08 01:28:50 +08:00
storage_ . policy_ = static_cast < unsigned > ( other . cstr_
2015-07-13 01:55:18 +08:00
? ( static_cast < DuplicationPolicy > ( other . storage_ . policy_ ) = = noDuplication
2014-11-19 16:13:11 +08:00
? noDuplication : duplicate )
2016-03-15 07:32:34 +08:00
: static_cast < DuplicationPolicy > ( other . storage_ . policy_ ) ) & 3U ;
2015-03-03 15:22:13 +08:00
storage_ . length_ = other . storage_ . length_ ;
}
2007-06-13 23:48:30 +08:00
2015-04-20 22:44:47 +08:00
# if JSON_HAS_RVALUE_REFERENCES
Value : : CZString : : CZString ( CZString & & other )
2015-10-20 12:49:07 +08:00
: cstr_ ( other . cstr_ ) , index_ ( other . index_ ) {
other . cstr_ = nullptr ;
2015-04-20 22:44:47 +08:00
}
# endif
2014-07-01 06:48:54 +08:00
Value : : CZString : : ~ CZString ( ) {
2016-03-15 08:11:02 +08:00
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
}
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
void Value : : CZString : : swap ( CZString & other ) {
2014-07-01 06:48:54 +08:00
std : : swap ( cstr_ , other . cstr_ ) ;
std : : swap ( index_ , other . index_ ) ;
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
Value : : CZString & Value : : CZString : : operator = ( CZString other ) {
2014-09-08 20:00:39 +08:00
swap ( other ) ;
2014-07-01 06:48:54 +08:00
return * this ;
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
bool Value : : CZString : : operator < ( const CZString & other ) const {
2015-03-03 01:18:06 +08:00
if ( ! cstr_ ) return index_ < other . index_ ;
//return strcmp(cstr_, other.cstr_) < 0;
// Assume both are strings.
2015-03-03 02:23:03 +08:00
unsigned this_len = this - > storage_ . length_ ;
unsigned other_len = other . storage_ . length_ ;
2015-03-03 01:18:06 +08:00
unsigned min_len = std : : min ( this_len , other_len ) ;
2016-03-01 16:43:28 +08:00
JSON_ASSERT ( this - > cstr_ & & other . cstr_ ) ;
2015-03-03 01:18:06 +08:00
int comp = memcmp ( this - > cstr_ , other . cstr_ , min_len ) ;
if ( comp < 0 ) return true ;
if ( comp > 0 ) return false ;
return ( this_len < other_len ) ;
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
bool Value : : CZString : : operator = = ( const CZString & other ) const {
2015-03-03 01:18:06 +08:00
if ( ! cstr_ ) return index_ = = other . index_ ;
//return strcmp(cstr_, other.cstr_) == 0;
// Assume both are strings.
2015-03-03 02:23:03 +08:00
unsigned this_len = this - > storage_ . length_ ;
unsigned other_len = other . storage_ . length_ ;
2015-03-03 01:18:06 +08:00
if ( this_len ! = other_len ) return false ;
2016-03-01 16:43:28 +08:00
JSON_ASSERT ( this - > cstr_ & & other . cstr_ ) ;
2015-03-03 01:18:06 +08:00
int comp = memcmp ( this - > cstr_ , other . cstr_ , this_len ) ;
return comp = = 0 ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
ArrayIndex Value : : CZString : : index ( ) const { return index_ ; }
2007-06-13 23:48:30 +08:00
2015-02-22 01:44:16 +08:00
//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_ ; }
2015-03-03 02:10:35 +08:00
bool Value : : CZString : : isStaticString ( ) const { return storage_ . policy_ = = noDuplication ; }
2007-06-13 23:48:30 +08:00
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::Value
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
/*! \internal Default constructor initialization must be equivalent to:
* memset ( this , 0 , sizeof ( Value ) )
* This optimization is used in ValueInternalMap fast allocator .
*/
2015-07-13 01:55:18 +08:00
Value : : Value ( ValueType vtype ) {
2016-10-14 17:59:28 +08:00
static char const emptyString [ ] = " " ;
2015-07-13 01:55:18 +08:00
initBasic ( vtype ) ;
switch ( vtype ) {
2014-07-01 06:48:54 +08:00
case nullValue :
break ;
case intValue :
case uintValue :
value_ . int_ = 0 ;
break ;
case realValue :
value_ . real_ = 0.0 ;
break ;
case stringValue :
2016-08-22 05:25:29 +08:00
// allocated_ == false, so this is safe.
2016-10-14 17:59:28 +08:00
value_ . string_ = const_cast < char * > ( static_cast < char const * > ( emptyString ) ) ;
2014-07-01 06:48:54 +08:00
break ;
case arrayValue :
case objectValue :
value_ . map_ = new ObjectValues ( ) ;
break ;
case booleanValue :
value_ . bool_ = false ;
break ;
default :
JSON_ASSERT_UNREACHABLE ;
}
2007-06-13 23:48:30 +08:00
}
2014-11-10 14:35:42 +08:00
Value : : Value ( Int value ) {
initBasic ( intValue ) ;
2014-07-01 06:48:54 +08:00
value_ . int_ = value ;
2007-06-13 23:48:30 +08:00
}
2014-11-10 14:35:42 +08:00
Value : : Value ( UInt value ) {
initBasic ( uintValue ) ;
value_ . uint_ = value ;
}
2014-07-01 06:48:54 +08:00
# if defined(JSON_HAS_INT64)
2014-11-10 14:35:42 +08:00
Value : : Value ( Int64 value ) {
initBasic ( intValue ) ;
2014-07-01 06:48:54 +08:00
value_ . int_ = value ;
}
2014-11-10 14:35:42 +08:00
Value : : Value ( UInt64 value ) {
initBasic ( uintValue ) ;
2014-07-01 06:48:54 +08:00
value_ . uint_ = value ;
2007-06-13 23:48:30 +08:00
}
2011-05-24 11:18:02 +08:00
# endif // defined(JSON_HAS_INT64)
2007-06-13 23:48:30 +08:00
2014-11-10 14:35:42 +08:00
Value : : Value ( double value ) {
initBasic ( realValue ) ;
2014-07-01 06:48:54 +08:00
value_ . real_ = value ;
2007-06-13 23:48:30 +08:00
}
2014-11-10 14:35:42 +08:00
Value : : Value ( const char * value ) {
initBasic ( stringValue , true ) ;
2015-03-05 23:15:08 +08:00
value_ . string_ = duplicateAndPrefixStringValue ( value , static_cast < unsigned > ( strlen ( value ) ) ) ;
2010-02-21 22:08:17 +08:00
}
2014-11-10 14:35:42 +08:00
Value : : Value ( const char * beginValue , const char * endValue ) {
initBasic ( stringValue , true ) ;
2014-07-01 06:48:54 +08:00
value_ . string_ =
2015-03-05 23:15:08 +08:00
duplicateAndPrefixStringValue ( beginValue , static_cast < unsigned > ( endValue - beginValue ) ) ;
2007-06-13 23:48:30 +08:00
}
2016-03-07 01:19:46 +08:00
Value : : Value ( const JSONCPP_STRING & value ) {
2014-11-10 14:35:42 +08:00
initBasic ( stringValue , true ) ;
2014-07-01 06:48:54 +08:00
value_ . string_ =
2015-03-05 23:15:08 +08:00
duplicateAndPrefixStringValue ( value . data ( ) , static_cast < unsigned > ( value . length ( ) ) ) ;
2007-06-13 23:48:30 +08:00
}
2014-11-10 14:35:42 +08:00
Value : : Value ( const StaticString & value ) {
initBasic ( stringValue ) ;
2014-09-15 08:15:29 +08:00
value_ . string_ = const_cast < char * > ( value . c_str ( ) ) ;
2014-07-01 06:48:54 +08:00
}
# ifdef JSON_USE_CPPTL
2014-11-10 14:35:42 +08:00
Value : : Value ( const CppTL : : ConstString & value ) {
initBasic ( stringValue , true ) ;
2015-03-05 23:15:08 +08:00
value_ . string_ = duplicateAndPrefixStringValue ( value , static_cast < unsigned > ( value . length ( ) ) ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
# endif
2007-06-13 23:48:30 +08:00
2014-11-10 14:35:42 +08:00
Value : : Value ( bool value ) {
initBasic ( booleanValue ) ;
2014-07-01 06:48:54 +08:00
value_ . bool_ = value ;
}
2007-06-13 23:48:30 +08:00
2015-03-03 23:35:58 +08:00
Value : : Value ( Value const & other )
2014-07-01 06:48:54 +08:00
: type_ ( other . type_ ) , allocated_ ( false )
,
2015-03-03 23:35:58 +08:00
comments_ ( 0 ) , start_ ( other . start_ ) , limit_ ( other . limit_ )
{
2014-07-01 06:48:54 +08:00
switch ( type_ ) {
case nullValue :
case intValue :
case uintValue :
case realValue :
case booleanValue :
value_ = other . value_ ;
break ;
case stringValue :
2015-03-03 23:35:58 +08:00
if ( other . value_ . string_ & & other . allocated_ ) {
2015-02-22 01:44:16 +08:00
unsigned len ;
char const * str ;
decodePrefixedString ( other . allocated_ , other . value_ . string_ ,
& len , & str ) ;
value_ . string_ = duplicateAndPrefixStringValue ( str , len ) ;
2015-01-25 03:42:37 +08:00
allocated_ = true ;
2014-07-01 06:48:54 +08:00
} else {
2015-03-03 23:35:58 +08:00
value_ . string_ = other . value_ . string_ ;
2014-07-01 06:48:54 +08:00
allocated_ = false ;
}
break ;
case arrayValue :
case objectValue :
value_ . map_ = new ObjectValues ( * other . value_ . map_ ) ;
break ;
default :
JSON_ASSERT_UNREACHABLE ;
}
if ( other . comments_ ) {
comments_ = new CommentInfo [ numberOfCommentPlacement ] ;
for ( int comment = 0 ; comment < numberOfCommentPlacement ; + + comment ) {
2014-09-15 08:15:29 +08:00
const CommentInfo & otherComment = other . comments_ [ comment ] ;
2014-07-01 06:48:54 +08:00
if ( otherComment . comment_ )
2015-01-26 04:16:13 +08:00
comments_ [ comment ] . setComment (
otherComment . comment_ , strlen ( otherComment . comment_ ) ) ;
2014-07-01 06:48:54 +08:00
}
}
}
2015-04-20 22:44:47 +08:00
# if JSON_HAS_RVALUE_REFERENCES
// Move constructor
2015-10-20 12:49:07 +08:00
Value : : Value ( Value & & other ) {
initBasic ( nullValue ) ;
swap ( other ) ;
2015-04-20 22:44:47 +08:00
}
# endif
2014-07-01 06:48:54 +08:00
Value : : ~ Value ( ) {
switch ( type_ ) {
case nullValue :
case intValue :
case uintValue :
case realValue :
case booleanValue :
break ;
case stringValue :
if ( allocated_ )
2016-03-15 08:11:02 +08:00
releasePrefixedStringValue ( value_ . string_ ) ;
2014-07-01 06:48:54 +08:00
break ;
case arrayValue :
case objectValue :
delete value_ . map_ ;
break ;
default :
JSON_ASSERT_UNREACHABLE ;
}
2016-08-22 05:30:05 +08:00
delete [ ] comments_ ;
2016-03-15 08:11:02 +08:00
value_ . uint_ = 0 ;
2014-07-01 06:48:54 +08:00
}
2014-09-15 08:15:29 +08:00
Value & Value : : operator = ( Value other ) {
2015-01-21 01:02:22 +08:00
swap ( other ) ;
2014-07-01 06:48:54 +08:00
return * this ;
}
2015-01-18 17:05:25 +08:00
void Value : : swapPayload ( Value & other ) {
2014-07-01 06:48:54 +08:00
ValueType temp = type_ ;
type_ = other . type_ ;
other . type_ = temp ;
std : : swap ( value_ , other . value_ ) ;
int temp2 = allocated_ ;
allocated_ = other . allocated_ ;
2015-07-13 01:55:18 +08:00
other . allocated_ = temp2 & 0x1 ;
2015-01-18 17:05:25 +08:00
}
void Value : : swap ( Value & other ) {
swapPayload ( other ) ;
std : : swap ( comments_ , other . comments_ ) ;
2014-07-01 06:48:54 +08:00
std : : swap ( start_ , other . start_ ) ;
std : : swap ( limit_ , other . limit_ ) ;
}
ValueType Value : : type ( ) const { return type_ ; }
2014-09-15 08:15:29 +08:00
int Value : : compare ( const Value & other ) const {
2014-07-01 06:48:54 +08:00
if ( * this < other )
return - 1 ;
if ( * this > other )
return 1 ;
return 0 ;
}
2014-09-15 08:15:29 +08:00
bool Value : : operator < ( const Value & other ) const {
2014-07-01 06:48:54 +08:00
int typeDelta = type_ - other . type_ ;
if ( typeDelta )
return typeDelta < 0 ? true : false ;
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 :
2015-02-22 01:44:16 +08:00
{
if ( ( value_ . string_ = = 0 ) | | ( other . value_ . string_ = = 0 ) ) {
if ( other . value_ . string_ ) return true ;
else return false ;
}
unsigned this_len ;
unsigned other_len ;
char const * this_str ;
char const * other_str ;
decodePrefixedString ( this - > allocated_ , this - > value_ . string_ , & this_len , & this_str ) ;
decodePrefixedString ( other . allocated_ , other . value_ . string_ , & other_len , & other_str ) ;
unsigned min_len = std : : min ( this_len , other_len ) ;
2016-03-01 16:43:28 +08:00
JSON_ASSERT ( this_str & & other_str ) ;
2015-02-22 01:44:16 +08:00
int comp = memcmp ( this_str , other_str , min_len ) ;
if ( comp < 0 ) return true ;
if ( comp > 0 ) return false ;
return ( this_len < other_len ) ;
}
2014-07-01 06:48:54 +08:00
case arrayValue :
case objectValue : {
int delta = int ( value_ . map_ - > size ( ) - other . value_ . map_ - > size ( ) ) ;
if ( delta )
return delta < 0 ;
return ( * value_ . map_ ) < ( * other . value_ . map_ ) ;
}
default :
JSON_ASSERT_UNREACHABLE ;
}
return false ; // unreachable
}
2014-09-15 08:15:29 +08:00
bool Value : : operator < = ( const Value & other ) const { return ! ( other < * this ) ; }
2014-07-01 06:48:54 +08:00
2014-09-15 08:15:29 +08:00
bool Value : : operator > = ( const Value & other ) const { return ! ( * this < other ) ; }
2014-07-01 06:48:54 +08:00
2014-09-15 08:15:29 +08:00
bool Value : : operator > ( const Value & other ) const { return other < * this ; }
2014-07-01 06:48:54 +08:00
2014-09-15 08:15:29 +08:00
bool Value : : operator = = ( const Value & other ) const {
2014-07-01 06:48:54 +08:00
// if ( type_ != other.type_ )
// GCC 2.95.3 says:
// attempt to take address of bit-field structure member `Json::Value::type_'
// Beats me, but a temp solves the problem.
int temp = other . type_ ;
if ( type_ ! = temp )
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 :
2015-02-22 01:44:16 +08:00
{
if ( ( value_ . string_ = = 0 ) | | ( other . value_ . string_ = = 0 ) ) {
return ( value_ . string_ = = other . value_ . string_ ) ;
}
unsigned this_len ;
unsigned other_len ;
char const * this_str ;
char const * other_str ;
decodePrefixedString ( this - > allocated_ , this - > value_ . string_ , & this_len , & this_str ) ;
decodePrefixedString ( other . allocated_ , other . value_ . string_ , & other_len , & other_str ) ;
if ( this_len ! = other_len ) return false ;
2016-03-01 16:43:28 +08:00
JSON_ASSERT ( this_str & & other_str ) ;
2015-02-22 01:44:16 +08:00
int comp = memcmp ( this_str , other_str , this_len ) ;
return comp = = 0 ;
}
2014-07-01 06:48:54 +08:00
case arrayValue :
case objectValue :
return value_ . map_ - > size ( ) = = other . value_ . map_ - > size ( ) & &
( * value_ . map_ ) = = ( * other . value_ . map_ ) ;
default :
JSON_ASSERT_UNREACHABLE ;
}
return false ; // unreachable
}
2014-09-15 08:15:29 +08:00
bool Value : : operator ! = ( const Value & other ) const { return ! ( * this = = other ) ; }
2014-07-01 06:48:54 +08:00
2014-09-15 08:15:29 +08:00
const char * Value : : asCString ( ) const {
2014-07-01 06:48:54 +08:00
JSON_ASSERT_MESSAGE ( type_ = = stringValue ,
" in Json::Value::asCString(): requires stringValue " ) ;
2015-02-22 01:44:16 +08:00
if ( value_ . string_ = = 0 ) return 0 ;
unsigned this_len ;
char const * this_str ;
decodePrefixedString ( this - > allocated_ , this - > value_ . string_ , & this_len , & this_str ) ;
return this_str ;
}
2016-03-15 08:11:02 +08:00
# if JSONCPP_USING_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 - > allocated_ , this - > value_ . string_ , & this_len , & this_str ) ;
return this_len ;
}
# endif
2015-07-13 01:55:18 +08:00
bool Value : : getString ( char const * * str , char const * * cend ) const {
2015-02-22 01:44:16 +08:00
if ( type_ ! = stringValue ) return false ;
if ( value_ . string_ = = 0 ) return false ;
unsigned length ;
decodePrefixedString ( this - > allocated_ , this - > value_ . string_ , & length , str ) ;
2015-07-13 01:55:18 +08:00
* cend = * str + length ;
2015-02-22 01:44:16 +08:00
return true ;
2014-07-01 06:48:54 +08:00
}
2016-03-07 01:19:46 +08:00
JSONCPP_STRING Value : : asString ( ) const {
2014-07-01 06:48:54 +08:00
switch ( type_ ) {
case nullValue :
return " " ;
case stringValue :
2015-02-22 01:44:16 +08:00
{
if ( value_ . string_ = = 0 ) return " " ;
unsigned this_len ;
char const * this_str ;
decodePrefixedString ( this - > allocated_ , this - > value_ . string_ , & this_len , & this_str ) ;
2016-03-07 01:19:46 +08:00
return JSONCPP_STRING ( this_str , this_len ) ;
2015-02-22 01:44:16 +08:00
}
2014-07-01 06:48:54 +08:00
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 " ) ;
}
}
# ifdef JSON_USE_CPPTL
CppTL : : ConstString Value : : asConstString ( ) const {
2015-02-22 01:44:16 +08:00
unsigned len ;
char const * str ;
decodePrefixedString ( allocated_ , value_ . string_ ,
& len , & str ) ;
return CppTL : : ConstString ( str , len ) ;
2014-07-01 06:48:54 +08:00
}
2010-12-28 01:45:23 +08:00
# endif
2014-07-01 06:48:54 +08:00
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_ , 0 , 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. " ) ;
2010-12-28 01:45:23 +08:00
}
2014-07-01 06:48:54 +08:00
# if defined(JSON_HAS_INT64)
2010-12-28 01:45:23 +08:00
2014-07-01 06:48:54 +08:00
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 :
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_ , 0 , 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 {
2010-12-28 01:45:23 +08:00
# if defined(JSON_NO_INT64)
2014-07-01 06:48:54 +08:00
return asInt ( ) ;
2010-12-28 01:45:23 +08:00
# else
2014-07-01 06:48:54 +08:00
return asInt64 ( ) ;
2010-12-28 01:45:23 +08:00
# endif
}
2014-07-01 06:48:54 +08:00
LargestUInt Value : : asLargestUInt ( ) const {
# if defined(JSON_NO_INT64)
return asUInt ( ) ;
# else
return asUInt64 ( ) ;
# endif
}
2010-12-28 01:45:23 +08:00
2014-07-01 06:48:54 +08:00
double Value : : asDouble ( ) const {
switch ( type_ ) {
case intValue :
return static_cast < double > ( value_ . int_ ) ;
case uintValue :
2010-04-19 15:37:41 +08:00
# if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2014-07-01 06:48:54 +08:00
return static_cast < double > ( value_ . uint_ ) ;
# else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
return integerToDouble ( value_ . uint_ ) ;
2010-04-19 15:37:41 +08:00
# endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2014-07-01 06:48:54 +08:00
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 :
2010-12-25 03:30:06 +08:00
# if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2014-07-01 06:48:54 +08:00
return static_cast < float > ( value_ . uint_ ) ;
# else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2016-02-08 01:09:41 +08:00
// This can fail (silently?) if the value is bigger than MAX_FLOAT.
return static_cast < float > ( integerToDouble ( value_ . uint_ ) ) ;
2010-12-25 03:30:06 +08:00
# endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2014-07-01 06:48:54 +08:00
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_ ? true : false ;
case uintValue :
return value_ . uint_ ? true : false ;
case realValue :
2015-07-13 01:55:18 +08:00
// This is kind of strange. Not recommended.
return ( value_ . real_ ! = 0.0 ) ? true : false ;
2014-07-01 06:48:54 +08:00
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_ = = false ) | |
( type_ = = stringValue & & asString ( ) = = " " ) | |
( type_ = = arrayValue & & value_ . map_ - > size ( ) = = 0 ) | |
( type_ = = objectValue & & value_ . map_ - > size ( ) = = 0 ) | |
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_ , 0 , 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 ;
2007-06-13 23:48:30 +08:00
}
/// Number of values in array or object
2014-07-01 06:48:54 +08:00
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;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
bool Value : : empty ( ) const {
if ( isNull ( ) | | isArray ( ) | | isObject ( ) )
return size ( ) = = 0u ;
else
return false ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
bool Value : : operator ! ( ) const { return isNull ( ) ; }
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
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 ;
}
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
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 )
( * this ) [ newSize - 1 ] ;
else {
for ( ArrayIndex index = newSize ; index < oldSize ; + + index ) {
value_ . map_ - > erase ( index ) ;
}
2016-03-01 16:43:28 +08:00
JSON_ASSERT ( size ( ) = = newSize ) ;
2014-07-01 06:48:54 +08:00
}
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
Value & Value : : operator [ ] ( ArrayIndex index ) {
2014-07-01 06:48:54 +08:00
JSON_ASSERT_MESSAGE (
type_ = = nullValue | | type_ = = arrayValue ,
" in Json::Value::operator[](ArrayIndex): requires arrayValue " ) ;
if ( type_ = = nullValue )
* this = Value ( arrayValue ) ;
CZString key ( index ) ;
ObjectValues : : iterator it = value_ . map_ - > lower_bound ( key ) ;
if ( it ! = value_ . map_ - > end ( ) & & ( * it ) . first = = key )
return ( * it ) . second ;
2016-06-27 07:47:43 +08:00
ObjectValues : : value_type defaultValue ( key , nullSingleton ( ) ) ;
2014-07-01 06:48:54 +08:00
it = value_ . map_ - > insert ( it , defaultValue ) ;
return ( * it ) . second ;
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
Value & Value : : operator [ ] ( int index ) {
2014-07-01 06:48:54 +08:00
JSON_ASSERT_MESSAGE (
index > = 0 ,
" in Json::Value::operator[](int index): index cannot be negative " ) ;
return ( * this ) [ ArrayIndex ( index ) ] ;
2010-12-24 20:47:14 +08:00
}
2014-09-15 08:15:29 +08:00
const Value & Value : : operator [ ] ( ArrayIndex index ) const {
2014-07-01 06:48:54 +08:00
JSON_ASSERT_MESSAGE (
type_ = = nullValue | | type_ = = arrayValue ,
" in Json::Value::operator[](ArrayIndex)const: requires arrayValue " ) ;
if ( type_ = = nullValue )
2016-06-27 07:47:43 +08:00
return nullSingleton ( ) ;
2014-07-01 06:48:54 +08:00
CZString key ( index ) ;
ObjectValues : : const_iterator it = value_ . map_ - > find ( key ) ;
if ( it = = value_ . map_ - > end ( ) )
2016-06-27 07:47:43 +08:00
return nullSingleton ( ) ;
2014-07-01 06:48:54 +08:00
return ( * it ) . second ;
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
const Value & Value : : operator [ ] ( int index ) const {
2014-07-01 06:48:54 +08:00
JSON_ASSERT_MESSAGE (
index > = 0 ,
" in Json::Value::operator[](int index) const: index cannot be negative " ) ;
return ( * this ) [ ArrayIndex ( index ) ] ;
2010-12-24 20:47:14 +08:00
}
2015-07-13 01:55:18 +08:00
void Value : : initBasic ( ValueType vtype , bool allocated ) {
type_ = vtype ;
2014-11-10 14:35:42 +08:00
allocated_ = allocated ;
comments_ = 0 ;
start_ = 0 ;
limit_ = 0 ;
}
2015-02-22 01:44:16 +08:00
// 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 ) {
2014-07-01 06:48:54 +08:00
JSON_ASSERT_MESSAGE (
type_ = = nullValue | | type_ = = objectValue ,
" in Json::Value::resolveReference(): requires objectValue " ) ;
if ( type_ = = nullValue )
* this = Value ( objectValue ) ;
CZString actualKey (
2015-03-05 23:15:08 +08:00
key , static_cast < unsigned > ( strlen ( key ) ) , CZString : : noDuplication ) ; // NOTE!
2015-02-22 01:44:16 +08:00
ObjectValues : : iterator it = value_ . map_ - > lower_bound ( actualKey ) ;
if ( it ! = value_ . map_ - > end ( ) & & ( * it ) . first = = actualKey )
return ( * it ) . second ;
2016-06-27 07:47:43 +08:00
ObjectValues : : value_type defaultValue ( actualKey , nullSingleton ( ) ) ;
2015-02-22 01:44:16 +08:00
it = value_ . map_ - > insert ( it , defaultValue ) ;
Value & value = ( * it ) . second ;
return value ;
}
// @param key is not null-terminated.
2015-07-13 01:55:18 +08:00
Value & Value : : resolveReference ( char const * key , char const * cend )
2015-02-22 01:44:16 +08:00
{
JSON_ASSERT_MESSAGE (
type_ = = nullValue | | type_ = = objectValue ,
" in Json::Value::resolveReference(key, end): requires objectValue " ) ;
if ( type_ = = nullValue )
* this = Value ( objectValue ) ;
CZString actualKey (
2015-07-13 01:55:18 +08:00
key , static_cast < unsigned > ( cend - key ) , CZString : : duplicateOnCopy ) ;
2014-07-01 06:48:54 +08:00
ObjectValues : : iterator it = value_ . map_ - > lower_bound ( actualKey ) ;
if ( it ! = value_ . map_ - > end ( ) & & ( * it ) . first = = actualKey )
return ( * it ) . second ;
2016-06-27 07:47:43 +08:00
ObjectValues : : value_type defaultValue ( actualKey , nullSingleton ( ) ) ;
2014-07-01 06:48:54 +08:00
it = value_ . map_ - > insert ( it , defaultValue ) ;
2014-09-15 08:15:29 +08:00
Value & value = ( * it ) . second ;
2014-07-01 06:48:54 +08:00
return value ;
2007-06-13 23:48:30 +08:00
}
2014-09-15 08:15:29 +08:00
Value Value : : get ( ArrayIndex index , const Value & defaultValue ) const {
const Value * value = & ( ( * this ) [ index ] ) ;
2016-06-27 07:47:43 +08:00
return value = = & nullSingleton ( ) ? defaultValue : * value ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
bool Value : : isValidIndex ( ArrayIndex index ) const { return index < size ( ) ; }
2007-06-13 23:48:30 +08:00
2015-07-13 01:55:18 +08:00
Value const * Value : : find ( char const * key , char const * cend ) const
2015-03-03 08:05:26 +08:00
{
2014-07-01 06:48:54 +08:00
JSON_ASSERT_MESSAGE (
type_ = = nullValue | | type_ = = objectValue ,
2015-03-03 08:05:26 +08:00
" in Json::Value::find(key, end, found): requires objectValue or nullValue " ) ;
if ( type_ = = nullValue ) return NULL ;
2015-07-13 01:55:18 +08:00
CZString actualKey ( key , static_cast < unsigned > ( cend - key ) , CZString : : noDuplication ) ;
2014-07-01 06:48:54 +08:00
ObjectValues : : const_iterator it = value_ . map_ - > find ( actualKey ) ;
2015-03-03 08:05:26 +08:00
if ( it = = value_ . map_ - > end ( ) ) return NULL ;
return & ( * it ) . second ;
2007-06-13 23:48:30 +08:00
}
2015-03-03 08:05:26 +08:00
const Value & Value : : operator [ ] ( const char * key ) const
{
Value const * found = find ( key , key + strlen ( key ) ) ;
2016-06-27 07:47:43 +08:00
if ( ! found ) return nullSingleton ( ) ;
2015-03-03 08:05:26 +08:00
return * found ;
2007-06-13 23:48:30 +08:00
}
2016-03-07 01:19:46 +08:00
Value const & Value : : operator [ ] ( JSONCPP_STRING const & key ) const
2015-03-03 08:05:26 +08:00
{
Value const * found = find ( key . data ( ) , key . data ( ) + key . length ( ) ) ;
2016-06-27 07:47:43 +08:00
if ( ! found ) return nullSingleton ( ) ;
2015-03-03 08:05:26 +08:00
return * found ;
}
2015-02-22 01:44:16 +08:00
Value & Value : : operator [ ] ( const char * key ) {
return resolveReference ( key , key + strlen ( key ) ) ;
}
2016-03-07 01:19:46 +08:00
Value & Value : : operator [ ] ( const JSONCPP_STRING & key ) {
2015-02-22 01:44:16 +08:00
return resolveReference ( key . data ( ) , key . data ( ) + key . length ( ) ) ;
}
Value & Value : : operator [ ] ( const StaticString & key ) {
return resolveReference ( key . c_str ( ) ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
# ifdef JSON_USE_CPPTL
2014-09-15 08:15:29 +08:00
Value & Value : : operator [ ] ( const CppTL : : ConstString & key ) {
2015-02-22 01:44:16 +08:00
return resolveReference ( key . c_str ( ) , key . end_c_str ( ) ) ;
2007-06-13 23:48:30 +08:00
}
2015-03-03 08:05:26 +08:00
Value const & Value : : operator [ ] ( CppTL : : ConstString const & key ) const
{
Value const * found = find ( key . c_str ( ) , key . end_c_str ( ) ) ;
2016-06-27 07:47:43 +08:00
if ( ! found ) return nullSingleton ( ) ;
2015-03-03 08:05:26 +08:00
return * found ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
# endif
2007-06-13 23:48:30 +08:00
2014-09-15 08:15:29 +08:00
Value & Value : : append ( const Value & value ) { return ( * this ) [ size ( ) ] = value ; }
2007-06-13 23:48:30 +08:00
2015-07-13 01:55:18 +08:00
Value Value : : get ( char const * key , char const * cend , Value const & defaultValue ) const
2015-03-03 08:05:26 +08:00
{
2015-07-13 01:55:18 +08:00
Value const * found = find ( key , cend ) ;
2015-03-06 06:38:43 +08:00
return ! found ? defaultValue : * found ;
2007-06-13 23:48:30 +08:00
}
2015-03-03 08:05:26 +08:00
Value Value : : get ( char const * key , Value const & defaultValue ) const
{
return get ( key , key + strlen ( key ) , defaultValue ) ;
}
2016-03-07 01:19:46 +08:00
Value Value : : get ( JSONCPP_STRING const & key , Value const & defaultValue ) const
2015-03-03 08:05:26 +08:00
{
2015-03-06 06:44:41 +08:00
return get ( key . data ( ) , key . data ( ) + key . length ( ) , defaultValue ) ;
2007-06-13 23:48:30 +08:00
}
2015-01-22 06:01:30 +08:00
2015-07-13 01:55:18 +08:00
bool Value : : removeMember ( const char * key , const char * cend , Value * removed )
2015-03-03 08:05:26 +08:00
{
2015-01-22 06:01:30 +08:00
if ( type_ ! = objectValue ) {
return false ;
}
2015-07-13 01:55:18 +08:00
CZString actualKey ( key , static_cast < unsigned > ( cend - key ) , CZString : : noDuplication ) ;
2014-07-01 06:48:54 +08:00
ObjectValues : : iterator it = value_ . map_ - > find ( actualKey ) ;
if ( it = = value_ . map_ - > end ( ) )
2015-01-22 06:01:30 +08:00
return false ;
* removed = it - > second ;
2014-07-01 06:48:54 +08:00
value_ . map_ - > erase ( it ) ;
2015-01-22 06:01:30 +08:00
return true ;
2007-06-13 23:48:30 +08:00
}
2015-03-03 08:05:26 +08:00
bool Value : : removeMember ( const char * key , Value * removed )
{
return removeMember ( key , key + strlen ( key ) , removed ) ;
}
2016-03-07 01:19:46 +08:00
bool Value : : removeMember ( JSONCPP_STRING const & key , Value * removed )
2015-03-03 08:05:26 +08:00
{
return removeMember ( key . data ( ) , key . data ( ) + key . length ( ) , removed ) ;
}
Value Value : : removeMember ( const char * key )
{
2015-01-22 06:01:30 +08:00
JSON_ASSERT_MESSAGE ( type_ = = nullValue | | type_ = = objectValue ,
" in Json::Value::removeMember(): requires objectValue " ) ;
if ( type_ = = nullValue )
2016-06-27 07:47:43 +08:00
return nullSingleton ( ) ;
2015-01-22 06:01:30 +08:00
Value removed ; // null
2015-03-03 08:05:26 +08:00
removeMember ( key , key + strlen ( key ) , & removed ) ;
2015-01-22 06:01:30 +08:00
return removed ; // still null if removeMember() did nothing
}
2016-03-07 01:19:46 +08:00
Value Value : : removeMember ( const JSONCPP_STRING & key )
2015-03-03 08:05:26 +08:00
{
2014-07-01 06:48:54 +08:00
return removeMember ( key . c_str ( ) ) ;
2007-06-13 23:48:30 +08:00
}
2015-01-21 06:24:11 +08:00
bool Value : : removeIndex ( ArrayIndex index , Value * removed ) {
2015-01-22 05:43:48 +08:00
if ( type_ ! = arrayValue ) {
2015-01-21 06:24:11 +08:00
return false ;
}
CZString key ( index ) ;
2015-01-22 05:43:48 +08:00
ObjectValues : : iterator it = value_ . map_ - > find ( key ) ;
if ( it = = value_ . map_ - > end ( ) ) {
2015-01-21 06:24:11 +08:00
return false ;
}
* removed = it - > second ;
2015-01-22 05:43:48 +08:00
ArrayIndex oldSize = size ( ) ;
2015-01-21 06:24:11 +08:00
// shift left all items left, into the place of the "removed"
2015-01-22 06:04:46 +08:00
for ( ArrayIndex i = index ; i < ( oldSize - 1 ) ; + + i ) {
2015-07-13 01:58:54 +08:00
CZString keey ( i ) ;
( * value_ . map_ ) [ keey ] = ( * this ) [ i + 1 ] ;
2015-01-21 06:24:11 +08:00
}
// erase the last one ("leftover")
2015-01-22 06:04:46 +08:00
CZString keyLast ( oldSize - 1 ) ;
2015-01-22 05:43:48 +08:00
ObjectValues : : iterator itLast = value_ . map_ - > find ( keyLast ) ;
value_ . map_ - > erase ( itLast ) ;
2015-01-21 06:15:40 +08:00
return true ;
}
2014-07-01 06:48:54 +08:00
# ifdef JSON_USE_CPPTL
2014-09-15 08:15:29 +08:00
Value Value : : get ( const CppTL : : ConstString & key ,
const Value & defaultValue ) const {
2015-03-06 06:38:43 +08:00
return get ( key . c_str ( ) , key . end_c_str ( ) , defaultValue ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
# endif
2007-06-13 23:48:30 +08:00
2015-07-13 01:55:18 +08:00
bool Value : : isMember ( char const * key , char const * cend ) const
2015-03-03 08:05:26 +08:00
{
2015-07-13 01:55:18 +08:00
Value const * value = find ( key , cend ) ;
2015-03-03 08:05:26 +08:00
return NULL ! = value ;
2007-06-13 23:48:30 +08:00
}
2015-02-22 01:44:16 +08:00
bool Value : : isMember ( char const * key ) const
2015-03-03 08:05:26 +08:00
{
return isMember ( key , key + strlen ( key ) ) ;
}
2016-03-07 01:19:46 +08:00
bool Value : : isMember ( JSONCPP_STRING const & key ) const
2015-03-03 08:05:26 +08:00
{
return isMember ( key . data ( ) , key . data ( ) + key . length ( ) ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
# ifdef JSON_USE_CPPTL
2014-09-15 08:15:29 +08:00
bool Value : : isMember ( const CppTL : : ConstString & key ) const {
2015-02-22 01:44:16 +08:00
return isMember ( key . c_str ( ) , key . end_c_str ( ) ) ;
2007-06-13 23:48:30 +08:00
}
# endif
2014-07-01 06:48:54 +08:00
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 ( ) ;
2015-02-22 01:44:16 +08:00
for ( ; it ! = itEnd ; + + it ) {
2016-03-07 01:19:46 +08:00
members . push_back ( JSONCPP_STRING ( ( * it ) . first . data ( ) ,
2015-02-22 01:44:16 +08:00
( * it ) . first . length ( ) ) ) ;
}
2014-07-01 06:48:54 +08:00
return members ;
2007-06-13 23:48:30 +08:00
}
//
//# ifdef JSON_USE_CPPTL
2014-07-01 06:48:54 +08:00
// EnumMemberNames
// Value::enumMemberNames() const
2007-06-13 23:48:30 +08:00
//{
// if ( type_ == objectValue )
// {
// return CppTL::Enum::any( CppTL::Enum::transform(
// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
// MemberNamesTransform() ) );
// }
// return EnumMemberNames();
//}
//
//
2014-07-01 06:48:54 +08:00
// EnumValues
// Value::enumValues() const
2007-06-13 23:48:30 +08:00
//{
// if ( type_ == objectValue || type_ == arrayValue )
2014-07-01 06:48:54 +08:00
// return CppTL::Enum::anyValues( *(value_.map_),
2007-06-13 23:48:30 +08:00
// CppTL::Type<const Value &>() );
// return EnumValues();
//}
//
//# endif
2011-05-25 12:19:17 +08:00
static bool IsIntegral ( double d ) {
double integral_part ;
return modf ( d , & integral_part ) = = 0.0 ;
}
2014-07-01 06:48:54 +08:00
bool Value : : isNull ( ) const { return type_ = = nullValue ; }
bool Value : : isBool ( ) const { return type_ = = booleanValue ; }
bool Value : : isInt ( ) const {
switch ( type_ ) {
case intValue :
return value_ . int_ > = minInt & & value_ . int_ < = maxInt ;
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 :
return value_ . int_ > = 0 & & LargestUInt ( value_ . int_ ) < = LargestUInt ( maxUInt ) ;
case uintValue :
return value_ . uint_ < = maxUInt ;
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.
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 {
2011-05-25 12:19:17 +08:00
# if defined(JSON_HAS_INT64)
return isInt64 ( ) | | isUInt64 ( ) ;
# else
return isInt ( ) | | isUInt ( ) ;
# endif
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
bool Value : : isDouble ( ) const { return type_ = = realValue | | isIntegral ( ) ; }
2007-06-13 23:48:30 +08:00
2016-11-20 08:28:15 +08:00
bool Value : : isNumeric ( ) const { return isDouble ( ) ; }
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
bool Value : : isString ( ) const { return type_ = = stringValue ; }
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
bool Value : : isArray ( ) const { return type_ = = arrayValue ; }
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
bool Value : : isObject ( ) const { return type_ = = objectValue ; }
2007-06-13 23:48:30 +08:00
2015-01-26 04:16:13 +08:00
void Value : : setComment ( const char * comment , size_t len , CommentPlacement placement ) {
2014-07-01 06:48:54 +08:00
if ( ! comments_ )
comments_ = new CommentInfo [ numberOfCommentPlacement ] ;
2015-01-26 04:16:13 +08:00
if ( ( len > 0 ) & & ( comment [ len - 1 ] = = ' \n ' ) ) {
// Always discard trailing newline, to aid indentation.
len - = 1 ;
}
comments_ [ placement ] . setComment ( comment , len ) ;
}
void Value : : setComment ( const char * comment , CommentPlacement placement ) {
setComment ( comment , strlen ( comment ) , placement ) ;
2007-06-13 23:48:30 +08:00
}
2016-03-07 01:19:46 +08:00
void Value : : setComment ( const JSONCPP_STRING & comment , CommentPlacement placement ) {
2015-01-26 04:16:13 +08:00
setComment ( comment . c_str ( ) , comment . length ( ) , placement ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
bool Value : : hasComment ( CommentPlacement placement ) const {
return comments_ ! = 0 & & comments_ [ placement ] . comment_ ! = 0 ;
2007-06-13 23:48:30 +08:00
}
2016-03-07 01:19:46 +08:00
JSONCPP_STRING Value : : getComment ( CommentPlacement placement ) const {
2014-07-01 06:48:54 +08:00
if ( hasComment ( placement ) )
return comments_ [ placement ] . comment_ ;
return " " ;
2007-06-13 23:48:30 +08:00
}
2016-02-06 23:25:20 +08:00
void Value : : setOffsetStart ( ptrdiff_t start ) { start_ = start ; }
2007-06-13 23:48:30 +08:00
2016-02-06 23:25:20 +08:00
void Value : : setOffsetLimit ( ptrdiff_t limit ) { limit_ = limit ; }
2014-04-24 07:41:12 +08:00
2016-02-06 23:25:20 +08:00
ptrdiff_t Value : : getOffsetStart ( ) const { return start_ ; }
2014-04-24 07:41:12 +08:00
2016-02-06 23:25:20 +08:00
ptrdiff_t Value : : getOffsetLimit ( ) const { return limit_ ; }
2014-04-24 07:41:12 +08:00
2016-03-07 01:19:46 +08:00
JSONCPP_STRING Value : : toStyledString ( ) const {
2014-07-01 06:48:54 +08:00
StyledWriter writer ;
return writer . write ( * this ) ;
2014-04-24 07:41:12 +08:00
}
2014-07-01 06:48:54 +08:00
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 const_iterator ( ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
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 const_iterator ( ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
Value : : iterator Value : : begin ( ) {
switch ( type_ ) {
case arrayValue :
case objectValue :
if ( value_ . map_ )
return iterator ( value_ . map_ - > begin ( ) ) ;
break ;
default :
break ;
}
return iterator ( ) ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
Value : : iterator Value : : end ( ) {
switch ( type_ ) {
case arrayValue :
case objectValue :
if ( value_ . map_ )
return iterator ( value_ . map_ - > end ( ) ) ;
break ;
default :
break ;
}
return iterator ( ) ;
2007-06-13 23:48:30 +08:00
}
// class PathArgument
// //////////////////////////////////////////////////////////////////
2014-07-01 06:48:54 +08:00
PathArgument : : PathArgument ( ) : key_ ( ) , index_ ( ) , kind_ ( kindNone ) { }
2007-06-13 23:48:30 +08:00
2014-07-01 06:48:54 +08:00
PathArgument : : PathArgument ( ArrayIndex index )
: key_ ( ) , index_ ( index ) , kind_ ( kindIndex ) { }
2007-06-13 23:48:30 +08:00
2014-09-15 08:15:29 +08:00
PathArgument : : PathArgument ( const char * key )
2014-07-01 06:48:54 +08:00
: key_ ( key ) , index_ ( ) , kind_ ( kindKey ) { }
2007-06-13 23:48:30 +08:00
2016-03-07 01:19:46 +08:00
PathArgument : : PathArgument ( const JSONCPP_STRING & key )
2014-07-01 06:48:54 +08:00
: key_ ( key . c_str ( ) ) , index_ ( ) , kind_ ( kindKey ) { }
2007-06-13 23:48:30 +08:00
// class Path
// //////////////////////////////////////////////////////////////////
2016-03-07 01:19:46 +08:00
Path : : Path ( const JSONCPP_STRING & path ,
2014-09-15 08:15:29 +08:00
const PathArgument & a1 ,
const PathArgument & a2 ,
const PathArgument & a3 ,
const PathArgument & a4 ,
const PathArgument & a5 ) {
2014-07-01 06:48:54 +08:00
InArgs in ;
in . push_back ( & a1 ) ;
in . push_back ( & a2 ) ;
in . push_back ( & a3 ) ;
in . push_back ( & a4 ) ;
in . push_back ( & a5 ) ;
makePath ( path , in ) ;
}
2016-03-07 01:19:46 +08:00
void Path : : makePath ( const JSONCPP_STRING & path , const InArgs & in ) {
2014-09-15 08:15:29 +08:00
const char * current = path . c_str ( ) ;
const char * end = current + path . length ( ) ;
2014-07-01 06:48:54 +08:00
InArgs : : const_iterator 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 ) ;
2007-06-13 23:48:30 +08:00
}
2016-09-07 19:56:19 +08:00
if ( current = = end | | * + + current ! = ' ] ' )
2014-07-01 06:48:54 +08:00
invalidPath ( path , int ( current - path . c_str ( ) ) ) ;
} else if ( * current = = ' % ' ) {
addPathInArg ( path , in , itInArg , PathArgument : : kindKey ) ;
+ + current ;
2016-09-07 19:56:19 +08:00
} else if ( * current = = ' . ' | | * current = = ' ] ' ) {
2014-07-01 06:48:54 +08:00
+ + current ;
} else {
2014-09-15 08:15:29 +08:00
const char * beginName = current ;
2014-07-01 06:48:54 +08:00
while ( current ! = end & & ! strchr ( " [. " , * current ) )
+ + current ;
2016-03-07 01:19:46 +08:00
args_ . push_back ( JSONCPP_STRING ( beginName , current ) ) ;
2014-07-01 06:48:54 +08:00
}
}
}
2016-03-07 01:19:46 +08:00
void Path : : addPathInArg ( const JSONCPP_STRING & /*path*/ ,
2014-09-15 08:15:29 +08:00
const InArgs & in ,
InArgs : : const_iterator & itInArg ,
2014-07-01 06:48:54 +08:00
PathArgument : : Kind kind ) {
if ( itInArg = = in . end ( ) ) {
// Error: missing argument %d
} else if ( ( * itInArg ) - > kind_ ! = kind ) {
// Error: bad argument type
} else {
2016-09-07 19:56:19 +08:00
args_ . push_back ( * * itInArg + + ) ;
2014-07-01 06:48:54 +08:00
}
}
2016-03-07 01:19:46 +08:00
void Path : : invalidPath ( const JSONCPP_STRING & /*path*/ , int /*location*/ ) {
2014-07-01 06:48:54 +08:00
// Error: invalid path.
}
2014-09-15 08:15:29 +08:00
const Value & Path : : resolve ( const Value & root ) const {
const Value * node = & root ;
2014-07-01 06:48:54 +08:00
for ( Args : : const_iterator it = args_ . begin ( ) ; it ! = args_ . end ( ) ; + + it ) {
2014-09-15 08:15:29 +08:00
const PathArgument & arg = * it ;
2014-07-01 06:48:54 +08:00
if ( arg . kind_ = = PathArgument : : kindIndex ) {
if ( ! node - > isArray ( ) | | ! node - > isValidIndex ( arg . index_ ) ) {
// Error: unable to resolve path (array value expected at position...
2016-09-07 19:56:19 +08:00
return Value : : null ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
node = & ( ( * node ) [ arg . index_ ] ) ;
} else if ( arg . kind_ = = PathArgument : : kindKey ) {
if ( ! node - > isObject ( ) ) {
// Error: unable to resolve path (object value expected at position...)
2016-09-07 19:56:19 +08:00
return Value : : null ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
node = & ( ( * node ) [ arg . key_ ] ) ;
2016-06-27 07:47:43 +08:00
if ( node = = & Value : : nullSingleton ( ) ) {
2014-07-01 06:48:54 +08:00
// Error: unable to resolve path (object has no member named '' at
// position...)
2016-09-07 19:56:19 +08:00
return Value : : null ;
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
}
}
return * node ;
}
2014-09-15 08:15:29 +08:00
Value Path : : resolve ( const Value & root , const Value & defaultValue ) const {
const Value * node = & root ;
2014-07-01 06:48:54 +08:00
for ( Args : : const_iterator it = args_ . begin ( ) ; it ! = args_ . end ( ) ; + + it ) {
2014-09-15 08:15:29 +08:00
const PathArgument & arg = * it ;
2014-07-01 06:48:54 +08:00
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_ ] ) ;
2016-06-27 07:47:43 +08:00
if ( node = = & Value : : nullSingleton ( ) )
2014-07-01 06:48:54 +08:00
return defaultValue ;
}
}
return * node ;
}
2014-09-15 08:15:29 +08:00
Value & Path : : make ( Value & root ) const {
Value * node = & root ;
2014-07-01 06:48:54 +08:00
for ( Args : : const_iterator it = args_ . begin ( ) ; it ! = args_ . end ( ) ; + + it ) {
2014-09-15 08:15:29 +08:00
const PathArgument & arg = * it ;
2014-07-01 06:48:54 +08:00
if ( arg . kind_ = = PathArgument : : kindIndex ) {
if ( ! node - > isArray ( ) ) {
// Error: node is not an array at position ...
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
node = & ( ( * node ) [ arg . index_ ] ) ;
} else if ( arg . kind_ = = PathArgument : : kindKey ) {
if ( ! node - > isObject ( ) ) {
// Error: node is not an object at position...
2007-06-13 23:48:30 +08:00
}
2014-07-01 06:48:54 +08:00
node = & ( ( * node ) [ arg . key_ ] ) ;
}
}
return * node ;
2007-06-13 23:48:30 +08:00
}
} // namespace Json