osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarth/JsonUtils.cpp

Go to the documentation of this file.
00001 /* -*-c++-*- */
00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
00003  * Copyright 2008-2010 Pelican Mapping
00004  * http://osgearth.org
00005  *
00006  * osgEarth is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00027 #include <osgEarth/JsonUtils>
00028 #include <osg/Notify>
00029 
00030 #include <string.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <sstream>
00034 
00035 #if _MSC_VER >= 1400 // VC++ 8.0
00036 #pragma warning( disable : 4996 )   // disable warning about strdup being deprecated.
00037 #endif
00038 
00039 #define JSON_ASSERT_UNREACHABLE assert( false )
00040 #define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
00041 #define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
00042 
00043 using namespace osgEarth;
00044 using namespace osgEarth::Json;
00045 
00046 const Value Value::null;
00047 const Value::Int Value::minInt = Value::Int( ~(Value::UInt(-1)/2) );
00048 const Value::Int Value::maxInt = Value::Int( Value::UInt(-1)/2 );
00049 const Value::UInt Value::maxUInt = Value::UInt(-1);
00050 
00051 
00052 ValueAllocator::~ValueAllocator()
00053 {
00054 }
00055 
00056 namespace osgEarth { namespace Json {
00057 
00058 class DefaultValueAllocator : public ValueAllocator
00059 {
00060 public:
00061    virtual ~DefaultValueAllocator()
00062    {
00063    }
00064 
00065    virtual char *makeMemberName( const char *memberName )
00066    {
00067       return duplicateStringValue( memberName );
00068    }
00069 
00070    virtual void releaseMemberName( char *memberName )
00071    {
00072       releaseStringValue( memberName );
00073    }
00074 
00075    virtual char *duplicateStringValue( const char *value, 
00076                                        unsigned int length = unknown )
00077    {
00078       //@todo invesgate this old optimization
00079       //if ( !value  ||  value[0] == 0 )
00080       //   return 0;
00081 
00082       if ( length == unknown )
00083          length = (unsigned int)strlen(value);
00084       char *newString = static_cast<char *>( malloc( length + 1 ) );
00085       memcpy( newString, value, length );
00086       newString[length] = 0;
00087       return newString;
00088    }
00089 
00090    virtual void releaseStringValue( char *value )
00091    {
00092       if ( value )
00093          free( value );
00094    }
00095 };
00096 
00097 } } // namespaces
00098 
00099 static ValueAllocator *&valueAllocator()
00100 {
00101    static DefaultValueAllocator defaultAllocator;
00102    static ValueAllocator *valueAllocator = &defaultAllocator;
00103    return valueAllocator;
00104 }
00105 
00106 static struct DummyValueAllocatorInitializer {
00107    DummyValueAllocatorInitializer() 
00108    {
00109       valueAllocator();      // ensure valueAllocator() statics are initialized before main().
00110    }
00111 } dummyValueAllocatorInitializer;
00112 
00113 
00114 
00115 // //////////////////////////////////////////////////////////////////
00116 // //////////////////////////////////////////////////////////////////
00117 // //////////////////////////////////////////////////////////////////
00118 // ValueInternals...
00119 // //////////////////////////////////////////////////////////////////
00120 // //////////////////////////////////////////////////////////////////
00121 // //////////////////////////////////////////////////////////////////
00122 #ifdef JSON_VALUE_USE_INTERNAL_MAP
00123 # include "json_internalarray.inl"
00124 # include "json_internalmap.inl"
00125 #endif // JSON_VALUE_USE_INTERNAL_MAP
00126 
00127 //# include "json_valueiterator.inl"
00128 
00129 
00130 // included by json_value.cpp
00131 // everything is within Json namespace
00132 
00133 
00134 // //////////////////////////////////////////////////////////////////
00135 // //////////////////////////////////////////////////////////////////
00136 // //////////////////////////////////////////////////////////////////
00137 // class ValueIteratorBase
00138 // //////////////////////////////////////////////////////////////////
00139 // //////////////////////////////////////////////////////////////////
00140 // //////////////////////////////////////////////////////////////////
00141 
00142 ValueIteratorBase::ValueIteratorBase()
00143 {
00144 }
00145 
00146 
00147 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00148 ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
00149    : current_( current )
00150 {
00151 }
00152 #else
00153 ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
00154    : isArray_( true )
00155 {
00156    iterator_.array_ = state;
00157 }
00158 
00159 
00160 ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
00161    : isArray_( false )
00162 {
00163    iterator_.map_ = state;
00164 }
00165 #endif
00166 
00167 Value &
00168 ValueIteratorBase::deref() const
00169 {
00170 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00171    return current_->second;
00172 #else
00173    if ( isArray_ )
00174       return ValueInternalArray::dereference( iterator_.array_ );
00175    return ValueInternalMap::value( iterator_.map_ );
00176 #endif
00177 }
00178 
00179 
00180 void 
00181 ValueIteratorBase::increment()
00182 {
00183 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00184    ++current_;
00185 #else
00186    if ( isArray_ )
00187       ValueInternalArray::increment( iterator_.array_ );
00188    ValueInternalMap::increment( iterator_.map_ );
00189 #endif
00190 }
00191 
00192 
00193 void 
00194 ValueIteratorBase::decrement()
00195 {
00196 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00197    --current_;
00198 #else
00199    if ( isArray_ )
00200       ValueInternalArray::decrement( iterator_.array_ );
00201    ValueInternalMap::decrement( iterator_.map_ );
00202 #endif
00203 }
00204 
00205 
00206 ValueIteratorBase::difference_type 
00207 ValueIteratorBase::computeDistance( const SelfType &other ) const
00208 {
00209 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00210 # ifdef JSON_USE_CPPTL_SMALLMAP
00211    return current_ - other.current_;
00212 # else
00213    return difference_type( std::distance( current_, other.current_ ) );
00214 # endif
00215 #else
00216    if ( isArray_ )
00217       return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
00218    return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
00219 #endif
00220 }
00221 
00222 
00223 bool 
00224 ValueIteratorBase::isEqual( const SelfType &other ) const
00225 {
00226 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00227    return current_ == other.current_;
00228 #else
00229    if ( isArray_ )
00230       return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
00231    return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
00232 #endif
00233 }
00234 
00235 
00236 void 
00237 ValueIteratorBase::copy( const SelfType &other )
00238 {
00239 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00240    current_ = other.current_;
00241 #else
00242    if ( isArray_ )
00243       iterator_.array_ = other.iterator_.array_;
00244    iterator_.map_ = other.iterator_.map_;
00245 #endif
00246 }
00247 
00248 
00249 Value 
00250 ValueIteratorBase::key() const
00251 {
00252 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00253    const Value::CZString czstring = (*current_).first;
00254    if ( czstring.c_str() )
00255    {
00256       if ( czstring.isStaticString() )
00257          return Value( StaticString( czstring.c_str() ) );
00258       return Value( czstring.c_str() );
00259    }
00260    return Value( czstring.index() );
00261 #else
00262    if ( isArray_ )
00263       return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
00264    bool isStatic;
00265    const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
00266    if ( isStatic )
00267       return Value( StaticString( memberName ) );
00268    return Value( memberName );
00269 #endif
00270 }
00271 
00272 
00273 Value::UInt 
00274 ValueIteratorBase::index() const
00275 {
00276 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00277    const Value::CZString czstring = (*current_).first;
00278    if ( !czstring.c_str() )
00279       return czstring.index();
00280    return Value::UInt( -1 );
00281 #else
00282    if ( isArray_ )
00283       return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
00284    return Value::UInt( -1 );
00285 #endif
00286 }
00287 
00288 
00289 const char *
00290 ValueIteratorBase::memberName() const
00291 {
00292 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00293    const char *name = (*current_).first.c_str();
00294    return name ? name : "";
00295 #else
00296    if ( !isArray_ )
00297       return ValueInternalMap::key( iterator_.map_ );
00298    return "";
00299 #endif
00300 }
00301 
00302 
00303 // //////////////////////////////////////////////////////////////////
00304 // //////////////////////////////////////////////////////////////////
00305 // //////////////////////////////////////////////////////////////////
00306 // class ValueConstIterator
00307 // //////////////////////////////////////////////////////////////////
00308 // //////////////////////////////////////////////////////////////////
00309 // //////////////////////////////////////////////////////////////////
00310 
00311 ValueConstIterator::ValueConstIterator()
00312 {
00313 }
00314 
00315 
00316 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00317 ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
00318    : ValueIteratorBase( current )
00319 {
00320 }
00321 #else
00322 ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
00323    : ValueIteratorBase( state )
00324 {
00325 }
00326 
00327 ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
00328    : ValueIteratorBase( state )
00329 {
00330 }
00331 #endif
00332 
00333 ValueConstIterator &
00334 ValueConstIterator::operator =( const ValueIteratorBase &other )
00335 {
00336    copy( other );
00337    return *this;
00338 }
00339 
00340 
00341 // //////////////////////////////////////////////////////////////////
00342 // //////////////////////////////////////////////////////////////////
00343 // //////////////////////////////////////////////////////////////////
00344 // class ValueIterator
00345 // //////////////////////////////////////////////////////////////////
00346 // //////////////////////////////////////////////////////////////////
00347 // //////////////////////////////////////////////////////////////////
00348 
00349 ValueIterator::ValueIterator()
00350 {
00351 }
00352 
00353 
00354 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00355 ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
00356    : ValueIteratorBase( current )
00357 {
00358 }
00359 #else
00360 ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
00361    : ValueIteratorBase( state )
00362 {
00363 }
00364 
00365 ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
00366    : ValueIteratorBase( state )
00367 {
00368 }
00369 #endif
00370 
00371 ValueIterator::ValueIterator( const ValueConstIterator &other )
00372    : ValueIteratorBase( other )
00373 {
00374 }
00375 
00376 ValueIterator::ValueIterator( const ValueIterator &other )
00377    : ValueIteratorBase( other )
00378 {
00379 }
00380 
00381 ValueIterator &
00382 ValueIterator::operator =( const SelfType &other )
00383 {
00384    copy( other );
00385    return *this;
00386 }
00387 
00388 
00389 
00390 // //////////////////////////////////////////////////////////////////
00391 // //////////////////////////////////////////////////////////////////
00392 // //////////////////////////////////////////////////////////////////
00393 // class Value::CommentInfo
00394 // //////////////////////////////////////////////////////////////////
00395 // //////////////////////////////////////////////////////////////////
00396 // //////////////////////////////////////////////////////////////////
00397 
00398 
00399 Value::CommentInfo::CommentInfo()
00400    : comment_( 0 )
00401 {
00402 }
00403 
00404 Value::CommentInfo::~CommentInfo()
00405 {
00406    if ( comment_ )
00407       valueAllocator()->releaseStringValue( comment_ );
00408 }
00409 
00410 
00411 void 
00412 Value::CommentInfo::setComment( const char *text )
00413 {
00414    if ( comment_ )
00415       valueAllocator()->releaseStringValue( comment_ );
00416    JSON_ASSERT( text );
00417    JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
00418    // It seems that /**/ style comments are acceptable as well.
00419    comment_ = valueAllocator()->duplicateStringValue( text );
00420 }
00421 
00422 
00423 // //////////////////////////////////////////////////////////////////
00424 // //////////////////////////////////////////////////////////////////
00425 // //////////////////////////////////////////////////////////////////
00426 // class Value::CZString
00427 // //////////////////////////////////////////////////////////////////
00428 // //////////////////////////////////////////////////////////////////
00429 // //////////////////////////////////////////////////////////////////
00430 # ifndef JSON_VALUE_USE_INTERNAL_MAP
00431 
00432 // Notes: index_ indicates if the string was allocated when
00433 // a string is stored.
00434 
00435 Value::CZString::CZString( int index )
00436    : cstr_( 0 )
00437    , index_( index )
00438 {
00439 }
00440 
00441 Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
00442    : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr) 
00443                                   : cstr )
00444    , index_( allocate )
00445 {
00446 }
00447 
00448 Value::CZString::CZString( const CZString &other )
00449 : cstr_( other.index_ != noDuplication &&  other.cstr_ != 0
00450                 ?  valueAllocator()->makeMemberName( other.cstr_ )
00451                 : other.cstr_ )
00452    , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
00453                          : other.index_ )
00454 {
00455 }
00456 
00457 Value::CZString::~CZString()
00458 {
00459    if ( cstr_  &&  index_ == duplicate )
00460       valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
00461 }
00462 
00463 void 
00464 Value::CZString::swap( CZString &other )
00465 {
00466    std::swap( cstr_, other.cstr_ );
00467    std::swap( index_, other.index_ );
00468 }
00469 
00470 Value::CZString &
00471 Value::CZString::operator =( const CZString &other )
00472 {
00473    CZString temp( other );
00474    swap( temp );
00475    return *this;
00476 }
00477 
00478 bool 
00479 Value::CZString::operator<( const CZString &other ) const 
00480 {
00481    if ( cstr_ )
00482       return strcmp( cstr_, other.cstr_ ) < 0;
00483    return index_ < other.index_;
00484 }
00485 
00486 bool 
00487 Value::CZString::operator==( const CZString &other ) const 
00488 {
00489    if ( cstr_ )
00490       return strcmp( cstr_, other.cstr_ ) == 0;
00491    return index_ == other.index_;
00492 }
00493 
00494 
00495 int 
00496 Value::CZString::index() const
00497 {
00498    return index_;
00499 }
00500 
00501 
00502 const char *
00503 Value::CZString::c_str() const
00504 {
00505    return cstr_;
00506 }
00507 
00508 bool 
00509 Value::CZString::isStaticString() const
00510 {
00511    return index_ == noDuplication;
00512 }
00513 
00514 #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
00515 
00516 
00517 // //////////////////////////////////////////////////////////////////
00518 // //////////////////////////////////////////////////////////////////
00519 // //////////////////////////////////////////////////////////////////
00520 // class Value::Value
00521 // //////////////////////////////////////////////////////////////////
00522 // //////////////////////////////////////////////////////////////////
00523 // //////////////////////////////////////////////////////////////////
00524 
00529 Value::Value( ValueType type )
00530    : type_( type )
00531    , allocated_( 0 )
00532    , comments_( 0 )
00533 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00534    , itemIsUsed_( 0 )
00535 #endif
00536 {
00537    switch ( type )
00538    {
00539    case nullValue:
00540       break;
00541    case intValue:
00542    case uintValue:
00543       value_.int_ = 0;
00544       break;
00545    case realValue:
00546       value_.real_ = 0.0;
00547       break;
00548    case stringValue:
00549       value_.string_ = 0;
00550       break;
00551 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00552    case arrayValue:
00553    case objectValue:
00554       value_.map_ = new ObjectValues();
00555       break;
00556 #else
00557    case arrayValue:
00558       value_.array_ = arrayAllocator()->newArray();
00559       break;
00560    case objectValue:
00561       value_.map_ = mapAllocator()->newMap();
00562       break;
00563 #endif
00564    case booleanValue:
00565       value_.bool_ = false;
00566       break;
00567    default:
00568       JSON_ASSERT_UNREACHABLE;
00569    }
00570 }
00571 
00572 
00573 Value::Value( Int value )
00574    : type_( intValue )
00575    , comments_( 0 )
00576 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00577    , itemIsUsed_( 0 )
00578 #endif
00579 {
00580    value_.int_ = value;
00581 }
00582 
00583 
00584 Value::Value( UInt value )
00585    : type_( uintValue )
00586    , comments_( 0 )
00587 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00588    , itemIsUsed_( 0 )
00589 #endif
00590 {
00591    value_.uint_ = value;
00592 }
00593 
00594 Value::Value( double value )
00595    : type_( realValue )
00596    , comments_( 0 )
00597 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00598    , itemIsUsed_( 0 )
00599 #endif
00600 {
00601    value_.real_ = value;
00602 }
00603 
00604 Value::Value( const char *value )
00605    : type_( stringValue )
00606    , allocated_( true )
00607    , comments_( 0 )
00608 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00609    , itemIsUsed_( 0 )
00610 #endif
00611 {
00612    value_.string_ = valueAllocator()->duplicateStringValue( value );
00613 }
00614 
00615 Value::Value( const std::string &value )
00616    : type_( stringValue )
00617    , allocated_( true )
00618    , comments_( 0 )
00619 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00620    , itemIsUsed_( 0 )
00621 #endif
00622 {
00623    value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(), 
00624                                                             (unsigned int)value.length() );
00625 
00626 }
00627 
00628 Value::Value( const StaticString &value )
00629    : type_( stringValue )
00630    , allocated_( false )
00631    , comments_( 0 )
00632 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00633    , itemIsUsed_( 0 )
00634 #endif
00635 {
00636    value_.string_ = const_cast<char *>( value.c_str() );
00637 }
00638 
00639 
00640 # ifdef JSON_USE_CPPTL
00641 Value::Value( const CppTL::ConstString &value )
00642    : type_( stringValue )
00643    , allocated_( true )
00644    , comments_( 0 )
00645 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00646    , itemIsUsed_( 0 )
00647 #endif
00648 {
00649    value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
00650 }
00651 # endif
00652 
00653 Value::Value( bool value )
00654    : type_( booleanValue )
00655    , comments_( 0 )
00656 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00657    , itemIsUsed_( 0 )
00658 #endif
00659 {
00660    value_.bool_ = value;
00661 }
00662 
00663 
00664 Value::Value( const Value &other )
00665    : type_( other.type_ )
00666    , comments_( 0 )
00667 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00668    , itemIsUsed_( 0 )
00669 #endif
00670 {
00671    switch ( type_ )
00672    {
00673    case nullValue:
00674    case intValue:
00675    case uintValue:
00676    case realValue:
00677    case booleanValue:
00678       value_ = other.value_;
00679       break;
00680    case stringValue:
00681       if ( other.value_.string_ )
00682       {
00683          value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
00684          allocated_ = true;
00685       }
00686       else
00687          value_.string_ = 0;
00688       break;
00689 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00690    case arrayValue:
00691    case objectValue:
00692       value_.map_ = new ObjectValues( *other.value_.map_ );
00693       break;
00694 #else
00695    case arrayValue:
00696       value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
00697       break;
00698    case objectValue:
00699       value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
00700       break;
00701 #endif
00702    default:
00703       JSON_ASSERT_UNREACHABLE;
00704    }
00705    if ( other.comments_ )
00706    {
00707       comments_ = new CommentInfo[numberOfCommentPlacement];
00708       for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
00709       {
00710          const CommentInfo &otherComment = other.comments_[comment];
00711          if ( otherComment.comment_ )
00712             comments_[comment].setComment( otherComment.comment_ );
00713       }
00714    }
00715 }
00716 
00717 
00718 Value::~Value()
00719 {
00720    switch ( type_ )
00721    {
00722    case nullValue:
00723    case intValue:
00724    case uintValue:
00725    case realValue:
00726    case booleanValue:
00727       break;
00728    case stringValue:
00729       if ( allocated_ )
00730          valueAllocator()->releaseStringValue( value_.string_ );
00731       break;
00732 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00733    case arrayValue:
00734    case objectValue:
00735       delete value_.map_;
00736       break;
00737 #else
00738    case arrayValue:
00739       arrayAllocator()->destructArray( value_.array_ );
00740       break;
00741    case objectValue:
00742       mapAllocator()->destructMap( value_.map_ );
00743       break;
00744 #endif
00745    default:
00746       JSON_ASSERT_UNREACHABLE;
00747    }
00748 
00749    if ( comments_ )
00750       delete[] comments_;
00751 }
00752 
00753 Value &
00754 Value::operator=( const Value &other )
00755 {
00756    Value temp( other );
00757    swap( temp );
00758    return *this;
00759 }
00760 
00761 void 
00762 Value::swap( Value &other )
00763 {
00764    ValueType temp = type_;
00765    type_ = other.type_;
00766    other.type_ = temp;
00767    std::swap( value_, other.value_ );
00768    int temp2 = allocated_;
00769    allocated_ = other.allocated_;
00770    other.allocated_ = temp2;
00771 }
00772 
00773 ValueType 
00774 Value::type() const
00775 {
00776    return type_;
00777 }
00778 
00779 
00780 int 
00781 Value::compare( const Value &other )
00782 {
00783    /*
00784    int typeDelta = other.type_ - type_;
00785    switch ( type_ )
00786    {
00787    case nullValue:
00788 
00789       return other.type_ == type_;
00790    case intValue:
00791       if ( other.type_.isNumeric()
00792    case uintValue:
00793    case realValue:
00794    case booleanValue:
00795       break;
00796    case stringValue,
00797       break;
00798    case arrayValue:
00799       delete value_.array_;
00800       break;
00801    case objectValue:
00802       delete value_.map_;
00803    default:
00804       JSON_ASSERT_UNREACHABLE;
00805    }
00806    */
00807    return 0;  // unreachable
00808 }
00809 
00810 bool 
00811 Value::operator <( const Value &other ) const
00812 {
00813    int typeDelta = type_ - other.type_;
00814    if ( typeDelta )
00815       return typeDelta < 0 ? true : false;
00816    switch ( type_ )
00817    {
00818    case nullValue:
00819       return false;
00820    case intValue:
00821       return value_.int_ < other.value_.int_;
00822    case uintValue:
00823       return value_.uint_ < other.value_.uint_;
00824    case realValue:
00825       return value_.real_ < other.value_.real_;
00826    case booleanValue:
00827       return value_.bool_ < other.value_.bool_;
00828    case stringValue:
00829       return ( value_.string_ == 0  &&  other.value_.string_ )
00830              || ( other.value_.string_  
00831                   &&  value_.string_  
00832                   && strcmp( value_.string_, other.value_.string_ ) < 0 );
00833 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00834    case arrayValue:
00835    case objectValue:
00836       {
00837          int delta = int( value_.map_->size() - other.value_.map_->size() );
00838          if ( delta )
00839             return delta < 0;
00840          return (*value_.map_) < (*other.value_.map_);
00841       }
00842 #else
00843    case arrayValue:
00844       return value_.array_->compare( *(other.value_.array_) ) < 0;
00845    case objectValue:
00846       return value_.map_->compare( *(other.value_.map_) ) < 0;
00847 #endif
00848    default:
00849       JSON_ASSERT_UNREACHABLE;
00850    }
00851    return 0;  // unreachable
00852 }
00853 
00854 bool 
00855 Value::operator <=( const Value &other ) const
00856 {
00857    return !(other > *this);
00858 }
00859 
00860 bool 
00861 Value::operator >=( const Value &other ) const
00862 {
00863    return !(*this < other);
00864 }
00865 
00866 bool 
00867 Value::operator >( const Value &other ) const
00868 {
00869    return other < *this;
00870 }
00871 
00872 bool 
00873 Value::operator ==( const Value &other ) const
00874 {
00875    //if ( type_ != other.type_ )
00876    // GCC 2.95.3 says:
00877    // attempt to take address of bit-field structure member `Json::Value::type_'
00878    // Beats me, but a temp solves the problem.
00879    int temp = other.type_;
00880    if ( type_ != temp )
00881       return false;
00882    switch ( type_ )
00883    {
00884    case nullValue:
00885       return true;
00886    case intValue:
00887       return value_.int_ == other.value_.int_;
00888    case uintValue:
00889       return value_.uint_ == other.value_.uint_;
00890    case realValue:
00891       return value_.real_ == other.value_.real_;
00892    case booleanValue:
00893       return value_.bool_ == other.value_.bool_;
00894    case stringValue:
00895       return ( value_.string_ == other.value_.string_ )
00896              || ( other.value_.string_  
00897                   &&  value_.string_  
00898                   && strcmp( value_.string_, other.value_.string_ ) == 0 );
00899 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00900    case arrayValue:
00901    case objectValue:
00902       return value_.map_->size() == other.value_.map_->size()
00903              && (*value_.map_) == (*other.value_.map_);
00904 #else
00905    case arrayValue:
00906       return value_.array_->compare( *(other.value_.array_) ) == 0;
00907    case objectValue:
00908       return value_.map_->compare( *(other.value_.map_) ) == 0;
00909 #endif
00910    default:
00911       JSON_ASSERT_UNREACHABLE;
00912    }
00913    return 0;  // unreachable
00914 }
00915 
00916 bool 
00917 Value::operator !=( const Value &other ) const
00918 {
00919    return !( *this == other );
00920 }
00921 
00922 const char *
00923 Value::asCString() const
00924 {
00925    JSON_ASSERT( type_ == stringValue );
00926    return value_.string_;
00927 }
00928 
00929 std::string 
00930 Value::asString() const
00931 {
00932    switch ( type_ )
00933    {
00934    case nullValue:
00935       return "";
00936    case stringValue:
00937       return value_.string_ ? value_.string_ : "";
00938    case booleanValue:
00939       return value_.bool_ ? "true" : "false";
00940    case intValue:
00941        {
00942            std::stringstream buf;
00943            buf << value_.int_;
00944                    std::string bufStr;
00945                    bufStr = buf.str();
00946            return bufStr;
00947        }
00948    case uintValue:
00949        {
00950            std::stringstream buf;
00951            buf << value_.uint_;
00952            std::string bufStr;
00953                    bufStr = buf.str();
00954                    return bufStr;
00955        }
00956    case realValue:
00957        {
00958            std::stringstream buf;
00959            buf << value_.real_;
00960            std::string bufStr;
00961                    bufStr = buf.str();
00962                    return bufStr;
00963        }
00964    case arrayValue:
00965    case objectValue:
00966       JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
00967    default:
00968       JSON_ASSERT_UNREACHABLE;
00969    }
00970    return ""; // unreachable
00971 }
00972 
00973 # ifdef JSON_USE_CPPTL
00974 CppTL::ConstString 
00975 Value::asConstString() const
00976 {
00977    return CppTL::ConstString( asString().c_str() );
00978 }
00979 # endif
00980 
00981 Value::Int 
00982 Value::asInt() const
00983 {
00984    switch ( type_ )
00985    {
00986    case nullValue:
00987       return 0;
00988    case intValue:
00989       return value_.int_;
00990    case uintValue:
00991       JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
00992       return value_.uint_;
00993    case realValue:
00994       JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
00995       return Int( value_.real_ );
00996    case booleanValue:
00997       return value_.bool_ ? 1 : 0;
00998    case stringValue:
00999    case arrayValue:
01000    case objectValue:
01001       JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
01002    default:
01003       JSON_ASSERT_UNREACHABLE;
01004    }
01005    return 0; // unreachable;
01006 }
01007 
01008 Value::UInt 
01009 Value::asUInt() const
01010 {
01011    switch ( type_ )
01012    {
01013    case nullValue:
01014       return 0;
01015    case intValue:
01016       JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
01017       return value_.int_;
01018    case uintValue:
01019       return value_.uint_;
01020    case realValue:
01021       JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
01022       return UInt( value_.real_ );
01023    case booleanValue:
01024       return value_.bool_ ? 1 : 0;
01025    case stringValue:
01026    case arrayValue:
01027    case objectValue:
01028       JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
01029    default:
01030       JSON_ASSERT_UNREACHABLE;
01031    }
01032    return 0; // unreachable;
01033 }
01034 
01035 double 
01036 Value::asDouble() const
01037 {
01038    switch ( type_ )
01039    {
01040    case nullValue:
01041       return 0.0;
01042    case intValue:
01043       return value_.int_;
01044    case uintValue:
01045       return value_.uint_;
01046    case realValue:
01047       return value_.real_;
01048    case booleanValue:
01049       return value_.bool_ ? 1.0 : 0.0;
01050    case stringValue:
01051    case arrayValue:
01052    case objectValue:
01053       JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
01054    default:
01055       JSON_ASSERT_UNREACHABLE;
01056    }
01057    return 0; // unreachable;
01058 }
01059 
01060 bool 
01061 Value::asBool() const
01062 {
01063    switch ( type_ )
01064    {
01065    case nullValue:
01066       return false;
01067    case intValue:
01068    case uintValue:
01069       return value_.int_ != 0;
01070    case realValue:
01071       return value_.real_ != 0.0;
01072    case booleanValue:
01073       return value_.bool_;
01074    case stringValue:
01075       return value_.string_  &&  value_.string_[0] != 0;
01076    case arrayValue:
01077    case objectValue:
01078       return value_.map_->size() != 0;
01079    default:
01080       JSON_ASSERT_UNREACHABLE;
01081    }
01082    return false; // unreachable;
01083 }
01084 
01085 
01086 bool 
01087 Value::isConvertibleTo( ValueType other ) const
01088 {
01089    switch ( type_ )
01090    {
01091    case nullValue:
01092       return true;
01093    case intValue:
01094       return ( other == nullValue  &&  value_.int_ == 0 )
01095              || other == intValue
01096              || ( other == uintValue  && value_.int_ >= 0 )
01097              || other == realValue
01098              || other == stringValue
01099              || other == booleanValue;
01100    case uintValue:
01101       return ( other == nullValue  &&  value_.uint_ == 0 )
01102              || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
01103              || other == uintValue
01104              || other == realValue
01105              || other == stringValue
01106              || other == booleanValue;
01107    case realValue:
01108       return ( other == nullValue  &&  value_.real_ == 0.0 )
01109              || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
01110              || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
01111              || other == realValue
01112              || other == stringValue
01113              || other == booleanValue;
01114    case booleanValue:
01115       return ( other == nullValue  &&  value_.bool_ == false )
01116              || other == intValue
01117              || other == uintValue
01118              || other == realValue
01119              || other == stringValue
01120              || other == booleanValue;
01121    case stringValue:
01122       return other == stringValue
01123              || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
01124    case arrayValue:
01125       return other == arrayValue
01126              ||  ( other == nullValue  &&  value_.map_->size() == 0 );
01127    case objectValue:
01128       return other == objectValue
01129              ||  ( other == nullValue  &&  value_.map_->size() == 0 );
01130    default:
01131       JSON_ASSERT_UNREACHABLE;
01132    }
01133    return false; // unreachable;
01134 }
01135 
01136 
01138 Value::UInt 
01139 Value::size() const
01140 {
01141    switch ( type_ )
01142    {
01143    case nullValue:
01144    case intValue:
01145    case uintValue:
01146    case realValue:
01147    case booleanValue:
01148    case stringValue:
01149       return 0;
01150 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01151    case arrayValue:  // size of the array is highest index + 1
01152       if ( !value_.map_->empty() )
01153       {
01154          ObjectValues::const_iterator itLast = value_.map_->end();
01155          --itLast;
01156          return (*itLast).first.index()+1;
01157       }
01158       return 0;
01159    case objectValue:
01160       return Int( value_.map_->size() );
01161 #else
01162    case arrayValue:
01163       return Int( value_.array_->size() );
01164    case objectValue:
01165       return Int( value_.map_->size() );
01166 #endif
01167    default:
01168       JSON_ASSERT_UNREACHABLE;
01169    }
01170    return 0; // unreachable;
01171 }
01172 
01173 
01174 bool 
01175 Value::empty() const
01176 {
01177    if ( isNull() || isArray() || isObject() )
01178       return size() == 0u;
01179    else
01180       return false;
01181 }
01182 
01183 
01184 bool
01185 Value::operator!() const
01186 {
01187    return isNull();
01188 }
01189 
01190 
01191 void 
01192 Value::clear()
01193 {
01194    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );
01195 
01196    switch ( type_ )
01197    {
01198 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01199    case arrayValue:
01200    case objectValue:
01201       value_.map_->clear();
01202       break;
01203 #else
01204    case arrayValue:
01205       value_.array_->clear();
01206       break;
01207    case objectValue:
01208       value_.map_->clear();
01209       break;
01210 #endif
01211    default:
01212       break;
01213    }
01214 }
01215 
01216 void 
01217 Value::resize( UInt newSize )
01218 {
01219    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
01220    if ( type_ == nullValue )
01221       *this = Value( arrayValue );
01222 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01223    UInt oldSize = size();
01224    if ( newSize == 0 )
01225       clear();
01226    else if ( newSize > oldSize )
01227       (*this)[ newSize - 1 ];
01228    else
01229    {
01230       for ( UInt index = newSize; index < oldSize; ++index )
01231          value_.map_->erase( index );
01232       assert( size() == newSize );
01233    }
01234 #else
01235    value_.array_->resize( newSize );
01236 #endif
01237 }
01238 
01239 
01240 Value &
01241 Value::operator[]( UInt index )
01242 {
01243    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
01244    if ( type_ == nullValue )
01245       *this = Value( arrayValue );
01246 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01247    CZString key( index );
01248    ObjectValues::iterator it = value_.map_->lower_bound( key );
01249    if ( it != value_.map_->end()  &&  (*it).first == key )
01250       return (*it).second;
01251 
01252    ObjectValues::value_type defaultValue( key, null );
01253    it = value_.map_->insert( it, defaultValue );
01254    return (*it).second;
01255 #else
01256    return value_.array_->resolveReference( index );
01257 #endif
01258 }
01259 
01260 
01261 const Value &
01262 Value::operator[]( UInt index ) const
01263 {
01264    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
01265    if ( type_ == nullValue )
01266       return null;
01267 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01268    CZString key( index );
01269    ObjectValues::const_iterator it = value_.map_->find( key );
01270    if ( it == value_.map_->end() )
01271       return null;
01272    return (*it).second;
01273 #else
01274    Value *value = value_.array_->find( index );
01275    return value ? *value : null;
01276 #endif
01277 }
01278 
01279 
01280 Value &
01281 Value::operator[]( const char *key )
01282 {
01283    return resolveReference( key, false );
01284 }
01285 
01286 
01287 Value &
01288 Value::resolveReference( const char *key, 
01289                          bool isStatic )
01290 {
01291    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01292    if ( type_ == nullValue )
01293       *this = Value( objectValue );
01294 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01295    CZString actualKey( key, isStatic ? CZString::noDuplication 
01296                                      : CZString::duplicateOnCopy );
01297    ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
01298    if ( it != value_.map_->end()  &&  (*it).first == actualKey )
01299       return (*it).second;
01300 
01301    ObjectValues::value_type defaultValue( actualKey, null );
01302    it = value_.map_->insert( it, defaultValue );
01303    Value &value = (*it).second;
01304    return value;
01305 #else
01306    return value_.map_->resolveReference( key, isStatic );
01307 #endif
01308 }
01309 
01310 
01311 Value 
01312 Value::get( UInt index, 
01313             const Value &defaultValue ) const
01314 {
01315    const Value *value = &((*this)[index]);
01316    return value == &null ? defaultValue : *value;
01317 }
01318 
01319 
01320 bool 
01321 Value::isValidIndex( UInt index ) const
01322 {
01323    return index < size();
01324 }
01325 
01326 
01327 
01328 const Value &
01329 Value::operator[]( const char *key ) const
01330 {
01331    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01332    if ( type_ == nullValue )
01333       return null;
01334 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01335    CZString actualKey( key, CZString::noDuplication );
01336    ObjectValues::const_iterator it = value_.map_->find( actualKey );
01337    if ( it == value_.map_->end() )
01338       return null;
01339    return (*it).second;
01340 #else
01341    const Value *value = value_.map_->find( key );
01342    return value ? *value : null;
01343 #endif
01344 }
01345 
01346 
01347 Value &
01348 Value::operator[]( const std::string &key )
01349 {
01350    return (*this)[ key.c_str() ];
01351 }
01352 
01353 
01354 const Value &
01355 Value::operator[]( const std::string &key ) const
01356 {
01357    return (*this)[ key.c_str() ];
01358 }
01359 
01360 Value &
01361 Value::operator[]( const StaticString &key )
01362 {
01363    return resolveReference( key, true );
01364 }
01365 
01366 
01367 # ifdef JSON_USE_CPPTL
01368 Value &
01369 Value::operator[]( const CppTL::ConstString &key )
01370 {
01371    return (*this)[ key.c_str() ];
01372 }
01373 
01374 
01375 const Value &
01376 Value::operator[]( const CppTL::ConstString &key ) const
01377 {
01378    return (*this)[ key.c_str() ];
01379 }
01380 # endif
01381 
01382 
01383 Value &
01384 Value::append( const Value &value )
01385 {
01386    return (*this)[size()] = value;
01387 }
01388 
01389 
01390 Value 
01391 Value::get( const char *key, 
01392             const Value &defaultValue ) const
01393 {
01394    const Value *value = &((*this)[key]);
01395    return value == &null ? defaultValue : *value;
01396 }
01397 
01398 
01399 Value 
01400 Value::get( const std::string &key,
01401             const Value &defaultValue ) const
01402 {
01403    return get( key.c_str(), defaultValue );
01404 }
01405 
01406 Value
01407 Value::removeMember( const char* key )
01408 {
01409    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01410    if ( type_ == nullValue )
01411       return null;
01412 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01413    CZString actualKey( key, CZString::noDuplication );
01414    ObjectValues::iterator it = value_.map_->find( actualKey );
01415    if ( it == value_.map_->end() )
01416       return null;
01417    Value old(it->second);
01418    value_.map_->erase(it);
01419    return old;
01420 #else
01421    Value *value = value_.map_->find( key );
01422    if (value){
01423       Value old(*value);
01424       value_.map_.remove( key );
01425       return old;
01426    } else {
01427       return null;
01428    }
01429 #endif
01430 }
01431 
01432 Value
01433 Value::removeMember( const std::string &key )
01434 {
01435    return removeMember( key.c_str() );
01436 }
01437 
01438 # ifdef JSON_USE_CPPTL
01439 Value 
01440 Value::get( const CppTL::ConstString &key,
01441             const Value &defaultValue ) const
01442 {
01443    return get( key.c_str(), defaultValue );
01444 }
01445 # endif
01446 
01447 bool 
01448 Value::isMember( const char *key ) const
01449 {
01450    const Value *value = &((*this)[key]);
01451    return value != &null;
01452 }
01453 
01454 
01455 bool 
01456 Value::isMember( const std::string &key ) const
01457 {
01458    return isMember( key.c_str() );
01459 }
01460 
01461 
01462 # ifdef JSON_USE_CPPTL
01463 bool 
01464 Value::isMember( const CppTL::ConstString &key ) const
01465 {
01466    return isMember( key.c_str() );
01467 }
01468 #endif
01469 
01470 Value::Members 
01471 Value::getMemberNames() const
01472 {
01473    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01474    if ( type_ == nullValue )
01475        return Value::Members();
01476    Members members;
01477    members.reserve( value_.map_->size() );
01478 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01479    ObjectValues::const_iterator it = value_.map_->begin();
01480    ObjectValues::const_iterator itEnd = value_.map_->end();
01481    for ( ; it != itEnd; ++it )
01482       members.push_back( std::string( (*it).first.c_str() ) );
01483 #else
01484    ValueInternalMap::IteratorState it;
01485    ValueInternalMap::IteratorState itEnd;
01486    value_.map_->makeBeginIterator( it );
01487    value_.map_->makeEndIterator( itEnd );
01488    for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
01489       members.push_back( std::string( ValueInternalMap::key( it ) ) );
01490 #endif
01491    return members;
01492 }
01493 //
01494 //# ifdef JSON_USE_CPPTL
01495 //EnumMemberNames
01496 //Value::enumMemberNames() const
01497 //{
01498 //   if ( type_ == objectValue )
01499 //   {
01500 //      return CppTL::Enum::any(  CppTL::Enum::transform(
01501 //         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
01502 //         MemberNamesTransform() ) );
01503 //   }
01504 //   return EnumMemberNames();
01505 //}
01506 //
01507 //
01508 //EnumValues 
01509 //Value::enumValues() const
01510 //{
01511 //   if ( type_ == objectValue  ||  type_ == arrayValue )
01512 //      return CppTL::Enum::anyValues( *(value_.map_), 
01513 //                                     CppTL::Type<const Value &>() );
01514 //   return EnumValues();
01515 //}
01516 //
01517 //# endif
01518 
01519 
01520 bool
01521 Value::isNull() const
01522 {
01523    return type_ == nullValue;
01524 }
01525 
01526 
01527 bool 
01528 Value::isBool() const
01529 {
01530    return type_ == booleanValue;
01531 }
01532 
01533 
01534 bool 
01535 Value::isInt() const
01536 {
01537    return type_ == intValue;
01538 }
01539 
01540 
01541 bool 
01542 Value::isUInt() const
01543 {
01544    return type_ == uintValue;
01545 }
01546 
01547 
01548 bool 
01549 Value::isIntegral() const
01550 {
01551    return type_ == intValue  
01552           ||  type_ == uintValue  
01553           ||  type_ == booleanValue;
01554 }
01555 
01556 
01557 bool 
01558 Value::isDouble() const
01559 {
01560    return type_ == realValue;
01561 }
01562 
01563 
01564 bool 
01565 Value::isNumeric() const
01566 {
01567    return isIntegral() || isDouble();
01568 }
01569 
01570 
01571 bool 
01572 Value::isString() const
01573 {
01574    return type_ == stringValue;
01575 }
01576 
01577 
01578 bool 
01579 Value::isArray() const
01580 {
01581    return type_ == nullValue  ||  type_ == arrayValue;
01582 }
01583 
01584 
01585 bool 
01586 Value::isObject() const
01587 {
01588    return type_ == nullValue  ||  type_ == objectValue;
01589 }
01590 
01591 
01592 void 
01593 Value::setComment( const char *comment,
01594                    CommentPlacement placement )
01595 {
01596    if ( !comments_ )
01597       comments_ = new CommentInfo[numberOfCommentPlacement];
01598    comments_[placement].setComment( comment );
01599 }
01600 
01601 
01602 void 
01603 Value::setComment( const std::string &comment,
01604                    CommentPlacement placement )
01605 {
01606    setComment( comment.c_str(), placement );
01607 }
01608 
01609 
01610 bool 
01611 Value::hasComment( CommentPlacement placement ) const
01612 {
01613    return comments_ != 0  &&  comments_[placement].comment_ != 0;
01614 }
01615 
01616 std::string 
01617 Value::getComment( CommentPlacement placement ) const
01618 {
01619    if ( hasComment(placement) )
01620       return comments_[placement].comment_;
01621    return "";
01622 }
01623 
01624 
01625 std::string 
01626 Value::toStyledString() const
01627 {
01628    StyledWriter writer;
01629    return writer.write( *this );
01630 }
01631 
01632 
01633 Value::const_iterator 
01634 Value::begin() const
01635 {
01636    switch ( type_ )
01637    {
01638 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01639    case arrayValue:
01640       if ( value_.array_ )
01641       {
01642          ValueInternalArray::IteratorState it;
01643          value_.array_->makeBeginIterator( it );
01644          return const_iterator( it );
01645       }
01646       break;
01647    case objectValue:
01648       if ( value_.map_ )
01649       {
01650          ValueInternalMap::IteratorState it;
01651          value_.map_->makeBeginIterator( it );
01652          return const_iterator( it );
01653       }
01654       break;
01655 #else
01656    case arrayValue:
01657    case objectValue:
01658       if ( value_.map_ )
01659          return const_iterator( value_.map_->begin() );
01660       break;
01661 #endif
01662    default:
01663       break;
01664    }
01665    return const_iterator();
01666 }
01667 
01668 Value::const_iterator 
01669 Value::end() const
01670 {
01671    switch ( type_ )
01672    {
01673 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01674    case arrayValue:
01675       if ( value_.array_ )
01676       {
01677          ValueInternalArray::IteratorState it;
01678          value_.array_->makeEndIterator( it );
01679          return const_iterator( it );
01680       }
01681       break;
01682    case objectValue:
01683       if ( value_.map_ )
01684       {
01685          ValueInternalMap::IteratorState it;
01686          value_.map_->makeEndIterator( it );
01687          return const_iterator( it );
01688       }
01689       break;
01690 #else
01691    case arrayValue:
01692    case objectValue:
01693       if ( value_.map_ )
01694          return const_iterator( value_.map_->end() );
01695       break;
01696 #endif
01697    default:
01698       break;
01699    }
01700    return const_iterator();
01701 }
01702 
01703 
01704 Value::iterator 
01705 Value::begin()
01706 {
01707    switch ( type_ )
01708    {
01709 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01710    case arrayValue:
01711       if ( value_.array_ )
01712       {
01713          ValueInternalArray::IteratorState it;
01714          value_.array_->makeBeginIterator( it );
01715          return iterator( it );
01716       }
01717       break;
01718    case objectValue:
01719       if ( value_.map_ )
01720       {
01721          ValueInternalMap::IteratorState it;
01722          value_.map_->makeBeginIterator( it );
01723          return iterator( it );
01724       }
01725       break;
01726 #else
01727    case arrayValue:
01728    case objectValue:
01729       if ( value_.map_ )
01730          return iterator( value_.map_->begin() );
01731       break;
01732 #endif
01733    default:
01734       break;
01735    }
01736    return iterator();
01737 }
01738 
01739 Value::iterator 
01740 Value::end()
01741 {
01742    switch ( type_ )
01743    {
01744 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01745    case arrayValue:
01746       if ( value_.array_ )
01747       {
01748          ValueInternalArray::IteratorState it;
01749          value_.array_->makeEndIterator( it );
01750          return iterator( it );
01751       }
01752       break;
01753    case objectValue:
01754       if ( value_.map_ )
01755       {
01756          ValueInternalMap::IteratorState it;
01757          value_.map_->makeEndIterator( it );
01758          return iterator( it );
01759       }
01760       break;
01761 #else
01762    case arrayValue:
01763    case objectValue:
01764       if ( value_.map_ )
01765          return iterator( value_.map_->end() );
01766       break;
01767 #endif
01768    default:
01769       break;
01770    }
01771    return iterator();
01772 }
01773 
01774 
01775 // class PathArgument
01776 // //////////////////////////////////////////////////////////////////
01777 
01778 PathArgument::PathArgument()
01779    : kind_( kindNone )
01780 {
01781 }
01782 
01783 
01784 PathArgument::PathArgument( Value::UInt index )
01785    : index_( index )
01786    , kind_( kindIndex )
01787 {
01788 }
01789 
01790 
01791 PathArgument::PathArgument( const char *key )
01792    : key_( key )
01793    , kind_( kindKey )
01794 {
01795 }
01796 
01797 
01798 PathArgument::PathArgument( const std::string &key )
01799    : key_( key.c_str() )
01800    , kind_( kindKey )
01801 {
01802 }
01803 
01804 // class Path
01805 // //////////////////////////////////////////////////////////////////
01806 
01807 Path::Path( const std::string &path,
01808             const PathArgument &a1,
01809             const PathArgument &a2,
01810             const PathArgument &a3,
01811             const PathArgument &a4,
01812             const PathArgument &a5 )
01813 {
01814    InArgs in;
01815    in.push_back( &a1 );
01816    in.push_back( &a2 );
01817    in.push_back( &a3 );
01818    in.push_back( &a4 );
01819    in.push_back( &a5 );
01820    makePath( path, in );
01821 }
01822 
01823 
01824 void 
01825 Path::makePath( const std::string &path,
01826                 const InArgs &in )
01827 {
01828    const char *current = path.c_str();
01829    const char *end = current + path.length();
01830    InArgs::const_iterator itInArg = in.begin();
01831    while ( current != end )
01832    {
01833       if ( *current == '[' )
01834       {
01835          ++current;
01836          if ( *current == '%' )
01837             addPathInArg( path, in, itInArg, PathArgument::kindIndex );
01838          else
01839          {
01840             Value::UInt index = 0;
01841             for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
01842                index = index * 10 + Value::UInt(*current - '0');
01843             args_.push_back( index );
01844          }
01845          if ( current == end  ||  *current++ != ']' )
01846             invalidPath( path, int(current - path.c_str()) );
01847       }
01848       else if ( *current == '%' )
01849       {
01850          addPathInArg( path, in, itInArg, PathArgument::kindKey );
01851          ++current;
01852       }
01853       else if ( *current == '.' )
01854       {
01855          ++current;
01856       }
01857       else
01858       {
01859          const char *beginName = current;
01860          while ( current != end  &&  !strchr( "[.", *current ) )
01861             ++current;
01862          args_.push_back( std::string( beginName, current ) );
01863       }
01864    }
01865 }
01866 
01867 
01868 void 
01869 Path::addPathInArg( const std::string &path, 
01870                     const InArgs &in, 
01871                     InArgs::const_iterator &itInArg, 
01872                     PathArgument::Kind kind )
01873 {
01874    if ( itInArg == in.end() )
01875    {
01876       // Error: missing argument %d
01877    }
01878    else if ( (*itInArg)->kind_ != kind )
01879    {
01880       // Error: bad argument type
01881    }
01882    else
01883    {
01884       args_.push_back( **itInArg );
01885    }
01886 }
01887 
01888 
01889 void 
01890 Path::invalidPath( const std::string &path, 
01891                    int location )
01892 {
01893    // Error: invalid path.
01894 }
01895 
01896 
01897 const Value &
01898 Path::resolve( const Value &root ) const
01899 {
01900    const Value *node = &root;
01901    for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
01902    {
01903       const PathArgument &arg = *it;
01904       if ( arg.kind_ == PathArgument::kindIndex )
01905       {
01906          if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
01907          {
01908             // Error: unable to resolve path (array value expected at position...
01909          }
01910          node = &((*node)[arg.index_]);
01911       }
01912       else if ( arg.kind_ == PathArgument::kindKey )
01913       {
01914          if ( !node->isObject() )
01915          {
01916             // Error: unable to resolve path (object value expected at position...)
01917          }
01918          node = &((*node)[arg.key_]);
01919          if ( node == &Value::null )
01920          {
01921             // Error: unable to resolve path (object has no member named '' at position...)
01922          }
01923       }
01924    }
01925    return *node;
01926 }
01927 
01928 
01929 Value 
01930 Path::resolve( const Value &root, 
01931                const Value &defaultValue ) const
01932 {
01933    const Value *node = &root;
01934    for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
01935    {
01936       const PathArgument &arg = *it;
01937       if ( arg.kind_ == PathArgument::kindIndex )
01938       {
01939          if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
01940             return defaultValue;
01941          node = &((*node)[arg.index_]);
01942       }
01943       else if ( arg.kind_ == PathArgument::kindKey )
01944       {
01945          if ( !node->isObject() )
01946             return defaultValue;
01947          node = &((*node)[arg.key_]);
01948          if ( node == &Value::null )
01949             return defaultValue;
01950       }
01951    }
01952    return *node;
01953 }
01954 
01955 
01956 Value &
01957 Path::make( Value &root ) const
01958 {
01959    Value *node = &root;
01960    for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
01961    {
01962       const PathArgument &arg = *it;
01963       if ( arg.kind_ == PathArgument::kindIndex )
01964       {
01965          if ( !node->isArray() )
01966          {
01967             // Error: node is not an array at position ...
01968          }
01969          node = &((*node)[arg.index_]);
01970       }
01971       else if ( arg.kind_ == PathArgument::kindKey )
01972       {
01973          if ( !node->isObject() )
01974          {
01975             // Error: node is not an object at position...
01976          }
01977          node = &((*node)[arg.key_]);
01978       }
01979    }
01980    return *node;
01981 }
01982 
01983 
01984 
01985 namespace osgEarth {
01986 
01987     namespace Json {
01988 
01989         static inline bool 
01990         in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
01991         {
01992            return c == c1  ||  c == c2  ||  c == c3  ||  c == c4;
01993         }
01994 
01995         static inline bool 
01996         in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
01997         {
01998            return c == c1  ||  c == c2  ||  c == c3  ||  c == c4  ||  c == c5;
01999         }
02000 
02001 
02002         static bool 
02003         containsNewLine( Reader::Location begin, 
02004                          Reader::Location end )
02005         {
02006            for ( ;begin < end; ++begin )
02007               if ( *begin == '\n'  ||  *begin == '\r' )
02008                  return true;
02009            return false;
02010         }
02011 
02012     }
02013 }
02014 
02015 
02016 // Class Reader
02017 // //////////////////////////////////////////////////////////////////
02018 
02019 Reader::Reader()
02020 {
02021 }
02022 
02023 bool
02024 Reader::parse( const std::string &document, 
02025                Value &root,
02026                bool collectComments )
02027 {
02028    document_ = document;
02029    const char *begin = document_.c_str();
02030    const char *end = begin + document_.length();
02031    return parse( begin, end, root, collectComments );
02032 }
02033 
02034 bool
02035 Reader::parse( std::istream& sin,
02036                Value &root,
02037                bool collectComments )
02038 {
02039    //std::istream_iterator<char> begin(sin);
02040    //std::istream_iterator<char> end;
02041    // Those would allow streamed input from a file, if parse() were a
02042    // template function.
02043 
02044    // Since std::string is reference-counted, this at least does not
02045    // create an extra copy.
02046    std::string doc;
02047    std::getline(sin, doc, (char)EOF);
02048    return parse( doc, root, collectComments );
02049 }
02050 
02051 bool 
02052 Reader::parse( const char *beginDoc, const char *endDoc, 
02053                Value &root,
02054                bool collectComments )
02055 {
02056    begin_ = beginDoc;
02057    end_ = endDoc;
02058    collectComments_ = collectComments;
02059    current_ = begin_;
02060    lastValueEnd_ = 0;
02061    lastValue_ = 0;
02062    commentsBefore_ = "";
02063    errors_.clear();
02064    while ( !nodes_.empty() )
02065       nodes_.pop();
02066    nodes_.push( &root );
02067    
02068    bool successful = readValue();
02069 
02070    Token token;
02071    skipCommentTokens( token );
02072    if ( collectComments_  &&  !commentsBefore_.empty() )
02073       root.setComment( commentsBefore_, commentAfter );
02074 
02075    return successful;
02076 }
02077 
02078 
02079 bool
02080 Reader::readValue()
02081 {
02082    Token token;
02083    skipCommentTokens( token );
02084    bool successful = true;
02085 
02086    if ( collectComments_  &&  !commentsBefore_.empty() )
02087    {
02088       currentValue().setComment( commentsBefore_, commentBefore );
02089       commentsBefore_ = "";
02090    }
02091 
02092 
02093    switch ( token.type_ )
02094    {
02095    case tokenObjectBegin:
02096       successful = readObject( token );
02097       break;
02098    case tokenArrayBegin:
02099       successful = readArray( token );
02100       break;
02101    case tokenNumber:
02102       successful = decodeNumber( token );
02103       break;
02104    case tokenString:
02105       successful = decodeString( token );
02106       break;
02107    case tokenTrue:
02108       currentValue() = true;
02109       break;
02110    case tokenFalse:
02111       currentValue() = false;
02112       break;
02113    case tokenNull:
02114       currentValue() = Value();
02115       break;
02116    default:
02117       return addError( "Syntax error: value, object or array expected.", token );
02118    }
02119 
02120    if ( collectComments_ )
02121    {
02122       lastValueEnd_ = current_;
02123       lastValue_ = &currentValue();
02124    }
02125 
02126    return successful;
02127 }
02128 
02129 
02130 void 
02131 Reader::skipCommentTokens( Token &token )
02132 {
02133    do
02134    {
02135       readToken( token );
02136    }
02137    while ( token.type_ == tokenComment );
02138 }
02139 
02140 
02141 bool 
02142 Reader::expectToken( TokenType type, Token &token, const char *message )
02143 {
02144    readToken( token );
02145    if ( token.type_ != type )
02146       return addError( message, token );
02147    return true;
02148 }
02149 
02150 
02151 bool 
02152 Reader::readToken( Token &token )
02153 {    
02154    skipSpaces();
02155    token.start_ = current_;
02156    Char c = getNextChar();
02157    bool ok = true;
02158    switch ( c )
02159    {
02160    case '{':
02161       token.type_ = tokenObjectBegin;
02162       break;
02163    case '}':
02164       token.type_ = tokenObjectEnd;
02165       break;
02166    case '[':
02167       token.type_ = tokenArrayBegin;
02168       break;
02169    case ']':
02170       token.type_ = tokenArrayEnd;
02171       break;
02172    case '"':
02173       token.type_ = tokenString;
02174       ok = readString();
02175       break;
02176    case '/':
02177       token.type_ = tokenComment;
02178       ok = readComment();
02179       break;
02180    case '0':
02181    case '1':
02182    case '2':
02183    case '3':
02184    case '4':
02185    case '5':
02186    case '6':
02187    case '7':
02188    case '8':
02189    case '9':
02190    case '-':
02191       token.type_ = tokenNumber;
02192       readNumber();
02193       break;
02194    case 't':
02195       token.type_ = tokenTrue;
02196       ok = match( "rue", 3 );
02197       break;
02198    case 'f':
02199       token.type_ = tokenFalse;
02200       ok = match( "alse", 4 );
02201       break;
02202    case 'n':
02203       token.type_ = tokenNull;
02204       ok = match( "ull", 3 );
02205       break;
02206    case ',':
02207       token.type_ = tokenArraySeparator;
02208       break;
02209    case ':':
02210       token.type_ = tokenMemberSeparator;
02211       break;
02212    case 0:
02213       token.type_ = tokenEndOfStream;
02214       break;
02215    default:
02216       ok = false;
02217       break;
02218    }
02219    if ( !ok )
02220       token.type_ = tokenError;
02221    token.end_ = current_;
02222    return true;
02223 }
02224 
02225 
02226 void 
02227 Reader::skipSpaces()
02228 {
02229    while ( current_ != end_ )
02230    {
02231       Char c = *current_;
02232       if ( c == ' '  ||  c == '\t'  ||  c == '\r'  ||  c == '\n' )
02233          ++current_;
02234       else
02235          break;
02236    }
02237 }
02238 
02239 
02240 bool 
02241 Reader::match( Location pattern, 
02242                int patternLength )
02243 {
02244    if ( end_ - current_ < patternLength )
02245       return false;
02246    int index = patternLength;
02247    while ( index-- )
02248       if ( current_[index] != pattern[index] )
02249          return false;
02250    current_ += patternLength;
02251    return true;
02252 }
02253 
02254 
02255 bool
02256 Reader::readComment()
02257 {
02258    Location commentBegin = current_ - 1;
02259    Char c = getNextChar();
02260    bool successful = false;
02261    if ( c == '*' )
02262       successful = readCStyleComment();
02263    else if ( c == '/' )
02264       successful = readCppStyleComment();
02265    if ( !successful )
02266       return false;
02267 
02268    if ( collectComments_ )
02269    {
02270       CommentPlacement placement = commentBefore;
02271       if ( lastValueEnd_  &&  !containsNewLine( lastValueEnd_, commentBegin ) )
02272       {
02273          if ( c != '*'  ||  !containsNewLine( commentBegin, current_ ) )
02274             placement = commentAfterOnSameLine;
02275       }
02276 
02277       addComment( commentBegin, current_, placement );
02278    }
02279    return true;
02280 }
02281 
02282 
02283 void 
02284 Reader::addComment( Location begin, 
02285                     Location end, 
02286                     CommentPlacement placement )
02287 {
02288    assert( collectComments_ );
02289    if ( placement == commentAfterOnSameLine )
02290    {
02291       assert( lastValue_ != 0 );
02292       lastValue_->setComment( std::string( begin, end ), placement );
02293    }
02294    else
02295    {
02296       if ( !commentsBefore_.empty() )
02297          commentsBefore_ += "\n";
02298       commentsBefore_ += std::string( begin, end );
02299    }
02300 }
02301 
02302 
02303 bool 
02304 Reader::readCStyleComment()
02305 {
02306    while ( current_ != end_ )
02307    {
02308       Char c = getNextChar();
02309       if ( c == '*'  &&  *current_ == '/' )
02310          break;
02311    }
02312    return getNextChar() == '/';
02313 }
02314 
02315 
02316 bool 
02317 Reader::readCppStyleComment()
02318 {
02319    while ( current_ != end_ )
02320    {
02321       Char c = getNextChar();
02322       if (  c == '\r'  ||  c == '\n' )
02323          break;
02324    }
02325    return true;
02326 }
02327 
02328 
02329 void 
02330 Reader::readNumber()
02331 {
02332    while ( current_ != end_ )
02333    {
02334       if ( !(*current_ >= '0'  &&  *current_ <= '9')  &&
02335            !in( *current_, '.', 'e', 'E', '+', '-' ) )
02336          break;
02337       ++current_;
02338    }
02339 }
02340 
02341 bool
02342 Reader::readString()
02343 {
02344    Char c = 0;
02345    while ( current_ != end_ )
02346    {
02347       c = getNextChar();
02348       if ( c == '\\' )
02349          getNextChar();
02350       else if ( c == '"' )
02351          break;
02352    }
02353    return c == '"';
02354 }
02355 
02356 
02357 bool 
02358 Reader::readObject( Token &tokenStart )
02359 {
02360    Token tokenName;
02361    std::string name;
02362    currentValue() = Value( objectValue );
02363    while ( readToken( tokenName ) )
02364    {
02365       bool initialTokenOk = true;
02366       while ( tokenName.type_ == tokenComment  &&  initialTokenOk )
02367          initialTokenOk = readToken( tokenName );
02368       if  ( !initialTokenOk )
02369          break;
02370       if ( tokenName.type_ == tokenObjectEnd  &&  name.empty() )  // empty object
02371          return true;
02372       if ( tokenName.type_ != tokenString )
02373          break;
02374       
02375       name = "";
02376       if ( !decodeString( tokenName, name ) )
02377          return recoverFromError( tokenObjectEnd );
02378 
02379       Token colon;
02380       if ( !readToken( colon ) ||  colon.type_ != tokenMemberSeparator )
02381       {
02382          return addErrorAndRecover( "Missing ':' after object member name", 
02383                                     colon, 
02384                                     tokenObjectEnd );
02385       }
02386       Value &value = currentValue()[ name ];
02387       nodes_.push( &value );
02388       bool ok = readValue();
02389       nodes_.pop();
02390       if ( !ok ) // error already set
02391          return recoverFromError( tokenObjectEnd );
02392 
02393       Token comma;
02394       if ( !readToken( comma )
02395             ||  ( comma.type_ != tokenObjectEnd  &&  
02396                   comma.type_ != tokenArraySeparator &&
02397                   comma.type_ != tokenComment ) )
02398       {
02399          return addErrorAndRecover( "Missing ',' or '}' in object declaration", 
02400                                     comma, 
02401                                     tokenObjectEnd );
02402       }
02403       bool finalizeTokenOk = true;
02404       while ( comma.type_ == tokenComment &&
02405               finalizeTokenOk )
02406          finalizeTokenOk = readToken( comma );
02407       if ( comma.type_ == tokenObjectEnd )
02408          return true;
02409    }
02410    return addErrorAndRecover( "Missing '}' or object member name", 
02411                               tokenName, 
02412                               tokenObjectEnd );
02413 }
02414 
02415 
02416 bool 
02417 Reader::readArray( Token &tokenStart )
02418 {
02419    currentValue() = Value( arrayValue );
02420    skipSpaces();
02421    if ( *current_ == ']' ) // empty array
02422    {
02423       Token endArray;
02424       readToken( endArray );
02425       return true;
02426    }
02427    int index = 0;
02428    while ( true )
02429    {
02430       Value &value = currentValue()[ index++ ];
02431       nodes_.push( &value );
02432       bool ok = readValue();
02433       nodes_.pop();
02434       if ( !ok ) // error already set
02435          return recoverFromError( tokenArrayEnd );
02436 
02437       Token token;
02438       if ( !readToken( token ) 
02439            ||  ( token.type_ != tokenArraySeparator  &&  
02440                  token.type_ != tokenArrayEnd ) )
02441       {
02442          return addErrorAndRecover( "Missing ',' or ']' in array declaration", 
02443                                     token, 
02444                                     tokenArrayEnd );
02445       }
02446       if ( token.type_ == tokenArrayEnd )
02447          break;
02448    }
02449    return true;
02450 }
02451 
02452 
02453 bool 
02454 Reader::decodeNumber( Token &token )
02455 {
02456    bool isDouble = false;
02457    for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
02458    {
02459       isDouble = isDouble  
02460                  ||  in( *inspect, '.', 'e', 'E', '+' )  
02461                  ||  ( *inspect == '-'  &&  inspect != token.start_ );
02462    }
02463    if ( isDouble )
02464       return decodeDouble( token );
02465    Location current = token.start_;
02466    bool isNegative = *current == '-';
02467    if ( isNegative )
02468       ++current;
02469    Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) 
02470                                        : Value::maxUInt) / 10;
02471    Value::UInt value = 0;
02472    while ( current < token.end_ )
02473    {
02474       Char c = *current++;
02475       if ( c < '0'  ||  c > '9' )
02476          return addError( std::string("'") + std::string( token.start_, token.end_ ) + std::string("' is not a number."), token );
02477       if ( value >= threshold )
02478          return decodeDouble( token );
02479       value = value * 10 + Value::UInt(c - '0');
02480    }
02481    if ( isNegative )
02482       currentValue() = -Value::Int( value );
02483    else if ( value <= Value::UInt(Value::maxInt) )
02484       currentValue() = Value::Int( value );
02485    else
02486       currentValue() = value;
02487    return true;
02488 }
02489 
02490 
02491 bool 
02492 Reader::decodeDouble( Token &token )
02493 {
02494    double value = 0;
02495    const int bufferSize = 32;
02496    int count;
02497    int length = int(token.end_ - token.start_);
02498    if ( length <= bufferSize )
02499    {
02500       Char buffer[bufferSize];
02501       memcpy( buffer, token.start_, length );
02502       buffer[length] = 0;
02503       count = sscanf( buffer, "%lf", &value );
02504    }
02505    else
02506    {
02507       std::string buffer( token.start_, token.end_ );
02508       count = sscanf( buffer.c_str(), "%lf", &value );
02509    }
02510 
02511    if ( count != 1 )
02512       return addError( std::string("'") + std::string( token.start_, token.end_ ) + std::string("' is not a number."), token );
02513    currentValue() = value;
02514    return true;
02515 }
02516 
02517 
02518 bool 
02519 Reader::decodeString( Token &token )
02520 {
02521    std::string decoded;
02522    if ( !decodeString( token, decoded ) )
02523       return false;
02524    currentValue() = decoded;
02525    return true;
02526 }
02527 
02528 
02529 bool 
02530 Reader::decodeString( Token &token, std::string &decoded )
02531 {
02532    decoded.reserve( token.end_ - token.start_ - 2 );
02533    Location current = token.start_ + 1; // skip '"'
02534    Location end = token.end_ - 1;      // do not include '"'
02535    while ( current != end )
02536    {
02537       Char c = *current++;
02538       if ( c == '"' )
02539          break;
02540       else if ( c == '\\' )
02541       {
02542          if ( current == end )
02543             return addError( "Empty escape sequence in string", token, current );
02544          Char escape = *current++;
02545          switch ( escape )
02546          {
02547          case '"': decoded += '"'; break;
02548          case '/': decoded += '/'; break;
02549          case '\\': decoded += '\\'; break;
02550          case 'b': decoded += '\b'; break;
02551          case 'f': decoded += '\f'; break;
02552          case 'n': decoded += '\n'; break;
02553          case 'r': decoded += '\r'; break;
02554          case 't': decoded += '\t'; break;
02555          case 'u':
02556             {
02557                unsigned int unicode;
02558                if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
02559                   return false;
02560                // @todo encode unicode as utf8.
02561                // @todo remember to alter the writer too.
02562             }
02563             break;
02564          default:
02565             return addError( "Bad escape sequence in string", token, current );
02566          }
02567       }
02568       else
02569       {
02570          decoded += c;
02571       }
02572    }
02573    return true;
02574 }
02575 
02576 
02577 bool 
02578 Reader::decodeUnicodeEscapeSequence( Token &token, 
02579                                      Location &current, 
02580                                      Location end, 
02581                                      unsigned int &unicode )
02582 {
02583    if ( end - current < 4 )
02584       return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
02585    unicode = 0;
02586    for ( int index =0; index < 4; ++index )
02587    {
02588       Char c = *current++;
02589       unicode *= 16;
02590       if ( c >= '0'  &&  c <= '9' )
02591          unicode += c - '0';
02592       else if ( c >= 'a'  &&  c <= 'f' )
02593          unicode += c - 'a' + 10;
02594       else if ( c >= 'A'  &&  c <= 'F' )
02595          unicode += c - 'A' + 10;
02596       else
02597          return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
02598    }
02599    return true;
02600 }
02601 
02602 
02603 bool 
02604 Reader::addError( const std::string &message, 
02605                   Token &token,
02606                   Location extra )
02607 {
02608    ErrorInfo info;
02609    info.token_ = token;
02610    info.message_ = message;
02611    info.extra_ = extra;
02612    errors_.push_back( info );
02613    return false;
02614 }
02615 
02616 
02617 bool 
02618 Reader::recoverFromError( TokenType skipUntilToken )
02619 {
02620    int errorCount = int(errors_.size());
02621    Token skip;
02622    while ( true )
02623    {
02624       if ( !readToken(skip) )
02625          errors_.resize( errorCount ); // discard errors caused by recovery
02626       if ( skip.type_ == skipUntilToken  ||  skip.type_ == tokenEndOfStream )
02627          break;
02628    }
02629    errors_.resize( errorCount );
02630    return false;
02631 }
02632 
02633 
02634 bool 
02635 Reader::addErrorAndRecover( const std::string &message, 
02636                             Token &token,
02637                             TokenType skipUntilToken )
02638 {
02639    addError( message, token );
02640    return recoverFromError( skipUntilToken );
02641 }
02642 
02643 
02644 Value &
02645 Reader::currentValue()
02646 {
02647    return *(nodes_.top());
02648 }
02649 
02650 
02651 Reader::Char 
02652 Reader::getNextChar()
02653 {
02654    if ( current_ == end_ )
02655       return 0;
02656    return *current_++;
02657 }
02658 
02659 
02660 void 
02661 Reader::getLocationLineAndColumn( Location location,
02662                                   int &line,
02663                                   int &column ) const
02664 {
02665    Location current = begin_;
02666    Location lastLineStart = current;
02667    line = 0;
02668    while ( current < location  &&  current != end_ )
02669    {
02670       Char c = *current++;
02671       if ( c == '\r' )
02672       {
02673          if ( *current == '\n' )
02674             ++current;
02675          lastLineStart = current;
02676          ++line;
02677       }
02678       else if ( c == '\n' )
02679       {
02680          lastLineStart = current;
02681          ++line;
02682       }
02683    }
02684    // column & line start at 1
02685    column = int(location - lastLineStart) + 1;
02686    ++line;
02687 }
02688 
02689 
02690 std::string
02691 Reader::getLocationLineAndColumn( Location location ) const
02692 {
02693    int line, column;
02694    getLocationLineAndColumn( location, line, column );
02695    char buffer[18+16+16+1];
02696    sprintf( buffer, "Line %d, Column %d", line, column );
02697    return buffer;
02698 }
02699 
02700 
02701 std::string 
02702 Reader::getFormatedErrorMessages() const
02703 {
02704    std::string formattedMessage;
02705    for ( Errors::const_iterator itError = errors_.begin();
02706          itError != errors_.end();
02707          ++itError )
02708    {
02709       const ErrorInfo &error = *itError;
02710       formattedMessage += std::string("* ") + getLocationLineAndColumn( error.token_.start_ ) + std::string("\n");
02711       formattedMessage += std::string("  ") + error.message_ + std::string("\n");
02712       if ( error.extra_ )
02713          formattedMessage += std::string("See ") + getLocationLineAndColumn( error.extra_ ) + std::string(" for detail.\n");
02714    }
02715    return formattedMessage;
02716 }
02717 
02718 
02719 std::istream& operator>>( std::istream &sin, Value &root )
02720 {
02721     Json::Reader reader;
02722     bool ok = reader.parse(sin, root, true);
02723     //JSON_ASSERT( ok );
02724     if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
02725     return sin;
02726 }
02727 
02728 namespace osgEarth {
02729     namespace Json {
02730 
02731         static void uintToString( unsigned int value, 
02732                                   char *&current )
02733         {
02734            *--current = 0;
02735            do
02736            {
02737               *--current = (value % 10) + '0';
02738               value /= 10;
02739            }
02740            while ( value != 0 );
02741         }
02742 
02743         std::string valueToString( Value::Int value )
02744         {
02745            char buffer[32];
02746            char *current = buffer + sizeof(buffer);
02747            bool isNegative = value < 0;
02748            if ( isNegative )
02749               value = -value;
02750            uintToString( Value::UInt(value), current );
02751            if ( isNegative )
02752               *--current = '-';
02753            assert( current >= buffer );
02754            return current;
02755         }
02756 
02757 
02758         std::string valueToString( Value::UInt value )
02759         {
02760            char buffer[32];
02761            char *current = buffer + sizeof(buffer);
02762            uintToString( value, current );
02763            assert( current >= buffer );
02764            return current;
02765         }
02766 
02767         std::string valueToString( double value )
02768         {
02769            char buffer[32];
02770         #ifdef __STDC_SECURE_LIB__ // Use secure version with visual studio 2005 to avoid warning.
02771            sprintf_s(buffer, sizeof(buffer), "%#.16g", value); 
02772         #else   
02773            sprintf(buffer, "%#.16g", value); 
02774         #endif
02775            char* ch = buffer + strlen(buffer) - 1;
02776            if (*ch != '0') return buffer; // nothing to truncate, so save time
02777            while(ch > buffer && *ch == '0'){
02778              --ch;
02779            }
02780            char* last_nonzero = ch;
02781            while(ch >= buffer){
02782              switch(*ch){
02783              case '0':
02784              case '1':
02785              case '2':
02786              case '3':
02787              case '4':
02788              case '5':
02789              case '6':
02790              case '7':
02791              case '8':
02792              case '9':
02793                --ch;
02794                continue;
02795              case '.':
02796                // Truncate zeroes to save bytes in output, but keep one.
02797                *(last_nonzero+2) = '\0';
02798                return buffer;
02799              default:
02800                return buffer;
02801              }
02802            }
02803            return buffer;
02804         }
02805 
02806 
02807         std::string valueToString( bool value )
02808         {
02809            return value ? "true" : "false";
02810         }
02811 
02812         std::string valueToQuotedString( const char *value )
02813         {
02814             if (value == NULL)
02815                 return "";
02816 
02817            // Not sure how to handle unicode...
02818            if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL)
02819                            return std::string("\"") + std::string(value) + std::string("\"");
02820            // We have to walk value and escape any special characters.
02821            // Appending to std::string is not efficient, but this should be rare.
02822            // (Note: forward slashes are *not* rare, but I am not escaping them.)
02823            unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
02824            std::string result;
02825            result.reserve(maxsize); // to avoid lots of mallocs
02826            result += "\"";
02827            for (const char* c=value; *c != 0; ++c){
02828               switch(*c){
02829                  case '\"':
02830                  result += "\\\"";
02831                  break;
02832                  case '\\':
02833                  result += "\\\\";
02834                  break;
02835                  case '\b':
02836                  result += "\\b";
02837                  break;
02838                  case '\f':
02839                  result += "\\f";
02840                  break;
02841                  case '\n':
02842                  result += "\\n";
02843                  break;
02844                  case '\r':
02845                  result += "\\r";
02846                  break;
02847                  case '\t':
02848                  result += "\\t";
02849                  break;
02850                  case '/':
02851                  // Even though \/ is considered a legal escape in JSON, a bare
02852                  // slash is also legal, so I see no reason to escape it.
02853                  // (I hope I am not misunderstanding something.)
02854                  default:
02855                     result += *c;
02856               }
02857            }
02858            result += "\"";
02859            return result;
02860         }
02861     }
02862 }
02863 
02864 // Class Writer
02865 // //////////////////////////////////////////////////////////////////
02866 Writer::~Writer()
02867 {
02868 }
02869 
02870 
02871 // Class FastWriter
02872 // //////////////////////////////////////////////////////////////////
02873 
02874 FastWriter::FastWriter()
02875    : yamlCompatiblityEnabled_( false )
02876 {
02877 }
02878 
02879 
02880 void 
02881 FastWriter::enableYAMLCompatibility()
02882 {
02883    yamlCompatiblityEnabled_ = true;
02884 }
02885 
02886 
02887 std::string 
02888 FastWriter::write( const Value &root )
02889 {
02890    document_ = "";
02891    writeValue( root );
02892    document_ += "\n";
02893    return document_;
02894 }
02895 
02896 
02897 void 
02898 FastWriter::writeValue( const Value &value )
02899 {
02900    switch ( value.type() )
02901    {
02902    case nullValue:
02903       document_ += "null";
02904       break;
02905    case intValue:
02906       document_ += valueToString( value.asInt() );
02907       break;
02908    case uintValue:
02909       document_ += valueToString( value.asUInt() );
02910       break;
02911    case realValue:
02912       document_ += valueToString( value.asDouble() );
02913       break;
02914    case stringValue:
02915       document_ += valueToQuotedString( value.asCString() );
02916       break;
02917    case booleanValue:
02918       document_ += valueToString( value.asBool() );
02919       break;
02920    case arrayValue:
02921       {
02922          document_ += "[";
02923          int size = value.size();
02924          for ( int index =0; index < size; ++index )
02925          {
02926             if ( index > 0 )
02927                document_ += ",";
02928             writeValue( value[index] );
02929          }
02930          document_ += "]";
02931       }
02932       break;
02933    case objectValue:
02934       {
02935          Value::Members members( value.getMemberNames() );
02936          document_ += "{";
02937          for ( Value::Members::iterator it = members.begin(); 
02938                it != members.end(); 
02939                ++it )
02940          {
02941             const std::string &name = *it;
02942             if ( it != members.begin() )
02943                document_ += ",";
02944             document_ += valueToQuotedString( name.c_str() );
02945             document_ += yamlCompatiblityEnabled_ ? ": " 
02946                                                   : ":";
02947             writeValue( value[name] );
02948          }
02949          document_ += "}";
02950       }
02951       break;
02952    }
02953 }
02954 
02955 
02956 // Class StyledWriter
02957 // //////////////////////////////////////////////////////////////////
02958 
02959 StyledWriter::StyledWriter()
02960    : rightMargin_( 74 )
02961    , indentSize_( 3 )
02962 {
02963 }
02964 
02965 
02966 std::string 
02967 StyledWriter::write( const Value &root )
02968 {
02969    document_ = "";
02970    addChildValues_ = false;
02971    indentString_ = "";
02972    writeCommentBeforeValue( root );
02973    writeValue( root );
02974    writeCommentAfterValueOnSameLine( root );
02975    document_ += "\n";
02976    return document_;
02977 }
02978 
02979 
02980 void 
02981 StyledWriter::writeValue( const Value &value )
02982 {
02983    switch ( value.type() )
02984    {
02985    case nullValue:
02986       pushValue( "null" );
02987       break;
02988    case intValue:
02989       pushValue( valueToString( value.asInt() ) );
02990       break;
02991    case uintValue:
02992       pushValue( valueToString( value.asUInt() ) );
02993       break;
02994    case realValue:
02995       pushValue( valueToString( value.asDouble() ) );
02996       break;
02997    case stringValue:
02998       pushValue( valueToQuotedString( value.asCString() ) );
02999       break;
03000    case booleanValue:
03001       pushValue( valueToString( value.asBool() ) );
03002       break;
03003    case arrayValue:
03004       writeArrayValue( value);
03005       break;
03006    case objectValue:
03007       {
03008          Value::Members members( value.getMemberNames() );
03009          if ( members.empty() )
03010             pushValue( "{}" );
03011          else
03012          {
03013             writeWithIndent( "{" );
03014             indent();
03015             Value::Members::iterator it = members.begin();
03016             while ( true )
03017             {
03018                const std::string &name = *it;
03019                const Value &childValue = value[name];
03020                writeCommentBeforeValue( childValue );
03021                writeWithIndent( valueToQuotedString( name.c_str() ) );
03022                document_ += " : ";
03023                writeValue( childValue );
03024                if ( ++it == members.end() )
03025                {
03026                   writeCommentAfterValueOnSameLine( childValue );
03027                   break;
03028                }
03029                document_ += ",";
03030                writeCommentAfterValueOnSameLine( childValue );
03031             }
03032             unindent();
03033             writeWithIndent( "}" );
03034          }
03035       }
03036       break;
03037    }
03038 }
03039 
03040 
03041 void 
03042 StyledWriter::writeArrayValue( const Value &value )
03043 {
03044    unsigned size = value.size();
03045    if ( size == 0 )
03046       pushValue( "[]" );
03047    else
03048    {
03049       bool isArrayMultiLine = isMultineArray( value );
03050       if ( isArrayMultiLine )
03051       {
03052          writeWithIndent( "[" );
03053          indent();
03054          bool hasChildValue = !childValues_.empty();
03055          unsigned index =0;
03056          while ( true )
03057          {
03058             const Value &childValue = value[index];
03059             writeCommentBeforeValue( childValue );
03060             if ( hasChildValue )
03061                writeWithIndent( childValues_[index] );
03062             else
03063             {
03064                writeIndent();
03065                writeValue( childValue );
03066             }
03067             if ( ++index == size )
03068             {
03069                writeCommentAfterValueOnSameLine( childValue );
03070                break;
03071             }
03072             document_ += ",";
03073             writeCommentAfterValueOnSameLine( childValue );
03074          }
03075          unindent();
03076          writeWithIndent( "]" );
03077       }
03078       else // output on a single line
03079       {
03080          assert( childValues_.size() == size );
03081          document_ += "[ ";
03082          for ( unsigned index =0; index < size; ++index )
03083          {
03084             if ( index > 0 )
03085                document_ += ", ";
03086             document_ += childValues_[index];
03087          }
03088          document_ += " ]";
03089       }
03090    }
03091 }
03092 
03093 
03094 bool 
03095 StyledWriter::isMultineArray( const Value &value )
03096 {
03097    int size = value.size();
03098    bool isMultiLine = size*3 >= rightMargin_ ;
03099    childValues_.clear();
03100    for ( int index =0; index < size  &&  !isMultiLine; ++index )
03101    {
03102       const Value &childValue = value[index];
03103       isMultiLine = isMultiLine  ||
03104                      ( (childValue.isArray()  ||  childValue.isObject())  &&  
03105                         childValue.size() > 0 );
03106    }
03107    if ( !isMultiLine ) // check if line length > max line length
03108    {
03109       childValues_.reserve( size );
03110       addChildValues_ = true;
03111       int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
03112       for ( int index =0; index < size  &&  !isMultiLine; ++index )
03113       {
03114          writeValue( value[index] );
03115          lineLength += int( childValues_[index].length() );
03116          isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
03117       }
03118       addChildValues_ = false;
03119       isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
03120    }
03121    return isMultiLine;
03122 }
03123 
03124 
03125 void 
03126 StyledWriter::pushValue( const std::string &value )
03127 {
03128    if ( addChildValues_ )
03129       childValues_.push_back( value );
03130    else
03131       document_ += value;
03132 }
03133 
03134 
03135 void 
03136 StyledWriter::writeIndent()
03137 {
03138    if ( !document_.empty() )
03139    {
03140       char last = document_[document_.length()-1];
03141       if ( last == ' ' )     // already indented
03142          return;
03143       if ( last != '\n' )    // Comments may add new-line
03144          document_ += '\n';
03145    }
03146    document_ += indentString_;
03147 }
03148 
03149 
03150 void 
03151 StyledWriter::writeWithIndent( const std::string &value )
03152 {
03153    writeIndent();
03154    document_ += value;
03155 }
03156 
03157 
03158 void 
03159 StyledWriter::indent()
03160 {
03161    indentString_ += std::string( indentSize_, ' ' );
03162 }
03163 
03164 
03165 void 
03166 StyledWriter::unindent()
03167 {
03168    assert( int(indentString_.size()) >= indentSize_ );
03169    indentString_.resize( indentString_.size() - indentSize_ );
03170 }
03171 
03172 
03173 void 
03174 StyledWriter::writeCommentBeforeValue( const Value &root )
03175 {
03176    if ( !root.hasComment( commentBefore ) )
03177       return;
03178    document_ += normalizeEOL( root.getComment( commentBefore ) );
03179    document_ += "\n";
03180 }
03181 
03182 
03183 void 
03184 StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
03185 {
03186    if ( root.hasComment( commentAfterOnSameLine ) )
03187       document_ += std::string(" ") + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
03188 
03189    if ( root.hasComment( commentAfter ) )
03190    {
03191       document_ += "\n";
03192       document_ += normalizeEOL( root.getComment( commentAfter ) );
03193       document_ += "\n";
03194    }
03195 }
03196 
03197 
03198 bool 
03199 StyledWriter::hasCommentForValue( const Value &value )
03200 {
03201    return value.hasComment( commentBefore )
03202           ||  value.hasComment( commentAfterOnSameLine )
03203           ||  value.hasComment( commentAfter );
03204 }
03205 
03206 
03207 std::string 
03208 StyledWriter::normalizeEOL( const std::string &text )
03209 {
03210    std::string normalized;
03211    normalized.reserve( text.length() );
03212    const char *begin = text.c_str();
03213    const char *end = begin + text.length();
03214    const char *current = begin;
03215    while ( current != end )
03216    {
03217       char c = *current++;
03218       if ( c == '\r' ) // mac or dos EOL
03219       {
03220          if ( *current == '\n' ) // convert dos EOL
03221             ++current;
03222          normalized += '\n';
03223       }
03224       else // handle unix EOL & other char
03225          normalized += c;
03226    }
03227    return normalized;
03228 }
03229 
03230 
03231 // Class StyledStreamWriter
03232 // //////////////////////////////////////////////////////////////////
03233 
03234 StyledStreamWriter::StyledStreamWriter( std::string indentation )
03235    : document_(NULL)
03236    , rightMargin_( 74 )
03237    , indentation_( indentation )
03238 {
03239 }
03240 
03241 
03242 void
03243 StyledStreamWriter::write( std::ostream &out, const Value &root )
03244 {
03245    document_ = &out;
03246    addChildValues_ = false;
03247    indentString_ = "";
03248    writeCommentBeforeValue( root );
03249    writeValue( root );
03250    writeCommentAfterValueOnSameLine( root );
03251    *document_ << "\n";
03252    document_ = NULL; // Forget the stream, for safety.
03253 }
03254 
03255 
03256 void 
03257 StyledStreamWriter::writeValue( const Value &value )
03258 {
03259    switch ( value.type() )
03260    {
03261    case nullValue:
03262       pushValue( "null" );
03263       break;
03264    case intValue:
03265       pushValue( valueToString( value.asInt() ) );
03266       break;
03267    case uintValue:
03268       pushValue( valueToString( value.asUInt() ) );
03269       break;
03270    case realValue:
03271       pushValue( valueToString( value.asDouble() ) );
03272       break;
03273    case stringValue:
03274       pushValue( valueToQuotedString( value.asCString() ) );
03275       break;
03276    case booleanValue:
03277       pushValue( valueToString( value.asBool() ) );
03278       break;
03279    case arrayValue:
03280       writeArrayValue( value);
03281       break;
03282    case objectValue:
03283       {
03284          Value::Members members( value.getMemberNames() );
03285          if ( members.empty() )
03286             pushValue( "{}" );
03287          else
03288          {
03289             writeWithIndent( "{" );
03290             indent();
03291             Value::Members::iterator it = members.begin();
03292             while ( true )
03293             {
03294                const std::string &name = *it;
03295                const Value &childValue = value[name];
03296                writeCommentBeforeValue( childValue );
03297                writeWithIndent( valueToQuotedString( name.c_str() ) );
03298                *document_ << " : ";
03299                writeValue( childValue );
03300                if ( ++it == members.end() )
03301                {
03302                   writeCommentAfterValueOnSameLine( childValue );
03303                   break;
03304                }
03305                *document_ << ",";
03306                writeCommentAfterValueOnSameLine( childValue );
03307             }
03308             unindent();
03309             writeWithIndent( "}" );
03310          }
03311       }
03312       break;
03313    }
03314 }
03315 
03316 
03317 void 
03318 StyledStreamWriter::writeArrayValue( const Value &value )
03319 {
03320    unsigned size = value.size();
03321    if ( size == 0 )
03322       pushValue( "[]" );
03323    else
03324    {
03325       bool isArrayMultiLine = isMultineArray( value );
03326       if ( isArrayMultiLine )
03327       {
03328          writeWithIndent( "[" );
03329          indent();
03330          bool hasChildValue = !childValues_.empty();
03331          unsigned index =0;
03332          while ( true )
03333          {
03334             const Value &childValue = value[index];
03335             writeCommentBeforeValue( childValue );
03336             if ( hasChildValue )
03337                writeWithIndent( childValues_[index] );
03338             else
03339             {
03340                writeIndent();
03341                writeValue( childValue );
03342             }
03343             if ( ++index == size )
03344             {
03345                writeCommentAfterValueOnSameLine( childValue );
03346                break;
03347             }
03348             *document_ << ",";
03349             writeCommentAfterValueOnSameLine( childValue );
03350          }
03351          unindent();
03352          writeWithIndent( "]" );
03353       }
03354       else // output on a single line
03355       {
03356          assert( childValues_.size() == size );
03357          *document_ << "[ ";
03358          for ( unsigned index =0; index < size; ++index )
03359          {
03360             if ( index > 0 )
03361                *document_ << ", ";
03362             *document_ << childValues_[index];
03363          }
03364          *document_ << " ]";
03365       }
03366    }
03367 }
03368 
03369 
03370 bool 
03371 StyledStreamWriter::isMultineArray( const Value &value )
03372 {
03373    int size = value.size();
03374    bool isMultiLine = size*3 >= rightMargin_ ;
03375    childValues_.clear();
03376    for ( int index =0; index < size  &&  !isMultiLine; ++index )
03377    {
03378       const Value &childValue = value[index];
03379       isMultiLine = isMultiLine  ||
03380                      ( (childValue.isArray()  ||  childValue.isObject())  &&  
03381                         childValue.size() > 0 );
03382    }
03383    if ( !isMultiLine ) // check if line length > max line length
03384    {
03385       childValues_.reserve( size );
03386       addChildValues_ = true;
03387       int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
03388       for ( int index =0; index < size  &&  !isMultiLine; ++index )
03389       {
03390          writeValue( value[index] );
03391          lineLength += int( childValues_[index].length() );
03392          isMultiLine = isMultiLine  &&  hasCommentForValue( value[index] );
03393       }
03394       addChildValues_ = false;
03395       isMultiLine = isMultiLine  ||  lineLength >= rightMargin_;
03396    }
03397    return isMultiLine;
03398 }
03399 
03400 
03401 void 
03402 StyledStreamWriter::pushValue( const std::string &value )
03403 {
03404    if ( addChildValues_ )
03405       childValues_.push_back( value );
03406    else
03407       *document_ << value;
03408 }
03409 
03410 
03411 void 
03412 StyledStreamWriter::writeIndent()
03413 {
03414   /*
03415     Some comments in this method would have been nice. ;-)
03416 
03417    if ( !document_.empty() )
03418    {
03419       char last = document_[document_.length()-1];
03420       if ( last == ' ' )     // already indented
03421          return;
03422       if ( last != '\n' )    // Comments may add new-line
03423          *document_ << '\n';
03424    }
03425   */
03426    *document_ << '\n' << indentString_;
03427 }
03428 
03429 
03430 void 
03431 StyledStreamWriter::writeWithIndent( const std::string &value )
03432 {
03433    writeIndent();
03434    *document_ << value;
03435 }
03436 
03437 
03438 void 
03439 StyledStreamWriter::indent()
03440 {
03441    indentString_ += indentation_;
03442 }
03443 
03444 
03445 void 
03446 StyledStreamWriter::unindent()
03447 {
03448    assert( indentString_.size() >= indentation_.size() );
03449    indentString_.resize( indentString_.size() - indentation_.size() );
03450 }
03451 
03452 
03453 void 
03454 StyledStreamWriter::writeCommentBeforeValue( const Value &root )
03455 {
03456    if ( !root.hasComment( commentBefore ) )
03457       return;
03458    *document_ << normalizeEOL( root.getComment( commentBefore ) );
03459    *document_ << "\n";
03460 }
03461 
03462 
03463 void 
03464 StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
03465 {
03466    if ( root.hasComment( commentAfterOnSameLine ) )
03467       *document_ << std::string(" ") + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
03468 
03469    if ( root.hasComment( commentAfter ) )
03470    {
03471       *document_ << "\n";
03472       *document_ << normalizeEOL( root.getComment( commentAfter ) );
03473       *document_ << "\n";
03474    }
03475 }
03476 
03477 
03478 bool 
03479 StyledStreamWriter::hasCommentForValue( const Value &value )
03480 {
03481    return value.hasComment( commentBefore )
03482           ||  value.hasComment( commentAfterOnSameLine )
03483           ||  value.hasComment( commentAfter );
03484 }
03485 
03486 
03487 std::string 
03488 StyledStreamWriter::normalizeEOL( const std::string &text )
03489 {
03490    std::string normalized;
03491    normalized.reserve( text.length() );
03492    const char *begin = text.c_str();
03493    const char *end = begin + text.length();
03494    const char *current = begin;
03495    while ( current != end )
03496    {
03497       char c = *current++;
03498       if ( c == '\r' ) // mac or dos EOL
03499       {
03500          if ( *current == '\n' ) // convert dos EOL
03501             ++current;
03502          normalized += '\n';
03503       }
03504       else // handle unix EOL & other char
03505          normalized += c;
03506    }
03507    return normalized;
03508 }
03509 
03510 
03511 std::ostream& operator<<( std::ostream &sout, const Value &root )
03512 {
03513    Json::StyledStreamWriter writer;
03514    writer.write(sout, root);
03515    return sout;
03516 }
03517 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines