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 
20 namespace Json {
21 
22 const Value Value::null;
23 const Int Value::minInt = Int( ~(UInt(-1)/2) );
24 const Int Value::maxInt = Int( UInt(-1)/2 );
25 const 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 
59 class DefaultValueAllocator : public ValueAllocator
60 {
61 public:
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 
105 static 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"
128 
129 // //////////////////////////////////////////////////////////////////
130 // //////////////////////////////////////////////////////////////////
131 // //////////////////////////////////////////////////////////////////
132 // class Value::CommentInfo
133 // //////////////////////////////////////////////////////////////////
134 // //////////////////////////////////////////////////////////////////
135 // //////////////////////////////////////////////////////////////////
136 
138 Value::CommentInfo::CommentInfo()
139  : comment_( 0 )
140 {
141 }
142 
143 Value::CommentInfo::~CommentInfo()
144 {
145  if ( comment_ )
146  valueAllocator()->releaseStringValue( comment_ );
147 }
148 
149 
150 void
151 Value::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 
174 Value::CZString::CZString( int index )
175  : cstr_( 0 )
176  , index_( index )
177 {
178 }
179 
180 Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
181  : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
182  : cstr )
183  , index_( allocate )
184 {
185 }
186 
187 Value::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 
196 Value::CZString::~CZString()
197 {
198  if ( cstr_ && index_ == duplicate )
199  valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
200 }
201 
202 void
203 Value::CZString::swap( CZString &other )
204 {
205  std::swap( cstr_, other.cstr_ );
206  std::swap( index_, other.index_ );
207 }
208 
209 Value::CZString &
210 Value::CZString::operator =( const CZString &other )
211 {
212  CZString temp( other );
213  swap( temp );
214  return *this;
215 }
216 
217 bool
218 Value::CZString::operator<( const CZString &other ) const
219 {
220  if ( cstr_ )
221  return strcmp( cstr_, other.cstr_ ) < 0;
222  return index_ < other.index_;
223 }
224 
225 bool
226 Value::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 
234 int
235 Value::CZString::index() const
236 {
237  return index_;
238 }
239 
240 
241 const char *
242 Value::CZString::c_str() const
243 {
244  return cstr_;
245 }
246 
247 bool
248 Value::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 
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 
333 Value::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 
343 Value::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 
355 Value::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 
369 Value::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 
382 Value::Value( const StaticString &value )
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
395 Value::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 
407 Value::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 
418 Value::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 
507 Value &
508 Value::operator=( const Value &other )
509 {
510  Value temp( other );
511  swap( temp );
512  return *this;
513 }
514 
515 void
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 
527 ValueType
528 Value::type() const
529 {
530  return type_;
531 }
532 
533 
534 int
535 Value::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 
564 bool
565 Value::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 
608 bool
609 Value::operator <=( const Value &other ) const
610 {
611  return !(other > *this);
612 }
613 
614 bool
615 Value::operator >=( const Value &other ) const
616 {
617  return !(*this < other);
618 }
619 
620 bool
621 Value::operator >( const Value &other ) const
622 {
623  return other < *this;
624 }
625 
626 bool
627 Value::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 
670 bool
671 Value::operator !=( const Value &other ) const
672 {
673  return !( *this == other );
674 }
675 
676 const char *
678 {
679  JSON_ASSERT( type_ == stringValue );
680  return value_.string_;
681 }
682 
683 
684 std::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
708 CppTL::ConstString
709 Value::asConstString() const
710 {
711  return CppTL::ConstString( asString().c_str() );
712 }
713 # endif
714 
715 Value::Int
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 
769 double
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 
794 bool
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 
820 bool
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 
873 Value::size() const
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 
908 bool
910 {
911  if ( isNull() || isArray() || isObject() )
912  return size() == 0u;
913  else
914  return false;
915 }
916 
917 
918 bool
920 {
921  return isNull();
922 }
923 
924 
925 void
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 
950 void
951 Value::resize( UInt newSize )
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 
974 Value &
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 
995 const Value &
996 Value::operator[]( UInt index ) const
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 
1014 Value &
1015 Value::operator[]( const char *key )
1016 {
1017  return resolveReference( key, false );
1018 }
1019 
1020 
1021 Value &
1022 Value::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 
1045 Value
1047  const Value &defaultValue ) const
1048 {
1049  const Value *value = &((*this)[index]);
1050  return value == &null ? defaultValue : *value;
1051 }
1052 
1053 
1054 bool
1056 {
1057  return index < size();
1058 }
1059 
1060 
1061 
1062 const Value &
1063 Value::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 
1081 Value &
1082 Value::operator[]( const std::string &key )
1083 {
1084  return (*this)[ key.c_str() ];
1085 }
1086 
1087 
1088 const Value &
1089 Value::operator[]( const std::string &key ) const
1090 {
1091  return (*this)[ key.c_str() ];
1092 }
1093 
1094 Value &
1096 {
1097  return resolveReference( key, true );
1098 }
1099 
1100 
1101 # ifdef JSON_USE_CPPTL
1102 Value &
1103 Value::operator[]( const CppTL::ConstString &key )
1104 {
1105  return (*this)[ key.c_str() ];
1106 }
1107 
1108 
1109 const Value &
1110 Value::operator[]( const CppTL::ConstString &key ) const
1111 {
1112  return (*this)[ key.c_str() ];
1113 }
1114 # endif
1115 
1116 
1117 Value &
1118 Value::append( const Value &value )
1119 {
1120  return (*this)[size()] = value;
1121 }
1122 
1123 
1124 Value
1125 Value::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 
1133 Value
1134 Value::get( const std::string &key,
1135  const Value &defaultValue ) const
1136 {
1137  return get( key.c_str(), defaultValue );
1138 }
1139 
1140 Value
1141 Value::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 
1166 Value
1167 Value::removeMember( const std::string &key )
1168 {
1169  return removeMember( key.c_str() );
1170 }
1171 
1172 # ifdef JSON_USE_CPPTL
1173 Value
1174 Value::get( const CppTL::ConstString &key,
1175  const Value &defaultValue ) const
1176 {
1177  return get( key.c_str(), defaultValue );
1178 }
1179 # endif
1180 
1181 bool
1182 Value::isMember( const char *key ) const
1183 {
1184  const Value *value = &((*this)[key]);
1185  return value != &null;
1186 }
1187 
1188 
1189 bool
1190 Value::isMember( const std::string &key ) const
1191 {
1192  return isMember( key.c_str() );
1193 }
1194 
1195 
1196 # ifdef JSON_USE_CPPTL
1197 bool
1198 Value::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 
1254 bool
1256 {
1257  return type_ == nullValue;
1258 }
1259 
1260 
1261 bool
1263 {
1264  return type_ == booleanValue;
1265 }
1266 
1267 
1268 bool
1270 {
1271  return type_ == intValue;
1272 }
1273 
1274 
1275 bool
1277 {
1278  return type_ == uintValue;
1279 }
1280 
1281 
1282 bool
1284 {
1285  return type_ == intValue
1286  || type_ == uintValue
1287  || type_ == booleanValue;
1288 }
1289 
1290 
1291 bool
1293 {
1294  return type_ == realValue;
1295 }
1296 
1297 
1298 bool
1300 {
1301  return isIntegral() || isDouble();
1302 }
1303 
1304 
1305 bool
1307 {
1308  return type_ == stringValue;
1309 }
1310 
1311 
1312 bool
1314 {
1315  return type_ == nullValue || type_ == arrayValue;
1316 }
1317 
1318 
1319 bool
1321 {
1322  return type_ == nullValue || type_ == objectValue;
1323 }
1324 
1325 
1326 void
1327 Value::setComment( const char *comment,
1328  CommentPlacement placement )
1329 {
1330  if ( !comments_ )
1331  comments_ = new CommentInfo[numberOfCommentPlacement];
1332  comments_[placement].setComment( comment );
1333 }
1334 
1335 
1336 void
1337 Value::setComment( const std::string &comment,
1338  CommentPlacement placement )
1339 {
1340  setComment( comment.c_str(), placement );
1341 }
1342 
1343 
1344 bool
1346 {
1347  return comments_ != 0 && comments_[placement].comment_ != 0;
1348 }
1349 
1350 std::string
1352 {
1353  if ( hasComment(placement) )
1354  return comments_[placement].comment_;
1355  return "";
1356 }
1357 
1358 
1359 std::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 
1403 Value::end() const
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 
1525 PathArgument::PathArgument( const char *key )
1526  : key_( key )
1527  , kind_( kindKey )
1528 {
1529 }
1530 
1531 
1532 PathArgument::PathArgument( const std::string &key )
1533  : key_( key.c_str() )
1534  , kind_( kindKey )
1535 {
1536 }
1537 
1538 // class Path
1539 // //////////////////////////////////////////////////////////////////
1540 
1541 Path::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 
1558 void
1559 Path::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 
1602 void
1603 Path::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 
1623 void
1624 Path::invalidPath( const std::string &path,
1625  int location )
1626 {
1627  // Error: invalid path.
1628 }
1629 
1630 
1631 const Value &
1632 Path::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 
1663 Value
1664 Path::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 
1690 Value &
1691 Path::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

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