aboutsummaryrefslogtreecommitdiff
path: root/lib/jsoncpp/src/lib_json/json_value.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/jsoncpp/src/lib_json/json_value.cpp')
-rw-r--r--lib/jsoncpp/src/lib_json/json_value.cpp373
1 files changed, 255 insertions, 118 deletions
diff --git a/lib/jsoncpp/src/lib_json/json_value.cpp b/lib/jsoncpp/src/lib_json/json_value.cpp
index bee3f70f64..218c127553 100644
--- a/lib/jsoncpp/src/lib_json/json_value.cpp
+++ b/lib/jsoncpp/src/lib_json/json_value.cpp
@@ -1,3 +1,8 @@
+// Copyright 2007-2010 Baptiste Lepilleur
+// 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
+
#include <iostream>
#include <json/value.h>
#include <json/writer.h>
@@ -20,95 +25,50 @@
namespace Json {
const Value Value::null;
-const Value::Int Value::minInt = Value::Int( ~(Value::UInt(-1)/2) );
-const Value::Int Value::maxInt = Value::Int( Value::UInt(-1)/2 );
-const Value::UInt Value::maxUInt = Value::UInt(-1);
-
-// A "safe" implementation of strdup. Allow null pointer to be passed.
-// Also avoid warning on msvc80.
-//
-//inline char *safeStringDup( const char *czstring )
-//{
-// if ( czstring )
-// {
-// const size_t length = (unsigned int)( strlen(czstring) + 1 );
-// char *newString = static_cast<char *>( malloc( length ) );
-// memcpy( newString, czstring, length );
-// return newString;
-// }
-// return 0;
-//}
-//
-//inline char *safeStringDup( const std::string &str )
-//{
-// if ( !str.empty() )
-// {
-// const size_t length = str.length();
-// char *newString = static_cast<char *>( malloc( length + 1 ) );
-// memcpy( newString, str.c_str(), length );
-// newString[length] = 0;
-// return newString;
-// }
-// return 0;
-//}
-
-ValueAllocator::~ValueAllocator()
+const Int Value::minInt = Int( ~(UInt(-1)/2) );
+const Int Value::maxInt = Int( UInt(-1)/2 );
+const UInt Value::maxUInt = UInt(-1);
+const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
+const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
+const UInt64 Value::maxUInt64 = UInt64(-1);
+const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
+const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
+const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+
+
+/// Unknown size marker
+enum { unknown = (unsigned)-1 };
+
+
+/** 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.
+ */
+static inline char *
+duplicateStringValue( const char *value,
+ unsigned int length = unknown )
{
+ if ( length == unknown )
+ length = (unsigned int)strlen(value);
+ char *newString = static_cast<char *>( malloc( length + 1 ) );
+ memcpy( newString, value, length );
+ newString[length] = 0;
+ return newString;
}
-class DefaultValueAllocator : public ValueAllocator
-{
-public:
- virtual ~DefaultValueAllocator()
- {
- }
-
- virtual char *makeMemberName( const char *memberName )
- {
- return duplicateStringValue( memberName );
- }
-
- virtual void releaseMemberName( char *memberName )
- {
- releaseStringValue( memberName );
- }
-
- virtual char *duplicateStringValue( const char *value,
- unsigned int length = unknown )
- {
- //@todo invesgate this old optimization
- //if ( !value || value[0] == 0 )
- // return 0;
-
- if ( length == unknown )
- length = (unsigned int)strlen(value);
- char *newString = static_cast<char *>( malloc( length + 1 ) );
- memcpy( newString, value, length );
- newString[length] = 0;
- return newString;
- }
- virtual void releaseStringValue( char *value )
- {
- if ( value )
- free( value );
- }
-};
-
-static ValueAllocator *&valueAllocator()
+/** Free the string duplicated by duplicateStringValue().
+ */
+static inline void
+releaseStringValue( char *value )
{
- static DefaultValueAllocator defaultAllocator;
- static ValueAllocator *valueAllocator = &defaultAllocator;
- return valueAllocator;
+ if ( value )
+ free( value );
}
-static struct DummyValueAllocatorInitializer {
- DummyValueAllocatorInitializer()
- {
- valueAllocator(); // ensure valueAllocator() statics are initialized before main().
- }
-} dummyValueAllocatorInitializer;
-
// //////////////////////////////////////////////////////////////////
@@ -143,7 +103,7 @@ Value::CommentInfo::CommentInfo()
Value::CommentInfo::~CommentInfo()
{
if ( comment_ )
- valueAllocator()->releaseStringValue( comment_ );
+ releaseStringValue( comment_ );
}
@@ -151,11 +111,11 @@ void
Value::CommentInfo::setComment( const char *text )
{
if ( comment_ )
- valueAllocator()->releaseStringValue( comment_ );
+ releaseStringValue( comment_ );
JSON_ASSERT( text );
JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
// It seems that /**/ style comments are acceptable as well.
- comment_ = valueAllocator()->duplicateStringValue( text );
+ comment_ = duplicateStringValue( text );
}
@@ -171,14 +131,14 @@ Value::CommentInfo::setComment( const char *text )
// Notes: index_ indicates if the string was allocated when
// a string is stored.
-Value::CZString::CZString( int index )
+Value::CZString::CZString( ArrayIndex index )
: cstr_( 0 )
, index_( index )
{
}
Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
- : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
+ : cstr_( allocate == duplicate ? duplicateStringValue(cstr)
: cstr )
, index_( allocate )
{
@@ -186,7 +146,7 @@ Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
Value::CZString::CZString( const CZString &other )
: cstr_( other.index_ != noDuplication && other.cstr_ != 0
- ? valueAllocator()->makeMemberName( other.cstr_ )
+ ? duplicateStringValue( other.cstr_ )
: other.cstr_ )
, index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
: other.index_ )
@@ -196,7 +156,7 @@ Value::CZString::CZString( const CZString &other )
Value::CZString::~CZString()
{
if ( cstr_ && index_ == duplicate )
- valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
+ releaseStringValue( const_cast<char *>( cstr_ ) );
}
void
@@ -231,7 +191,7 @@ Value::CZString::operator==( const CZString &other ) const
}
-int
+ArrayIndex
Value::CZString::index() const
{
return index_;
@@ -309,6 +269,17 @@ Value::Value( ValueType type )
}
+#if defined(JSON_HAS_INT64)
+Value::Value( UInt value )
+ : type_( uintValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.uint_ = value;
+}
+
Value::Value( Int value )
: type_( intValue )
, comments_( 0 )
@@ -319,8 +290,21 @@ Value::Value( Int value )
value_.int_ = value;
}
+#endif // if defined(JSON_HAS_INT64)
-Value::Value( UInt value )
+
+Value::Value( Int64 value )
+ : type_( intValue )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.int_ = value;
+}
+
+
+Value::Value( UInt64 value )
: type_( uintValue )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
@@ -348,9 +332,24 @@ Value::Value( const char *value )
, itemIsUsed_( 0 )
#endif
{
- value_.string_ = valueAllocator()->duplicateStringValue( value );
+ value_.string_ = duplicateStringValue( value );
+}
+
+
+Value::Value( const char *beginValue,
+ const char *endValue )
+ : type_( stringValue )
+ , allocated_( true )
+ , comments_( 0 )
+# ifdef JSON_VALUE_USE_INTERNAL_MAP
+ , itemIsUsed_( 0 )
+#endif
+{
+ value_.string_ = duplicateStringValue( beginValue,
+ (unsigned int)(endValue - beginValue) );
}
+
Value::Value( const std::string &value )
: type_( stringValue )
, allocated_( true )
@@ -359,8 +358,8 @@ Value::Value( const std::string &value )
, itemIsUsed_( 0 )
#endif
{
- value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
- (unsigned int)value.length() );
+ value_.string_ = duplicateStringValue( value.c_str(),
+ (unsigned int)value.length() );
}
@@ -385,7 +384,7 @@ Value::Value( const CppTL::ConstString &value )
, itemIsUsed_( 0 )
#endif
{
- value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
+ value_.string_ = duplicateStringValue( value, value.length() );
}
# endif
@@ -419,7 +418,7 @@ Value::Value( const Value &other )
case stringValue:
if ( other.value_.string_ )
{
- value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
+ value_.string_ = duplicateStringValue( other.value_.string_ );
allocated_ = true;
}
else
@@ -466,7 +465,7 @@ Value::~Value()
break;
case stringValue:
if ( allocated_ )
- valueAllocator()->releaseStringValue( value_.string_ );
+ releaseStringValue( value_.string_ );
break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
case arrayValue:
@@ -697,6 +696,7 @@ Value::asConstString() const
}
# endif
+
Value::Int
Value::asInt() const
{
@@ -705,10 +705,11 @@ Value::asInt() const
case nullValue:
return 0;
case intValue:
- return value_.int_;
+ JSON_ASSERT_MESSAGE( value_.int_ >= minInt && value_.int_ <= maxInt, "unsigned integer out of signed int range" );
+ return Int(value_.int_);
case uintValue:
- JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
- return value_.uint_;
+ JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" );
+ return Int(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
return Int( value_.real_ );
@@ -724,6 +725,7 @@ Value::asInt() const
return 0; // unreachable;
}
+
Value::UInt
Value::asUInt() const
{
@@ -733,9 +735,11 @@ Value::asUInt() const
return 0;
case intValue:
JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
- return value_.int_;
+ JSON_ASSERT_MESSAGE( value_.int_ <= maxUInt, "signed integer out of UInt range" );
+ return UInt(value_.int_);
case uintValue:
- return value_.uint_;
+ JSON_ASSERT_MESSAGE( value_.uint_ <= maxUInt, "unsigned integer out of UInt range" );
+ return UInt(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" );
return UInt( value_.real_ );
@@ -751,6 +755,88 @@ Value::asUInt() const
return 0; // unreachable;
}
+
+# if defined(JSON_HAS_INT64)
+
+Value::Int64
+Value::asInt64() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0;
+ case intValue:
+ return value_.int_;
+ case uintValue:
+ JSON_ASSERT_MESSAGE( value_.uint_ <= UInt64(maxInt64), "unsigned integer out of Int64 range" );
+ return value_.uint_;
+ case realValue:
+ JSON_ASSERT_MESSAGE( value_.real_ >= minInt64 && value_.real_ <= maxInt64, "Real out of Int64 range" );
+ return Int( value_.real_ );
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to Int64" );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+
+
+Value::UInt64
+Value::asUInt64() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0;
+ case intValue:
+ JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to UInt64" );
+ return value_.int_;
+ case uintValue:
+ return value_.uint_;
+ case realValue:
+ JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt64, "Real out of UInt64 range" );
+ return UInt( value_.real_ );
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to UInt64" );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0; // unreachable;
+}
+# 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
{
@@ -759,9 +845,13 @@ Value::asDouble() const
case nullValue:
return 0.0;
case intValue:
- return value_.int_;
+ return static_cast<double>( value_.int_ );
case uintValue:
- return value_.uint_;
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return static_cast<double>( value_.uint_ );
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return static_cast<double>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
case realValue:
return value_.real_;
case booleanValue:
@@ -776,6 +866,35 @@ Value::asDouble() const
return 0; // unreachable;
}
+float
+Value::asFloat() const
+{
+ switch ( type_ )
+ {
+ case nullValue:
+ return 0.0f;
+ 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)
+ return static_cast<float>( Int(value_.uint_/2) ) * 2 + Int(value_.uint_ & 1);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ case realValue:
+ return static_cast<float>( value_.real_ );
+ case booleanValue:
+ return value_.bool_ ? 1.0f : 0.0f;
+ case stringValue:
+ case arrayValue:
+ case objectValue:
+ JSON_ASSERT_MESSAGE( false, "Type is not convertible to float" );
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return 0.0f; // unreachable;
+}
+
bool
Value::asBool() const
{
@@ -854,7 +973,7 @@ Value::isConvertibleTo( ValueType other ) const
/// Number of values in array or object
-Value::UInt
+ArrayIndex
Value::size() const
{
switch ( type_ )
@@ -876,7 +995,7 @@ Value::size() const
}
return 0;
case objectValue:
- return Int( value_.map_->size() );
+ return ArrayIndex( value_.map_->size() );
#else
case arrayValue:
return Int( value_.array_->size() );
@@ -933,21 +1052,23 @@ Value::clear()
}
void
-Value::resize( UInt newSize )
+Value::resize( ArrayIndex newSize )
{
JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
if ( type_ == nullValue )
*this = Value( arrayValue );
#ifndef JSON_VALUE_USE_INTERNAL_MAP
- UInt oldSize = size();
+ ArrayIndex oldSize = size();
if ( newSize == 0 )
clear();
else if ( newSize > oldSize )
(*this)[ newSize - 1 ];
else
{
- for ( UInt index = newSize; index < oldSize; ++index )
+ for ( ArrayIndex index = newSize; index < oldSize; ++index )
+ {
value_.map_->erase( index );
+ }
assert( size() == newSize );
}
#else
@@ -957,7 +1078,7 @@ Value::resize( UInt newSize )
Value &
-Value::operator[]( UInt index )
+Value::operator[]( ArrayIndex index )
{
JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
if ( type_ == nullValue )
@@ -977,8 +1098,16 @@ Value::operator[]( UInt index )
}
+Value &
+Value::operator[]( int index )
+{
+ JSON_ASSERT( index >= 0 );
+ return (*this)[ ArrayIndex(index) ];
+}
+
+
const Value &
-Value::operator[]( UInt index ) const
+Value::operator[]( ArrayIndex index ) const
{
JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
if ( type_ == nullValue )
@@ -996,6 +1125,14 @@ Value::operator[]( UInt index ) const
}
+const Value &
+Value::operator[]( int index ) const
+{
+ JSON_ASSERT( index >= 0 );
+ return (*this)[ ArrayIndex(index) ];
+}
+
+
Value &
Value::operator[]( const char *key )
{
@@ -1028,7 +1165,7 @@ Value::resolveReference( const char *key,
Value
-Value::get( UInt index,
+Value::get( ArrayIndex index,
const Value &defaultValue ) const
{
const Value *value = &((*this)[index]);
@@ -1037,7 +1174,7 @@ Value::get( UInt index,
bool
-Value::isValidIndex( UInt index ) const
+Value::isValidIndex( ArrayIndex index ) const
{
return index < size();
}
@@ -1047,8 +1184,8 @@ Value::isValidIndex( UInt index ) const
const Value &
Value::operator[]( const char *key ) const
{
- JSON_ASSERT( type_ == nullValue || type_ == objectValue || type_ == arrayValue );
- if ( type_ == nullValue || type_ == arrayValue)
+ JSON_ASSERT( type_ == nullValue || type_ == objectValue );
+ if ( type_ == nullValue )
return null;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
CZString actualKey( key, CZString::noDuplication );
@@ -1500,7 +1637,7 @@ PathArgument::PathArgument()
}
-PathArgument::PathArgument( Value::UInt index )
+PathArgument::PathArgument( ArrayIndex index )
: index_( index )
, kind_( kindIndex )
{
@@ -1556,9 +1693,9 @@ Path::makePath( const std::string &path,
addPathInArg( path, in, itInArg, PathArgument::kindIndex );
else
{
- Value::UInt index = 0;
+ ArrayIndex index = 0;
for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
- index = index * 10 + Value::UInt(*current - '0');
+ index = index * 10 + ArrayIndex(*current - '0');
args_.push_back( index );
}
if ( current == end || *current++ != ']' )