json_value.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <bwi_tools/json/value.h>
00003 #include <bwi_tools/json/writer.h>
00004 #include <utility>
00005 #include <stdexcept>
00006 #include <cstring>
00007 #include <cassert>
00008 #ifdef JSON_USE_CPPTL
00009 # include <cpptl/conststring.h>
00010 #endif
00011 #include <cstddef>    // size_t
00012 #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00013 # include "json_batchallocator.h"
00014 #endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
00015 
00016 #define JSON_ASSERT_UNREACHABLE assert( false )
00017 #define JSON_ASSERT( condition ) assert( condition );  // @todo <= change this into an exception throw
00018 #define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
00019 
00020 namespace Json {
00021 
00022 const Value Value::null;
00023 const Int Value::minInt = Int( ~(UInt(-1)/2) );
00024 const Int Value::maxInt = Int( UInt(-1)/2 );
00025 const UInt Value::maxUInt = UInt(-1);
00026 
00027 // A "safe" implementation of strdup. Allow null pointer to be passed. 
00028 // Also avoid warning on msvc80.
00029 //
00030 //inline char *safeStringDup( const char *czstring )
00031 //{
00032 //   if ( czstring )
00033 //   {
00034 //      const size_t length = (unsigned int)( strlen(czstring) + 1 );
00035 //      char *newString = static_cast<char *>( malloc( length ) );
00036 //      memcpy( newString, czstring, length );
00037 //      return newString;
00038 //   }
00039 //   return 0;
00040 //}
00041 //
00042 //inline char *safeStringDup( const std::string &str )
00043 //{
00044 //   if ( !str.empty() )
00045 //   {
00046 //      const size_t length = str.length();
00047 //      char *newString = static_cast<char *>( malloc( length + 1 ) );
00048 //      memcpy( newString, str.c_str(), length );
00049 //      newString[length] = 0;
00050 //      return newString;
00051 //   }
00052 //   return 0;
00053 //}
00054 
00055 ValueAllocator::~ValueAllocator()
00056 {
00057 }
00058 
00059 class DefaultValueAllocator : public ValueAllocator
00060 {
00061 public:
00062    virtual ~DefaultValueAllocator()
00063    {
00064    }
00065 
00066    virtual char *makeMemberName( const char *memberName )
00067    {
00068       return duplicateStringValue( memberName );
00069    }
00070 
00071    virtual void releaseMemberName( char *memberName )
00072    {
00073       releaseStringValue( memberName );
00074    }
00075 
00076    virtual char *duplicateStringValue( const char *value, 
00077                                        unsigned int length = unknown )
00078    {
00079       //@todo invesgate this old optimization
00080       //if ( !value  ||  value[0] == 0 )
00081       //   return 0;
00082 
00083       if ( length == unknown )
00084          length = (unsigned int)strlen(value);
00085       char *newString = static_cast<char *>( malloc( length + 1 ) );
00086       memcpy( newString, value, length );
00087       newString[length] = 0;
00088       return newString;
00089    }
00090 
00091    virtual void releaseStringValue( char *value )
00092    {
00093       if ( value )
00094          free( value );
00095    }
00096 };
00097 
00098 static ValueAllocator *&valueAllocator()
00099 {
00100    static DefaultValueAllocator defaultAllocator;
00101    static ValueAllocator *valueAllocator = &defaultAllocator;
00102    return valueAllocator;
00103 }
00104 
00105 static struct DummyValueAllocatorInitializer {
00106    DummyValueAllocatorInitializer() 
00107    {
00108       valueAllocator();      // ensure valueAllocator() statics are initialized before main().
00109    }
00110 } dummyValueAllocatorInitializer;
00111 
00112 
00113 
00114 // //////////////////////////////////////////////////////////////////
00115 // //////////////////////////////////////////////////////////////////
00116 // //////////////////////////////////////////////////////////////////
00117 // ValueInternals...
00118 // //////////////////////////////////////////////////////////////////
00119 // //////////////////////////////////////////////////////////////////
00120 // //////////////////////////////////////////////////////////////////
00121 #ifdef JSON_VALUE_USE_INTERNAL_MAP
00122 # include "json_internalarray.inl"
00123 # include "json_internalmap.inl"
00124 #endif // JSON_VALUE_USE_INTERNAL_MAP
00125 
00126 # include "json_valueiterator.inl"
00127 
00128 
00129 // //////////////////////////////////////////////////////////////////
00130 // //////////////////////////////////////////////////////////////////
00131 // //////////////////////////////////////////////////////////////////
00132 // class Value::CommentInfo
00133 // //////////////////////////////////////////////////////////////////
00134 // //////////////////////////////////////////////////////////////////
00135 // //////////////////////////////////////////////////////////////////
00136 
00137 
00138 Value::CommentInfo::CommentInfo()
00139    : comment_( 0 )
00140 {
00141 }
00142 
00143 Value::CommentInfo::~CommentInfo()
00144 {
00145    if ( comment_ )
00146       valueAllocator()->releaseStringValue( comment_ );
00147 }
00148 
00149 
00150 void 
00151 Value::CommentInfo::setComment( const char *text )
00152 {
00153    if ( comment_ )
00154       valueAllocator()->releaseStringValue( comment_ );
00155    JSON_ASSERT( text );
00156    JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
00157    // It seems that /**/ style comments are acceptable as well.
00158    comment_ = valueAllocator()->duplicateStringValue( text );
00159 }
00160 
00161 
00162 // //////////////////////////////////////////////////////////////////
00163 // //////////////////////////////////////////////////////////////////
00164 // //////////////////////////////////////////////////////////////////
00165 // class Value::CZString
00166 // //////////////////////////////////////////////////////////////////
00167 // //////////////////////////////////////////////////////////////////
00168 // //////////////////////////////////////////////////////////////////
00169 # ifndef JSON_VALUE_USE_INTERNAL_MAP
00170 
00171 // Notes: index_ indicates if the string was allocated when
00172 // a string is stored.
00173 
00174 Value::CZString::CZString( int index )
00175    : cstr_( 0 )
00176    , index_( index )
00177 {
00178 }
00179 
00180 Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
00181    : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr) 
00182                                   : cstr )
00183    , index_( allocate )
00184 {
00185 }
00186 
00187 Value::CZString::CZString( const CZString &other )
00188 : cstr_( other.index_ != noDuplication &&  other.cstr_ != 0
00189                 ?  valueAllocator()->makeMemberName( other.cstr_ )
00190                 : other.cstr_ )
00191    , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
00192                          : other.index_ )
00193 {
00194 }
00195 
00196 Value::CZString::~CZString()
00197 {
00198    if ( cstr_  &&  index_ == duplicate )
00199       valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
00200 }
00201 
00202 void 
00203 Value::CZString::swap( CZString &other )
00204 {
00205    std::swap( cstr_, other.cstr_ );
00206    std::swap( index_, other.index_ );
00207 }
00208 
00209 Value::CZString &
00210 Value::CZString::operator =( const CZString &other )
00211 {
00212    CZString temp( other );
00213    swap( temp );
00214    return *this;
00215 }
00216 
00217 bool 
00218 Value::CZString::operator<( const CZString &other ) const 
00219 {
00220    if ( cstr_ )
00221       return strcmp( cstr_, other.cstr_ ) < 0;
00222    return index_ < other.index_;
00223 }
00224 
00225 bool 
00226 Value::CZString::operator==( const CZString &other ) const 
00227 {
00228    if ( cstr_ )
00229       return strcmp( cstr_, other.cstr_ ) == 0;
00230    return index_ == other.index_;
00231 }
00232 
00233 
00234 int 
00235 Value::CZString::index() const
00236 {
00237    return index_;
00238 }
00239 
00240 
00241 const char *
00242 Value::CZString::c_str() const
00243 {
00244    return cstr_;
00245 }
00246 
00247 bool 
00248 Value::CZString::isStaticString() const
00249 {
00250    return index_ == noDuplication;
00251 }
00252 
00253 #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
00254 
00255 
00256 // //////////////////////////////////////////////////////////////////
00257 // //////////////////////////////////////////////////////////////////
00258 // //////////////////////////////////////////////////////////////////
00259 // class Value::Value
00260 // //////////////////////////////////////////////////////////////////
00261 // //////////////////////////////////////////////////////////////////
00262 // //////////////////////////////////////////////////////////////////
00263 
00268 Value::Value( ValueType type )
00269    : type_( type )
00270    , allocated_( 0 )
00271    , comments_( 0 )
00272 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00273    , itemIsUsed_( 0 )
00274 #endif
00275 {
00276    switch ( type )
00277    {
00278    case nullValue:
00279       break;
00280    case intValue:
00281    case uintValue:
00282       value_.int_ = 0;
00283       break;
00284    case realValue:
00285       value_.real_ = 0.0;
00286       break;
00287    case stringValue:
00288       value_.string_ = 0;
00289       break;
00290 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00291    case arrayValue:
00292    case objectValue:
00293       value_.map_ = new ObjectValues();
00294       break;
00295 #else
00296    case arrayValue:
00297       value_.array_ = arrayAllocator()->newArray();
00298       break;
00299    case objectValue:
00300       value_.map_ = mapAllocator()->newMap();
00301       break;
00302 #endif
00303    case booleanValue:
00304       value_.bool_ = false;
00305       break;
00306    default:
00307       JSON_ASSERT_UNREACHABLE;
00308    }
00309 }
00310 
00311 
00312 Value::Value( Int value )
00313    : type_( intValue )
00314    , comments_( 0 )
00315 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00316    , itemIsUsed_( 0 )
00317 #endif
00318 {
00319    value_.int_ = value;
00320 }
00321 
00322 
00323 Value::Value( UInt value )
00324    : type_( uintValue )
00325    , comments_( 0 )
00326 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00327    , itemIsUsed_( 0 )
00328 #endif
00329 {
00330    value_.uint_ = value;
00331 }
00332 
00333 Value::Value( double value )
00334    : type_( realValue )
00335    , comments_( 0 )
00336 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00337    , itemIsUsed_( 0 )
00338 #endif
00339 {
00340    value_.real_ = value;
00341 }
00342 
00343 Value::Value( const char *value )
00344    : type_( stringValue )
00345    , allocated_( true )
00346    , comments_( 0 )
00347 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00348    , itemIsUsed_( 0 )
00349 #endif
00350 {
00351    value_.string_ = valueAllocator()->duplicateStringValue( value );
00352 }
00353 
00354 
00355 Value::Value( const char *beginValue, 
00356               const char *endValue )
00357    : type_( stringValue )
00358    , allocated_( true )
00359    , comments_( 0 )
00360 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00361    , itemIsUsed_( 0 )
00362 #endif
00363 {
00364    value_.string_ = valueAllocator()->duplicateStringValue( beginValue, 
00365                                                             UInt(endValue - beginValue) );
00366 }
00367 
00368 
00369 Value::Value( const std::string &value )
00370    : type_( stringValue )
00371    , allocated_( true )
00372    , comments_( 0 )
00373 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00374    , itemIsUsed_( 0 )
00375 #endif
00376 {
00377    value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(), 
00378                                                             (unsigned int)value.length() );
00379 
00380 }
00381 
00382 Value::Value( const StaticString &value )
00383    : type_( stringValue )
00384    , allocated_( false )
00385    , comments_( 0 )
00386 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00387    , itemIsUsed_( 0 )
00388 #endif
00389 {
00390    value_.string_ = const_cast<char *>( value.c_str() );
00391 }
00392 
00393 
00394 # ifdef JSON_USE_CPPTL
00395 Value::Value( const CppTL::ConstString &value )
00396    : type_( stringValue )
00397    , allocated_( true )
00398    , comments_( 0 )
00399 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00400    , itemIsUsed_( 0 )
00401 #endif
00402 {
00403    value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
00404 }
00405 # endif
00406 
00407 Value::Value( bool value )
00408    : type_( booleanValue )
00409    , comments_( 0 )
00410 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00411    , itemIsUsed_( 0 )
00412 #endif
00413 {
00414    value_.bool_ = value;
00415 }
00416 
00417 
00418 Value::Value( const Value &other )
00419    : type_( other.type_ )
00420    , comments_( 0 )
00421 # ifdef JSON_VALUE_USE_INTERNAL_MAP
00422    , itemIsUsed_( 0 )
00423 #endif
00424 {
00425    switch ( type_ )
00426    {
00427    case nullValue:
00428    case intValue:
00429    case uintValue:
00430    case realValue:
00431    case booleanValue:
00432       value_ = other.value_;
00433       break;
00434    case stringValue:
00435       if ( other.value_.string_ )
00436       {
00437          value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
00438          allocated_ = true;
00439       }
00440       else
00441          value_.string_ = 0;
00442       break;
00443 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00444    case arrayValue:
00445    case objectValue:
00446       value_.map_ = new ObjectValues( *other.value_.map_ );
00447       break;
00448 #else
00449    case arrayValue:
00450       value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
00451       break;
00452    case objectValue:
00453       value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
00454       break;
00455 #endif
00456    default:
00457       JSON_ASSERT_UNREACHABLE;
00458    }
00459    if ( other.comments_ )
00460    {
00461       comments_ = new CommentInfo[numberOfCommentPlacement];
00462       for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
00463       {
00464          const CommentInfo &otherComment = other.comments_[comment];
00465          if ( otherComment.comment_ )
00466             comments_[comment].setComment( otherComment.comment_ );
00467       }
00468    }
00469 }
00470 
00471 
00472 Value::~Value()
00473 {
00474    switch ( type_ )
00475    {
00476    case nullValue:
00477    case intValue:
00478    case uintValue:
00479    case realValue:
00480    case booleanValue:
00481       break;
00482    case stringValue:
00483       if ( allocated_ )
00484          valueAllocator()->releaseStringValue( value_.string_ );
00485       break;
00486 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00487    case arrayValue:
00488    case objectValue:
00489       delete value_.map_;
00490       break;
00491 #else
00492    case arrayValue:
00493       arrayAllocator()->destructArray( value_.array_ );
00494       break;
00495    case objectValue:
00496       mapAllocator()->destructMap( value_.map_ );
00497       break;
00498 #endif
00499    default:
00500       JSON_ASSERT_UNREACHABLE;
00501    }
00502 
00503    if ( comments_ )
00504       delete[] comments_;
00505 }
00506 
00507 Value &
00508 Value::operator=( const Value &other )
00509 {
00510    Value temp( other );
00511    swap( temp );
00512    return *this;
00513 }
00514 
00515 void 
00516 Value::swap( Value &other )
00517 {
00518    ValueType temp = type_;
00519    type_ = other.type_;
00520    other.type_ = temp;
00521    std::swap( value_, other.value_ );
00522    int temp2 = allocated_;
00523    allocated_ = other.allocated_;
00524    other.allocated_ = temp2;
00525 }
00526 
00527 ValueType 
00528 Value::type() const
00529 {
00530    return type_;
00531 }
00532 
00533 
00534 int 
00535 Value::compare( const Value &other )
00536 {
00537    /*
00538    int typeDelta = other.type_ - type_;
00539    switch ( type_ )
00540    {
00541    case nullValue:
00542 
00543       return other.type_ == type_;
00544    case intValue:
00545       if ( other.type_.isNumeric()
00546    case uintValue:
00547    case realValue:
00548    case booleanValue:
00549       break;
00550    case stringValue,
00551       break;
00552    case arrayValue:
00553       delete value_.array_;
00554       break;
00555    case objectValue:
00556       delete value_.map_;
00557    default:
00558       JSON_ASSERT_UNREACHABLE;
00559    }
00560    */
00561    return 0;  // unreachable
00562 }
00563 
00564 bool 
00565 Value::operator <( const Value &other ) const
00566 {
00567    int typeDelta = type_ - other.type_;
00568    if ( typeDelta )
00569       return typeDelta < 0 ? true : false;
00570    switch ( type_ )
00571    {
00572    case nullValue:
00573       return false;
00574    case intValue:
00575       return value_.int_ < other.value_.int_;
00576    case uintValue:
00577       return value_.uint_ < other.value_.uint_;
00578    case realValue:
00579       return value_.real_ < other.value_.real_;
00580    case booleanValue:
00581       return value_.bool_ < other.value_.bool_;
00582    case stringValue:
00583       return ( value_.string_ == 0  &&  other.value_.string_ )
00584              || ( other.value_.string_  
00585                   &&  value_.string_  
00586                   && strcmp( value_.string_, other.value_.string_ ) < 0 );
00587 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00588    case arrayValue:
00589    case objectValue:
00590       {
00591          int delta = int( value_.map_->size() - other.value_.map_->size() );
00592          if ( delta )
00593             return delta < 0;
00594          return (*value_.map_) < (*other.value_.map_);
00595       }
00596 #else
00597    case arrayValue:
00598       return value_.array_->compare( *(other.value_.array_) ) < 0;
00599    case objectValue:
00600       return value_.map_->compare( *(other.value_.map_) ) < 0;
00601 #endif
00602    default:
00603       JSON_ASSERT_UNREACHABLE;
00604    }
00605    return 0;  // unreachable
00606 }
00607 
00608 bool 
00609 Value::operator <=( const Value &other ) const
00610 {
00611    return !(other > *this);
00612 }
00613 
00614 bool 
00615 Value::operator >=( const Value &other ) const
00616 {
00617    return !(*this < other);
00618 }
00619 
00620 bool 
00621 Value::operator >( const Value &other ) const
00622 {
00623    return other < *this;
00624 }
00625 
00626 bool 
00627 Value::operator ==( const Value &other ) const
00628 {
00629    //if ( type_ != other.type_ )
00630    // GCC 2.95.3 says:
00631    // attempt to take address of bit-field structure member `Json::Value::type_'
00632    // Beats me, but a temp solves the problem.
00633    int temp = other.type_;
00634    if ( type_ != temp )
00635       return false;
00636    switch ( type_ )
00637    {
00638    case nullValue:
00639       return true;
00640    case intValue:
00641       return value_.int_ == other.value_.int_;
00642    case uintValue:
00643       return value_.uint_ == other.value_.uint_;
00644    case realValue:
00645       return value_.real_ == other.value_.real_;
00646    case booleanValue:
00647       return value_.bool_ == other.value_.bool_;
00648    case stringValue:
00649       return ( value_.string_ == other.value_.string_ )
00650              || ( other.value_.string_  
00651                   &&  value_.string_  
00652                   && strcmp( value_.string_, other.value_.string_ ) == 0 );
00653 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00654    case arrayValue:
00655    case objectValue:
00656       return value_.map_->size() == other.value_.map_->size()
00657              && (*value_.map_) == (*other.value_.map_);
00658 #else
00659    case arrayValue:
00660       return value_.array_->compare( *(other.value_.array_) ) == 0;
00661    case objectValue:
00662       return value_.map_->compare( *(other.value_.map_) ) == 0;
00663 #endif
00664    default:
00665       JSON_ASSERT_UNREACHABLE;
00666    }
00667    return 0;  // unreachable
00668 }
00669 
00670 bool 
00671 Value::operator !=( const Value &other ) const
00672 {
00673    return !( *this == other );
00674 }
00675 
00676 const char *
00677 Value::asCString() const
00678 {
00679    JSON_ASSERT( type_ == stringValue );
00680    return value_.string_;
00681 }
00682 
00683 
00684 std::string 
00685 Value::asString() const
00686 {
00687    switch ( type_ )
00688    {
00689    case nullValue:
00690       return "";
00691    case stringValue:
00692       return value_.string_ ? value_.string_ : "";
00693    case booleanValue:
00694       return value_.bool_ ? "true" : "false";
00695    case intValue:
00696    case uintValue:
00697    case realValue:
00698    case arrayValue:
00699    case objectValue:
00700       JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
00701    default:
00702       JSON_ASSERT_UNREACHABLE;
00703    }
00704    return ""; // unreachable
00705 }
00706 
00707 # ifdef JSON_USE_CPPTL
00708 CppTL::ConstString 
00709 Value::asConstString() const
00710 {
00711    return CppTL::ConstString( asString().c_str() );
00712 }
00713 # endif
00714 
00715 Value::Int 
00716 Value::asInt() const
00717 {
00718    switch ( type_ )
00719    {
00720    case nullValue:
00721       return 0;
00722    case intValue:
00723       return value_.int_;
00724    case uintValue:
00725       JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
00726       return value_.uint_;
00727    case realValue:
00728       JSON_ASSERT_MESSAGE( value_.real_ >= minInt  &&  value_.real_ <= maxInt, "Real out of signed integer range" );
00729       return Int( value_.real_ );
00730    case booleanValue:
00731       return value_.bool_ ? 1 : 0;
00732    case stringValue:
00733    case arrayValue:
00734    case objectValue:
00735       JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
00736    default:
00737       JSON_ASSERT_UNREACHABLE;
00738    }
00739    return 0; // unreachable;
00740 }
00741 
00742 Value::UInt 
00743 Value::asUInt() const
00744 {
00745    switch ( type_ )
00746    {
00747    case nullValue:
00748       return 0;
00749    case intValue:
00750       JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
00751       return value_.int_;
00752    case uintValue:
00753       return value_.uint_;
00754    case realValue:
00755       JSON_ASSERT_MESSAGE( value_.real_ >= 0  &&  value_.real_ <= maxUInt,  "Real out of unsigned integer range" );
00756       return UInt( value_.real_ );
00757    case booleanValue:
00758       return value_.bool_ ? 1 : 0;
00759    case stringValue:
00760    case arrayValue:
00761    case objectValue:
00762       JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
00763    default:
00764       JSON_ASSERT_UNREACHABLE;
00765    }
00766    return 0; // unreachable;
00767 }
00768 
00769 double 
00770 Value::asDouble() const
00771 {
00772    switch ( type_ )
00773    {
00774    case nullValue:
00775       return 0.0;
00776    case intValue:
00777       return value_.int_;
00778    case uintValue:
00779       return value_.uint_;
00780    case realValue:
00781       return value_.real_;
00782    case booleanValue:
00783       return value_.bool_ ? 1.0 : 0.0;
00784    case stringValue:
00785    case arrayValue:
00786    case objectValue:
00787       JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
00788    default:
00789       JSON_ASSERT_UNREACHABLE;
00790    }
00791    return 0; // unreachable;
00792 }
00793 
00794 bool 
00795 Value::asBool() const
00796 {
00797    switch ( type_ )
00798    {
00799    case nullValue:
00800       return false;
00801    case intValue:
00802    case uintValue:
00803       return value_.int_ != 0;
00804    case realValue:
00805       return value_.real_ != 0.0;
00806    case booleanValue:
00807       return value_.bool_;
00808    case stringValue:
00809       return value_.string_  &&  value_.string_[0] != 0;
00810    case arrayValue:
00811    case objectValue:
00812       return value_.map_->size() != 0;
00813    default:
00814       JSON_ASSERT_UNREACHABLE;
00815    }
00816    return false; // unreachable;
00817 }
00818 
00819 
00820 bool 
00821 Value::isConvertibleTo( ValueType other ) const
00822 {
00823    switch ( type_ )
00824    {
00825    case nullValue:
00826       return true;
00827    case intValue:
00828       return ( other == nullValue  &&  value_.int_ == 0 )
00829              || other == intValue
00830              || ( other == uintValue  && value_.int_ >= 0 )
00831              || other == realValue
00832              || other == stringValue
00833              || other == booleanValue;
00834    case uintValue:
00835       return ( other == nullValue  &&  value_.uint_ == 0 )
00836              || ( other == intValue  && value_.uint_ <= (unsigned)maxInt )
00837              || other == uintValue
00838              || other == realValue
00839              || other == stringValue
00840              || other == booleanValue;
00841    case realValue:
00842       return ( other == nullValue  &&  value_.real_ == 0.0 )
00843              || ( other == intValue  &&  value_.real_ >= minInt  &&  value_.real_ <= maxInt )
00844              || ( other == uintValue  &&  value_.real_ >= 0  &&  value_.real_ <= maxUInt )
00845              || other == realValue
00846              || other == stringValue
00847              || other == booleanValue;
00848    case booleanValue:
00849       return ( other == nullValue  &&  value_.bool_ == false )
00850              || other == intValue
00851              || other == uintValue
00852              || other == realValue
00853              || other == stringValue
00854              || other == booleanValue;
00855    case stringValue:
00856       return other == stringValue
00857              || ( other == nullValue  &&  (!value_.string_  ||  value_.string_[0] == 0) );
00858    case arrayValue:
00859       return other == arrayValue
00860              ||  ( other == nullValue  &&  value_.map_->size() == 0 );
00861    case objectValue:
00862       return other == objectValue
00863              ||  ( other == nullValue  &&  value_.map_->size() == 0 );
00864    default:
00865       JSON_ASSERT_UNREACHABLE;
00866    }
00867    return false; // unreachable;
00868 }
00869 
00870 
00872 Value::UInt 
00873 Value::size() const
00874 {
00875    switch ( type_ )
00876    {
00877    case nullValue:
00878    case intValue:
00879    case uintValue:
00880    case realValue:
00881    case booleanValue:
00882    case stringValue:
00883       return 0;
00884 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00885    case arrayValue:  // size of the array is highest index + 1
00886       if ( !value_.map_->empty() )
00887       {
00888          ObjectValues::const_iterator itLast = value_.map_->end();
00889          --itLast;
00890          return (*itLast).first.index()+1;
00891       }
00892       return 0;
00893    case objectValue:
00894       return Int( value_.map_->size() );
00895 #else
00896    case arrayValue:
00897       return Int( value_.array_->size() );
00898    case objectValue:
00899       return Int( value_.map_->size() );
00900 #endif
00901    default:
00902       JSON_ASSERT_UNREACHABLE;
00903    }
00904    return 0; // unreachable;
00905 }
00906 
00907 
00908 bool 
00909 Value::empty() const
00910 {
00911    if ( isNull() || isArray() || isObject() )
00912       return size() == 0u;
00913    else
00914       return false;
00915 }
00916 
00917 
00918 bool
00919 Value::operator!() const
00920 {
00921    return isNull();
00922 }
00923 
00924 
00925 void 
00926 Value::clear()
00927 {
00928    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue  || type_ == objectValue );
00929 
00930    switch ( type_ )
00931    {
00932 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00933    case arrayValue:
00934    case objectValue:
00935       value_.map_->clear();
00936       break;
00937 #else
00938    case arrayValue:
00939       value_.array_->clear();
00940       break;
00941    case objectValue:
00942       value_.map_->clear();
00943       break;
00944 #endif
00945    default:
00946       break;
00947    }
00948 }
00949 
00950 void 
00951 Value::resize( UInt newSize )
00952 {
00953    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
00954    if ( type_ == nullValue )
00955       *this = Value( arrayValue );
00956 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00957    UInt oldSize = size();
00958    if ( newSize == 0 )
00959       clear();
00960    else if ( newSize > oldSize )
00961       (*this)[ newSize - 1 ];
00962    else
00963    {
00964       for ( UInt index = newSize; index < oldSize; ++index )
00965          value_.map_->erase( index );
00966       assert( size() == newSize );
00967    }
00968 #else
00969    value_.array_->resize( newSize );
00970 #endif
00971 }
00972 
00973 
00974 Value &
00975 Value::operator[]( UInt index )
00976 {
00977    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
00978    if ( type_ == nullValue )
00979       *this = Value( arrayValue );
00980 #ifndef JSON_VALUE_USE_INTERNAL_MAP
00981    CZString key( index );
00982    ObjectValues::iterator it = value_.map_->lower_bound( key );
00983    if ( it != value_.map_->end()  &&  (*it).first == key )
00984       return (*it).second;
00985 
00986    ObjectValues::value_type defaultValue( key, null );
00987    it = value_.map_->insert( it, defaultValue );
00988    return (*it).second;
00989 #else
00990    return value_.array_->resolveReference( index );
00991 #endif
00992 }
00993 
00994 
00995 const Value &
00996 Value::operator[]( UInt index ) const
00997 {
00998    JSON_ASSERT( type_ == nullValue  ||  type_ == arrayValue );
00999    if ( type_ == nullValue )
01000       return null;
01001 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01002    CZString key( index );
01003    ObjectValues::const_iterator it = value_.map_->find( key );
01004    if ( it == value_.map_->end() )
01005       return null;
01006    return (*it).second;
01007 #else
01008    Value *value = value_.array_->find( index );
01009    return value ? *value : null;
01010 #endif
01011 }
01012 
01013 
01014 Value &
01015 Value::operator[]( const char *key )
01016 {
01017    return resolveReference( key, false );
01018 }
01019 
01020 
01021 Value &
01022 Value::resolveReference( const char *key, 
01023                          bool isStatic )
01024 {
01025    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01026    if ( type_ == nullValue )
01027       *this = Value( objectValue );
01028 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01029    CZString actualKey( key, isStatic ? CZString::noDuplication 
01030                                      : CZString::duplicateOnCopy );
01031    ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
01032    if ( it != value_.map_->end()  &&  (*it).first == actualKey )
01033       return (*it).second;
01034 
01035    ObjectValues::value_type defaultValue( actualKey, null );
01036    it = value_.map_->insert( it, defaultValue );
01037    Value &value = (*it).second;
01038    return value;
01039 #else
01040    return value_.map_->resolveReference( key, isStatic );
01041 #endif
01042 }
01043 
01044 
01045 Value 
01046 Value::get( UInt index, 
01047             const Value &defaultValue ) const
01048 {
01049    const Value *value = &((*this)[index]);
01050    return value == &null ? defaultValue : *value;
01051 }
01052 
01053 
01054 bool 
01055 Value::isValidIndex( UInt index ) const
01056 {
01057    return index < size();
01058 }
01059 
01060 
01061 
01062 const Value &
01063 Value::operator[]( const char *key ) const
01064 {
01065    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01066    if ( type_ == nullValue )
01067       return null;
01068 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01069    CZString actualKey( key, CZString::noDuplication );
01070    ObjectValues::const_iterator it = value_.map_->find( actualKey );
01071    if ( it == value_.map_->end() )
01072       return null;
01073    return (*it).second;
01074 #else
01075    const Value *value = value_.map_->find( key );
01076    return value ? *value : null;
01077 #endif
01078 }
01079 
01080 
01081 Value &
01082 Value::operator[]( const std::string &key )
01083 {
01084    return (*this)[ key.c_str() ];
01085 }
01086 
01087 
01088 const Value &
01089 Value::operator[]( const std::string &key ) const
01090 {
01091    return (*this)[ key.c_str() ];
01092 }
01093 
01094 Value &
01095 Value::operator[]( const StaticString &key )
01096 {
01097    return resolveReference( key, true );
01098 }
01099 
01100 
01101 # ifdef JSON_USE_CPPTL
01102 Value &
01103 Value::operator[]( const CppTL::ConstString &key )
01104 {
01105    return (*this)[ key.c_str() ];
01106 }
01107 
01108 
01109 const Value &
01110 Value::operator[]( const CppTL::ConstString &key ) const
01111 {
01112    return (*this)[ key.c_str() ];
01113 }
01114 # endif
01115 
01116 
01117 Value &
01118 Value::append( const Value &value )
01119 {
01120    return (*this)[size()] = value;
01121 }
01122 
01123 
01124 Value 
01125 Value::get( const char *key, 
01126             const Value &defaultValue ) const
01127 {
01128    const Value *value = &((*this)[key]);
01129    return value == &null ? defaultValue : *value;
01130 }
01131 
01132 
01133 Value 
01134 Value::get( const std::string &key,
01135             const Value &defaultValue ) const
01136 {
01137    return get( key.c_str(), defaultValue );
01138 }
01139 
01140 Value
01141 Value::removeMember( const char* key )
01142 {
01143    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01144    if ( type_ == nullValue )
01145       return null;
01146 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01147    CZString actualKey( key, CZString::noDuplication );
01148    ObjectValues::iterator it = value_.map_->find( actualKey );
01149    if ( it == value_.map_->end() )
01150       return null;
01151    Value old(it->second);
01152    value_.map_->erase(it);
01153    return old;
01154 #else
01155    Value *value = value_.map_->find( key );
01156    if (value){
01157       Value old(*value);
01158       value_.map_.remove( key );
01159       return old;
01160    } else {
01161       return null;
01162    }
01163 #endif
01164 }
01165 
01166 Value
01167 Value::removeMember( const std::string &key )
01168 {
01169    return removeMember( key.c_str() );
01170 }
01171 
01172 # ifdef JSON_USE_CPPTL
01173 Value 
01174 Value::get( const CppTL::ConstString &key,
01175             const Value &defaultValue ) const
01176 {
01177    return get( key.c_str(), defaultValue );
01178 }
01179 # endif
01180 
01181 bool 
01182 Value::isMember( const char *key ) const
01183 {
01184    const Value *value = &((*this)[key]);
01185    return value != &null;
01186 }
01187 
01188 
01189 bool 
01190 Value::isMember( const std::string &key ) const
01191 {
01192    return isMember( key.c_str() );
01193 }
01194 
01195 
01196 # ifdef JSON_USE_CPPTL
01197 bool 
01198 Value::isMember( const CppTL::ConstString &key ) const
01199 {
01200    return isMember( key.c_str() );
01201 }
01202 #endif
01203 
01204 Value::Members 
01205 Value::getMemberNames() const
01206 {
01207    JSON_ASSERT( type_ == nullValue  ||  type_ == objectValue );
01208    if ( type_ == nullValue )
01209        return Value::Members();
01210    Members members;
01211    members.reserve( value_.map_->size() );
01212 #ifndef JSON_VALUE_USE_INTERNAL_MAP
01213    ObjectValues::const_iterator it = value_.map_->begin();
01214    ObjectValues::const_iterator itEnd = value_.map_->end();
01215    for ( ; it != itEnd; ++it )
01216       members.push_back( std::string( (*it).first.c_str() ) );
01217 #else
01218    ValueInternalMap::IteratorState it;
01219    ValueInternalMap::IteratorState itEnd;
01220    value_.map_->makeBeginIterator( it );
01221    value_.map_->makeEndIterator( itEnd );
01222    for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
01223       members.push_back( std::string( ValueInternalMap::key( it ) ) );
01224 #endif
01225    return members;
01226 }
01227 //
01228 //# ifdef JSON_USE_CPPTL
01229 //EnumMemberNames
01230 //Value::enumMemberNames() const
01231 //{
01232 //   if ( type_ == objectValue )
01233 //   {
01234 //      return CppTL::Enum::any(  CppTL::Enum::transform(
01235 //         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
01236 //         MemberNamesTransform() ) );
01237 //   }
01238 //   return EnumMemberNames();
01239 //}
01240 //
01241 //
01242 //EnumValues 
01243 //Value::enumValues() const
01244 //{
01245 //   if ( type_ == objectValue  ||  type_ == arrayValue )
01246 //      return CppTL::Enum::anyValues( *(value_.map_), 
01247 //                                     CppTL::Type<const Value &>() );
01248 //   return EnumValues();
01249 //}
01250 //
01251 //# endif
01252 
01253 
01254 bool
01255 Value::isNull() const
01256 {
01257    return type_ == nullValue;
01258 }
01259 
01260 
01261 bool 
01262 Value::isBool() const
01263 {
01264    return type_ == booleanValue;
01265 }
01266 
01267 
01268 bool 
01269 Value::isInt() const
01270 {
01271    return type_ == intValue;
01272 }
01273 
01274 
01275 bool 
01276 Value::isUInt() const
01277 {
01278    return type_ == uintValue;
01279 }
01280 
01281 
01282 bool 
01283 Value::isIntegral() const
01284 {
01285    return type_ == intValue  
01286           ||  type_ == uintValue  
01287           ||  type_ == booleanValue;
01288 }
01289 
01290 
01291 bool 
01292 Value::isDouble() const
01293 {
01294    return type_ == realValue;
01295 }
01296 
01297 
01298 bool 
01299 Value::isNumeric() const
01300 {
01301    return isIntegral() || isDouble();
01302 }
01303 
01304 
01305 bool 
01306 Value::isString() const
01307 {
01308    return type_ == stringValue;
01309 }
01310 
01311 
01312 bool 
01313 Value::isArray() const
01314 {
01315    return type_ == nullValue  ||  type_ == arrayValue;
01316 }
01317 
01318 
01319 bool 
01320 Value::isObject() const
01321 {
01322    return type_ == nullValue  ||  type_ == objectValue;
01323 }
01324 
01325 
01326 void 
01327 Value::setComment( const char *comment,
01328                    CommentPlacement placement )
01329 {
01330    if ( !comments_ )
01331       comments_ = new CommentInfo[numberOfCommentPlacement];
01332    comments_[placement].setComment( comment );
01333 }
01334 
01335 
01336 void 
01337 Value::setComment( const std::string &comment,
01338                    CommentPlacement placement )
01339 {
01340    setComment( comment.c_str(), placement );
01341 }
01342 
01343 
01344 bool 
01345 Value::hasComment( CommentPlacement placement ) const
01346 {
01347    return comments_ != 0  &&  comments_[placement].comment_ != 0;
01348 }
01349 
01350 std::string 
01351 Value::getComment( CommentPlacement placement ) const
01352 {
01353    if ( hasComment(placement) )
01354       return comments_[placement].comment_;
01355    return "";
01356 }
01357 
01358 
01359 std::string 
01360 Value::toStyledString() const
01361 {
01362    StyledWriter writer;
01363    return writer.write( *this );
01364 }
01365 
01366 
01367 Value::const_iterator 
01368 Value::begin() const
01369 {
01370    switch ( type_ )
01371    {
01372 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01373    case arrayValue:
01374       if ( value_.array_ )
01375       {
01376          ValueInternalArray::IteratorState it;
01377          value_.array_->makeBeginIterator( it );
01378          return const_iterator( it );
01379       }
01380       break;
01381    case objectValue:
01382       if ( value_.map_ )
01383       {
01384          ValueInternalMap::IteratorState it;
01385          value_.map_->makeBeginIterator( it );
01386          return const_iterator( it );
01387       }
01388       break;
01389 #else
01390    case arrayValue:
01391    case objectValue:
01392       if ( value_.map_ )
01393          return const_iterator( value_.map_->begin() );
01394       break;
01395 #endif
01396    default:
01397       break;
01398    }
01399    return const_iterator();
01400 }
01401 
01402 Value::const_iterator 
01403 Value::end() const
01404 {
01405    switch ( type_ )
01406    {
01407 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01408    case arrayValue:
01409       if ( value_.array_ )
01410       {
01411          ValueInternalArray::IteratorState it;
01412          value_.array_->makeEndIterator( it );
01413          return const_iterator( it );
01414       }
01415       break;
01416    case objectValue:
01417       if ( value_.map_ )
01418       {
01419          ValueInternalMap::IteratorState it;
01420          value_.map_->makeEndIterator( it );
01421          return const_iterator( it );
01422       }
01423       break;
01424 #else
01425    case arrayValue:
01426    case objectValue:
01427       if ( value_.map_ )
01428          return const_iterator( value_.map_->end() );
01429       break;
01430 #endif
01431    default:
01432       break;
01433    }
01434    return const_iterator();
01435 }
01436 
01437 
01438 Value::iterator 
01439 Value::begin()
01440 {
01441    switch ( type_ )
01442    {
01443 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01444    case arrayValue:
01445       if ( value_.array_ )
01446       {
01447          ValueInternalArray::IteratorState it;
01448          value_.array_->makeBeginIterator( it );
01449          return iterator( it );
01450       }
01451       break;
01452    case objectValue:
01453       if ( value_.map_ )
01454       {
01455          ValueInternalMap::IteratorState it;
01456          value_.map_->makeBeginIterator( it );
01457          return iterator( it );
01458       }
01459       break;
01460 #else
01461    case arrayValue:
01462    case objectValue:
01463       if ( value_.map_ )
01464          return iterator( value_.map_->begin() );
01465       break;
01466 #endif
01467    default:
01468       break;
01469    }
01470    return iterator();
01471 }
01472 
01473 Value::iterator 
01474 Value::end()
01475 {
01476    switch ( type_ )
01477    {
01478 #ifdef JSON_VALUE_USE_INTERNAL_MAP
01479    case arrayValue:
01480       if ( value_.array_ )
01481       {
01482          ValueInternalArray::IteratorState it;
01483          value_.array_->makeEndIterator( it );
01484          return iterator( it );
01485       }
01486       break;
01487    case objectValue:
01488       if ( value_.map_ )
01489       {
01490          ValueInternalMap::IteratorState it;
01491          value_.map_->makeEndIterator( it );
01492          return iterator( it );
01493       }
01494       break;
01495 #else
01496    case arrayValue:
01497    case objectValue:
01498       if ( value_.map_ )
01499          return iterator( value_.map_->end() );
01500       break;
01501 #endif
01502    default:
01503       break;
01504    }
01505    return iterator();
01506 }
01507 
01508 
01509 // class PathArgument
01510 // //////////////////////////////////////////////////////////////////
01511 
01512 PathArgument::PathArgument()
01513    : kind_( kindNone )
01514 {
01515 }
01516 
01517 
01518 PathArgument::PathArgument( Value::UInt index )
01519    : index_( index )
01520    , kind_( kindIndex )
01521 {
01522 }
01523 
01524 
01525 PathArgument::PathArgument( const char *key )
01526    : key_( key )
01527    , kind_( kindKey )
01528 {
01529 }
01530 
01531 
01532 PathArgument::PathArgument( const std::string &key )
01533    : key_( key.c_str() )
01534    , kind_( kindKey )
01535 {
01536 }
01537 
01538 // class Path
01539 // //////////////////////////////////////////////////////////////////
01540 
01541 Path::Path( const std::string &path,
01542             const PathArgument &a1,
01543             const PathArgument &a2,
01544             const PathArgument &a3,
01545             const PathArgument &a4,
01546             const PathArgument &a5 )
01547 {
01548    InArgs in;
01549    in.push_back( &a1 );
01550    in.push_back( &a2 );
01551    in.push_back( &a3 );
01552    in.push_back( &a4 );
01553    in.push_back( &a5 );
01554    makePath( path, in );
01555 }
01556 
01557 
01558 void 
01559 Path::makePath( const std::string &path,
01560                 const InArgs &in )
01561 {
01562    const char *current = path.c_str();
01563    const char *end = current + path.length();
01564    InArgs::const_iterator itInArg = in.begin();
01565    while ( current != end )
01566    {
01567       if ( *current == '[' )
01568       {
01569          ++current;
01570          if ( *current == '%' )
01571             addPathInArg( path, in, itInArg, PathArgument::kindIndex );
01572          else
01573          {
01574             Value::UInt index = 0;
01575             for ( ; current != end && *current >= '0'  &&  *current <= '9'; ++current )
01576                index = index * 10 + Value::UInt(*current - '0');
01577             args_.push_back( index );
01578          }
01579          if ( current == end  ||  *current++ != ']' )
01580             invalidPath( path, int(current - path.c_str()) );
01581       }
01582       else if ( *current == '%' )
01583       {
01584          addPathInArg( path, in, itInArg, PathArgument::kindKey );
01585          ++current;
01586       }
01587       else if ( *current == '.' )
01588       {
01589          ++current;
01590       }
01591       else
01592       {
01593          const char *beginName = current;
01594          while ( current != end  &&  !strchr( "[.", *current ) )
01595             ++current;
01596          args_.push_back( std::string( beginName, current ) );
01597       }
01598    }
01599 }
01600 
01601 
01602 void 
01603 Path::addPathInArg( const std::string &path, 
01604                     const InArgs &in, 
01605                     InArgs::const_iterator &itInArg, 
01606                     PathArgument::Kind kind )
01607 {
01608    if ( itInArg == in.end() )
01609    {
01610       // Error: missing argument %d
01611    }
01612    else if ( (*itInArg)->kind_ != kind )
01613    {
01614       // Error: bad argument type
01615    }
01616    else
01617    {
01618       args_.push_back( **itInArg );
01619    }
01620 }
01621 
01622 
01623 void 
01624 Path::invalidPath( const std::string &path, 
01625                    int location )
01626 {
01627    // Error: invalid path.
01628 }
01629 
01630 
01631 const Value &
01632 Path::resolve( const Value &root ) const
01633 {
01634    const Value *node = &root;
01635    for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
01636    {
01637       const PathArgument &arg = *it;
01638       if ( arg.kind_ == PathArgument::kindIndex )
01639       {
01640          if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
01641          {
01642             // Error: unable to resolve path (array value expected at position...
01643          }
01644          node = &((*node)[arg.index_]);
01645       }
01646       else if ( arg.kind_ == PathArgument::kindKey )
01647       {
01648          if ( !node->isObject() )
01649          {
01650             // Error: unable to resolve path (object value expected at position...)
01651          }
01652          node = &((*node)[arg.key_]);
01653          if ( node == &Value::null )
01654          {
01655             // Error: unable to resolve path (object has no member named '' at position...)
01656          }
01657       }
01658    }
01659    return *node;
01660 }
01661 
01662 
01663 Value 
01664 Path::resolve( const Value &root, 
01665                const Value &defaultValue ) const
01666 {
01667    const Value *node = &root;
01668    for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
01669    {
01670       const PathArgument &arg = *it;
01671       if ( arg.kind_ == PathArgument::kindIndex )
01672       {
01673          if ( !node->isArray()  ||  node->isValidIndex( arg.index_ ) )
01674             return defaultValue;
01675          node = &((*node)[arg.index_]);
01676       }
01677       else if ( arg.kind_ == PathArgument::kindKey )
01678       {
01679          if ( !node->isObject() )
01680             return defaultValue;
01681          node = &((*node)[arg.key_]);
01682          if ( node == &Value::null )
01683             return defaultValue;
01684       }
01685    }
01686    return *node;
01687 }
01688 
01689 
01690 Value &
01691 Path::make( Value &root ) const
01692 {
01693    Value *node = &root;
01694    for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
01695    {
01696       const PathArgument &arg = *it;
01697       if ( arg.kind_ == PathArgument::kindIndex )
01698       {
01699          if ( !node->isArray() )
01700          {
01701             // Error: node is not an array at position ...
01702          }
01703          node = &((*node)[arg.index_]);
01704       }
01705       else if ( arg.kind_ == PathArgument::kindKey )
01706       {
01707          if ( !node->isObject() )
01708          {
01709             // Error: node is not an object at position...
01710          }
01711          node = &((*node)[arg.key_]);
01712       }
01713    }
01714    return *node;
01715 }
01716 
01717 
01718 } // namespace Json


bwi_tools
Author(s): Piyush Khandelwal
autogenerated on Fri Aug 28 2015 10:14:30