Drizzled Public API Documentation

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