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