📄 json_value.cpp.svn-base
字号:
#include <iostream>
#include <json/value.h>
#include <json/writer.h>
#include <utility>
#include <stdexcept>
#include "assert.h"
#ifdef JSON_USE_CPPTL
# include <cpptl/conststring.h>
#endif
#include <stddef.h> // size_t
#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
# include "json_batchallocator.h"
#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
#define JSON_ASSERT_UNREACHABLE assert( false )
#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
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()
{
}
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()
{
static DefaultValueAllocator defaultAllocator;
static ValueAllocator *valueAllocator = &defaultAllocator;
return valueAllocator;
}
static struct DummyValueAllocatorInitializer {
DummyValueAllocatorInitializer()
{
valueAllocator(); // ensure valueAllocator() statics are initialized before main().
}
} dummyValueAllocatorInitializer;
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// ValueInternals...
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
#ifdef JSON_VALUE_USE_INTERNAL_MAP
# include "json_internalarray.inl"
# include "json_internalmap.inl"
#endif // JSON_VALUE_USE_INTERNAL_MAP
# include "json_valueiterator.inl"
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::CommentInfo
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
Value::CommentInfo::CommentInfo()
: comment_( 0 )
{
}
Value::CommentInfo::~CommentInfo()
{
if ( comment_ )
valueAllocator()->releaseStringValue( comment_ );
}
void
Value::CommentInfo::setComment( const char *text )
{
if ( comment_ )
valueAllocator()->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 );
}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::CZString
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
# ifndef JSON_VALUE_USE_INTERNAL_MAP
// Notes: index_ indicates if the string was allocated when
// a string is stored.
Value::CZString::CZString( int index )
: cstr_( 0 )
, index_( index )
{
}
Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
: cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
: cstr )
, index_( allocate )
{
}
Value::CZString::CZString( const CZString &other )
: cstr_( other.index_ != noDuplication && other.cstr_ != 0
? valueAllocator()->makeMemberName( other.cstr_ )
: other.cstr_ )
, index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
: other.index_ )
{
}
Value::CZString::~CZString()
{
if ( cstr_ && index_ == duplicate )
valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
}
void
Value::CZString::swap( CZString &other )
{
std::swap( cstr_, other.cstr_ );
std::swap( index_, other.index_ );
}
Value::CZString &
Value::CZString::operator =( const CZString &other )
{
CZString temp( other );
swap( temp );
return *this;
}
bool
Value::CZString::operator<( const CZString &other ) const
{
if ( cstr_ )
return strcmp( cstr_, other.cstr_ ) < 0;
return index_ < other.index_;
}
bool
Value::CZString::operator==( const CZString &other ) const
{
if ( cstr_ )
return strcmp( cstr_, other.cstr_ ) == 0;
return index_ == other.index_;
}
int
Value::CZString::index() const
{
return index_;
}
const char *
Value::CZString::c_str() const
{
return cstr_;
}
bool
Value::CZString::isStaticString() const
{
return index_ == noDuplication;
}
#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class Value::Value
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
/*! \internal Default constructor initialization must be equivalent to:
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
Value::Value( ValueType type )
: type_( type )
, allocated_( 0 )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
switch ( type )
{
case nullValue:
break;
case intValue:
case uintValue:
value_.int_ = 0;
break;
case realValue:
value_.real_ = 0.0;
break;
case stringValue:
value_.string_ = 0;
break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
case arrayValue:
case objectValue:
value_.map_ = new ObjectValues();
break;
#else
case arrayValue:
value_.array_ = arrayAllocator()->newArray();
break;
case objectValue:
value_.map_ = mapAllocator()->newMap();
break;
#endif
case booleanValue:
value_.bool_ = false;
break;
default:
JSON_ASSERT_UNREACHABLE;
}
}
Value::Value( Int value )
: type_( intValue )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.int_ = value;
}
Value::Value( UInt value )
: type_( uintValue )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.uint_ = value;
}
Value::Value( double value )
: type_( realValue )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.real_ = value;
}
Value::Value( const char *value )
: type_( stringValue )
, allocated_( true )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.string_ = valueAllocator()->duplicateStringValue( value );
}
Value::Value( const std::string &value )
: type_( stringValue )
, allocated_( true )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
(unsigned int)value.length() );
}
Value::Value( const StaticString &value )
: type_( stringValue )
, allocated_( false )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.string_ = const_cast<char *>( value.c_str() );
}
# ifdef JSON_USE_CPPTL
Value::Value( const CppTL::ConstString &value )
: type_( stringValue )
, allocated_( true )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
}
# endif
Value::Value( bool value )
: type_( booleanValue )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
value_.bool_ = value;
}
Value::Value( const Value &other )
: type_( other.type_ )
, comments_( 0 )
# ifdef JSON_VALUE_USE_INTERNAL_MAP
, itemIsUsed_( 0 )
#endif
{
switch ( type_ )
{
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
value_ = other.value_;
break;
case stringValue:
if ( other.value_.string_ )
{
value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
allocated_ = true;
}
else
value_.string_ = 0;
break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
case arrayValue:
case objectValue:
value_.map_ = new ObjectValues( *other.value_.map_ );
break;
#else
case arrayValue:
value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
break;
case objectValue:
value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
break;
#endif
default:
JSON_ASSERT_UNREACHABLE;
}
if ( other.comments_ )
{
comments_ = new CommentInfo[numberOfCommentPlacement];
for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
{
const CommentInfo &otherComment = other.comments_[comment];
if ( otherComment.comment_ )
comments_[comment].setComment( otherComment.comment_ );
}
}
}
Value::~Value()
{
switch ( type_ )
{
case nullValue:
case intValue:
case uintValue:
case realValue:
case booleanValue:
break;
case stringValue:
if ( allocated_ )
valueAllocator()->releaseStringValue( value_.string_ );
break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP
case arrayValue:
case objectValue:
delete value_.map_;
break;
#else
case arrayValue:
arrayAllocator()->destructArray( value_.array_ );
break;
case objectValue:
mapAllocator()->destructMap( value_.map_ );
break;
#endif
default:
JSON_ASSERT_UNREACHABLE;
}
if ( comments_ )
delete[] comments_;
}
Value &
Value::operator=( const Value &other )
{
Value temp( other );
swap( temp );
return *this;
}
void
Value::swap( Value &other )
{
ValueType temp = type_;
type_ = other.type_;
other.type_ = temp;
std::swap( value_, other.value_ );
int temp2 = allocated_;
allocated_ = other.allocated_;
other.allocated_ = temp2;
}
ValueType
Value::type() const
{
return type_;
}
int
Value::compare( const Value &other )
{
/*
int typeDelta = other.type_ - type_;
switch ( type_ )
{
case nullValue:
return other.type_ == type_;
case intValue:
if ( other.type_.isNumeric()
case uintValue:
case realValue:
case booleanValue:
break;
case stringValue,
break;
case arrayValue:
delete value_.array_;
break;
case objectValue:
delete value_.map_;
default:
JSON_ASSERT_UNREACHABLE;
}
*/
return 0; // unreachable
}
bool
Value::operator <( const Value &other ) const
{
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:
return ( value_.string_ == 0 && other.value_.string_ )
|| ( other.value_.string_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -