annotate third_party/json/json_value.cpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
rev   line source
ian@0 1 // Copyright 2011 Baptiste Lepilleur
ian@0 2 // Distributed under MIT license, or public domain if desired and
ian@0 3 // recognized in your jurisdiction.
ian@0 4 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
ian@0 5
ian@0 6 #if !defined(JSON_IS_AMALGAMATION)
ian@0 7 # include <json/assertions.h>
ian@0 8 # include <json/value.h>
ian@0 9 # include <json/writer.h>
ian@0 10 # ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
ian@0 11 # include "json_batchallocator.h"
ian@0 12 # endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
ian@0 13 #endif // if !defined(JSON_IS_AMALGAMATION)
ian@0 14 #include <math.h>
ian@0 15 #include <iostream>
ian@0 16 #include <sstream>
ian@0 17 #include <utility>
ian@0 18 #include <stdexcept>
ian@0 19 #include <cstring>
ian@0 20 #include <cassert>
ian@0 21 #ifdef JSON_USE_CPPTL
ian@0 22 # include <cpptl/conststring.h>
ian@0 23 #endif
ian@0 24 #include <cstddef> // size_t
ian@0 25
ian@0 26 #define JSON_ASSERT_UNREACHABLE assert( false )
ian@0 27
ian@0 28 namespace Json {
ian@0 29
ian@0 30 const Value Value::null;
ian@0 31 const Int Value::minInt = Int( ~(UInt(-1)/2) );
ian@0 32 const Int Value::maxInt = Int( UInt(-1)/2 );
ian@0 33 const UInt Value::maxUInt = UInt(-1);
ian@0 34 # if defined(JSON_HAS_INT64)
ian@0 35 const Int64 Value::minInt64 = Int64( ~(UInt64(-1)/2) );
ian@0 36 const Int64 Value::maxInt64 = Int64( UInt64(-1)/2 );
ian@0 37 const UInt64 Value::maxUInt64 = UInt64(-1);
ian@0 38 // The constant is hard-coded because some compiler have trouble
ian@0 39 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
ian@0 40 // Assumes that UInt64 is a 64 bits integer.
ian@0 41 static const double maxUInt64AsDouble = 18446744073709551615.0;
ian@0 42 #endif // defined(JSON_HAS_INT64)
ian@0 43 const LargestInt Value::minLargestInt = LargestInt( ~(LargestUInt(-1)/2) );
ian@0 44 const LargestInt Value::maxLargestInt = LargestInt( LargestUInt(-1)/2 );
ian@0 45 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
ian@0 46
ian@0 47
ian@0 48 /// Unknown size marker
ian@0 49 static const unsigned int unknown = (unsigned)-1;
ian@0 50
ian@0 51 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 52 template <typename T, typename U>
ian@0 53 static inline bool InRange(double d, T min, U max) {
ian@0 54 return d >= min && d <= max;
ian@0 55 }
ian@0 56 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 57 static inline double integerToDouble( Json::UInt64 value )
ian@0 58 {
ian@0 59 return static_cast<double>( Int64(value/2) ) * 2.0 + Int64(value & 1);
ian@0 60 }
ian@0 61
ian@0 62 template<typename T>
ian@0 63 static inline double integerToDouble( T value )
ian@0 64 {
ian@0 65 return static_cast<double>( value );
ian@0 66 }
ian@0 67
ian@0 68 template <typename T, typename U>
ian@0 69 static inline bool InRange(double d, T min, U max) {
ian@0 70 return d >= integerToDouble(min) && d <= integerToDouble(max);
ian@0 71 }
ian@0 72 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 73
ian@0 74
ian@0 75 /** Duplicates the specified string value.
ian@0 76 * @param value Pointer to the string to duplicate. Must be zero-terminated if
ian@0 77 * length is "unknown".
ian@0 78 * @param length Length of the value. if equals to unknown, then it will be
ian@0 79 * computed using strlen(value).
ian@0 80 * @return Pointer on the duplicate instance of string.
ian@0 81 */
ian@0 82 static inline char *
ian@0 83 duplicateStringValue( const char *value,
ian@0 84 unsigned int length = unknown )
ian@0 85 {
ian@0 86 if ( length == unknown )
ian@0 87 length = (unsigned int)strlen(value);
ian@0 88
ian@0 89 // Avoid an integer overflow in the call to malloc below by limiting length
ian@0 90 // to a sane value.
ian@0 91 if (length >= (unsigned)Value::maxInt)
ian@0 92 length = Value::maxInt - 1;
ian@0 93
ian@0 94 char *newString = static_cast<char *>( malloc( length + 1 ) );
ian@0 95 JSON_ASSERT_MESSAGE( newString != 0, "Failed to allocate string value buffer" );
ian@0 96 memcpy( newString, value, length );
ian@0 97 newString[length] = 0;
ian@0 98 return newString;
ian@0 99 }
ian@0 100
ian@0 101
ian@0 102 /** Free the string duplicated by duplicateStringValue().
ian@0 103 */
ian@0 104 static inline void
ian@0 105 releaseStringValue( char *value )
ian@0 106 {
ian@0 107 if ( value )
ian@0 108 free( value );
ian@0 109 }
ian@0 110
ian@0 111 } // namespace Json
ian@0 112
ian@0 113
ian@0 114 // //////////////////////////////////////////////////////////////////
ian@0 115 // //////////////////////////////////////////////////////////////////
ian@0 116 // //////////////////////////////////////////////////////////////////
ian@0 117 // ValueInternals...
ian@0 118 // //////////////////////////////////////////////////////////////////
ian@0 119 // //////////////////////////////////////////////////////////////////
ian@0 120 // //////////////////////////////////////////////////////////////////
ian@0 121 #if !defined(JSON_IS_AMALGAMATION)
ian@0 122 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 123 # include "json_internalarray.inl"
ian@0 124 # include "json_internalmap.inl"
ian@0 125 # endif // JSON_VALUE_USE_INTERNAL_MAP
ian@0 126
ian@0 127 # include "json_valueiterator.inl"
ian@0 128 #endif // if !defined(JSON_IS_AMALGAMATION)
ian@0 129
ian@0 130 namespace Json {
ian@0 131
ian@0 132 // //////////////////////////////////////////////////////////////////
ian@0 133 // //////////////////////////////////////////////////////////////////
ian@0 134 // //////////////////////////////////////////////////////////////////
ian@0 135 // class Value::CommentInfo
ian@0 136 // //////////////////////////////////////////////////////////////////
ian@0 137 // //////////////////////////////////////////////////////////////////
ian@0 138 // //////////////////////////////////////////////////////////////////
ian@0 139
ian@0 140
ian@0 141 Value::CommentInfo::CommentInfo()
ian@0 142 : comment_( 0 )
ian@0 143 {
ian@0 144 }
ian@0 145
ian@0 146 Value::CommentInfo::~CommentInfo()
ian@0 147 {
ian@0 148 if ( comment_ )
ian@0 149 releaseStringValue( comment_ );
ian@0 150 }
ian@0 151
ian@0 152
ian@0 153 void
ian@0 154 Value::CommentInfo::setComment( const char *text )
ian@0 155 {
ian@0 156 if ( comment_ )
ian@0 157 releaseStringValue( comment_ );
ian@0 158 JSON_ASSERT( text != 0 );
ian@0 159 JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
ian@0 160 // It seems that /**/ style comments are acceptable as well.
ian@0 161 comment_ = duplicateStringValue( text );
ian@0 162 }
ian@0 163
ian@0 164
ian@0 165 // //////////////////////////////////////////////////////////////////
ian@0 166 // //////////////////////////////////////////////////////////////////
ian@0 167 // //////////////////////////////////////////////////////////////////
ian@0 168 // class Value::CZString
ian@0 169 // //////////////////////////////////////////////////////////////////
ian@0 170 // //////////////////////////////////////////////////////////////////
ian@0 171 // //////////////////////////////////////////////////////////////////
ian@0 172 # ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 173
ian@0 174 // Notes: index_ indicates if the string was allocated when
ian@0 175 // a string is stored.
ian@0 176
ian@0 177 Value::CZString::CZString( ArrayIndex index )
ian@0 178 : cstr_( 0 )
ian@0 179 , index_( index )
ian@0 180 {
ian@0 181 }
ian@0 182
ian@0 183 Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
ian@0 184 : cstr_( allocate == duplicate ? duplicateStringValue(cstr)
ian@0 185 : cstr )
ian@0 186 , index_( allocate )
ian@0 187 {
ian@0 188 }
ian@0 189
ian@0 190 Value::CZString::CZString( const CZString &other )
ian@0 191 : cstr_( other.index_ != noDuplication && other.cstr_ != 0
ian@0 192 ? duplicateStringValue( other.cstr_ )
ian@0 193 : other.cstr_ )
ian@0 194 , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
ian@0 195 : other.index_ )
ian@0 196 {
ian@0 197 }
ian@0 198
ian@0 199 Value::CZString::~CZString()
ian@0 200 {
ian@0 201 if ( cstr_ && index_ == duplicate )
ian@0 202 releaseStringValue( const_cast<char *>( cstr_ ) );
ian@0 203 }
ian@0 204
ian@0 205 void
ian@0 206 Value::CZString::swap( CZString &other )
ian@0 207 {
ian@0 208 std::swap( cstr_, other.cstr_ );
ian@0 209 std::swap( index_, other.index_ );
ian@0 210 }
ian@0 211
ian@0 212 Value::CZString &
ian@0 213 Value::CZString::operator =( const CZString &other )
ian@0 214 {
ian@0 215 CZString temp( other );
ian@0 216 swap( temp );
ian@0 217 return *this;
ian@0 218 }
ian@0 219
ian@0 220 bool
ian@0 221 Value::CZString::operator<( const CZString &other ) const
ian@0 222 {
ian@0 223 if ( cstr_ )
ian@0 224 return strcmp( cstr_, other.cstr_ ) < 0;
ian@0 225 return index_ < other.index_;
ian@0 226 }
ian@0 227
ian@0 228 bool
ian@0 229 Value::CZString::operator==( const CZString &other ) const
ian@0 230 {
ian@0 231 if ( cstr_ )
ian@0 232 return strcmp( cstr_, other.cstr_ ) == 0;
ian@0 233 return index_ == other.index_;
ian@0 234 }
ian@0 235
ian@0 236
ian@0 237 ArrayIndex
ian@0 238 Value::CZString::index() const
ian@0 239 {
ian@0 240 return index_;
ian@0 241 }
ian@0 242
ian@0 243
ian@0 244 const char *
ian@0 245 Value::CZString::c_str() const
ian@0 246 {
ian@0 247 return cstr_;
ian@0 248 }
ian@0 249
ian@0 250 bool
ian@0 251 Value::CZString::isStaticString() const
ian@0 252 {
ian@0 253 return index_ == noDuplication;
ian@0 254 }
ian@0 255
ian@0 256 #endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 257
ian@0 258
ian@0 259 // //////////////////////////////////////////////////////////////////
ian@0 260 // //////////////////////////////////////////////////////////////////
ian@0 261 // //////////////////////////////////////////////////////////////////
ian@0 262 // class Value::Value
ian@0 263 // //////////////////////////////////////////////////////////////////
ian@0 264 // //////////////////////////////////////////////////////////////////
ian@0 265 // //////////////////////////////////////////////////////////////////
ian@0 266
ian@0 267 /*! \internal Default constructor initialization must be equivalent to:
ian@0 268 * memset( this, 0, sizeof(Value) )
ian@0 269 * This optimization is used in ValueInternalMap fast allocator.
ian@0 270 */
ian@0 271 Value::Value( ValueType type )
ian@0 272 : type_( type )
ian@0 273 , allocated_( false )
ian@0 274 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 275 , itemIsUsed_( 0 )
ian@0 276 #endif
ian@0 277 , comments_( 0 )
ian@0 278 {
ian@0 279 switch ( type )
ian@0 280 {
ian@0 281 case nullValue:
ian@0 282 break;
ian@0 283 case intValue:
ian@0 284 case uintValue:
ian@0 285 value_.int_ = 0;
ian@0 286 break;
ian@0 287 case realValue:
ian@0 288 value_.real_ = 0.0;
ian@0 289 break;
ian@0 290 case stringValue:
ian@0 291 value_.string_ = 0;
ian@0 292 break;
ian@0 293 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 294 case arrayValue:
ian@0 295 case objectValue:
ian@0 296 value_.map_ = new ObjectValues();
ian@0 297 break;
ian@0 298 #else
ian@0 299 case arrayValue:
ian@0 300 value_.array_ = arrayAllocator()->newArray();
ian@0 301 break;
ian@0 302 case objectValue:
ian@0 303 value_.map_ = mapAllocator()->newMap();
ian@0 304 break;
ian@0 305 #endif
ian@0 306 case booleanValue:
ian@0 307 value_.bool_ = false;
ian@0 308 break;
ian@0 309 default:
ian@0 310 JSON_ASSERT_UNREACHABLE;
ian@0 311 }
ian@0 312 }
ian@0 313
ian@0 314
ian@0 315 Value::Value( UInt value )
ian@0 316 : type_( uintValue )
ian@0 317 , allocated_( false )
ian@0 318 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 319 , itemIsUsed_( 0 )
ian@0 320 #endif
ian@0 321 , comments_( 0 )
ian@0 322 {
ian@0 323 value_.uint_ = value;
ian@0 324 }
ian@0 325
ian@0 326 Value::Value( Int value )
ian@0 327 : type_( intValue )
ian@0 328 , allocated_( false )
ian@0 329 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 330 , itemIsUsed_( 0 )
ian@0 331 #endif
ian@0 332 , comments_( 0 )
ian@0 333 {
ian@0 334 value_.int_ = value;
ian@0 335 }
ian@0 336
ian@0 337
ian@0 338 # if defined(JSON_HAS_INT64)
ian@0 339 Value::Value( Int64 value )
ian@0 340 : type_( intValue )
ian@0 341 , allocated_( false )
ian@0 342 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 343 , itemIsUsed_( 0 )
ian@0 344 #endif
ian@0 345 , comments_( 0 )
ian@0 346 {
ian@0 347 value_.int_ = value;
ian@0 348 }
ian@0 349
ian@0 350
ian@0 351 Value::Value( UInt64 value )
ian@0 352 : type_( uintValue )
ian@0 353 , allocated_( false )
ian@0 354 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 355 , itemIsUsed_( 0 )
ian@0 356 #endif
ian@0 357 , comments_( 0 )
ian@0 358 {
ian@0 359 value_.uint_ = value;
ian@0 360 }
ian@0 361 #endif // defined(JSON_HAS_INT64)
ian@0 362
ian@0 363 Value::Value( double value )
ian@0 364 : type_( realValue )
ian@0 365 , allocated_( false )
ian@0 366 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 367 , itemIsUsed_( 0 )
ian@0 368 #endif
ian@0 369 , comments_( 0 )
ian@0 370 {
ian@0 371 value_.real_ = value;
ian@0 372 }
ian@0 373
ian@0 374 Value::Value( const char *value )
ian@0 375 : type_( stringValue )
ian@0 376 , allocated_( true )
ian@0 377 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 378 , itemIsUsed_( 0 )
ian@0 379 #endif
ian@0 380 , comments_( 0 )
ian@0 381 {
ian@0 382 value_.string_ = duplicateStringValue( value );
ian@0 383 }
ian@0 384
ian@0 385
ian@0 386 Value::Value( const char *beginValue,
ian@0 387 const char *endValue )
ian@0 388 : type_( stringValue )
ian@0 389 , allocated_( true )
ian@0 390 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 391 , itemIsUsed_( 0 )
ian@0 392 #endif
ian@0 393 , comments_( 0 )
ian@0 394 {
ian@0 395 value_.string_ = duplicateStringValue( beginValue,
ian@0 396 (unsigned int)(endValue - beginValue) );
ian@0 397 }
ian@0 398
ian@0 399
ian@0 400 Value::Value( const std::string &value )
ian@0 401 : type_( stringValue )
ian@0 402 , allocated_( true )
ian@0 403 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 404 , itemIsUsed_( 0 )
ian@0 405 #endif
ian@0 406 , comments_( 0 )
ian@0 407 {
ian@0 408 value_.string_ = duplicateStringValue( value.c_str(),
ian@0 409 (unsigned int)value.length() );
ian@0 410
ian@0 411 }
ian@0 412
ian@0 413 Value::Value( const StaticString &value )
ian@0 414 : type_( stringValue )
ian@0 415 , allocated_( false )
ian@0 416 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 417 , itemIsUsed_( 0 )
ian@0 418 #endif
ian@0 419 , comments_( 0 )
ian@0 420 {
ian@0 421 value_.string_ = const_cast<char *>( value.c_str() );
ian@0 422 }
ian@0 423
ian@0 424
ian@0 425 # ifdef JSON_USE_CPPTL
ian@0 426 Value::Value( const CppTL::ConstString &value )
ian@0 427 : type_( stringValue )
ian@0 428 , allocated_( true )
ian@0 429 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 430 , itemIsUsed_( 0 )
ian@0 431 #endif
ian@0 432 , comments_( 0 )
ian@0 433 {
ian@0 434 value_.string_ = duplicateStringValue( value, value.length() );
ian@0 435 }
ian@0 436 # endif
ian@0 437
ian@0 438 Value::Value( bool value )
ian@0 439 : type_( booleanValue )
ian@0 440 , allocated_( false )
ian@0 441 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 442 , itemIsUsed_( 0 )
ian@0 443 #endif
ian@0 444 , comments_( 0 )
ian@0 445 {
ian@0 446 value_.bool_ = value;
ian@0 447 }
ian@0 448
ian@0 449
ian@0 450 Value::Value( const Value &other )
ian@0 451 : type_( other.type_ )
ian@0 452 , allocated_( false )
ian@0 453 # ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 454 , itemIsUsed_( 0 )
ian@0 455 #endif
ian@0 456 , comments_( 0 )
ian@0 457 {
ian@0 458 switch ( type_ )
ian@0 459 {
ian@0 460 case nullValue:
ian@0 461 case intValue:
ian@0 462 case uintValue:
ian@0 463 case realValue:
ian@0 464 case booleanValue:
ian@0 465 value_ = other.value_;
ian@0 466 break;
ian@0 467 case stringValue:
ian@0 468 if ( other.value_.string_ )
ian@0 469 {
ian@0 470 value_.string_ = duplicateStringValue( other.value_.string_ );
ian@0 471 allocated_ = true;
ian@0 472 }
ian@0 473 else
ian@0 474 value_.string_ = 0;
ian@0 475 break;
ian@0 476 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 477 case arrayValue:
ian@0 478 case objectValue:
ian@0 479 value_.map_ = new ObjectValues( *other.value_.map_ );
ian@0 480 break;
ian@0 481 #else
ian@0 482 case arrayValue:
ian@0 483 value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
ian@0 484 break;
ian@0 485 case objectValue:
ian@0 486 value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
ian@0 487 break;
ian@0 488 #endif
ian@0 489 default:
ian@0 490 JSON_ASSERT_UNREACHABLE;
ian@0 491 }
ian@0 492 if ( other.comments_ )
ian@0 493 {
ian@0 494 comments_ = new CommentInfo[numberOfCommentPlacement];
ian@0 495 for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
ian@0 496 {
ian@0 497 const CommentInfo &otherComment = other.comments_[comment];
ian@0 498 if ( otherComment.comment_ )
ian@0 499 comments_[comment].setComment( otherComment.comment_ );
ian@0 500 }
ian@0 501 }
ian@0 502 }
ian@0 503
ian@0 504
ian@0 505 Value::~Value()
ian@0 506 {
ian@0 507 switch ( type_ )
ian@0 508 {
ian@0 509 case nullValue:
ian@0 510 case intValue:
ian@0 511 case uintValue:
ian@0 512 case realValue:
ian@0 513 case booleanValue:
ian@0 514 break;
ian@0 515 case stringValue:
ian@0 516 if ( allocated_ )
ian@0 517 releaseStringValue( value_.string_ );
ian@0 518 break;
ian@0 519 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 520 case arrayValue:
ian@0 521 case objectValue:
ian@0 522 delete value_.map_;
ian@0 523 break;
ian@0 524 #else
ian@0 525 case arrayValue:
ian@0 526 arrayAllocator()->destructArray( value_.array_ );
ian@0 527 break;
ian@0 528 case objectValue:
ian@0 529 mapAllocator()->destructMap( value_.map_ );
ian@0 530 break;
ian@0 531 #endif
ian@0 532 default:
ian@0 533 JSON_ASSERT_UNREACHABLE;
ian@0 534 }
ian@0 535
ian@0 536 if ( comments_ )
ian@0 537 delete[] comments_;
ian@0 538 }
ian@0 539
ian@0 540 Value &
ian@0 541 Value::operator=( const Value &other )
ian@0 542 {
ian@0 543 Value temp( other );
ian@0 544 swap( temp );
ian@0 545 return *this;
ian@0 546 }
ian@0 547
ian@0 548 void
ian@0 549 Value::swap( Value &other )
ian@0 550 {
ian@0 551 ValueType temp = type_;
ian@0 552 type_ = other.type_;
ian@0 553 other.type_ = temp;
ian@0 554 std::swap( value_, other.value_ );
ian@0 555 int temp2 = allocated_;
ian@0 556 allocated_ = other.allocated_;
ian@0 557 other.allocated_ = temp2;
ian@0 558 }
ian@0 559
ian@0 560 ValueType
ian@0 561 Value::type() const
ian@0 562 {
ian@0 563 return type_;
ian@0 564 }
ian@0 565
ian@0 566
ian@0 567 int
ian@0 568 Value::compare( const Value &other ) const
ian@0 569 {
ian@0 570 if ( *this < other )
ian@0 571 return -1;
ian@0 572 if ( *this > other )
ian@0 573 return 1;
ian@0 574 return 0;
ian@0 575 }
ian@0 576
ian@0 577
ian@0 578 bool
ian@0 579 Value::operator <( const Value &other ) const
ian@0 580 {
ian@0 581 int typeDelta = type_ - other.type_;
ian@0 582 if ( typeDelta )
ian@0 583 return typeDelta < 0 ? true : false;
ian@0 584 switch ( type_ )
ian@0 585 {
ian@0 586 case nullValue:
ian@0 587 return false;
ian@0 588 case intValue:
ian@0 589 return value_.int_ < other.value_.int_;
ian@0 590 case uintValue:
ian@0 591 return value_.uint_ < other.value_.uint_;
ian@0 592 case realValue:
ian@0 593 return value_.real_ < other.value_.real_;
ian@0 594 case booleanValue:
ian@0 595 return value_.bool_ < other.value_.bool_;
ian@0 596 case stringValue:
ian@0 597 return ( value_.string_ == 0 && other.value_.string_ )
ian@0 598 || ( other.value_.string_
ian@0 599 && value_.string_
ian@0 600 && strcmp( value_.string_, other.value_.string_ ) < 0 );
ian@0 601 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 602 case arrayValue:
ian@0 603 case objectValue:
ian@0 604 {
ian@0 605 int delta = int( value_.map_->size() - other.value_.map_->size() );
ian@0 606 if ( delta )
ian@0 607 return delta < 0;
ian@0 608 return (*value_.map_) < (*other.value_.map_);
ian@0 609 }
ian@0 610 #else
ian@0 611 case arrayValue:
ian@0 612 return value_.array_->compare( *(other.value_.array_) ) < 0;
ian@0 613 case objectValue:
ian@0 614 return value_.map_->compare( *(other.value_.map_) ) < 0;
ian@0 615 #endif
ian@0 616 default:
ian@0 617 JSON_ASSERT_UNREACHABLE;
ian@0 618 }
ian@0 619 return false; // unreachable
ian@0 620 }
ian@0 621
ian@0 622 bool
ian@0 623 Value::operator <=( const Value &other ) const
ian@0 624 {
ian@0 625 return !(other < *this);
ian@0 626 }
ian@0 627
ian@0 628 bool
ian@0 629 Value::operator >=( const Value &other ) const
ian@0 630 {
ian@0 631 return !(*this < other);
ian@0 632 }
ian@0 633
ian@0 634 bool
ian@0 635 Value::operator >( const Value &other ) const
ian@0 636 {
ian@0 637 return other < *this;
ian@0 638 }
ian@0 639
ian@0 640 bool
ian@0 641 Value::operator ==( const Value &other ) const
ian@0 642 {
ian@0 643 //if ( type_ != other.type_ )
ian@0 644 // GCC 2.95.3 says:
ian@0 645 // attempt to take address of bit-field structure member `Json::Value::type_'
ian@0 646 // Beats me, but a temp solves the problem.
ian@0 647 int temp = other.type_;
ian@0 648 if ( type_ != temp )
ian@0 649 return false;
ian@0 650 switch ( type_ )
ian@0 651 {
ian@0 652 case nullValue:
ian@0 653 return true;
ian@0 654 case intValue:
ian@0 655 return value_.int_ == other.value_.int_;
ian@0 656 case uintValue:
ian@0 657 return value_.uint_ == other.value_.uint_;
ian@0 658 case realValue:
ian@0 659 return value_.real_ == other.value_.real_;
ian@0 660 case booleanValue:
ian@0 661 return value_.bool_ == other.value_.bool_;
ian@0 662 case stringValue:
ian@0 663 return ( value_.string_ == other.value_.string_ )
ian@0 664 || ( other.value_.string_
ian@0 665 && value_.string_
ian@0 666 && strcmp( value_.string_, other.value_.string_ ) == 0 );
ian@0 667 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 668 case arrayValue:
ian@0 669 case objectValue:
ian@0 670 return value_.map_->size() == other.value_.map_->size()
ian@0 671 && (*value_.map_) == (*other.value_.map_);
ian@0 672 #else
ian@0 673 case arrayValue:
ian@0 674 return value_.array_->compare( *(other.value_.array_) ) == 0;
ian@0 675 case objectValue:
ian@0 676 return value_.map_->compare( *(other.value_.map_) ) == 0;
ian@0 677 #endif
ian@0 678 default:
ian@0 679 JSON_ASSERT_UNREACHABLE;
ian@0 680 }
ian@0 681 return false; // unreachable
ian@0 682 }
ian@0 683
ian@0 684 bool
ian@0 685 Value::operator !=( const Value &other ) const
ian@0 686 {
ian@0 687 return !( *this == other );
ian@0 688 }
ian@0 689
ian@0 690 const char *
ian@0 691 Value::asCString() const
ian@0 692 {
ian@0 693 JSON_ASSERT( type_ == stringValue );
ian@0 694 return value_.string_;
ian@0 695 }
ian@0 696
ian@0 697
ian@0 698 std::string
ian@0 699 Value::asString() const
ian@0 700 {
ian@0 701 switch ( type_ )
ian@0 702 {
ian@0 703 case nullValue:
ian@0 704 return "";
ian@0 705 case stringValue:
ian@0 706 return value_.string_ ? value_.string_ : "";
ian@0 707 case booleanValue:
ian@0 708 return value_.bool_ ? "true" : "false";
ian@0 709 case intValue:
ian@0 710 return valueToString( value_.int_ );
ian@0 711 case uintValue:
ian@0 712 return valueToString( value_.uint_ );
ian@0 713 case realValue:
ian@0 714 return valueToString( value_.real_ );
ian@0 715 default:
ian@0 716 JSON_FAIL_MESSAGE( "Type is not convertible to string" );
ian@0 717 }
ian@0 718 }
ian@0 719
ian@0 720 # ifdef JSON_USE_CPPTL
ian@0 721 CppTL::ConstString
ian@0 722 Value::asConstString() const
ian@0 723 {
ian@0 724 return CppTL::ConstString( asString().c_str() );
ian@0 725 }
ian@0 726 # endif
ian@0 727
ian@0 728
ian@0 729 Value::Int
ian@0 730 Value::asInt() const
ian@0 731 {
ian@0 732 switch ( type_ )
ian@0 733 {
ian@0 734 case intValue:
ian@0 735 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
ian@0 736 return Int(value_.int_);
ian@0 737 case uintValue:
ian@0 738 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
ian@0 739 return Int(value_.uint_);
ian@0 740 case realValue:
ian@0 741 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), "double out of Int range");
ian@0 742 return Int(value_.real_);
ian@0 743 case nullValue:
ian@0 744 return 0;
ian@0 745 case booleanValue:
ian@0 746 return value_.bool_ ? 1 : 0;
ian@0 747 default:
ian@0 748 break;
ian@0 749 }
ian@0 750 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
ian@0 751 }
ian@0 752
ian@0 753
ian@0 754 Value::UInt
ian@0 755 Value::asUInt() const
ian@0 756 {
ian@0 757 switch ( type_ )
ian@0 758 {
ian@0 759 case intValue:
ian@0 760 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
ian@0 761 return UInt(value_.int_);
ian@0 762 case uintValue:
ian@0 763 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
ian@0 764 return UInt(value_.uint_);
ian@0 765 case realValue:
ian@0 766 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), "double out of UInt range");
ian@0 767 return UInt( value_.real_ );
ian@0 768 case nullValue:
ian@0 769 return 0;
ian@0 770 case booleanValue:
ian@0 771 return value_.bool_ ? 1 : 0;
ian@0 772 default:
ian@0 773 break;
ian@0 774 }
ian@0 775 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
ian@0 776 }
ian@0 777
ian@0 778
ian@0 779 # if defined(JSON_HAS_INT64)
ian@0 780
ian@0 781 Value::Int64
ian@0 782 Value::asInt64() const
ian@0 783 {
ian@0 784 switch ( type_ )
ian@0 785 {
ian@0 786 case intValue:
ian@0 787 return Int64(value_.int_);
ian@0 788 case uintValue:
ian@0 789 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
ian@0 790 return Int64(value_.uint_);
ian@0 791 case realValue:
ian@0 792 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), "double out of Int64 range");
ian@0 793 return Int64(value_.real_);
ian@0 794 case nullValue:
ian@0 795 return 0;
ian@0 796 case booleanValue:
ian@0 797 return value_.bool_ ? 1 : 0;
ian@0 798 default:
ian@0 799 break;
ian@0 800 }
ian@0 801 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
ian@0 802 }
ian@0 803
ian@0 804
ian@0 805 Value::UInt64
ian@0 806 Value::asUInt64() const
ian@0 807 {
ian@0 808 switch ( type_ )
ian@0 809 {
ian@0 810 case intValue:
ian@0 811 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
ian@0 812 return UInt64(value_.int_);
ian@0 813 case uintValue:
ian@0 814 return UInt64(value_.uint_);
ian@0 815 case realValue:
ian@0 816 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), "double out of UInt64 range");
ian@0 817 return UInt64( value_.real_ );
ian@0 818 case nullValue:
ian@0 819 return 0;
ian@0 820 case booleanValue:
ian@0 821 return value_.bool_ ? 1 : 0;
ian@0 822 default:
ian@0 823 break;
ian@0 824 }
ian@0 825 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
ian@0 826 }
ian@0 827 # endif // if defined(JSON_HAS_INT64)
ian@0 828
ian@0 829
ian@0 830 LargestInt
ian@0 831 Value::asLargestInt() const
ian@0 832 {
ian@0 833 #if defined(JSON_NO_INT64)
ian@0 834 return asInt();
ian@0 835 #else
ian@0 836 return asInt64();
ian@0 837 #endif
ian@0 838 }
ian@0 839
ian@0 840
ian@0 841 LargestUInt
ian@0 842 Value::asLargestUInt() const
ian@0 843 {
ian@0 844 #if defined(JSON_NO_INT64)
ian@0 845 return asUInt();
ian@0 846 #else
ian@0 847 return asUInt64();
ian@0 848 #endif
ian@0 849 }
ian@0 850
ian@0 851
ian@0 852 double
ian@0 853 Value::asDouble() const
ian@0 854 {
ian@0 855 switch ( type_ )
ian@0 856 {
ian@0 857 case intValue:
ian@0 858 return static_cast<double>( value_.int_ );
ian@0 859 case uintValue:
ian@0 860 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 861 return static_cast<double>( value_.uint_ );
ian@0 862 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 863 return integerToDouble( value_.uint_ );
ian@0 864 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 865 case realValue:
ian@0 866 return value_.real_;
ian@0 867 case nullValue:
ian@0 868 return 0.0;
ian@0 869 case booleanValue:
ian@0 870 return value_.bool_ ? 1.0 : 0.0;
ian@0 871 default:
ian@0 872 break;
ian@0 873 }
ian@0 874 JSON_FAIL_MESSAGE("Value is not convertible to double.");
ian@0 875 }
ian@0 876
ian@0 877 float
ian@0 878 Value::asFloat() const
ian@0 879 {
ian@0 880 switch ( type_ )
ian@0 881 {
ian@0 882 case intValue:
ian@0 883 return static_cast<float>( value_.int_ );
ian@0 884 case uintValue:
ian@0 885 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 886 return static_cast<float>( value_.uint_ );
ian@0 887 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 888 return integerToDouble( value_.uint_ );
ian@0 889 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
ian@0 890 case realValue:
ian@0 891 return static_cast<float>( value_.real_ );
ian@0 892 case nullValue:
ian@0 893 return 0.0;
ian@0 894 case booleanValue:
ian@0 895 return value_.bool_ ? 1.0f : 0.0f;
ian@0 896 default:
ian@0 897 break;
ian@0 898 }
ian@0 899 JSON_FAIL_MESSAGE("Value is not convertible to float.");
ian@0 900 }
ian@0 901
ian@0 902 bool
ian@0 903 Value::asBool() const
ian@0 904 {
ian@0 905 switch ( type_ )
ian@0 906 {
ian@0 907 case booleanValue:
ian@0 908 return value_.bool_;
ian@0 909 case nullValue:
ian@0 910 return false;
ian@0 911 case intValue:
ian@0 912 return value_.int_ ? true : false;
ian@0 913 case uintValue:
ian@0 914 return value_.uint_ ? true : false;
ian@0 915 case realValue:
ian@0 916 return value_.real_ ? true : false;
ian@0 917 default:
ian@0 918 break;
ian@0 919 }
ian@0 920 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
ian@0 921 }
ian@0 922
ian@0 923
ian@0 924 bool
ian@0 925 Value::isConvertibleTo( ValueType other ) const
ian@0 926 {
ian@0 927 switch ( other )
ian@0 928 {
ian@0 929 case nullValue:
ian@0 930 return ( isNumeric() && asDouble() == 0.0 )
ian@0 931 || ( type_ == booleanValue && value_.bool_ == false )
ian@0 932 || ( type_ == stringValue && asString() == "" )
ian@0 933 || ( type_ == arrayValue && value_.map_->size() == 0 )
ian@0 934 || ( type_ == objectValue && value_.map_->size() == 0 )
ian@0 935 || type_ == nullValue;
ian@0 936 case intValue:
ian@0 937 return isInt()
ian@0 938 || (type_ == realValue && InRange(value_.real_, minInt, maxInt))
ian@0 939 || type_ == booleanValue
ian@0 940 || type_ == nullValue;
ian@0 941 case uintValue:
ian@0 942 return isUInt()
ian@0 943 || (type_ == realValue && InRange(value_.real_, 0, maxUInt))
ian@0 944 || type_ == booleanValue
ian@0 945 || type_ == nullValue;
ian@0 946 case realValue:
ian@0 947 return isNumeric()
ian@0 948 || type_ == booleanValue
ian@0 949 || type_ == nullValue;
ian@0 950 case booleanValue:
ian@0 951 return isNumeric()
ian@0 952 || type_ == booleanValue
ian@0 953 || type_ == nullValue;
ian@0 954 case stringValue:
ian@0 955 return isNumeric()
ian@0 956 || type_ == booleanValue
ian@0 957 || type_ == stringValue
ian@0 958 || type_ == nullValue;
ian@0 959 case arrayValue:
ian@0 960 return type_ == arrayValue
ian@0 961 || type_ == nullValue;
ian@0 962 case objectValue:
ian@0 963 return type_ == objectValue
ian@0 964 || type_ == nullValue;
ian@0 965 }
ian@0 966 JSON_ASSERT_UNREACHABLE;
ian@0 967 return false;
ian@0 968 }
ian@0 969
ian@0 970
ian@0 971 /// Number of values in array or object
ian@0 972 ArrayIndex
ian@0 973 Value::size() const
ian@0 974 {
ian@0 975 switch ( type_ )
ian@0 976 {
ian@0 977 case nullValue:
ian@0 978 case intValue:
ian@0 979 case uintValue:
ian@0 980 case realValue:
ian@0 981 case booleanValue:
ian@0 982 case stringValue:
ian@0 983 return 0;
ian@0 984 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 985 case arrayValue: // size of the array is highest index + 1
ian@0 986 if ( !value_.map_->empty() )
ian@0 987 {
ian@0 988 ObjectValues::const_iterator itLast = value_.map_->end();
ian@0 989 --itLast;
ian@0 990 return (*itLast).first.index()+1;
ian@0 991 }
ian@0 992 return 0;
ian@0 993 case objectValue:
ian@0 994 return ArrayIndex( value_.map_->size() );
ian@0 995 #else
ian@0 996 case arrayValue:
ian@0 997 return Int( value_.array_->size() );
ian@0 998 case objectValue:
ian@0 999 return Int( value_.map_->size() );
ian@0 1000 #endif
ian@0 1001 }
ian@0 1002 JSON_ASSERT_UNREACHABLE;
ian@0 1003 return 0; // unreachable;
ian@0 1004 }
ian@0 1005
ian@0 1006
ian@0 1007 bool
ian@0 1008 Value::empty() const
ian@0 1009 {
ian@0 1010 if ( isNull() || isArray() || isObject() )
ian@0 1011 return size() == 0u;
ian@0 1012 else
ian@0 1013 return false;
ian@0 1014 }
ian@0 1015
ian@0 1016
ian@0 1017 bool
ian@0 1018 Value::operator!() const
ian@0 1019 {
ian@0 1020 return isNull();
ian@0 1021 }
ian@0 1022
ian@0 1023
ian@0 1024 void
ian@0 1025 Value::clear()
ian@0 1026 {
ian@0 1027 JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
ian@0 1028
ian@0 1029 switch ( type_ )
ian@0 1030 {
ian@0 1031 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1032 case arrayValue:
ian@0 1033 case objectValue:
ian@0 1034 value_.map_->clear();
ian@0 1035 break;
ian@0 1036 #else
ian@0 1037 case arrayValue:
ian@0 1038 value_.array_->clear();
ian@0 1039 break;
ian@0 1040 case objectValue:
ian@0 1041 value_.map_->clear();
ian@0 1042 break;
ian@0 1043 #endif
ian@0 1044 default:
ian@0 1045 break;
ian@0 1046 }
ian@0 1047 }
ian@0 1048
ian@0 1049 void
ian@0 1050 Value::resize( ArrayIndex newSize )
ian@0 1051 {
ian@0 1052 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
ian@0 1053 if ( type_ == nullValue )
ian@0 1054 *this = Value( arrayValue );
ian@0 1055 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1056 ArrayIndex oldSize = size();
ian@0 1057 if ( newSize == 0 )
ian@0 1058 clear();
ian@0 1059 else if ( newSize > oldSize )
ian@0 1060 (*this)[ newSize - 1 ];
ian@0 1061 else
ian@0 1062 {
ian@0 1063 for ( ArrayIndex index = newSize; index < oldSize; ++index )
ian@0 1064 {
ian@0 1065 value_.map_->erase( index );
ian@0 1066 }
ian@0 1067 assert( size() == newSize );
ian@0 1068 }
ian@0 1069 #else
ian@0 1070 value_.array_->resize( newSize );
ian@0 1071 #endif
ian@0 1072 }
ian@0 1073
ian@0 1074
ian@0 1075 Value &
ian@0 1076 Value::operator[]( ArrayIndex index )
ian@0 1077 {
ian@0 1078 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
ian@0 1079 if ( type_ == nullValue )
ian@0 1080 *this = Value( arrayValue );
ian@0 1081 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1082 CZString key( index );
ian@0 1083 ObjectValues::iterator it = value_.map_->lower_bound( key );
ian@0 1084 if ( it != value_.map_->end() && (*it).first == key )
ian@0 1085 return (*it).second;
ian@0 1086
ian@0 1087 ObjectValues::value_type defaultValue( key, null );
ian@0 1088 it = value_.map_->insert( it, defaultValue );
ian@0 1089 return (*it).second;
ian@0 1090 #else
ian@0 1091 return value_.array_->resolveReference( index );
ian@0 1092 #endif
ian@0 1093 }
ian@0 1094
ian@0 1095
ian@0 1096 Value &
ian@0 1097 Value::operator[]( int index )
ian@0 1098 {
ian@0 1099 JSON_ASSERT( index >= 0 );
ian@0 1100 return (*this)[ ArrayIndex(index) ];
ian@0 1101 }
ian@0 1102
ian@0 1103
ian@0 1104 const Value &
ian@0 1105 Value::operator[]( ArrayIndex index ) const
ian@0 1106 {
ian@0 1107 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
ian@0 1108 if ( type_ == nullValue )
ian@0 1109 return null;
ian@0 1110 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1111 CZString key( index );
ian@0 1112 ObjectValues::const_iterator it = value_.map_->find( key );
ian@0 1113 if ( it == value_.map_->end() )
ian@0 1114 return null;
ian@0 1115 return (*it).second;
ian@0 1116 #else
ian@0 1117 Value *value = value_.array_->find( index );
ian@0 1118 return value ? *value : null;
ian@0 1119 #endif
ian@0 1120 }
ian@0 1121
ian@0 1122
ian@0 1123 const Value &
ian@0 1124 Value::operator[]( int index ) const
ian@0 1125 {
ian@0 1126 JSON_ASSERT( index >= 0 );
ian@0 1127 return (*this)[ ArrayIndex(index) ];
ian@0 1128 }
ian@0 1129
ian@0 1130
ian@0 1131 Value &
ian@0 1132 Value::operator[]( const char *key )
ian@0 1133 {
ian@0 1134 return resolveReference( key, false );
ian@0 1135 }
ian@0 1136
ian@0 1137
ian@0 1138 Value &
ian@0 1139 Value::resolveReference( const char *key,
ian@0 1140 bool isStatic )
ian@0 1141 {
ian@0 1142 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
ian@0 1143 if ( type_ == nullValue )
ian@0 1144 *this = Value( objectValue );
ian@0 1145 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1146 CZString actualKey( key, isStatic ? CZString::noDuplication
ian@0 1147 : CZString::duplicateOnCopy );
ian@0 1148 ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
ian@0 1149 if ( it != value_.map_->end() && (*it).first == actualKey )
ian@0 1150 return (*it).second;
ian@0 1151
ian@0 1152 ObjectValues::value_type defaultValue( actualKey, null );
ian@0 1153 it = value_.map_->insert( it, defaultValue );
ian@0 1154 Value &value = (*it).second;
ian@0 1155 return value;
ian@0 1156 #else
ian@0 1157 return value_.map_->resolveReference( key, isStatic );
ian@0 1158 #endif
ian@0 1159 }
ian@0 1160
ian@0 1161
ian@0 1162 Value
ian@0 1163 Value::get( ArrayIndex index,
ian@0 1164 const Value &defaultValue ) const
ian@0 1165 {
ian@0 1166 const Value *value = &((*this)[index]);
ian@0 1167 return value == &null ? defaultValue : *value;
ian@0 1168 }
ian@0 1169
ian@0 1170
ian@0 1171 bool
ian@0 1172 Value::isValidIndex( ArrayIndex index ) const
ian@0 1173 {
ian@0 1174 return index < size();
ian@0 1175 }
ian@0 1176
ian@0 1177
ian@0 1178
ian@0 1179 const Value &
ian@0 1180 Value::operator[]( const char *key ) const
ian@0 1181 {
ian@0 1182 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
ian@0 1183 if ( type_ == nullValue )
ian@0 1184 return null;
ian@0 1185 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1186 CZString actualKey( key, CZString::noDuplication );
ian@0 1187 ObjectValues::const_iterator it = value_.map_->find( actualKey );
ian@0 1188 if ( it == value_.map_->end() )
ian@0 1189 return null;
ian@0 1190 return (*it).second;
ian@0 1191 #else
ian@0 1192 const Value *value = value_.map_->find( key );
ian@0 1193 return value ? *value : null;
ian@0 1194 #endif
ian@0 1195 }
ian@0 1196
ian@0 1197
ian@0 1198 Value &
ian@0 1199 Value::operator[]( const std::string &key )
ian@0 1200 {
ian@0 1201 return (*this)[ key.c_str() ];
ian@0 1202 }
ian@0 1203
ian@0 1204
ian@0 1205 const Value &
ian@0 1206 Value::operator[]( const std::string &key ) const
ian@0 1207 {
ian@0 1208 return (*this)[ key.c_str() ];
ian@0 1209 }
ian@0 1210
ian@0 1211 Value &
ian@0 1212 Value::operator[]( const StaticString &key )
ian@0 1213 {
ian@0 1214 return resolveReference( key, true );
ian@0 1215 }
ian@0 1216
ian@0 1217
ian@0 1218 # ifdef JSON_USE_CPPTL
ian@0 1219 Value &
ian@0 1220 Value::operator[]( const CppTL::ConstString &key )
ian@0 1221 {
ian@0 1222 return (*this)[ key.c_str() ];
ian@0 1223 }
ian@0 1224
ian@0 1225
ian@0 1226 const Value &
ian@0 1227 Value::operator[]( const CppTL::ConstString &key ) const
ian@0 1228 {
ian@0 1229 return (*this)[ key.c_str() ];
ian@0 1230 }
ian@0 1231 # endif
ian@0 1232
ian@0 1233
ian@0 1234 Value &
ian@0 1235 Value::append( const Value &value )
ian@0 1236 {
ian@0 1237 return (*this)[size()] = value;
ian@0 1238 }
ian@0 1239
ian@0 1240
ian@0 1241 Value
ian@0 1242 Value::get( const char *key,
ian@0 1243 const Value &defaultValue ) const
ian@0 1244 {
ian@0 1245 const Value *value = &((*this)[key]);
ian@0 1246 return value == &null ? defaultValue : *value;
ian@0 1247 }
ian@0 1248
ian@0 1249
ian@0 1250 Value
ian@0 1251 Value::get( const std::string &key,
ian@0 1252 const Value &defaultValue ) const
ian@0 1253 {
ian@0 1254 return get( key.c_str(), defaultValue );
ian@0 1255 }
ian@0 1256
ian@0 1257 Value
ian@0 1258 Value::removeMember( const char* key )
ian@0 1259 {
ian@0 1260 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
ian@0 1261 if ( type_ == nullValue )
ian@0 1262 return null;
ian@0 1263 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1264 CZString actualKey( key, CZString::noDuplication );
ian@0 1265 ObjectValues::iterator it = value_.map_->find( actualKey );
ian@0 1266 if ( it == value_.map_->end() )
ian@0 1267 return null;
ian@0 1268 Value old(it->second);
ian@0 1269 value_.map_->erase(it);
ian@0 1270 return old;
ian@0 1271 #else
ian@0 1272 Value *value = value_.map_->find( key );
ian@0 1273 if (value){
ian@0 1274 Value old(*value);
ian@0 1275 value_.map_.remove( key );
ian@0 1276 return old;
ian@0 1277 } else {
ian@0 1278 return null;
ian@0 1279 }
ian@0 1280 #endif
ian@0 1281 }
ian@0 1282
ian@0 1283 Value
ian@0 1284 Value::removeMember( const std::string &key )
ian@0 1285 {
ian@0 1286 return removeMember( key.c_str() );
ian@0 1287 }
ian@0 1288
ian@0 1289 # ifdef JSON_USE_CPPTL
ian@0 1290 Value
ian@0 1291 Value::get( const CppTL::ConstString &key,
ian@0 1292 const Value &defaultValue ) const
ian@0 1293 {
ian@0 1294 return get( key.c_str(), defaultValue );
ian@0 1295 }
ian@0 1296 # endif
ian@0 1297
ian@0 1298 bool
ian@0 1299 Value::isMember( const char *key ) const
ian@0 1300 {
ian@0 1301 const Value *value = &((*this)[key]);
ian@0 1302 return value != &null;
ian@0 1303 }
ian@0 1304
ian@0 1305
ian@0 1306 bool
ian@0 1307 Value::isMember( const std::string &key ) const
ian@0 1308 {
ian@0 1309 return isMember( key.c_str() );
ian@0 1310 }
ian@0 1311
ian@0 1312
ian@0 1313 # ifdef JSON_USE_CPPTL
ian@0 1314 bool
ian@0 1315 Value::isMember( const CppTL::ConstString &key ) const
ian@0 1316 {
ian@0 1317 return isMember( key.c_str() );
ian@0 1318 }
ian@0 1319 #endif
ian@0 1320
ian@0 1321 Value::Members
ian@0 1322 Value::getMemberNames() const
ian@0 1323 {
ian@0 1324 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
ian@0 1325 if ( type_ == nullValue )
ian@0 1326 return Value::Members();
ian@0 1327 Members members;
ian@0 1328 members.reserve( value_.map_->size() );
ian@0 1329 #ifndef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1330 ObjectValues::const_iterator it = value_.map_->begin();
ian@0 1331 ObjectValues::const_iterator itEnd = value_.map_->end();
ian@0 1332 for ( ; it != itEnd; ++it )
ian@0 1333 members.push_back( std::string( (*it).first.c_str() ) );
ian@0 1334 #else
ian@0 1335 ValueInternalMap::IteratorState it;
ian@0 1336 ValueInternalMap::IteratorState itEnd;
ian@0 1337 value_.map_->makeBeginIterator( it );
ian@0 1338 value_.map_->makeEndIterator( itEnd );
ian@0 1339 for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
ian@0 1340 members.push_back( std::string( ValueInternalMap::key( it ) ) );
ian@0 1341 #endif
ian@0 1342 return members;
ian@0 1343 }
ian@0 1344 //
ian@0 1345 //# ifdef JSON_USE_CPPTL
ian@0 1346 //EnumMemberNames
ian@0 1347 //Value::enumMemberNames() const
ian@0 1348 //{
ian@0 1349 // if ( type_ == objectValue )
ian@0 1350 // {
ian@0 1351 // return CppTL::Enum::any( CppTL::Enum::transform(
ian@0 1352 // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
ian@0 1353 // MemberNamesTransform() ) );
ian@0 1354 // }
ian@0 1355 // return EnumMemberNames();
ian@0 1356 //}
ian@0 1357 //
ian@0 1358 //
ian@0 1359 //EnumValues
ian@0 1360 //Value::enumValues() const
ian@0 1361 //{
ian@0 1362 // if ( type_ == objectValue || type_ == arrayValue )
ian@0 1363 // return CppTL::Enum::anyValues( *(value_.map_),
ian@0 1364 // CppTL::Type<const Value &>() );
ian@0 1365 // return EnumValues();
ian@0 1366 //}
ian@0 1367 //
ian@0 1368 //# endif
ian@0 1369
ian@0 1370 static bool IsIntegral(double d) {
ian@0 1371 double integral_part;
ian@0 1372 return modf(d, &integral_part) == 0.0;
ian@0 1373 }
ian@0 1374
ian@0 1375
ian@0 1376 bool
ian@0 1377 Value::isNull() const
ian@0 1378 {
ian@0 1379 return type_ == nullValue;
ian@0 1380 }
ian@0 1381
ian@0 1382
ian@0 1383 bool
ian@0 1384 Value::isBool() const
ian@0 1385 {
ian@0 1386 return type_ == booleanValue;
ian@0 1387 }
ian@0 1388
ian@0 1389
ian@0 1390 bool
ian@0 1391 Value::isInt() const
ian@0 1392 {
ian@0 1393 switch ( type_ )
ian@0 1394 {
ian@0 1395 case intValue:
ian@0 1396 return value_.int_ >= minInt && value_.int_ <= maxInt;
ian@0 1397 case uintValue:
ian@0 1398 return value_.uint_ <= UInt(maxInt);
ian@0 1399 case realValue:
ian@0 1400 return value_.real_ >= minInt &&
ian@0 1401 value_.real_ <= maxInt &&
ian@0 1402 IsIntegral(value_.real_);
ian@0 1403 default:
ian@0 1404 break;
ian@0 1405 }
ian@0 1406 return false;
ian@0 1407 }
ian@0 1408
ian@0 1409
ian@0 1410 bool
ian@0 1411 Value::isUInt() const
ian@0 1412 {
ian@0 1413 switch ( type_ )
ian@0 1414 {
ian@0 1415 case intValue:
ian@0 1416 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
ian@0 1417 case uintValue:
ian@0 1418 return value_.uint_ <= maxUInt;
ian@0 1419 case realValue:
ian@0 1420 return value_.real_ >= 0 &&
ian@0 1421 value_.real_ <= maxUInt &&
ian@0 1422 IsIntegral(value_.real_);
ian@0 1423 default:
ian@0 1424 break;
ian@0 1425 }
ian@0 1426 return false;
ian@0 1427 }
ian@0 1428
ian@0 1429 bool
ian@0 1430 Value::isInt64() const
ian@0 1431 {
ian@0 1432 # if defined(JSON_HAS_INT64)
ian@0 1433 switch ( type_ )
ian@0 1434 {
ian@0 1435 case intValue:
ian@0 1436 return true;
ian@0 1437 case uintValue:
ian@0 1438 return value_.uint_ <= UInt64(maxInt64);
ian@0 1439 case realValue:
ian@0 1440 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
ian@0 1441 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
ian@0 1442 // require the value to be strictly less than the limit.
ian@0 1443 return value_.real_ >= double(minInt64) &&
ian@0 1444 value_.real_ < double(maxInt64) &&
ian@0 1445 IsIntegral(value_.real_);
ian@0 1446 default:
ian@0 1447 break;
ian@0 1448 }
ian@0 1449 # endif // JSON_HAS_INT64
ian@0 1450 return false;
ian@0 1451 }
ian@0 1452
ian@0 1453 bool
ian@0 1454 Value::isUInt64() const
ian@0 1455 {
ian@0 1456 # if defined(JSON_HAS_INT64)
ian@0 1457 switch ( type_ )
ian@0 1458 {
ian@0 1459 case intValue:
ian@0 1460 return value_.int_ >= 0;
ian@0 1461 case uintValue:
ian@0 1462 return true;
ian@0 1463 case realValue:
ian@0 1464 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
ian@0 1465 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
ian@0 1466 // require the value to be strictly less than the limit.
ian@0 1467 return value_.real_ >= 0 &&
ian@0 1468 value_.real_ < maxUInt64AsDouble &&
ian@0 1469 IsIntegral(value_.real_);
ian@0 1470 default:
ian@0 1471 break;
ian@0 1472 }
ian@0 1473 # endif // JSON_HAS_INT64
ian@0 1474 return false;
ian@0 1475 }
ian@0 1476
ian@0 1477
ian@0 1478 bool
ian@0 1479 Value::isIntegral() const
ian@0 1480 {
ian@0 1481 #if defined(JSON_HAS_INT64)
ian@0 1482 return isInt64() || isUInt64();
ian@0 1483 #else
ian@0 1484 return isInt() || isUInt();
ian@0 1485 #endif
ian@0 1486 }
ian@0 1487
ian@0 1488
ian@0 1489 bool
ian@0 1490 Value::isDouble() const
ian@0 1491 {
ian@0 1492 return type_ == realValue || isIntegral();
ian@0 1493 }
ian@0 1494
ian@0 1495
ian@0 1496 bool
ian@0 1497 Value::isNumeric() const
ian@0 1498 {
ian@0 1499 return isIntegral() || isDouble();
ian@0 1500 }
ian@0 1501
ian@0 1502
ian@0 1503 bool
ian@0 1504 Value::isString() const
ian@0 1505 {
ian@0 1506 return type_ == stringValue;
ian@0 1507 }
ian@0 1508
ian@0 1509
ian@0 1510 bool
ian@0 1511 Value::isArray() const
ian@0 1512 {
ian@0 1513 return type_ == arrayValue;
ian@0 1514 }
ian@0 1515
ian@0 1516
ian@0 1517 bool
ian@0 1518 Value::isObject() const
ian@0 1519 {
ian@0 1520 return type_ == objectValue;
ian@0 1521 }
ian@0 1522
ian@0 1523
ian@0 1524 void
ian@0 1525 Value::setComment( const char *comment,
ian@0 1526 CommentPlacement placement )
ian@0 1527 {
ian@0 1528 if ( !comments_ )
ian@0 1529 comments_ = new CommentInfo[numberOfCommentPlacement];
ian@0 1530 comments_[placement].setComment( comment );
ian@0 1531 }
ian@0 1532
ian@0 1533
ian@0 1534 void
ian@0 1535 Value::setComment( const std::string &comment,
ian@0 1536 CommentPlacement placement )
ian@0 1537 {
ian@0 1538 setComment( comment.c_str(), placement );
ian@0 1539 }
ian@0 1540
ian@0 1541
ian@0 1542 bool
ian@0 1543 Value::hasComment( CommentPlacement placement ) const
ian@0 1544 {
ian@0 1545 return comments_ != 0 && comments_[placement].comment_ != 0;
ian@0 1546 }
ian@0 1547
ian@0 1548 std::string
ian@0 1549 Value::getComment( CommentPlacement placement ) const
ian@0 1550 {
ian@0 1551 if ( hasComment(placement) )
ian@0 1552 return comments_[placement].comment_;
ian@0 1553 return "";
ian@0 1554 }
ian@0 1555
ian@0 1556
ian@0 1557 std::string
ian@0 1558 Value::toStyledString() const
ian@0 1559 {
ian@0 1560 StyledWriter writer;
ian@0 1561 return writer.write( *this );
ian@0 1562 }
ian@0 1563
ian@0 1564
ian@0 1565 Value::const_iterator
ian@0 1566 Value::begin() const
ian@0 1567 {
ian@0 1568 switch ( type_ )
ian@0 1569 {
ian@0 1570 #ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1571 case arrayValue:
ian@0 1572 if ( value_.array_ )
ian@0 1573 {
ian@0 1574 ValueInternalArray::IteratorState it;
ian@0 1575 value_.array_->makeBeginIterator( it );
ian@0 1576 return const_iterator( it );
ian@0 1577 }
ian@0 1578 break;
ian@0 1579 case objectValue:
ian@0 1580 if ( value_.map_ )
ian@0 1581 {
ian@0 1582 ValueInternalMap::IteratorState it;
ian@0 1583 value_.map_->makeBeginIterator( it );
ian@0 1584 return const_iterator( it );
ian@0 1585 }
ian@0 1586 break;
ian@0 1587 #else
ian@0 1588 case arrayValue:
ian@0 1589 case objectValue:
ian@0 1590 if ( value_.map_ )
ian@0 1591 return const_iterator( value_.map_->begin() );
ian@0 1592 break;
ian@0 1593 #endif
ian@0 1594 default:
ian@0 1595 break;
ian@0 1596 }
ian@0 1597 return const_iterator();
ian@0 1598 }
ian@0 1599
ian@0 1600 Value::const_iterator
ian@0 1601 Value::end() const
ian@0 1602 {
ian@0 1603 switch ( type_ )
ian@0 1604 {
ian@0 1605 #ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1606 case arrayValue:
ian@0 1607 if ( value_.array_ )
ian@0 1608 {
ian@0 1609 ValueInternalArray::IteratorState it;
ian@0 1610 value_.array_->makeEndIterator( it );
ian@0 1611 return const_iterator( it );
ian@0 1612 }
ian@0 1613 break;
ian@0 1614 case objectValue:
ian@0 1615 if ( value_.map_ )
ian@0 1616 {
ian@0 1617 ValueInternalMap::IteratorState it;
ian@0 1618 value_.map_->makeEndIterator( it );
ian@0 1619 return const_iterator( it );
ian@0 1620 }
ian@0 1621 break;
ian@0 1622 #else
ian@0 1623 case arrayValue:
ian@0 1624 case objectValue:
ian@0 1625 if ( value_.map_ )
ian@0 1626 return const_iterator( value_.map_->end() );
ian@0 1627 break;
ian@0 1628 #endif
ian@0 1629 default:
ian@0 1630 break;
ian@0 1631 }
ian@0 1632 return const_iterator();
ian@0 1633 }
ian@0 1634
ian@0 1635
ian@0 1636 Value::iterator
ian@0 1637 Value::begin()
ian@0 1638 {
ian@0 1639 switch ( type_ )
ian@0 1640 {
ian@0 1641 #ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1642 case arrayValue:
ian@0 1643 if ( value_.array_ )
ian@0 1644 {
ian@0 1645 ValueInternalArray::IteratorState it;
ian@0 1646 value_.array_->makeBeginIterator( it );
ian@0 1647 return iterator( it );
ian@0 1648 }
ian@0 1649 break;
ian@0 1650 case objectValue:
ian@0 1651 if ( value_.map_ )
ian@0 1652 {
ian@0 1653 ValueInternalMap::IteratorState it;
ian@0 1654 value_.map_->makeBeginIterator( it );
ian@0 1655 return iterator( it );
ian@0 1656 }
ian@0 1657 break;
ian@0 1658 #else
ian@0 1659 case arrayValue:
ian@0 1660 case objectValue:
ian@0 1661 if ( value_.map_ )
ian@0 1662 return iterator( value_.map_->begin() );
ian@0 1663 break;
ian@0 1664 #endif
ian@0 1665 default:
ian@0 1666 break;
ian@0 1667 }
ian@0 1668 return iterator();
ian@0 1669 }
ian@0 1670
ian@0 1671 Value::iterator
ian@0 1672 Value::end()
ian@0 1673 {
ian@0 1674 switch ( type_ )
ian@0 1675 {
ian@0 1676 #ifdef JSON_VALUE_USE_INTERNAL_MAP
ian@0 1677 case arrayValue:
ian@0 1678 if ( value_.array_ )
ian@0 1679 {
ian@0 1680 ValueInternalArray::IteratorState it;
ian@0 1681 value_.array_->makeEndIterator( it );
ian@0 1682 return iterator( it );
ian@0 1683 }
ian@0 1684 break;
ian@0 1685 case objectValue:
ian@0 1686 if ( value_.map_ )
ian@0 1687 {
ian@0 1688 ValueInternalMap::IteratorState it;
ian@0 1689 value_.map_->makeEndIterator( it );
ian@0 1690 return iterator( it );
ian@0 1691 }
ian@0 1692 break;
ian@0 1693 #else
ian@0 1694 case arrayValue:
ian@0 1695 case objectValue:
ian@0 1696 if ( value_.map_ )
ian@0 1697 return iterator( value_.map_->end() );
ian@0 1698 break;
ian@0 1699 #endif
ian@0 1700 default:
ian@0 1701 break;
ian@0 1702 }
ian@0 1703 return iterator();
ian@0 1704 }
ian@0 1705
ian@0 1706
ian@0 1707 // class PathArgument
ian@0 1708 // //////////////////////////////////////////////////////////////////
ian@0 1709
ian@0 1710 PathArgument::PathArgument()
ian@0 1711 : key_()
ian@0 1712 , index_()
ian@0 1713 , kind_( kindNone )
ian@0 1714 {
ian@0 1715 }
ian@0 1716
ian@0 1717
ian@0 1718 PathArgument::PathArgument( ArrayIndex index )
ian@0 1719 : key_()
ian@0 1720 , index_( index )
ian@0 1721 , kind_( kindIndex )
ian@0 1722 {
ian@0 1723 }
ian@0 1724
ian@0 1725
ian@0 1726 PathArgument::PathArgument( const char *key )
ian@0 1727 : key_( key )
ian@0 1728 , index_()
ian@0 1729 , kind_( kindKey )
ian@0 1730 {
ian@0 1731 }
ian@0 1732
ian@0 1733
ian@0 1734 PathArgument::PathArgument( const std::string &key )
ian@0 1735 : key_( key.c_str() )
ian@0 1736 , index_()
ian@0 1737 , kind_( kindKey )
ian@0 1738 {
ian@0 1739 }
ian@0 1740
ian@0 1741 // class Path
ian@0 1742 // //////////////////////////////////////////////////////////////////
ian@0 1743
ian@0 1744 Path::Path( const std::string &path,
ian@0 1745 const PathArgument &a1,
ian@0 1746 const PathArgument &a2,
ian@0 1747 const PathArgument &a3,
ian@0 1748 const PathArgument &a4,
ian@0 1749 const PathArgument &a5 )
ian@0 1750 {
ian@0 1751 InArgs in;
ian@0 1752 in.push_back( &a1 );
ian@0 1753 in.push_back( &a2 );
ian@0 1754 in.push_back( &a3 );
ian@0 1755 in.push_back( &a4 );
ian@0 1756 in.push_back( &a5 );
ian@0 1757 makePath( path, in );
ian@0 1758 }
ian@0 1759
ian@0 1760
ian@0 1761 void
ian@0 1762 Path::makePath( const std::string &path,
ian@0 1763 const InArgs &in )
ian@0 1764 {
ian@0 1765 const char *current = path.c_str();
ian@0 1766 const char *end = current + path.length();
ian@0 1767 InArgs::const_iterator itInArg = in.begin();
ian@0 1768 while ( current != end )
ian@0 1769 {
ian@0 1770 if ( *current == '[' )
ian@0 1771 {
ian@0 1772 ++current;
ian@0 1773 if ( *current == '%' )
ian@0 1774 addPathInArg( path, in, itInArg, PathArgument::kindIndex );
ian@0 1775 else
ian@0 1776 {
ian@0 1777 ArrayIndex index = 0;
ian@0 1778 for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
ian@0 1779 index = index * 10 + ArrayIndex(*current - '0');
ian@0 1780 args_.push_back( index );
ian@0 1781 }
ian@0 1782 if ( current == end || *current++ != ']' )
ian@0 1783 invalidPath( path, int(current - path.c_str()) );
ian@0 1784 }
ian@0 1785 else if ( *current == '%' )
ian@0 1786 {
ian@0 1787 addPathInArg( path, in, itInArg, PathArgument::kindKey );
ian@0 1788 ++current;
ian@0 1789 }
ian@0 1790 else if ( *current == '.' )
ian@0 1791 {
ian@0 1792 ++current;
ian@0 1793 }
ian@0 1794 else
ian@0 1795 {
ian@0 1796 const char *beginName = current;
ian@0 1797 while ( current != end && !strchr( "[.", *current ) )
ian@0 1798 ++current;
ian@0 1799 args_.push_back( std::string( beginName, current ) );
ian@0 1800 }
ian@0 1801 }
ian@0 1802 }
ian@0 1803
ian@0 1804
ian@0 1805 void
ian@0 1806 Path::addPathInArg( const std::string &path,
ian@0 1807 const InArgs &in,
ian@0 1808 InArgs::const_iterator &itInArg,
ian@0 1809 PathArgument::Kind kind )
ian@0 1810 {
ian@0 1811 if ( itInArg == in.end() )
ian@0 1812 {
ian@0 1813 // Error: missing argument %d
ian@0 1814 }
ian@0 1815 else if ( (*itInArg)->kind_ != kind )
ian@0 1816 {
ian@0 1817 // Error: bad argument type
ian@0 1818 }
ian@0 1819 else
ian@0 1820 {
ian@0 1821 args_.push_back( **itInArg );
ian@0 1822 }
ian@0 1823 }
ian@0 1824
ian@0 1825
ian@0 1826 void
ian@0 1827 Path::invalidPath( const std::string &path,
ian@0 1828 int location )
ian@0 1829 {
ian@0 1830 // Error: invalid path.
ian@0 1831 }
ian@0 1832
ian@0 1833
ian@0 1834 const Value &
ian@0 1835 Path::resolve( const Value &root ) const
ian@0 1836 {
ian@0 1837 const Value *node = &root;
ian@0 1838 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
ian@0 1839 {
ian@0 1840 const PathArgument &arg = *it;
ian@0 1841 if ( arg.kind_ == PathArgument::kindIndex )
ian@0 1842 {
ian@0 1843 if ( !node->isArray() || !node->isValidIndex( arg.index_ ) )
ian@0 1844 {
ian@0 1845 // Error: unable to resolve path (array value expected at position...
ian@0 1846 }
ian@0 1847 node = &((*node)[arg.index_]);
ian@0 1848 }
ian@0 1849 else if ( arg.kind_ == PathArgument::kindKey )
ian@0 1850 {
ian@0 1851 if ( !node->isObject() )
ian@0 1852 {
ian@0 1853 // Error: unable to resolve path (object value expected at position...)
ian@0 1854 }
ian@0 1855 node = &((*node)[arg.key_]);
ian@0 1856 if ( node == &Value::null )
ian@0 1857 {
ian@0 1858 // Error: unable to resolve path (object has no member named '' at position...)
ian@0 1859 }
ian@0 1860 }
ian@0 1861 }
ian@0 1862 return *node;
ian@0 1863 }
ian@0 1864
ian@0 1865
ian@0 1866 Value
ian@0 1867 Path::resolve( const Value &root,
ian@0 1868 const Value &defaultValue ) const
ian@0 1869 {
ian@0 1870 const Value *node = &root;
ian@0 1871 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
ian@0 1872 {
ian@0 1873 const PathArgument &arg = *it;
ian@0 1874 if ( arg.kind_ == PathArgument::kindIndex )
ian@0 1875 {
ian@0 1876 if ( !node->isArray() || !node->isValidIndex( arg.index_ ) )
ian@0 1877 return defaultValue;
ian@0 1878 node = &((*node)[arg.index_]);
ian@0 1879 }
ian@0 1880 else if ( arg.kind_ == PathArgument::kindKey )
ian@0 1881 {
ian@0 1882 if ( !node->isObject() )
ian@0 1883 return defaultValue;
ian@0 1884 node = &((*node)[arg.key_]);
ian@0 1885 if ( node == &Value::null )
ian@0 1886 return defaultValue;
ian@0 1887 }
ian@0 1888 }
ian@0 1889 return *node;
ian@0 1890 }
ian@0 1891
ian@0 1892
ian@0 1893 Value &
ian@0 1894 Path::make( Value &root ) const
ian@0 1895 {
ian@0 1896 Value *node = &root;
ian@0 1897 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
ian@0 1898 {
ian@0 1899 const PathArgument &arg = *it;
ian@0 1900 if ( arg.kind_ == PathArgument::kindIndex )
ian@0 1901 {
ian@0 1902 if ( !node->isArray() )
ian@0 1903 {
ian@0 1904 // Error: node is not an array at position ...
ian@0 1905 }
ian@0 1906 node = &((*node)[arg.index_]);
ian@0 1907 }
ian@0 1908 else if ( arg.kind_ == PathArgument::kindKey )
ian@0 1909 {
ian@0 1910 if ( !node->isObject() )
ian@0 1911 {
ian@0 1912 // Error: node is not an object at position...
ian@0 1913 }
ian@0 1914 node = &((*node)[arg.key_]);
ian@0 1915 }
ian@0 1916 }
ian@0 1917 return *node;
ian@0 1918 }
ian@0 1919
ian@0 1920
ian@0 1921 } // namespace Json