JsonCpp project page JsonCpp home page

json_value.cpp
Go to the documentation of this file.
1#include <iostream>
2#include <json/value.h>
3#include <json/writer.h>
4#include <utility>
5#include <stdexcept>
6#include <cstring>
7#include <cassert>
8#ifdef JSON_USE_CPPTL
9# include <cpptl/conststring.h>
10#endif
11#include <cstddef> // size_t
12#ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
13# include "json_batchallocator.h"
14#endif // #ifndef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
15
16#define JSON_ASSERT_UNREACHABLE assert( false )
17#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
18#define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
19
20namespace Json {
21
22const Value Value::null;
23const Int Value::minInt = Int( ~(UInt(-1)/2) );
24const Int Value::maxInt = Int( UInt(-1)/2 );
25const UInt Value::maxUInt = UInt(-1);
26
27// A "safe" implementation of strdup. Allow null pointer to be passed.
28// Also avoid warning on msvc80.
29//
30//inline char *safeStringDup( const char *czstring )
31//{
32// if ( czstring )
33// {
34// const size_t length = (unsigned int)( strlen(czstring) + 1 );
35// char *newString = static_cast<char *>( malloc( length ) );
36// memcpy( newString, czstring, length );
37// return newString;
38// }
39// return 0;
40//}
41//
42//inline char *safeStringDup( const std::string &str )
43//{
44// if ( !str.empty() )
45// {
46// const size_t length = str.length();
47// char *newString = static_cast<char *>( malloc( length + 1 ) );
48// memcpy( newString, str.c_str(), length );
49// newString[length] = 0;
50// return newString;
51// }
52// return 0;
53//}
54
56{
57}
58
59class DefaultValueAllocator : public ValueAllocator
60{
61public:
62 virtual ~DefaultValueAllocator()
63 {
64 }
65
66 virtual char *makeMemberName( const char *memberName )
67 {
68 return duplicateStringValue( memberName );
69 }
70
71 virtual void releaseMemberName( char *memberName )
72 {
73 releaseStringValue( memberName );
74 }
75
76 virtual char *duplicateStringValue( const char *value,
77 unsigned int length = unknown )
78 {
79 //@todo invesgate this old optimization
80 //if ( !value || value[0] == 0 )
81 // return 0;
82
83 if ( length == unknown )
84 length = (unsigned int)strlen(value);
85 char *newString = static_cast<char *>( malloc( length + 1 ) );
86 memcpy( newString, value, length );
87 newString[length] = 0;
88 return newString;
89 }
90
91 virtual void releaseStringValue( char *value )
92 {
93 if ( value )
94 free( value );
95 }
96};
97
99{
100 static DefaultValueAllocator defaultAllocator;
101 static ValueAllocator *valueAllocator = &defaultAllocator;
102 return valueAllocator;
103}
104
105static struct DummyValueAllocatorInitializer {
106 DummyValueAllocatorInitializer()
107 {
108 valueAllocator(); // ensure valueAllocator() statics are initialized before main().
109 }
111
112
113
114// //////////////////////////////////////////////////////////////////
115// //////////////////////////////////////////////////////////////////
116// //////////////////////////////////////////////////////////////////
117// ValueInternals...
118// //////////////////////////////////////////////////////////////////
119// //////////////////////////////////////////////////////////////////
120// //////////////////////////////////////////////////////////////////
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
128
129// //////////////////////////////////////////////////////////////////
130// //////////////////////////////////////////////////////////////////
131// //////////////////////////////////////////////////////////////////
132// class Value::CommentInfo
133// //////////////////////////////////////////////////////////////////
134// //////////////////////////////////////////////////////////////////
135// //////////////////////////////////////////////////////////////////
136
137
138Value::CommentInfo::CommentInfo()
139 : comment_( 0 )
140{
141}
142
143Value::CommentInfo::~CommentInfo()
144{
145 if ( comment_ )
146 valueAllocator()->releaseStringValue( comment_ );
147}
148
149
150void
151Value::CommentInfo::setComment( const char *text )
152{
153 if ( comment_ )
154 valueAllocator()->releaseStringValue( comment_ );
155 JSON_ASSERT( text );
156 JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
157 // It seems that /**/ style comments are acceptable as well.
158 comment_ = valueAllocator()->duplicateStringValue( text );
159}
160
161
162// //////////////////////////////////////////////////////////////////
163// //////////////////////////////////////////////////////////////////
164// //////////////////////////////////////////////////////////////////
165// class Value::CZString
166// //////////////////////////////////////////////////////////////////
167// //////////////////////////////////////////////////////////////////
168// //////////////////////////////////////////////////////////////////
169# ifndef JSON_VALUE_USE_INTERNAL_MAP
170
171// Notes: index_ indicates if the string was allocated when
172// a string is stored.
173
174Value::CZString::CZString( int index )
175 : cstr_( 0 )
176 , index_( index )
177{
178}
179
180Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
181 : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
182 : cstr )
183 , index_( allocate )
184{
185}
186
187Value::CZString::CZString( const CZString &other )
188: cstr_( other.index_ != noDuplication && other.cstr_ != 0
189 ? valueAllocator()->makeMemberName( other.cstr_ )
190 : other.cstr_ )
191 , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
192 : other.index_ )
193{
194}
195
196Value::CZString::~CZString()
197{
198 if ( cstr_ && index_ == duplicate )
199 valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
200}
201
202void
203Value::CZString::swap( CZString &other )
204{
205 std::swap( cstr_, other.cstr_ );
206 std::swap( index_, other.index_ );
207}
208
209Value::CZString &
210Value::CZString::operator =( const CZString &other )
211{
212 CZString temp( other );
213 swap( temp );
214 return *this;
215}
216
217bool
218Value::CZString::operator<( const CZString &other ) const
219{
220 if ( cstr_ )
221 return strcmp( cstr_, other.cstr_ ) < 0;
222 return index_ < other.index_;
223}
224
225bool
226Value::CZString::operator==( const CZString &other ) const
227{
228 if ( cstr_ )
229 return strcmp( cstr_, other.cstr_ ) == 0;
230 return index_ == other.index_;
231}
232
233
234int
235Value::CZString::index() const
236{
237 return index_;
238}
239
240
241const char *
242Value::CZString::c_str() const
243{
244 return cstr_;
245}
246
247bool
248Value::CZString::isStaticString() const
249{
250 return index_ == noDuplication;
251}
252
253#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
254
255
256// //////////////////////////////////////////////////////////////////
257// //////////////////////////////////////////////////////////////////
258// //////////////////////////////////////////////////////////////////
259// class Value::Value
260// //////////////////////////////////////////////////////////////////
261// //////////////////////////////////////////////////////////////////
262// //////////////////////////////////////////////////////////////////
263
268Value::Value( ValueType type )
269 : type_( type )
270 , allocated_( 0 )
271 , comments_( 0 )
272# ifdef JSON_VALUE_USE_INTERNAL_MAP
273 , itemIsUsed_( 0 )
274#endif
275{
276 switch ( type )
277 {
278 case nullValue:
279 break;
280 case intValue:
281 case uintValue:
282 value_.int_ = 0;
283 break;
284 case realValue:
285 value_.real_ = 0.0;
286 break;
287 case stringValue:
288 value_.string_ = 0;
289 break;
290#ifndef JSON_VALUE_USE_INTERNAL_MAP
291 case arrayValue:
292 case objectValue:
293 value_.map_ = new ObjectValues();
294 break;
295#else
296 case arrayValue:
297 value_.array_ = arrayAllocator()->newArray();
298 break;
299 case objectValue:
300 value_.map_ = mapAllocator()->newMap();
301 break;
302#endif
303 case booleanValue:
304 value_.bool_ = false;
305 break;
306 default:
308 }
309}
310
311
313 : type_( intValue )
314 , comments_( 0 )
315# ifdef JSON_VALUE_USE_INTERNAL_MAP
316 , itemIsUsed_( 0 )
317#endif
318{
319 value_.int_ = value;
320}
321
322
324 : type_( uintValue )
325 , comments_( 0 )
326# ifdef JSON_VALUE_USE_INTERNAL_MAP
327 , itemIsUsed_( 0 )
328#endif
329{
330 value_.uint_ = value;
331}
332
333Value::Value( double value )
334 : type_( realValue )
335 , comments_( 0 )
336# ifdef JSON_VALUE_USE_INTERNAL_MAP
337 , itemIsUsed_( 0 )
338#endif
339{
340 value_.real_ = value;
341}
342
343Value::Value( const char *value )
344 : type_( stringValue )
345 , allocated_( true )
346 , comments_( 0 )
347# ifdef JSON_VALUE_USE_INTERNAL_MAP
348 , itemIsUsed_( 0 )
349#endif
350{
351 value_.string_ = valueAllocator()->duplicateStringValue( value );
352}
353
354
355Value::Value( const char *beginValue,
356 const char *endValue )
357 : type_( stringValue )
358 , allocated_( true )
359 , comments_( 0 )
360# ifdef JSON_VALUE_USE_INTERNAL_MAP
361 , itemIsUsed_( 0 )
362#endif
363{
364 value_.string_ = valueAllocator()->duplicateStringValue( beginValue,
365 UInt(endValue - beginValue) );
366}
367
368
369Value::Value( const std::string &value )
370 : type_( stringValue )
371 , allocated_( true )
372 , comments_( 0 )
373# ifdef JSON_VALUE_USE_INTERNAL_MAP
374 , itemIsUsed_( 0 )
375#endif
376{
377 value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
378 (unsigned int)value.length() );
379
380}
381
383 : type_( stringValue )
384 , allocated_( false )
385 , comments_( 0 )
386# ifdef JSON_VALUE_USE_INTERNAL_MAP
387 , itemIsUsed_( 0 )
388#endif
389{
390 value_.string_ = const_cast<char *>( value.c_str() );
391}
392
393
394# ifdef JSON_USE_CPPTL
395Value::Value( const CppTL::ConstString &value )
396 : type_( stringValue )
397 , allocated_( true )
398 , comments_( 0 )
399# ifdef JSON_VALUE_USE_INTERNAL_MAP
400 , itemIsUsed_( 0 )
401#endif
402{
403 value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
404}
405# endif
406
407Value::Value( bool value )
408 : type_( booleanValue )
409 , comments_( 0 )
410# ifdef JSON_VALUE_USE_INTERNAL_MAP
411 , itemIsUsed_( 0 )
412#endif
413{
414 value_.bool_ = value;
415}
416
417
418Value::Value( const Value &other )
419 : type_( other.type_ )
420 , comments_( 0 )
421# ifdef JSON_VALUE_USE_INTERNAL_MAP
422 , itemIsUsed_( 0 )
423#endif
424{
425 switch ( type_ )
426 {
427 case nullValue:
428 case intValue:
429 case uintValue:
430 case realValue:
431 case booleanValue:
432 value_ = other.value_;
433 break;
434 case stringValue:
435 if ( other.value_.string_ )
436 {
437 value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
438 allocated_ = true;
439 }
440 else
441 value_.string_ = 0;
442 break;
443#ifndef JSON_VALUE_USE_INTERNAL_MAP
444 case arrayValue:
445 case objectValue:
446 value_.map_ = new ObjectValues( *other.value_.map_ );
447 break;
448#else
449 case arrayValue:
450 value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
451 break;
452 case objectValue:
453 value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
454 break;
455#endif
456 default:
458 }
459 if ( other.comments_ )
460 {
461 comments_ = new CommentInfo[numberOfCommentPlacement];
462 for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
463 {
464 const CommentInfo &otherComment = other.comments_[comment];
465 if ( otherComment.comment_ )
466 comments_[comment].setComment( otherComment.comment_ );
467 }
468 }
469}
470
471
473{
474 switch ( type_ )
475 {
476 case nullValue:
477 case intValue:
478 case uintValue:
479 case realValue:
480 case booleanValue:
481 break;
482 case stringValue:
483 if ( allocated_ )
484 valueAllocator()->releaseStringValue( value_.string_ );
485 break;
486#ifndef JSON_VALUE_USE_INTERNAL_MAP
487 case arrayValue:
488 case objectValue:
489 delete value_.map_;
490 break;
491#else
492 case arrayValue:
493 arrayAllocator()->destructArray( value_.array_ );
494 break;
495 case objectValue:
496 mapAllocator()->destructMap( value_.map_ );
497 break;
498#endif
499 default:
501 }
502
503 if ( comments_ )
504 delete[] comments_;
505}
506
507Value &
508Value::operator=( const Value &other )
509{
510 Value temp( other );
511 swap( temp );
512 return *this;
513}
514
515void
517{
518 ValueType temp = type_;
519 type_ = other.type_;
520 other.type_ = temp;
521 std::swap( value_, other.value_ );
522 int temp2 = allocated_;
523 allocated_ = other.allocated_;
524 other.allocated_ = temp2;
525}
526
529{
530 return type_;
531}
532
533
534int
535Value::compare( const Value &other )
536{
537 /*
538 int typeDelta = other.type_ - type_;
539 switch ( type_ )
540 {
541 case nullValue:
542
543 return other.type_ == type_;
544 case intValue:
545 if ( other.type_.isNumeric()
546 case uintValue:
547 case realValue:
548 case booleanValue:
549 break;
550 case stringValue,
551 break;
552 case arrayValue:
553 delete value_.array_;
554 break;
555 case objectValue:
556 delete value_.map_;
557 default:
558 JSON_ASSERT_UNREACHABLE;
559 }
560 */
561 return 0; // unreachable
562}
563
564bool
565Value::operator <( const Value &other ) const
566{
567 int typeDelta = type_ - other.type_;
568 if ( typeDelta )
569 return typeDelta < 0 ? true : false;
570 switch ( type_ )
571 {
572 case nullValue:
573 return false;
574 case intValue:
575 return value_.int_ < other.value_.int_;
576 case uintValue:
577 return value_.uint_ < other.value_.uint_;
578 case realValue:
579 return value_.real_ < other.value_.real_;
580 case booleanValue:
581 return value_.bool_ < other.value_.bool_;
582 case stringValue:
583 return ( value_.string_ == 0 && other.value_.string_ )
584 || ( other.value_.string_
585 && value_.string_
586 && strcmp( value_.string_, other.value_.string_ ) < 0 );
587#ifndef JSON_VALUE_USE_INTERNAL_MAP
588 case arrayValue:
589 case objectValue:
590 {
591 int delta = int( value_.map_->size() - other.value_.map_->size() );
592 if ( delta )
593 return delta < 0;
594 return (*value_.map_) < (*other.value_.map_);
595 }
596#else
597 case arrayValue:
598 return value_.array_->compare( *(other.value_.array_) ) < 0;
599 case objectValue:
600 return value_.map_->compare( *(other.value_.map_) ) < 0;
601#endif
602 default:
604 }
605 return 0; // unreachable
606}
607
608bool
609Value::operator <=( const Value &other ) const
610{
611 return !(other > *this);
612}
613
614bool
615Value::operator >=( const Value &other ) const
616{
617 return !(*this < other);
618}
619
620bool
621Value::operator >( const Value &other ) const
622{
623 return other < *this;
624}
625
626bool
627Value::operator ==( const Value &other ) const
628{
629 //if ( type_ != other.type_ )
630 // GCC 2.95.3 says:
631 // attempt to take address of bit-field structure member `Json::Value::type_'
632 // Beats me, but a temp solves the problem.
633 int temp = other.type_;
634 if ( type_ != temp )
635 return false;
636 switch ( type_ )
637 {
638 case nullValue:
639 return true;
640 case intValue:
641 return value_.int_ == other.value_.int_;
642 case uintValue:
643 return value_.uint_ == other.value_.uint_;
644 case realValue:
645 return value_.real_ == other.value_.real_;
646 case booleanValue:
647 return value_.bool_ == other.value_.bool_;
648 case stringValue:
649 return ( value_.string_ == other.value_.string_ )
650 || ( other.value_.string_
651 && value_.string_
652 && strcmp( value_.string_, other.value_.string_ ) == 0 );
653#ifndef JSON_VALUE_USE_INTERNAL_MAP
654 case arrayValue:
655 case objectValue:
656 return value_.map_->size() == other.value_.map_->size()
657 && (*value_.map_) == (*other.value_.map_);
658#else
659 case arrayValue:
660 return value_.array_->compare( *(other.value_.array_) ) == 0;
661 case objectValue:
662 return value_.map_->compare( *(other.value_.map_) ) == 0;
663#endif
664 default:
666 }
667 return 0; // unreachable
668}
669
670bool
671Value::operator !=( const Value &other ) const
672{
673 return !( *this == other );
674}
675
676const char *
678{
679 JSON_ASSERT( type_ == stringValue );
680 return value_.string_;
681}
682
683
684std::string
686{
687 switch ( type_ )
688 {
689 case nullValue:
690 return "";
691 case stringValue:
692 return value_.string_ ? value_.string_ : "";
693 case booleanValue:
694 return value_.bool_ ? "true" : "false";
695 case intValue:
696 case uintValue:
697 case realValue:
698 case arrayValue:
699 case objectValue:
700 JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
701 default:
703 }
704 return ""; // unreachable
705}
706
707# ifdef JSON_USE_CPPTL
708CppTL::ConstString
709Value::asConstString() const
710{
711 return CppTL::ConstString( asString().c_str() );
712}
713# endif
714
717{
718 switch ( type_ )
719 {
720 case nullValue:
721 return 0;
722 case intValue:
723 return value_.int_;
724 case uintValue:
725 JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
726 return value_.uint_;
727 case realValue:
728 JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
729 return Int( value_.real_ );
730 case booleanValue:
731 return value_.bool_ ? 1 : 0;
732 case stringValue:
733 case arrayValue:
734 case objectValue:
735 JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
736 default:
738 }
739 return 0; // unreachable;
740}
741
744{
745 switch ( type_ )
746 {
747 case nullValue:
748 return 0;
749 case intValue:
750 JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
751 return value_.int_;
752 case uintValue:
753 return value_.uint_;
754 case realValue:
755 JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" );
756 return UInt( value_.real_ );
757 case booleanValue:
758 return value_.bool_ ? 1 : 0;
759 case stringValue:
760 case arrayValue:
761 case objectValue:
762 JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
763 default:
765 }
766 return 0; // unreachable;
767}
768
769double
771{
772 switch ( type_ )
773 {
774 case nullValue:
775 return 0.0;
776 case intValue:
777 return value_.int_;
778 case uintValue:
779 return value_.uint_;
780 case realValue:
781 return value_.real_;
782 case booleanValue:
783 return value_.bool_ ? 1.0 : 0.0;
784 case stringValue:
785 case arrayValue:
786 case objectValue:
787 JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
788 default:
790 }
791 return 0; // unreachable;
792}
793
794bool
796{
797 switch ( type_ )
798 {
799 case nullValue:
800 return false;
801 case intValue:
802 case uintValue:
803 return value_.int_ != 0;
804 case realValue:
805 return value_.real_ != 0.0;
806 case booleanValue:
807 return value_.bool_;
808 case stringValue:
809 return value_.string_ && value_.string_[0] != 0;
810 case arrayValue:
811 case objectValue:
812 return value_.map_->size() != 0;
813 default:
815 }
816 return false; // unreachable;
817}
818
819
820bool
822{
823 switch ( type_ )
824 {
825 case nullValue:
826 return true;
827 case intValue:
828 return ( other == nullValue && value_.int_ == 0 )
829 || other == intValue
830 || ( other == uintValue && value_.int_ >= 0 )
831 || other == realValue
832 || other == stringValue
833 || other == booleanValue;
834 case uintValue:
835 return ( other == nullValue && value_.uint_ == 0 )
836 || ( other == intValue && value_.uint_ <= (unsigned)maxInt )
837 || other == uintValue
838 || other == realValue
839 || other == stringValue
840 || other == booleanValue;
841 case realValue:
842 return ( other == nullValue && value_.real_ == 0.0 )
843 || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt )
844 || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt )
845 || other == realValue
846 || other == stringValue
847 || other == booleanValue;
848 case booleanValue:
849 return ( other == nullValue && value_.bool_ == false )
850 || other == intValue
851 || other == uintValue
852 || other == realValue
853 || other == stringValue
854 || other == booleanValue;
855 case stringValue:
856 return other == stringValue
857 || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) );
858 case arrayValue:
859 return other == arrayValue
860 || ( other == nullValue && value_.map_->size() == 0 );
861 case objectValue:
862 return other == objectValue
863 || ( other == nullValue && value_.map_->size() == 0 );
864 default:
866 }
867 return false; // unreachable;
868}
869
870
874{
875 switch ( type_ )
876 {
877 case nullValue:
878 case intValue:
879 case uintValue:
880 case realValue:
881 case booleanValue:
882 case stringValue:
883 return 0;
884#ifndef JSON_VALUE_USE_INTERNAL_MAP
885 case arrayValue: // size of the array is highest index + 1
886 if ( !value_.map_->empty() )
887 {
888 ObjectValues::const_iterator itLast = value_.map_->end();
889 --itLast;
890 return (*itLast).first.index()+1;
891 }
892 return 0;
893 case objectValue:
894 return Int( value_.map_->size() );
895#else
896 case arrayValue:
897 return Int( value_.array_->size() );
898 case objectValue:
899 return Int( value_.map_->size() );
900#endif
901 default:
903 }
904 return 0; // unreachable;
905}
906
907
908bool
910{
911 if ( isNull() || isArray() || isObject() )
912 return size() == 0u;
913 else
914 return false;
915}
916
917
918bool
920{
921 return isNull();
922}
923
924
925void
927{
928 JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
929
930 switch ( type_ )
931 {
932#ifndef JSON_VALUE_USE_INTERNAL_MAP
933 case arrayValue:
934 case objectValue:
935 value_.map_->clear();
936 break;
937#else
938 case arrayValue:
939 value_.array_->clear();
940 break;
941 case objectValue:
942 value_.map_->clear();
943 break;
944#endif
945 default:
946 break;
947 }
948}
949
950void
952{
953 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
954 if ( type_ == nullValue )
955 *this = Value( arrayValue );
956#ifndef JSON_VALUE_USE_INTERNAL_MAP
957 UInt oldSize = size();
958 if ( newSize == 0 )
959 clear();
960 else if ( newSize > oldSize )
961 (*this)[ newSize - 1 ];
962 else
963 {
964 for ( UInt index = newSize; index < oldSize; ++index )
965 value_.map_->erase( index );
966 assert( size() == newSize );
967 }
968#else
969 value_.array_->resize( newSize );
970#endif
971}
972
973
974Value &
976{
977 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
978 if ( type_ == nullValue )
979 *this = Value( arrayValue );
980#ifndef JSON_VALUE_USE_INTERNAL_MAP
981 CZString key( index );
982 ObjectValues::iterator it = value_.map_->lower_bound( key );
983 if ( it != value_.map_->end() && (*it).first == key )
984 return (*it).second;
985
986 ObjectValues::value_type defaultValue( key, null );
987 it = value_.map_->insert( it, defaultValue );
988 return (*it).second;
989#else
990 return value_.array_->resolveReference( index );
991#endif
992}
993
994
995const Value &
997{
998 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
999 if ( type_ == nullValue )
1000 return null;
1001#ifndef JSON_VALUE_USE_INTERNAL_MAP
1002 CZString key( index );
1003 ObjectValues::const_iterator it = value_.map_->find( key );
1004 if ( it == value_.map_->end() )
1005 return null;
1006 return (*it).second;
1007#else
1008 Value *value = value_.array_->find( index );
1009 return value ? *value : null;
1010#endif
1011}
1012
1013
1014Value &
1015Value::operator[]( const char *key )
1016{
1017 return resolveReference( key, false );
1018}
1019
1020
1021Value &
1022Value::resolveReference( const char *key,
1023 bool isStatic )
1024{
1025 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1026 if ( type_ == nullValue )
1027 *this = Value( objectValue );
1028#ifndef JSON_VALUE_USE_INTERNAL_MAP
1029 CZString actualKey( key, isStatic ? CZString::noDuplication
1030 : CZString::duplicateOnCopy );
1031 ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
1032 if ( it != value_.map_->end() && (*it).first == actualKey )
1033 return (*it).second;
1034
1035 ObjectValues::value_type defaultValue( actualKey, null );
1036 it = value_.map_->insert( it, defaultValue );
1037 Value &value = (*it).second;
1038 return value;
1039#else
1040 return value_.map_->resolveReference( key, isStatic );
1041#endif
1042}
1043
1044
1045Value
1047 const Value &defaultValue ) const
1048{
1049 const Value *value = &((*this)[index]);
1050 return value == &null ? defaultValue : *value;
1051}
1052
1053
1054bool
1056{
1057 return index < size();
1058}
1059
1060
1061
1062const Value &
1063Value::operator[]( const char *key ) const
1064{
1065 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1066 if ( type_ == nullValue )
1067 return null;
1068#ifndef JSON_VALUE_USE_INTERNAL_MAP
1069 CZString actualKey( key, CZString::noDuplication );
1070 ObjectValues::const_iterator it = value_.map_->find( actualKey );
1071 if ( it == value_.map_->end() )
1072 return null;
1073 return (*it).second;
1074#else
1075 const Value *value = value_.map_->find( key );
1076 return value ? *value : null;
1077#endif
1078}
1079
1080
1081Value &
1082Value::operator[]( const std::string &key )
1083{
1084 return (*this)[ key.c_str() ];
1085}
1086
1087
1088const Value &
1089Value::operator[]( const std::string &key ) const
1090{
1091 return (*this)[ key.c_str() ];
1092}
1093
1094Value &
1096{
1097 return resolveReference( key, true );
1098}
1099
1100
1101# ifdef JSON_USE_CPPTL
1102Value &
1103Value::operator[]( const CppTL::ConstString &key )
1104{
1105 return (*this)[ key.c_str() ];
1106}
1107
1108
1109const Value &
1110Value::operator[]( const CppTL::ConstString &key ) const
1111{
1112 return (*this)[ key.c_str() ];
1113}
1114# endif
1115
1116
1117Value &
1118Value::append( const Value &value )
1119{
1120 return (*this)[size()] = value;
1121}
1122
1123
1124Value
1125Value::get( const char *key,
1126 const Value &defaultValue ) const
1127{
1128 const Value *value = &((*this)[key]);
1129 return value == &null ? defaultValue : *value;
1130}
1131
1132
1133Value
1134Value::get( const std::string &key,
1135 const Value &defaultValue ) const
1136{
1137 return get( key.c_str(), defaultValue );
1138}
1139
1140Value
1141Value::removeMember( const char* key )
1142{
1143 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1144 if ( type_ == nullValue )
1145 return null;
1146#ifndef JSON_VALUE_USE_INTERNAL_MAP
1147 CZString actualKey( key, CZString::noDuplication );
1148 ObjectValues::iterator it = value_.map_->find( actualKey );
1149 if ( it == value_.map_->end() )
1150 return null;
1151 Value old(it->second);
1152 value_.map_->erase(it);
1153 return old;
1154#else
1155 Value *value = value_.map_->find( key );
1156 if (value){
1157 Value old(*value);
1158 value_.map_.remove( key );
1159 return old;
1160 } else {
1161 return null;
1162 }
1163#endif
1164}
1165
1166Value
1167Value::removeMember( const std::string &key )
1168{
1169 return removeMember( key.c_str() );
1170}
1171
1172# ifdef JSON_USE_CPPTL
1173Value
1174Value::get( const CppTL::ConstString &key,
1175 const Value &defaultValue ) const
1176{
1177 return get( key.c_str(), defaultValue );
1178}
1179# endif
1180
1181bool
1182Value::isMember( const char *key ) const
1183{
1184 const Value *value = &((*this)[key]);
1185 return value != &null;
1186}
1187
1188
1189bool
1190Value::isMember( const std::string &key ) const
1191{
1192 return isMember( key.c_str() );
1193}
1194
1195
1196# ifdef JSON_USE_CPPTL
1197bool
1198Value::isMember( const CppTL::ConstString &key ) const
1199{
1200 return isMember( key.c_str() );
1201}
1202#endif
1203
1206{
1207 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1208 if ( type_ == nullValue )
1209 return Value::Members();
1210 Members members;
1211 members.reserve( value_.map_->size() );
1212#ifndef JSON_VALUE_USE_INTERNAL_MAP
1213 ObjectValues::const_iterator it = value_.map_->begin();
1214 ObjectValues::const_iterator itEnd = value_.map_->end();
1215 for ( ; it != itEnd; ++it )
1216 members.push_back( std::string( (*it).first.c_str() ) );
1217#else
1218 ValueInternalMap::IteratorState it;
1219 ValueInternalMap::IteratorState itEnd;
1220 value_.map_->makeBeginIterator( it );
1221 value_.map_->makeEndIterator( itEnd );
1222 for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
1223 members.push_back( std::string( ValueInternalMap::key( it ) ) );
1224#endif
1225 return members;
1226}
1227//
1228//# ifdef JSON_USE_CPPTL
1229//EnumMemberNames
1230//Value::enumMemberNames() const
1231//{
1232// if ( type_ == objectValue )
1233// {
1234// return CppTL::Enum::any( CppTL::Enum::transform(
1235// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
1236// MemberNamesTransform() ) );
1237// }
1238// return EnumMemberNames();
1239//}
1240//
1241//
1242//EnumValues
1243//Value::enumValues() const
1244//{
1245// if ( type_ == objectValue || type_ == arrayValue )
1246// return CppTL::Enum::anyValues( *(value_.map_),
1247// CppTL::Type<const Value &>() );
1248// return EnumValues();
1249//}
1250//
1251//# endif
1252
1253
1254bool
1256{
1257 return type_ == nullValue;
1258}
1259
1260
1261bool
1263{
1264 return type_ == booleanValue;
1265}
1266
1267
1268bool
1270{
1271 return type_ == intValue;
1272}
1273
1274
1275bool
1277{
1278 return type_ == uintValue;
1279}
1280
1281
1282bool
1284{
1285 return type_ == intValue
1286 || type_ == uintValue
1287 || type_ == booleanValue;
1288}
1289
1290
1291bool
1293{
1294 return type_ == realValue;
1295}
1296
1297
1298bool
1300{
1301 return isIntegral() || isDouble();
1302}
1303
1304
1305bool
1307{
1308 return type_ == stringValue;
1309}
1310
1311
1312bool
1314{
1315 return type_ == nullValue || type_ == arrayValue;
1316}
1317
1318
1319bool
1321{
1322 return type_ == nullValue || type_ == objectValue;
1323}
1324
1325
1326void
1327Value::setComment( const char *comment,
1328 CommentPlacement placement )
1329{
1330 if ( !comments_ )
1331 comments_ = new CommentInfo[numberOfCommentPlacement];
1332 comments_[placement].setComment( comment );
1333}
1334
1335
1336void
1337Value::setComment( const std::string &comment,
1338 CommentPlacement placement )
1339{
1340 setComment( comment.c_str(), placement );
1341}
1342
1343
1344bool
1346{
1347 return comments_ != 0 && comments_[placement].comment_ != 0;
1348}
1349
1350std::string
1352{
1353 if ( hasComment(placement) )
1354 return comments_[placement].comment_;
1355 return "";
1356}
1357
1358
1359std::string
1361{
1362 StyledWriter writer;
1363 return writer.write( *this );
1364}
1365
1366
1369{
1370 switch ( type_ )
1371 {
1372#ifdef JSON_VALUE_USE_INTERNAL_MAP
1373 case arrayValue:
1374 if ( value_.array_ )
1375 {
1376 ValueInternalArray::IteratorState it;
1377 value_.array_->makeBeginIterator( it );
1378 return const_iterator( it );
1379 }
1380 break;
1381 case objectValue:
1382 if ( value_.map_ )
1383 {
1384 ValueInternalMap::IteratorState it;
1385 value_.map_->makeBeginIterator( it );
1386 return const_iterator( it );
1387 }
1388 break;
1389#else
1390 case arrayValue:
1391 case objectValue:
1392 if ( value_.map_ )
1393 return const_iterator( value_.map_->begin() );
1394 break;
1395#endif
1396 default:
1397 break;
1398 }
1399 return const_iterator();
1400}
1401
1404{
1405 switch ( type_ )
1406 {
1407#ifdef JSON_VALUE_USE_INTERNAL_MAP
1408 case arrayValue:
1409 if ( value_.array_ )
1410 {
1411 ValueInternalArray::IteratorState it;
1412 value_.array_->makeEndIterator( it );
1413 return const_iterator( it );
1414 }
1415 break;
1416 case objectValue:
1417 if ( value_.map_ )
1418 {
1419 ValueInternalMap::IteratorState it;
1420 value_.map_->makeEndIterator( it );
1421 return const_iterator( it );
1422 }
1423 break;
1424#else
1425 case arrayValue:
1426 case objectValue:
1427 if ( value_.map_ )
1428 return const_iterator( value_.map_->end() );
1429 break;
1430#endif
1431 default:
1432 break;
1433 }
1434 return const_iterator();
1435}
1436
1437
1440{
1441 switch ( type_ )
1442 {
1443#ifdef JSON_VALUE_USE_INTERNAL_MAP
1444 case arrayValue:
1445 if ( value_.array_ )
1446 {
1447 ValueInternalArray::IteratorState it;
1448 value_.array_->makeBeginIterator( it );
1449 return iterator( it );
1450 }
1451 break;
1452 case objectValue:
1453 if ( value_.map_ )
1454 {
1455 ValueInternalMap::IteratorState it;
1456 value_.map_->makeBeginIterator( it );
1457 return iterator( it );
1458 }
1459 break;
1460#else
1461 case arrayValue:
1462 case objectValue:
1463 if ( value_.map_ )
1464 return iterator( value_.map_->begin() );
1465 break;
1466#endif
1467 default:
1468 break;
1469 }
1470 return iterator();
1471}
1472
1475{
1476 switch ( type_ )
1477 {
1478#ifdef JSON_VALUE_USE_INTERNAL_MAP
1479 case arrayValue:
1480 if ( value_.array_ )
1481 {
1482 ValueInternalArray::IteratorState it;
1483 value_.array_->makeEndIterator( it );
1484 return iterator( it );
1485 }
1486 break;
1487 case objectValue:
1488 if ( value_.map_ )
1489 {
1490 ValueInternalMap::IteratorState it;
1491 value_.map_->makeEndIterator( it );
1492 return iterator( it );
1493 }
1494 break;
1495#else
1496 case arrayValue:
1497 case objectValue:
1498 if ( value_.map_ )
1499 return iterator( value_.map_->end() );
1500 break;
1501#endif
1502 default:
1503 break;
1504 }
1505 return iterator();
1506}
1507
1508
1509// class PathArgument
1510// //////////////////////////////////////////////////////////////////
1511
1513 : kind_( kindNone )
1514{
1515}
1516
1517
1519 : index_( index )
1520 , kind_( kindIndex )
1521{
1522}
1523
1524
1526 : key_( key )
1527 , kind_( kindKey )
1528{
1529}
1530
1531
1532PathArgument::PathArgument( const std::string &key )
1533 : key_( key.c_str() )
1534 , kind_( kindKey )
1535{
1536}
1537
1538// class Path
1539// //////////////////////////////////////////////////////////////////
1540
1541Path::Path( const std::string &path,
1542 const PathArgument &a1,
1543 const PathArgument &a2,
1544 const PathArgument &a3,
1545 const PathArgument &a4,
1546 const PathArgument &a5 )
1547{
1548 InArgs in;
1549 in.push_back( &a1 );
1550 in.push_back( &a2 );
1551 in.push_back( &a3 );
1552 in.push_back( &a4 );
1553 in.push_back( &a5 );
1554 makePath( path, in );
1555}
1556
1557
1558void
1559Path::makePath( const std::string &path,
1560 const InArgs &in )
1561{
1562 const char *current = path.c_str();
1563 const char *end = current + path.length();
1564 InArgs::const_iterator itInArg = in.begin();
1565 while ( current != end )
1566 {
1567 if ( *current == '[' )
1568 {
1569 ++current;
1570 if ( *current == '%' )
1571 addPathInArg( path, in, itInArg, PathArgument::kindIndex );
1572 else
1573 {
1574 Value::UInt index = 0;
1575 for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
1576 index = index * 10 + Value::UInt(*current - '0');
1577 args_.push_back( index );
1578 }
1579 if ( current == end || *current++ != ']' )
1580 invalidPath( path, int(current - path.c_str()) );
1581 }
1582 else if ( *current == '%' )
1583 {
1584 addPathInArg( path, in, itInArg, PathArgument::kindKey );
1585 ++current;
1586 }
1587 else if ( *current == '.' )
1588 {
1589 ++current;
1590 }
1591 else
1592 {
1593 const char *beginName = current;
1594 while ( current != end && !strchr( "[.", *current ) )
1595 ++current;
1596 args_.push_back( std::string( beginName, current ) );
1597 }
1598 }
1599}
1600
1601
1602void
1603Path::addPathInArg( const std::string &path,
1604 const InArgs &in,
1605 InArgs::const_iterator &itInArg,
1606 PathArgument::Kind kind )
1607{
1608 if ( itInArg == in.end() )
1609 {
1610 // Error: missing argument %d
1611 }
1612 else if ( (*itInArg)->kind_ != kind )
1613 {
1614 // Error: bad argument type
1615 }
1616 else
1617 {
1618 args_.push_back( **itInArg );
1619 }
1620}
1621
1622
1623void
1624Path::invalidPath( const std::string &path,
1625 int location )
1626{
1627 // Error: invalid path.
1628}
1629
1630
1631const Value &
1632Path::resolve( const Value &root ) const
1633{
1634 const Value *node = &root;
1635 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1636 {
1637 const PathArgument &arg = *it;
1638 if ( arg.kind_ == PathArgument::kindIndex )
1639 {
1640 if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
1641 {
1642 // Error: unable to resolve path (array value expected at position...
1643 }
1644 node = &((*node)[arg.index_]);
1645 }
1646 else if ( arg.kind_ == PathArgument::kindKey )
1647 {
1648 if ( !node->isObject() )
1649 {
1650 // Error: unable to resolve path (object value expected at position...)
1651 }
1652 node = &((*node)[arg.key_]);
1653 if ( node == &Value::null )
1654 {
1655 // Error: unable to resolve path (object has no member named '' at position...)
1656 }
1657 }
1658 }
1659 return *node;
1660}
1661
1662
1663Value
1664Path::resolve( const Value &root,
1665 const Value &defaultValue ) const
1666{
1667 const Value *node = &root;
1668 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1669 {
1670 const PathArgument &arg = *it;
1671 if ( arg.kind_ == PathArgument::kindIndex )
1672 {
1673 if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
1674 return defaultValue;
1675 node = &((*node)[arg.index_]);
1676 }
1677 else if ( arg.kind_ == PathArgument::kindKey )
1678 {
1679 if ( !node->isObject() )
1680 return defaultValue;
1681 node = &((*node)[arg.key_]);
1682 if ( node == &Value::null )
1683 return defaultValue;
1684 }
1685 }
1686 return *node;
1687}
1688
1689
1690Value &
1691Path::make( Value &root ) const
1692{
1693 Value *node = &root;
1694 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1695 {
1696 const PathArgument &arg = *it;
1697 if ( arg.kind_ == PathArgument::kindIndex )
1698 {
1699 if ( !node->isArray() )
1700 {
1701 // Error: node is not an array at position ...
1702 }
1703 node = &((*node)[arg.index_]);
1704 }
1705 else if ( arg.kind_ == PathArgument::kindKey )
1706 {
1707 if ( !node->isObject() )
1708 {
1709 // Error: node is not an object at position...
1710 }
1711 node = &((*node)[arg.key_]);
1712 }
1713 }
1714 return *node;
1715}
1716
1717
1718} // namespace Json
Experimental and untested: represents an element of the "path" to access a node.
Definition: value.h:452
Value & make(Value &root) const
Creates the "path" to access the specified node and returns a reference on the node.
Path(const std::string &path, const PathArgument &a1=PathArgument(), const PathArgument &a2=PathArgument(), const PathArgument &a3=PathArgument(), const PathArgument &a4=PathArgument(), const PathArgument &a5=PathArgument())
const Value & resolve(const Value &root) const
Lightweight wrapper to tag static string.
Definition: value.h:63
const char * c_str() const
Definition: value.h:75
Writes a Value in JSON format in a human friendly way.
Definition: writer.h:66
virtual std::string write(const Value &root)
Serialize a Value in JSON format.
Experimental do not use: Allocator to customize member name and string value memory management done b...
Definition: value.h:524
virtual ~ValueAllocator()
Definition: json_value.cpp:55
virtual void releaseStringValue(char *value)=0
virtual void releaseMemberName(char *memberName)=0
virtual char * duplicateStringValue(const char *value, unsigned int length=unknown)=0
const iterator for object and array value.
Definition: value.h:950
Represents a JSON value.
Definition: value.h:112
const_iterator begin() const
bool empty() const
Return true if empty array, empty object, or null; otherwise, false.
Definition: json_value.cpp:909
Json::UInt UInt
Definition: value.h:122
bool isArray() const
const char * asCString() const
Definition: json_value.cpp:677
Value get(UInt index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
bool operator==(const Value &other) const
Definition: json_value.cpp:627
UInt size() const
Number of values in array or object.
Definition: json_value.cpp:873
void setComment(const char *comment, CommentPlacement placement)
Comments must be //... or /* ... *‍/.
ValueIterator iterator
Definition: value.h:120
std::string toStyledString() const
const_iterator end() const
bool operator<=(const Value &other) const
Definition: json_value.cpp:609
bool operator>(const Value &other) const
Definition: json_value.cpp:621
bool isDouble() const
int compare(const Value &other)
Definition: json_value.cpp:535
void clear()
Remove all object members and array elements.
Definition: json_value.cpp:926
static const Value null
Definition: value.h:126
Int asInt() const
Definition: json_value.cpp:716
bool hasComment(CommentPlacement placement) const
bool isString() const
bool operator!() const
Return isNull()
Definition: json_value.cpp:919
UInt asUInt() const
Definition: json_value.cpp:743
Members getMemberNames() const
Return a list of the member names.
static const Int minInt
Definition: value.h:127
Value & append(const Value &value)
Append value to array at the end.
bool operator!=(const Value &other) const
Definition: json_value.cpp:671
ValueType type() const
Definition: json_value.cpp:528
bool isObject() const
std::string getComment(CommentPlacement placement) const
Include delimiters and embedded newlines.
static const Int maxInt
Definition: value.h:128
void resize(UInt size)
Resize the array to size elements.
Definition: json_value.cpp:951
Value removeMember(const char *key)
Remove and return the named member.
void swap(Value &other)
Swap values.
Definition: json_value.cpp:516
bool operator<(const Value &other) const
Definition: json_value.cpp:565
bool isValidIndex(UInt index) const
Return true if index < size().
std::string asString() const
Definition: json_value.cpp:685
bool isBool() const
bool isIntegral() const
bool asBool() const
Definition: json_value.cpp:795
bool isUInt() const
bool isNull() const
Json::Int Int
Definition: value.h:123
std::vector< std::string > Members
Definition: value.h:119
static const UInt maxUInt
Definition: value.h:129
bool isMember(const char *key) const
Return true if the object has a member named key.
Value(ValueType type=nullValue)
Create a default Value of the given type.
Definition: json_value.cpp:268
Value & operator=(const Value &other)
Definition: json_value.cpp:508
bool isConvertibleTo(ValueType other) const
Definition: json_value.cpp:821
ValueConstIterator const_iterator
Definition: value.h:121
bool isNumeric() const
double asDouble() const
Definition: json_value.cpp:770
Value & operator[](UInt index)
Access an array element (zero based index ).
Definition: json_value.cpp:975
bool operator>=(const Value &other) const
Definition: json_value.cpp:615
bool isInt() const
Iterator for object and array value.
Definition: value.h:1008
static ValueArrayAllocator *& arrayAllocator()
static ValueMapAllocator *& mapAllocator()
#define JSON_ASSERT(condition)
Definition: json_value.cpp:17
#define JSON_ASSERT_UNREACHABLE
Definition: json_value.cpp:16
#define JSON_ASSERT_MESSAGE(condition, message)
Definition: json_value.cpp:18
JSON (JavaScript Object Notation).
Definition: features.h:6
int Int
Definition: forwards.h:19
CommentPlacement
Definition: value.h:36
@ numberOfCommentPlacement
Definition: value.h:40
static struct Json::DummyValueAllocatorInitializer dummyValueAllocatorInitializer
static bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4)
Definition: json_reader.cpp:47
ValueType
Type of the value held by a Value object.
Definition: value.h:24
@ booleanValue
bool value
Definition: value.h:30
@ nullValue
'null' value
Definition: value.h:25
@ stringValue
UTF-8 string value.
Definition: value.h:29
@ realValue
double value
Definition: value.h:28
@ arrayValue
array value (ordered list)
Definition: value.h:31
@ intValue
signed integer value
Definition: value.h:26
@ objectValue
object value (collection of name/value pairs).
Definition: value.h:32
@ uintValue
unsigned integer value
Definition: value.h:27
unsigned int UInt
Definition: forwards.h:20
static ValueAllocator *& valueAllocator()
Definition: json_value.cpp:98

SourceForge Logo hosts this site. Send comments to:
Json-cpp Developers