osgEarth 2.1.1
|
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 ¤t ) 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 ¤t ) 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 ¤t ) 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_ = ¤tValue(); 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 ¤t, 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 *¤t ) 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