text: #include <iostream>
  #include "../json/value.h"
  #include "../json/writer.h"
  #include <utility>
  #include <stdexcept>
  #include <cstring>
  #include <cassert>
  #ifdef JSON_USE_CPPTL
  # include <cpptl/conststring.h>
  #endif
  #include <cstddef>    // 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 Int Value::minInt = Int( ~(UInt(-1)/2) );
  const Int Value::maxInt = Int( UInt(-1)/2 );
  const UInt Value::maxUInt = 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 char *beginValue, 
                const char *endValue )
     : type_( stringValue )
     , allocated_( true )
     , comments_( 0 )
  # ifdef JSON_VALUE_USE_INTERNAL_MAP
     , itemIsUsed_( 0 )
  #endif
  {
     value_.string_ = valueAllocator()->duplicateStringValue( beginValue, 
                                                              UInt(endValue - beginValue) );
  }
  
  
  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_  
                    &&  value_.string_  
                    && strcmp( value_.string_, other.value_.string_ ) < 0 );
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     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_);
        }
  #else
     case arrayValue:
        return value_.array_->compare( *(other.value_.array_) ) < 0;
     case objectValue:
        return value_.map_->compare( *(other.value_.map_) ) < 0;
  #endif
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return 0;  // unreachable
  }
  
  bool 
  Value::operator <=( const Value &other ) const
  {
     return !(other > *this);
  }
  
  bool 
  Value::operator >=( const Value &other ) const
  {
     return !(*this < other);
  }
  
  bool 
  Value::operator >( const Value &other ) const
  {
     return other < *this;
  }
  
  bool 
  Value::operator ==( const Value &other ) const
  {
     //if ( type_ != other.type_ )
     // 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:
        return ( value_.string_ == other.value_.string_ )
               || ( other.value_.string_  
                    &&  value_.string_  
                    && strcmp( value_.string_, other.value_.string_ ) == 0 );
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     case arrayValue:
     case objectValue:
        return value_.map_->size() == other.value_.map_->size()
               && (*value_.map_) == (*other.value_.map_);
  #else
     case arrayValue:
        return value_.array_->compare( *(other.value_.array_) ) == 0;
     case objectValue:
        return value_.map_->compare( *(other.value_.map_) ) == 0;
  #endif
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return 0;  // unreachable
  }
  
  bool 
  Value::operator !=( const Value &other ) const
  {
     return !( *this == other );
  }
  
  const char *
  Value::asCString() const
  {
     JSON_ASSERT( type_ == stringValue );
     return value_.string_;
  }
  
  
  std::string 
  Value::asString() const
  {
     switch ( type_ )
     {
     case nullValue:
        return "";
     case stringValue:
        return value_.string_ ? value_.string_ : "";
     case booleanValue:
        return value_.bool_ ? "true" : "false";
     case intValue:
     case uintValue:
     case realValue:
     case arrayValue:
     case objectValue:
        JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return ""; // unreachable
  }
  
  # ifdef JSON_USE_CPPTL
  CppTL::ConstString 
  Value::asConstString() const
  {
     return CppTL::ConstString( asString().c_str() );
  }
  # endif
  
  Value::Int 
  Value::asInt() const
  {
     switch ( type_ )
     {
     case nullValue:
        return 0;
     case intValue:
        return value_.int_;
     case uintValue:
        JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
        return value_.uint_;
     case realValue:
        JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer 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 int" );
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return 0; // unreachable;
  }
  
  Value::UInt 
  Value::asUInt() const
  {
     switch ( type_ )
     {
     case nullValue:
        return 0;
     case intValue:
        JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
        return value_.int_;
     case uintValue:
        return value_.uint_;
     case realValue:
        JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer 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 uint" );
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return 0; // unreachable;
  }
  
  double 
  Value::asDouble() const
  {
     switch ( type_ )
     {
     case nullValue:
        return 0.0;
     case intValue:
        return value_.int_;
     case uintValue:
        return value_.uint_;
     case realValue:
        return value_.real_;
     case booleanValue:
        return value_.bool_ ? 1.0 : 0.0;
     case stringValue:
     case arrayValue:
     case objectValue:
        JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return 0; // unreachable;
  }
  
  bool 
  Value::asBool() const
  {
     switch ( type_ )
     {
     case nullValue:
        return false;
     case intValue:
     case uintValue:
        return value_.int_ != 0;
     case realValue:
        return value_.real_ != 0.0;
     case booleanValue:
        return value_.bool_;
     case stringValue:
        return value_.string_  &&  value_.string_[0] != 0;
     case arrayValue:
     case objectValue:
        return value_.map_->size() != 0;
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return false; // unreachable;
  }
  
  
  bool 
  Value::isConvertibleTo( ValueType other ) const
  {
     switch ( type_ )
     {
     case nullValue:
        return true;
     case intValue:
        return ( other == nullValue  &&  value_.int_ == 0 )
               || other == intValue
               || ( other == uintValue  && value_.int_ >= 0 )
               || other == realValue
               || other == stringValue
               || other == booleanValue;
     case uintValue:
        return ( other == nullValue  &&  value_.uint_ == 0 )
               || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
               || other == uintValue
               || other == realValue
               || other == stringValue
               || other == booleanValue;
     case realValue:
        return ( other == nullValue  &&  value_.real_ == 0.0 )
               || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
               || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
               || other == realValue
               || other == stringValue
               || other == booleanValue;
     case booleanValue:
        return ( other == nullValue  &&  value_.bool_ == false )
               || other == intValue
               || other == uintValue
               || other == realValue
               || other == stringValue
               || other == booleanValue;
     case stringValue:
        return other == stringValue
               || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
     case arrayValue:
        return other == arrayValue
               ||  ( other == nullValue  &&  value_.map_->size() == 0 );
     case objectValue:
        return other == objectValue
               ||  ( other == nullValue  &&  value_.map_->size() == 0 );
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return false; // unreachable;
  }
  
  
  /// Number of values in array or object
  Value::UInt 
  Value::size() const
  {
     switch ( type_ )
     {
     case nullValue:
     case intValue:
     case uintValue:
     case realValue:
     case booleanValue:
     case stringValue:
        return 0;
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     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 Int( value_.map_->size() );
  #else
     case arrayValue:
        return Int( value_.array_->size() );
     case objectValue:
        return Int( value_.map_->size() );
  #endif
     default:
        JSON_ASSERT_UNREACHABLE;
     }
     return 0; // unreachable;
  }
  
  
  bool 
  Value::empty() const
  {
     if ( isNull() || isArray() || isObject() )
        return size() == 0u;
     else
        return false;
  }
  
  
  bool
  Value::operator!() const
  {
     return isNull();
  }
  
  
  void 
  Value::clear()
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );
  
     switch ( type_ )
     {
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     case arrayValue:
     case objectValue:
        value_.map_->clear();
        break;
  #else
     case arrayValue:
        value_.array_->clear();
        break;
     case objectValue:
        value_.map_->clear();
        break;
  #endif
     default:
        break;
     }
  }
  
  void 
  Value::resize( UInt newSize )
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
     if ( type_ == nullValue )
        *this = Value( arrayValue );
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     UInt oldSize = size();
     if ( newSize == 0 )
        clear();
     else if ( newSize > oldSize )
        (*this)[ newSize - 1 ];
     else
     {
        for ( UInt index = newSize; index < oldSize; ++index )
           value_.map_->erase( index );
        assert( size() == newSize );
     }
  #else
     value_.array_->resize( newSize );
  #endif
  }
  
  
  Value &
  Value::operator[]( UInt index )
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
     if ( type_ == nullValue )
        *this = Value( arrayValue );
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     CZString key( index );
     ObjectValues::iterator it = value_.map_->lower_bound( key );
     if ( it != value_.map_->end()  &&  (*it).first == key )
        return (*it).second;
  
     ObjectValues::value_type defaultValue( key, null );
     it = value_.map_->insert( it, defaultValue );
     return (*it).second;
  #else
     return value_.array_->resolveReference( index );
  #endif
  }
  
  
  const Value &
  Value::operator[]( UInt index ) const
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
     if ( type_ == nullValue )
        return null;
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     CZString key( index );
     ObjectValues::const_iterator it = value_.map_->find( key );
     if ( it == value_.map_->end() )
        return null;
     return (*it).second;
  #else
     Value *value = value_.array_->find( index );
     return value ? *value : null;
  #endif
  }
  
  
  Value &
  Value::operator[]( const char *key )
  {
     return resolveReference( key, false );
  }
  
  
  Value &
  Value::resolveReference( const char *key, 
                           bool isStatic )
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
     if ( type_ == nullValue )
        *this = Value( objectValue );
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     CZString actualKey( key, isStatic ? CZString::noDuplication 
                                       : CZString::duplicateOnCopy );
     ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
     if ( it != value_.map_->end()  &&  (*it).first == actualKey )
        return (*it).second;
  
     ObjectValues::value_type defaultValue( actualKey, null );
     it = value_.map_->insert( it, defaultValue );
     Value &value = (*it).second;
     return value;
  #else
     return value_.map_->resolveReference( key, isStatic );
  #endif
  }
  
  
  Value 
  Value::get( UInt index, 
              const Value &defaultValue ) const
  {
     const Value *value = &((*this)[index]);
     return value == &null ? defaultValue : *value;
  }
  
  
  bool 
  Value::isValidIndex( UInt index ) const
  {
     return index < size();
  }
  
  
  
  const Value &
  Value::operator[]( const char *key ) const
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
     if ( type_ == nullValue )
        return null;
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     CZString actualKey( key, CZString::noDuplication );
     ObjectValues::const_iterator it = value_.map_->find( actualKey );
     if ( it == value_.map_->end() )
        return null;
     return (*it).second;
  #else
     const Value *value = value_.map_->find( key );
     return value ? *value : null;
  #endif
  }
  
  
  Value &
  Value::operator[]( const std::string &key )
  {
     return (*this)[ key.c_str() ];
  }
  
  
  const Value &
  Value::operator[]( const std::string &key ) const
  {
     return (*this)[ key.c_str() ];
  }
  
  Value &
  Value::operator[]( const StaticString &key )
  {
     return resolveReference( key, true );
  }
  
  
  # ifdef JSON_USE_CPPTL
  Value &
  Value::operator[]( const CppTL::ConstString &key )
  {
     return (*this)[ key.c_str() ];
  }
  
  
  const Value &
  Value::operator[]( const CppTL::ConstString &key ) const
  {
     return (*this)[ key.c_str() ];
  }
  # endif
  
  
  Value &
  Value::append( const Value &value )
  {
     return (*this)[size()] = value;
  }
  
  
  Value 
  Value::get( const char *key, 
              const Value &defaultValue ) const
  {
     const Value *value = &((*this)[key]);
     return value == &null ? defaultValue : *value;
  }
  
  
  Value 
  Value::get( const std::string &key,
              const Value &defaultValue ) const
  {
     return get( key.c_str(), defaultValue );
  }
  
  Value
  Value::removeMember( const char* key )
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
     if ( type_ == nullValue )
        return null;
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     CZString actualKey( key, CZString::noDuplication );
     ObjectValues::iterator it = value_.map_->find( actualKey );
     if ( it == value_.map_->end() )
        return null;
     Value old(it->second);
     value_.map_->erase(it);
     return old;
  #else
     Value *value = value_.map_->find( key );
     if (value){
        Value old(*value);
        value_.map_.remove( key );
        return old;
     } else {
        return null;
     }
  #endif
  }
  
  Value
  Value::removeMember( const std::string &key )
  {
     return removeMember( key.c_str() );
  }
  
  # ifdef JSON_USE_CPPTL
  Value 
  Value::get( const CppTL::ConstString &key,
              const Value &defaultValue ) const
  {
     return get( key.c_str(), defaultValue );
  }
  # endif
  
  bool 
  Value::isMember( const char *key ) const
  {
     const Value *value = &((*this)[key]);
     return value != &null;
  }
  
  
  bool 
  Value::isMember( const std::string &key ) const
  {
     return isMember( key.c_str() );
  }
  
  
  # ifdef JSON_USE_CPPTL
  bool 
  Value::isMember( const CppTL::ConstString &key ) const
  {
     return isMember( key.c_str() );
  }
  #endif
  
  Value::Members 
  Value::getMemberNames() const
  {
     JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
     if ( type_ == nullValue )
         return Value::Members();
     Members members;
     members.reserve( value_.map_->size() );
  #ifndef JSON_VALUE_USE_INTERNAL_MAP
     ObjectValues::const_iterator it = value_.map_->begin();
     ObjectValues::const_iterator itEnd = value_.map_->end();
     for ( ; it != itEnd; ++it )
        members.push_back( std::string( (*it).first.c_str() ) );
  #else
     ValueInternalMap::IteratorState it;
     ValueInternalMap::IteratorState itEnd;
     value_.map_->makeBeginIterator( it );
     value_.map_->makeEndIterator( itEnd );
     for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
        members.push_back( std::string( ValueInternalMap::key( it ) ) );
  #endif
     return members;
  }
  //
  //# ifdef JSON_USE_CPPTL
  //EnumMemberNames
  //Value::enumMemberNames() const
  //{
  //   if ( type_ == objectValue )
  //   {
  //      return CppTL::Enum::any(  CppTL::Enum::transform(
  //         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
  //         MemberNamesTransform() ) );
  //   }
  //   return EnumMemberNames();
  //}
  //
  //
  //EnumValues 
  //Value::enumValues() const
  //{
  //   if ( type_ == objectValue  ||  type_ == arrayValue )
  //      return CppTL::Enum::anyValues( *(value_.map_), 
  //                                     CppTL::Type<const Value &>() );
  //   return EnumValues();
  //}
  //
  //# endif
  
  
  bool
  Value::isNull() const
  {
     return type_ == nullValue;
  }
  
  
  bool 
  Value::isBool() const
  {
     return type_ == booleanValue;
  }
  
  
  bool 
  Value::isInt() const
  {
     return type_ == intValue;
  }
  
  
  bool 
  Value::isUInt() const
  {
     return type_ == uintValue;
  }
  
  
  bool 
  Value::isIntegral() const
  {
     return type_ == intValue  
            ||  type_ == uintValue  
            ||  type_ == booleanValue;
  }
  
  
  bool 
  Value::isDouble() const
  {
     return type_ == realValue;
  }
  
  
  bool 
  Value::isNumeric() const
  {
     return isIntegral() || isDouble();
  }
  
  
  bool 
  Value::isString() const
  {
     return type_ == stringValue;
  }
  
  
  bool 
  Value::isArray() const
  {
     return type_ == nullValue  ||  type_ == arrayValue;
  }
  
  
  bool 
  Value::isObject() const
  {
     return type_ == nullValue  ||  type_ == objectValue;
  }
  
  
  void 
  Value::setComment( const char *comment,
                     CommentPlacement placement )
  {
     if ( !comments_ )
        comments_ = new CommentInfo[numberOfCommentPlacement];
     comments_[placement].setComment( comment );
  }
  
  
  void 
  Value::setComment( const std::string &comment,
                     CommentPlacement placement )
  {
     setComment( comment.c_str(), placement );
  }
  
  
  bool 
  Value::hasComment( CommentPlacement placement ) const
  {
     return comments_ != 0  &&  comments_[placement].comment_ != 0;
  }
  
  std::string 
  Value::getComment( CommentPlacement placement ) const
  {
     if ( hasComment(placement) )
        return comments_[placement].comment_;
     return "";
  }
  
  
  std::string 
  Value::toStyledString() const
  {
     StyledWriter writer;
     return writer.write( *this );
  }
  
  
  Value::const_iterator 
  Value::begin() const
  {
     switch ( type_ )
     {
  #ifdef JSON_VALUE_USE_INTERNAL_MAP
     case arrayValue:
        if ( value_.array_ )
        {
           ValueInternalArray::IteratorState it;
           value_.array_->makeBeginIterator( it );
           return const_iterator( it );
        }
        break;
     case objectValue:
        if ( value_.map_ )
        {
           ValueInternalMap::IteratorState it;
           value_.map_->makeBeginIterator( it );
           return const_iterator( it );
        }
        break;
  #else
     case arrayValue:
     case objectValue:
        if ( value_.map_ )
           return const_iterator( value_.map_->begin() );
        break;
  #endif
     default:
        break;
     }
     return const_iterator();
  }
  
  Value::const_iterator 
  Value::end() const
  {
     switch ( type_ )
     {
  #ifdef JSON_VALUE_USE_INTERNAL_MAP
     case arrayValue:
        if ( value_.array_ )
        {
           ValueInternalArray::IteratorState it;
           value_.array_->makeEndIterator( it );
           return const_iterator( it );
        }
        break;
     case objectValue:
        if ( value_.map_ )
        {
           ValueInternalMap::IteratorState it;
           value_.map_->makeEndIterator( it );
           return const_iterator( it );
        }
        break;
  #else
     case arrayValue:
     case objectValue:
        if ( value_.map_ )
           return const_iterator( value_.map_->end() );
        break;
  #endif
     default:
        break;
     }
     return const_iterator();
  }
  
  
  Value::iterator 
  Value::begin()
  {
     switch ( type_ )
     {
  #ifdef JSON_VALUE_USE_INTERNAL_MAP
     case arrayValue:
        if ( value_.array_ )
        {
           ValueInternalArray::IteratorState it;
           value_.array_->makeBeginIterator( it );
           return iterator( it );
        }
        break;
     case objectValue:
        if ( value_.map_ )
        {
           ValueInternalMap::IteratorState it;
           value_.map_->makeBeginIterator( it );
           return iterator( it );
        }
        break;
  #else
     case arrayValue:
     case objectValue:
        if ( value_.map_ )
           return iterator( value_.map_->begin() );
        break;
  #endif
     default:
        break;
     }
     return iterator();
  }
  
  Value::iterator 
  Value::end()
  {
     switch ( type_ )
     {
  #ifdef JSON_VALUE_USE_INTERNAL_MAP
     case arrayValue:
        if ( value_.array_ )
        {
           ValueInternalArray::IteratorState it;
           value_.array_->makeEndIterator( it );
           return iterator( it );
        }
        break;
     case objectValue:
        if ( value_.map_ )
        {
           ValueInternalMap::IteratorState it;
           value_.map_->makeEndIterator( it );
           return iterator( it );
        }
        break;
  #else
     case arrayValue:
     case objectValue:
        if ( value_.map_ )
           return iterator( value_.map_->end() );
        break;
  #endif
     default:
        break;
     }
     return iterator();
  }
  
  
  // class PathArgument
  // //////////////////////////////////////////////////////////////////
  
  PathArgument::PathArgument()
     : kind_( kindNone )
  {
  }
  
  
  PathArgument::PathArgument( Value::UInt index )
     : index_( index )
     , kind_( kindIndex )
  {
  }
  
  
  PathArgument::PathArgument( const char *key )
     : key_( key )
     , kind_( kindKey )
  {
  }
  
  
  PathArgument::PathArgument( const std::string &key )
     : key_( key.c_str() )
     , kind_( kindKey )
  {
  }
  
  // class Path
  // //////////////////////////////////////////////////////////////////
  
  Path::Path( const std::string &path,
              const PathArgument &a1,
              const PathArgument &a2,
              const PathArgument &a3,
              const PathArgument &a4,
              const PathArgument &a5 )
  {
     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 );
  }
  
  
  void 
  Path::makePath( const std::string &path,
                  const InArgs &in )
  {
     const char *current = path.c_str();
     const char *end = current + path.length();
     InArgs::const_iterator itInArg = in.begin();
     while ( current != end )
     {
        if ( *current == '[' )
        {
           ++current;
           if ( *current == '%' )
              addPathInArg( path, in, itInArg, PathArgument::kindIndex );
           else
           {
              Value::UInt index = 0;
              for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
                 index = index * 10 + Value::UInt(*current - '0');
              args_.push_back( index );
           }
           if ( current == end  ||  *current++ != ']' )
              invalidPath( path, int(current - path.c_str()) );
        }
        else if ( *current == '%' )
        {
           addPathInArg( path, in, itInArg, PathArgument::kindKey );
           ++current;
        }
        else if ( *current == '.' )
        {
           ++current;
        }
        else
        {
           const char *beginName = current;
           while ( current != end  &&  !strchr( "[.", *current ) )
              ++current;
           args_.push_back( std::string( beginName, current ) );
        }
     }
  }
  
  
  void 
  Path::addPathInArg( const std::string &path, 
                      const InArgs &in, 
                      InArgs::const_iterator &itInArg, 
                      PathArgument::Kind kind )
  {
     if ( itInArg == in.end() )
     {
        // Error: missing argument %d
     }
     else if ( (*itInArg)->kind_ != kind )
     {
        // Error: bad argument type
     }
     else
     {
        args_.push_back( **itInArg );
     }
  }
  
  
  void 
  Path::invalidPath( const std::string &path, 
                     int location )
  {
     // Error: invalid path.
  }
  
  
  const Value &
  Path::resolve( const Value &root ) const
  {
     const Value *node = &root;
     for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
     {
        const PathArgument &arg = *it;
        if ( arg.kind_ == PathArgument::kindIndex )
        {
           if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
           {
              // Error: unable to resolve path (array value expected at position...
           }
           node = &((*node)[arg.index_]);
        }
        else if ( arg.kind_ == PathArgument::kindKey )
        {
           if ( !node->isObject() )
           {
              // Error: unable to resolve path (object value expected at position...)
           }
           node = &((*node)[arg.key_]);
           if ( node == &Value::null )
           {
              // Error: unable to resolve path (object has no member named '' at position...)
           }
        }
     }
     return *node;
  }
  
  
  Value 
  Path::resolve( const Value &root, 
                 const Value &defaultValue ) const
  {
     const Value *node = &root;
     for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
     {
        const PathArgument &arg = *it;
        if ( arg.kind_ == PathArgument::kindIndex )
        {
           if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
              return defaultValue;
           node = &((*node)[arg.index_]);
        }
        else if ( arg.kind_ == PathArgument::kindKey )
        {
           if ( !node->isObject() )
              return defaultValue;
           node = &((*node)[arg.key_]);
           if ( node == &Value::null )
              return defaultValue;
        }
     }
     return *node;
  }
  
  
  Value &
  Path::make( Value &root ) const
  {
     Value *node = &root;
     for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
     {
        const PathArgument &arg = *it;
        if ( arg.kind_ == PathArgument::kindIndex )
        {
           if ( !node->isArray() )
           {
              // Error: node is not an array at position ...
           }
           node = &((*node)[arg.index_]);
        }
        else if ( arg.kind_ == PathArgument::kindKey )
        {
           if ( !node->isObject() )
           {
              // Error: node is not an object at position...
           }
           node = &((*node)[arg.key_]);
        }
     }
     return *node;
  }
  
  
  } // namespace Json
  