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