blob: 691e41898225a07b20694869e3323509298b0c98 [file] [log] [blame]
Tobias Grosser75805372011-04-29 06:27:02 +00001#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
Tobias Grossera1f09342012-01-30 09:07:45 +000016// Disable warnings. We do not fix these warnings, as this is a file imported
17// into Polly and we do not want to diverge from the original source.
Tobias Grosser20532b82014-04-11 17:56:49 +000018#ifdef __clang__
Tobias Grossera1f09342012-01-30 09:07:45 +000019#pragma clang diagnostic ignored "-Wcovered-switch-default"
Tobias Grosser20532b82014-04-11 17:56:49 +000020#endif
21#ifdef __GNUC__
22#pragma GCC diagnostic ignored "-Woverflow"
23#endif
Tobias Grossera1f09342012-01-30 09:07:45 +000024
Tobias Grosser75805372011-04-29 06:27:02 +000025#define JSON_ASSERT_UNREACHABLE assert( false )
26#define JSON_ASSERT( condition ) assert( condition ); // @todo <= change this into an exception throw
Hongbin Zhengad691562011-04-30 02:47:34 +000027// Do not use throw when exception is disable.
28#if JSON_USE_EXCEPTION
29# define JSON_ASSERT_MESSAGE( condition, message ) if (!( condition )) throw std::runtime_error( message );
30#else
31# define JSON_ASSERT_MESSAGE( condition, message ) JSON_ASSERT( condition ) // @todo <= provide the message
32#endif
Tobias Grosser75805372011-04-29 06:27:02 +000033
34namespace Json {
35
36const Value Value::null;
37const Int Value::minInt = Int( ~(UInt(-1)/2) );
38const Int Value::maxInt = Int( UInt(-1)/2 );
39const UInt Value::maxUInt = UInt(-1);
40
Tobias Grosser20532b82014-04-11 17:56:49 +000041// A "safe" implementation of strdup. Allow null pointer to be passed.
Tobias Grosser75805372011-04-29 06:27:02 +000042// Also avoid warning on msvc80.
43//
44//inline char *safeStringDup( const char *czstring )
45//{
46// if ( czstring )
47// {
48// const size_t length = (unsigned int)( strlen(czstring) + 1 );
49// char *newString = static_cast<char *>( malloc( length ) );
50// memcpy( newString, czstring, length );
51// return newString;
52// }
53// return 0;
54//}
55//
56//inline char *safeStringDup( const std::string &str )
57//{
58// if ( !str.empty() )
59// {
60// const size_t length = str.length();
61// char *newString = static_cast<char *>( malloc( length + 1 ) );
62// memcpy( newString, str.c_str(), length );
63// newString[length] = 0;
64// return newString;
65// }
66// return 0;
67//}
68
69ValueAllocator::~ValueAllocator()
70{
71}
72
73class DefaultValueAllocator : public ValueAllocator
74{
75public:
76 virtual ~DefaultValueAllocator()
77 {
78 }
79
80 virtual char *makeMemberName( const char *memberName )
81 {
82 return duplicateStringValue( memberName );
83 }
84
85 virtual void releaseMemberName( char *memberName )
86 {
87 releaseStringValue( memberName );
88 }
89
Tobias Grosser20532b82014-04-11 17:56:49 +000090 virtual char *duplicateStringValue( const char *value,
Tobias Grosser75805372011-04-29 06:27:02 +000091 unsigned int length = unknown )
92 {
93 //@todo invesgate this old optimization
94 //if ( !value || value[0] == 0 )
95 // return 0;
96
97 if ( length == unknown )
98 length = (unsigned int)strlen(value);
99 char *newString = static_cast<char *>( malloc( length + 1 ) );
100 memcpy( newString, value, length );
101 newString[length] = 0;
102 return newString;
103 }
104
105 virtual void releaseStringValue( char *value )
106 {
107 if ( value )
108 free( value );
109 }
110};
111
112static ValueAllocator *&valueAllocator()
113{
114 static DefaultValueAllocator defaultAllocator;
115 static ValueAllocator *valueAllocator = &defaultAllocator;
116 return valueAllocator;
117}
118
119static struct DummyValueAllocatorInitializer {
Tobias Grosser20532b82014-04-11 17:56:49 +0000120 DummyValueAllocatorInitializer()
Tobias Grosser75805372011-04-29 06:27:02 +0000121 {
122 valueAllocator(); // ensure valueAllocator() statics are initialized before main().
123 }
124} dummyValueAllocatorInitializer;
125
126
127
128// //////////////////////////////////////////////////////////////////
129// //////////////////////////////////////////////////////////////////
130// //////////////////////////////////////////////////////////////////
131// ValueInternals...
132// //////////////////////////////////////////////////////////////////
133// //////////////////////////////////////////////////////////////////
134// //////////////////////////////////////////////////////////////////
135#ifdef JSON_VALUE_USE_INTERNAL_MAP
136# include "json_internalarray.inl"
137# include "json_internalmap.inl"
138#endif // JSON_VALUE_USE_INTERNAL_MAP
139
140# include "json_valueiterator.inl"
141
142
143// //////////////////////////////////////////////////////////////////
144// //////////////////////////////////////////////////////////////////
145// //////////////////////////////////////////////////////////////////
146// class Value::CommentInfo
147// //////////////////////////////////////////////////////////////////
148// //////////////////////////////////////////////////////////////////
149// //////////////////////////////////////////////////////////////////
150
151
152Value::CommentInfo::CommentInfo()
153 : comment_( 0 )
154{
155}
156
157Value::CommentInfo::~CommentInfo()
158{
159 if ( comment_ )
160 valueAllocator()->releaseStringValue( comment_ );
161}
162
163
Tobias Grosser20532b82014-04-11 17:56:49 +0000164void
Tobias Grosser75805372011-04-29 06:27:02 +0000165Value::CommentInfo::setComment( const char *text )
166{
167 if ( comment_ )
168 valueAllocator()->releaseStringValue( comment_ );
169 JSON_ASSERT( text );
170 JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
171 // It seems that /**/ style comments are acceptable as well.
172 comment_ = valueAllocator()->duplicateStringValue( text );
173}
174
175
176// //////////////////////////////////////////////////////////////////
177// //////////////////////////////////////////////////////////////////
178// //////////////////////////////////////////////////////////////////
179// class Value::CZString
180// //////////////////////////////////////////////////////////////////
181// //////////////////////////////////////////////////////////////////
182// //////////////////////////////////////////////////////////////////
183# ifndef JSON_VALUE_USE_INTERNAL_MAP
184
185// Notes: index_ indicates if the string was allocated when
186// a string is stored.
187
188Value::CZString::CZString( int index )
189 : cstr_( 0 )
190 , index_( index )
191{
192}
193
194Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
Tobias Grosser20532b82014-04-11 17:56:49 +0000195 : cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr)
Tobias Grosser75805372011-04-29 06:27:02 +0000196 : cstr )
197 , index_( allocate )
198{
199}
200
201Value::CZString::CZString( const CZString &other )
202: cstr_( other.index_ != noDuplication && other.cstr_ != 0
203 ? valueAllocator()->makeMemberName( other.cstr_ )
204 : other.cstr_ )
205 , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
206 : other.index_ )
207{
208}
209
210Value::CZString::~CZString()
211{
212 if ( cstr_ && index_ == duplicate )
213 valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) );
214}
215
Tobias Grosser20532b82014-04-11 17:56:49 +0000216void
Tobias Grosser75805372011-04-29 06:27:02 +0000217Value::CZString::swap( CZString &other )
218{
219 std::swap( cstr_, other.cstr_ );
220 std::swap( index_, other.index_ );
221}
222
223Value::CZString &
224Value::CZString::operator =( const CZString &other )
225{
226 CZString temp( other );
227 swap( temp );
228 return *this;
229}
230
Tobias Grosser20532b82014-04-11 17:56:49 +0000231bool
232Value::CZString::operator<( const CZString &other ) const
Tobias Grosser75805372011-04-29 06:27:02 +0000233{
234 if ( cstr_ )
235 return strcmp( cstr_, other.cstr_ ) < 0;
236 return index_ < other.index_;
237}
238
Tobias Grosser20532b82014-04-11 17:56:49 +0000239bool
240Value::CZString::operator==( const CZString &other ) const
Tobias Grosser75805372011-04-29 06:27:02 +0000241{
242 if ( cstr_ )
243 return strcmp( cstr_, other.cstr_ ) == 0;
244 return index_ == other.index_;
245}
246
247
Tobias Grosser20532b82014-04-11 17:56:49 +0000248int
Tobias Grosser75805372011-04-29 06:27:02 +0000249Value::CZString::index() const
250{
251 return index_;
252}
253
254
255const char *
256Value::CZString::c_str() const
257{
258 return cstr_;
259}
260
Tobias Grosser20532b82014-04-11 17:56:49 +0000261bool
Tobias Grosser75805372011-04-29 06:27:02 +0000262Value::CZString::isStaticString() const
263{
264 return index_ == noDuplication;
265}
266
267#endif // ifndef JSON_VALUE_USE_INTERNAL_MAP
268
269
270// //////////////////////////////////////////////////////////////////
271// //////////////////////////////////////////////////////////////////
272// //////////////////////////////////////////////////////////////////
273// class Value::Value
274// //////////////////////////////////////////////////////////////////
275// //////////////////////////////////////////////////////////////////
276// //////////////////////////////////////////////////////////////////
277
278/*! \internal Default constructor initialization must be equivalent to:
279 * memset( this, 0, sizeof(Value) )
280 * This optimization is used in ValueInternalMap fast allocator.
281 */
282Value::Value( ValueType type )
283 : type_( type )
284 , allocated_( 0 )
285 , comments_( 0 )
286# ifdef JSON_VALUE_USE_INTERNAL_MAP
287 , itemIsUsed_( 0 )
288#endif
289{
290 switch ( type )
291 {
292 case nullValue:
293 break;
294 case intValue:
295 case uintValue:
296 value_.int_ = 0;
297 break;
298 case realValue:
299 value_.real_ = 0.0;
300 break;
301 case stringValue:
302 value_.string_ = 0;
303 break;
304#ifndef JSON_VALUE_USE_INTERNAL_MAP
305 case arrayValue:
306 case objectValue:
307 value_.map_ = new ObjectValues();
308 break;
309#else
310 case arrayValue:
311 value_.array_ = arrayAllocator()->newArray();
312 break;
313 case objectValue:
314 value_.map_ = mapAllocator()->newMap();
315 break;
316#endif
317 case booleanValue:
318 value_.bool_ = false;
319 break;
320 default:
321 JSON_ASSERT_UNREACHABLE;
322 }
323}
324
325
326Value::Value( Int value )
327 : type_( intValue )
328 , comments_( 0 )
329# ifdef JSON_VALUE_USE_INTERNAL_MAP
330 , itemIsUsed_( 0 )
331#endif
332{
333 value_.int_ = value;
334}
335
336
337Value::Value( UInt value )
338 : type_( uintValue )
339 , comments_( 0 )
340# ifdef JSON_VALUE_USE_INTERNAL_MAP
341 , itemIsUsed_( 0 )
342#endif
343{
344 value_.uint_ = value;
345}
346
347Value::Value( double value )
348 : type_( realValue )
349 , comments_( 0 )
350# ifdef JSON_VALUE_USE_INTERNAL_MAP
351 , itemIsUsed_( 0 )
352#endif
353{
354 value_.real_ = value;
355}
356
357Value::Value( const char *value )
358 : type_( stringValue )
359 , allocated_( true )
360 , comments_( 0 )
361# ifdef JSON_VALUE_USE_INTERNAL_MAP
362 , itemIsUsed_( 0 )
363#endif
364{
365 value_.string_ = valueAllocator()->duplicateStringValue( value );
366}
367
368
Tobias Grosser20532b82014-04-11 17:56:49 +0000369Value::Value( const char *beginValue,
Tobias Grosser75805372011-04-29 06:27:02 +0000370 const char *endValue )
371 : type_( stringValue )
372 , allocated_( true )
373 , comments_( 0 )
374# ifdef JSON_VALUE_USE_INTERNAL_MAP
375 , itemIsUsed_( 0 )
376#endif
377{
Tobias Grosser20532b82014-04-11 17:56:49 +0000378 value_.string_ = valueAllocator()->duplicateStringValue( beginValue,
Tobias Grosser75805372011-04-29 06:27:02 +0000379 UInt(endValue - beginValue) );
380}
381
382
383Value::Value( const std::string &value )
384 : type_( stringValue )
385 , allocated_( true )
386 , comments_( 0 )
387# ifdef JSON_VALUE_USE_INTERNAL_MAP
388 , itemIsUsed_( 0 )
389#endif
390{
Tobias Grosser20532b82014-04-11 17:56:49 +0000391 value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(),
Tobias Grosser75805372011-04-29 06:27:02 +0000392 (unsigned int)value.length() );
393
394}
395
396Value::Value( const StaticString &value )
397 : type_( stringValue )
398 , allocated_( false )
399 , comments_( 0 )
400# ifdef JSON_VALUE_USE_INTERNAL_MAP
401 , itemIsUsed_( 0 )
402#endif
403{
404 value_.string_ = const_cast<char *>( value.c_str() );
405}
406
407
408# ifdef JSON_USE_CPPTL
409Value::Value( const CppTL::ConstString &value )
410 : type_( stringValue )
411 , allocated_( true )
412 , comments_( 0 )
413# ifdef JSON_VALUE_USE_INTERNAL_MAP
414 , itemIsUsed_( 0 )
415#endif
416{
417 value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() );
418}
419# endif
420
421Value::Value( bool value )
422 : type_( booleanValue )
423 , comments_( 0 )
424# ifdef JSON_VALUE_USE_INTERNAL_MAP
425 , itemIsUsed_( 0 )
426#endif
427{
428 value_.bool_ = value;
429}
430
431
432Value::Value( const Value &other )
433 : type_( other.type_ )
434 , comments_( 0 )
435# ifdef JSON_VALUE_USE_INTERNAL_MAP
436 , itemIsUsed_( 0 )
437#endif
438{
439 switch ( type_ )
440 {
441 case nullValue:
442 case intValue:
443 case uintValue:
444 case realValue:
445 case booleanValue:
446 value_ = other.value_;
447 break;
448 case stringValue:
449 if ( other.value_.string_ )
450 {
451 value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ );
452 allocated_ = true;
453 }
454 else
455 value_.string_ = 0;
456 break;
457#ifndef JSON_VALUE_USE_INTERNAL_MAP
458 case arrayValue:
459 case objectValue:
460 value_.map_ = new ObjectValues( *other.value_.map_ );
461 break;
462#else
463 case arrayValue:
464 value_.array_ = arrayAllocator()->newArrayCopy( *other.value_.array_ );
465 break;
466 case objectValue:
467 value_.map_ = mapAllocator()->newMapCopy( *other.value_.map_ );
468 break;
469#endif
470 default:
471 JSON_ASSERT_UNREACHABLE;
472 }
473 if ( other.comments_ )
474 {
475 comments_ = new CommentInfo[numberOfCommentPlacement];
476 for ( int comment =0; comment < numberOfCommentPlacement; ++comment )
477 {
478 const CommentInfo &otherComment = other.comments_[comment];
479 if ( otherComment.comment_ )
480 comments_[comment].setComment( otherComment.comment_ );
481 }
482 }
483}
484
485
486Value::~Value()
487{
488 switch ( type_ )
489 {
490 case nullValue:
491 case intValue:
492 case uintValue:
493 case realValue:
494 case booleanValue:
495 break;
496 case stringValue:
497 if ( allocated_ )
498 valueAllocator()->releaseStringValue( value_.string_ );
499 break;
500#ifndef JSON_VALUE_USE_INTERNAL_MAP
501 case arrayValue:
502 case objectValue:
503 delete value_.map_;
504 break;
505#else
506 case arrayValue:
507 arrayAllocator()->destructArray( value_.array_ );
508 break;
509 case objectValue:
510 mapAllocator()->destructMap( value_.map_ );
511 break;
512#endif
513 default:
514 JSON_ASSERT_UNREACHABLE;
515 }
516
517 if ( comments_ )
518 delete[] comments_;
519}
520
521Value &
522Value::operator=( const Value &other )
523{
524 Value temp( other );
525 swap( temp );
526 return *this;
527}
528
Tobias Grosser20532b82014-04-11 17:56:49 +0000529void
Tobias Grosser75805372011-04-29 06:27:02 +0000530Value::swap( Value &other )
531{
532 ValueType temp = type_;
533 type_ = other.type_;
534 other.type_ = temp;
535 std::swap( value_, other.value_ );
536 int temp2 = allocated_;
537 allocated_ = other.allocated_;
538 other.allocated_ = temp2;
539}
540
Tobias Grosser20532b82014-04-11 17:56:49 +0000541ValueType
Tobias Grosser75805372011-04-29 06:27:02 +0000542Value::type() const
543{
544 return type_;
545}
546
547
Tobias Grosser20532b82014-04-11 17:56:49 +0000548int
Tobias Grosser75805372011-04-29 06:27:02 +0000549Value::compare( const Value &other )
550{
551 /*
552 int typeDelta = other.type_ - type_;
553 switch ( type_ )
554 {
555 case nullValue:
556
557 return other.type_ == type_;
558 case intValue:
559 if ( other.type_.isNumeric()
560 case uintValue:
561 case realValue:
562 case booleanValue:
563 break;
564 case stringValue,
565 break;
566 case arrayValue:
567 delete value_.array_;
568 break;
569 case objectValue:
570 delete value_.map_;
571 default:
572 JSON_ASSERT_UNREACHABLE;
573 }
574 */
575 return 0; // unreachable
576}
577
Tobias Grosser20532b82014-04-11 17:56:49 +0000578bool
Tobias Grosser75805372011-04-29 06:27:02 +0000579Value::operator <( const Value &other ) const
580{
581 int typeDelta = type_ - other.type_;
582 if ( typeDelta )
583 return typeDelta < 0 ? true : false;
584 switch ( type_ )
585 {
586 case nullValue:
587 return false;
588 case intValue:
589 return value_.int_ < other.value_.int_;
590 case uintValue:
591 return value_.uint_ < other.value_.uint_;
592 case realValue:
593 return value_.real_ < other.value_.real_;
594 case booleanValue:
595 return value_.bool_ < other.value_.bool_;
596 case stringValue:
597 return ( value_.string_ == 0 && other.value_.string_ )
Tobias Grosser20532b82014-04-11 17:56:49 +0000598 || ( other.value_.string_
599 && value_.string_
Tobias Grosser75805372011-04-29 06:27:02 +0000600 && strcmp( value_.string_, other.value_.string_ ) < 0 );
601#ifndef JSON_VALUE_USE_INTERNAL_MAP
602 case arrayValue:
603 case objectValue:
604 {
605 int delta = int( value_.map_->size() - other.value_.map_->size() );
606 if ( delta )
607 return delta < 0;
608 return (*value_.map_) < (*other.value_.map_);
609 }
610#else
611 case arrayValue:
612 return value_.array_->compare( *(other.value_.array_) ) < 0;
613 case objectValue:
614 return value_.map_->compare( *(other.value_.map_) ) < 0;
615#endif
616 default:
617 JSON_ASSERT_UNREACHABLE;
618 }
619 return 0; // unreachable
620}
621
Tobias Grosser20532b82014-04-11 17:56:49 +0000622bool
Tobias Grosser75805372011-04-29 06:27:02 +0000623Value::operator <=( const Value &other ) const
624{
625 return !(other > *this);
626}
627
Tobias Grosser20532b82014-04-11 17:56:49 +0000628bool
Tobias Grosser75805372011-04-29 06:27:02 +0000629Value::operator >=( const Value &other ) const
630{
631 return !(*this < other);
632}
633
Tobias Grosser20532b82014-04-11 17:56:49 +0000634bool
Tobias Grosser75805372011-04-29 06:27:02 +0000635Value::operator >( const Value &other ) const
636{
637 return other < *this;
638}
639
Tobias Grosser20532b82014-04-11 17:56:49 +0000640bool
Tobias Grosser75805372011-04-29 06:27:02 +0000641Value::operator ==( const Value &other ) const
642{
643 //if ( type_ != other.type_ )
644 // GCC 2.95.3 says:
645 // attempt to take address of bit-field structure member `Json::Value::type_'
646 // Beats me, but a temp solves the problem.
647 int temp = other.type_;
648 if ( type_ != temp )
649 return false;
650 switch ( type_ )
651 {
652 case nullValue:
653 return true;
654 case intValue:
655 return value_.int_ == other.value_.int_;
656 case uintValue:
657 return value_.uint_ == other.value_.uint_;
658 case realValue:
659 return value_.real_ == other.value_.real_;
660 case booleanValue:
661 return value_.bool_ == other.value_.bool_;
662 case stringValue:
663 return ( value_.string_ == other.value_.string_ )
Tobias Grosser20532b82014-04-11 17:56:49 +0000664 || ( other.value_.string_
665 && value_.string_
Tobias Grosser75805372011-04-29 06:27:02 +0000666 && strcmp( value_.string_, other.value_.string_ ) == 0 );
667#ifndef JSON_VALUE_USE_INTERNAL_MAP
668 case arrayValue:
669 case objectValue:
670 return value_.map_->size() == other.value_.map_->size()
671 && (*value_.map_) == (*other.value_.map_);
672#else
673 case arrayValue:
674 return value_.array_->compare( *(other.value_.array_) ) == 0;
675 case objectValue:
676 return value_.map_->compare( *(other.value_.map_) ) == 0;
677#endif
678 default:
679 JSON_ASSERT_UNREACHABLE;
680 }
681 return 0; // unreachable
682}
683
Tobias Grosser20532b82014-04-11 17:56:49 +0000684bool
Tobias Grosser75805372011-04-29 06:27:02 +0000685Value::operator !=( const Value &other ) const
686{
687 return !( *this == other );
688}
689
690const char *
691Value::asCString() const
692{
693 JSON_ASSERT( type_ == stringValue );
694 return value_.string_;
695}
696
697
Tobias Grosser20532b82014-04-11 17:56:49 +0000698std::string
Tobias Grosser75805372011-04-29 06:27:02 +0000699Value::asString() const
700{
701 switch ( type_ )
702 {
703 case nullValue:
704 return "";
705 case stringValue:
706 return value_.string_ ? value_.string_ : "";
707 case booleanValue:
708 return value_.bool_ ? "true" : "false";
709 case intValue:
710 case uintValue:
711 case realValue:
712 case arrayValue:
713 case objectValue:
714 JSON_ASSERT_MESSAGE( false, "Type is not convertible to string" );
715 default:
716 JSON_ASSERT_UNREACHABLE;
717 }
718 return ""; // unreachable
719}
720
721# ifdef JSON_USE_CPPTL
Tobias Grosser20532b82014-04-11 17:56:49 +0000722CppTL::ConstString
Tobias Grosser75805372011-04-29 06:27:02 +0000723Value::asConstString() const
724{
725 return CppTL::ConstString( asString().c_str() );
726}
727# endif
728
Tobias Grosser20532b82014-04-11 17:56:49 +0000729Value::Int
Tobias Grosser75805372011-04-29 06:27:02 +0000730Value::asInt() const
731{
732 switch ( type_ )
733 {
734 case nullValue:
735 return 0;
736 case intValue:
737 return value_.int_;
738 case uintValue:
739 JSON_ASSERT_MESSAGE( value_.uint_ < (unsigned)maxInt, "integer out of signed integer range" );
740 return value_.uint_;
741 case realValue:
742 JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
743 return Int( value_.real_ );
744 case booleanValue:
745 return value_.bool_ ? 1 : 0;
746 case stringValue:
747 case arrayValue:
748 case objectValue:
749 JSON_ASSERT_MESSAGE( false, "Type is not convertible to int" );
750 default:
751 JSON_ASSERT_UNREACHABLE;
752 }
753 return 0; // unreachable;
754}
755
Tobias Grosser20532b82014-04-11 17:56:49 +0000756Value::UInt
Tobias Grosser75805372011-04-29 06:27:02 +0000757Value::asUInt() const
758{
759 switch ( type_ )
760 {
761 case nullValue:
762 return 0;
763 case intValue:
764 JSON_ASSERT_MESSAGE( value_.int_ >= 0, "Negative integer can not be converted to unsigned integer" );
765 return value_.int_;
766 case uintValue:
767 return value_.uint_;
768 case realValue:
769 JSON_ASSERT_MESSAGE( value_.real_ >= 0 && value_.real_ <= maxUInt, "Real out of unsigned integer range" );
770 return UInt( value_.real_ );
771 case booleanValue:
772 return value_.bool_ ? 1 : 0;
773 case stringValue:
774 case arrayValue:
775 case objectValue:
776 JSON_ASSERT_MESSAGE( false, "Type is not convertible to uint" );
777 default:
778 JSON_ASSERT_UNREACHABLE;
779 }
780 return 0; // unreachable;
781}
782
Tobias Grosser20532b82014-04-11 17:56:49 +0000783double
Tobias Grosser75805372011-04-29 06:27:02 +0000784Value::asDouble() const
785{
786 switch ( type_ )
787 {
788 case nullValue:
789 return 0.0;
790 case intValue:
791 return value_.int_;
792 case uintValue:
793 return value_.uint_;
794 case realValue:
795 return value_.real_;
796 case booleanValue:
797 return value_.bool_ ? 1.0 : 0.0;
798 case stringValue:
799 case arrayValue:
800 case objectValue:
801 JSON_ASSERT_MESSAGE( false, "Type is not convertible to double" );
802 default:
803 JSON_ASSERT_UNREACHABLE;
804 }
805 return 0; // unreachable;
806}
807
Tobias Grosser20532b82014-04-11 17:56:49 +0000808bool
Tobias Grosser75805372011-04-29 06:27:02 +0000809Value::asBool() const
810{
811 switch ( type_ )
812 {
813 case nullValue:
814 return false;
815 case intValue:
816 case uintValue:
817 return value_.int_ != 0;
818 case realValue:
819 return value_.real_ != 0.0;
820 case booleanValue:
821 return value_.bool_;
822 case stringValue:
823 return value_.string_ && value_.string_[0] != 0;
824 case arrayValue:
825 case objectValue:
826 return value_.map_->size() != 0;
827 default:
828 JSON_ASSERT_UNREACHABLE;
829 }
830 return false; // unreachable;
831}
832
833
Tobias Grosser20532b82014-04-11 17:56:49 +0000834bool
Tobias Grosser75805372011-04-29 06:27:02 +0000835Value::isConvertibleTo( ValueType other ) const
836{
837 switch ( type_ )
838 {
839 case nullValue:
840 return true;
841 case intValue:
842 return ( other == nullValue && value_.int_ == 0 )
843 || other == intValue
844 || ( other == uintValue && value_.int_ >= 0 )
845 || other == realValue
846 || other == stringValue
847 || other == booleanValue;
848 case uintValue:
849 return ( other == nullValue && value_.uint_ == 0 )
850 || ( other == intValue && value_.uint_ <= (unsigned)maxInt )
851 || other == uintValue
852 || other == realValue
853 || other == stringValue
854 || other == booleanValue;
855 case realValue:
856 return ( other == nullValue && value_.real_ == 0.0 )
857 || ( other == intValue && value_.real_ >= minInt && value_.real_ <= maxInt )
858 || ( other == uintValue && value_.real_ >= 0 && value_.real_ <= maxUInt )
859 || other == realValue
860 || other == stringValue
861 || other == booleanValue;
862 case booleanValue:
863 return ( other == nullValue && value_.bool_ == false )
864 || other == intValue
865 || other == uintValue
866 || other == realValue
867 || other == stringValue
868 || other == booleanValue;
869 case stringValue:
870 return other == stringValue
871 || ( other == nullValue && (!value_.string_ || value_.string_[0] == 0) );
872 case arrayValue:
873 return other == arrayValue
874 || ( other == nullValue && value_.map_->size() == 0 );
875 case objectValue:
876 return other == objectValue
877 || ( other == nullValue && value_.map_->size() == 0 );
878 default:
879 JSON_ASSERT_UNREACHABLE;
880 }
881 return false; // unreachable;
882}
883
884
885/// Number of values in array or object
Tobias Grosser20532b82014-04-11 17:56:49 +0000886Value::UInt
Tobias Grosser75805372011-04-29 06:27:02 +0000887Value::size() const
888{
889 switch ( type_ )
890 {
891 case nullValue:
892 case intValue:
893 case uintValue:
894 case realValue:
895 case booleanValue:
896 case stringValue:
897 return 0;
898#ifndef JSON_VALUE_USE_INTERNAL_MAP
899 case arrayValue: // size of the array is highest index + 1
900 if ( !value_.map_->empty() )
901 {
902 ObjectValues::const_iterator itLast = value_.map_->end();
903 --itLast;
904 return (*itLast).first.index()+1;
905 }
906 return 0;
907 case objectValue:
908 return Int( value_.map_->size() );
909#else
910 case arrayValue:
911 return Int( value_.array_->size() );
912 case objectValue:
913 return Int( value_.map_->size() );
914#endif
915 default:
916 JSON_ASSERT_UNREACHABLE;
917 }
918 return 0; // unreachable;
919}
920
921
Tobias Grosser20532b82014-04-11 17:56:49 +0000922bool
Tobias Grosser75805372011-04-29 06:27:02 +0000923Value::empty() const
924{
925 if ( isNull() || isArray() || isObject() )
926 return size() == 0u;
927 else
928 return false;
929}
930
931
932bool
933Value::operator!() const
934{
935 return isNull();
936}
937
938
Tobias Grosser20532b82014-04-11 17:56:49 +0000939void
Tobias Grosser75805372011-04-29 06:27:02 +0000940Value::clear()
941{
942 JSON_ASSERT( type_ == nullValue || type_ == arrayValue || type_ == objectValue );
943
944 switch ( type_ )
945 {
946#ifndef JSON_VALUE_USE_INTERNAL_MAP
947 case arrayValue:
948 case objectValue:
949 value_.map_->clear();
950 break;
951#else
952 case arrayValue:
953 value_.array_->clear();
954 break;
955 case objectValue:
956 value_.map_->clear();
957 break;
958#endif
959 default:
960 break;
961 }
962}
963
Tobias Grosser20532b82014-04-11 17:56:49 +0000964void
Tobias Grosser75805372011-04-29 06:27:02 +0000965Value::resize( UInt newSize )
966{
967 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
968 if ( type_ == nullValue )
969 *this = Value( arrayValue );
970#ifndef JSON_VALUE_USE_INTERNAL_MAP
971 UInt oldSize = size();
972 if ( newSize == 0 )
973 clear();
974 else if ( newSize > oldSize )
975 (*this)[ newSize - 1 ];
976 else
977 {
978 for ( UInt index = newSize; index < oldSize; ++index )
979 value_.map_->erase( index );
980 assert( size() == newSize );
981 }
982#else
983 value_.array_->resize( newSize );
984#endif
985}
986
987
988Value &
989Value::operator[]( UInt index )
990{
991 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
992 if ( type_ == nullValue )
993 *this = Value( arrayValue );
994#ifndef JSON_VALUE_USE_INTERNAL_MAP
995 CZString key( index );
996 ObjectValues::iterator it = value_.map_->lower_bound( key );
997 if ( it != value_.map_->end() && (*it).first == key )
998 return (*it).second;
999
1000 ObjectValues::value_type defaultValue( key, null );
1001 it = value_.map_->insert( it, defaultValue );
1002 return (*it).second;
1003#else
1004 return value_.array_->resolveReference( index );
1005#endif
1006}
1007
1008
1009const Value &
1010Value::operator[]( UInt index ) const
1011{
1012 JSON_ASSERT( type_ == nullValue || type_ == arrayValue );
1013 if ( type_ == nullValue )
1014 return null;
1015#ifndef JSON_VALUE_USE_INTERNAL_MAP
1016 CZString key( index );
1017 ObjectValues::const_iterator it = value_.map_->find( key );
1018 if ( it == value_.map_->end() )
1019 return null;
1020 return (*it).second;
1021#else
1022 Value *value = value_.array_->find( index );
1023 return value ? *value : null;
1024#endif
1025}
1026
1027
1028Value &
1029Value::operator[]( const char *key )
1030{
1031 return resolveReference( key, false );
1032}
1033
1034
1035Value &
Tobias Grosser20532b82014-04-11 17:56:49 +00001036Value::resolveReference( const char *key,
Tobias Grosser75805372011-04-29 06:27:02 +00001037 bool isStatic )
1038{
1039 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1040 if ( type_ == nullValue )
1041 *this = Value( objectValue );
1042#ifndef JSON_VALUE_USE_INTERNAL_MAP
Tobias Grosser20532b82014-04-11 17:56:49 +00001043 CZString actualKey( key, isStatic ? CZString::noDuplication
Tobias Grosser75805372011-04-29 06:27:02 +00001044 : CZString::duplicateOnCopy );
1045 ObjectValues::iterator it = value_.map_->lower_bound( actualKey );
1046 if ( it != value_.map_->end() && (*it).first == actualKey )
1047 return (*it).second;
1048
1049 ObjectValues::value_type defaultValue( actualKey, null );
1050 it = value_.map_->insert( it, defaultValue );
1051 Value &value = (*it).second;
1052 return value;
1053#else
1054 return value_.map_->resolveReference( key, isStatic );
1055#endif
1056}
1057
1058
Tobias Grosser20532b82014-04-11 17:56:49 +00001059Value
1060Value::get( UInt index,
Tobias Grosser75805372011-04-29 06:27:02 +00001061 const Value &defaultValue ) const
1062{
1063 const Value *value = &((*this)[index]);
1064 return value == &null ? defaultValue : *value;
1065}
1066
1067
Tobias Grosser20532b82014-04-11 17:56:49 +00001068bool
Tobias Grosser75805372011-04-29 06:27:02 +00001069Value::isValidIndex( UInt index ) const
1070{
1071 return index < size();
1072}
1073
1074
1075
1076const Value &
1077Value::operator[]( const char *key ) const
1078{
1079 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1080 if ( type_ == nullValue )
1081 return null;
1082#ifndef JSON_VALUE_USE_INTERNAL_MAP
1083 CZString actualKey( key, CZString::noDuplication );
1084 ObjectValues::const_iterator it = value_.map_->find( actualKey );
1085 if ( it == value_.map_->end() )
1086 return null;
1087 return (*it).second;
1088#else
1089 const Value *value = value_.map_->find( key );
1090 return value ? *value : null;
1091#endif
1092}
1093
1094
1095Value &
1096Value::operator[]( const std::string &key )
1097{
1098 return (*this)[ key.c_str() ];
1099}
1100
1101
1102const Value &
1103Value::operator[]( const std::string &key ) const
1104{
1105 return (*this)[ key.c_str() ];
1106}
1107
1108Value &
1109Value::operator[]( const StaticString &key )
1110{
1111 return resolveReference( key, true );
1112}
1113
1114
1115# ifdef JSON_USE_CPPTL
1116Value &
1117Value::operator[]( const CppTL::ConstString &key )
1118{
1119 return (*this)[ key.c_str() ];
1120}
1121
1122
1123const Value &
1124Value::operator[]( const CppTL::ConstString &key ) const
1125{
1126 return (*this)[ key.c_str() ];
1127}
1128# endif
1129
1130
1131Value &
1132Value::append( const Value &value )
1133{
1134 return (*this)[size()] = value;
1135}
1136
1137
Tobias Grosser20532b82014-04-11 17:56:49 +00001138Value
1139Value::get( const char *key,
Tobias Grosser75805372011-04-29 06:27:02 +00001140 const Value &defaultValue ) const
1141{
1142 const Value *value = &((*this)[key]);
1143 return value == &null ? defaultValue : *value;
1144}
1145
1146
Tobias Grosser20532b82014-04-11 17:56:49 +00001147Value
Tobias Grosser75805372011-04-29 06:27:02 +00001148Value::get( const std::string &key,
1149 const Value &defaultValue ) const
1150{
1151 return get( key.c_str(), defaultValue );
1152}
1153
1154Value
1155Value::removeMember( const char* key )
1156{
1157 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1158 if ( type_ == nullValue )
1159 return null;
1160#ifndef JSON_VALUE_USE_INTERNAL_MAP
1161 CZString actualKey( key, CZString::noDuplication );
1162 ObjectValues::iterator it = value_.map_->find( actualKey );
1163 if ( it == value_.map_->end() )
1164 return null;
1165 Value old(it->second);
1166 value_.map_->erase(it);
1167 return old;
1168#else
1169 Value *value = value_.map_->find( key );
1170 if (value){
1171 Value old(*value);
1172 value_.map_.remove( key );
1173 return old;
1174 } else {
1175 return null;
1176 }
1177#endif
1178}
1179
1180Value
1181Value::removeMember( const std::string &key )
1182{
1183 return removeMember( key.c_str() );
1184}
1185
1186# ifdef JSON_USE_CPPTL
Tobias Grosser20532b82014-04-11 17:56:49 +00001187Value
Tobias Grosser75805372011-04-29 06:27:02 +00001188Value::get( const CppTL::ConstString &key,
1189 const Value &defaultValue ) const
1190{
1191 return get( key.c_str(), defaultValue );
1192}
1193# endif
1194
Tobias Grosser20532b82014-04-11 17:56:49 +00001195bool
Tobias Grosser75805372011-04-29 06:27:02 +00001196Value::isMember( const char *key ) const
1197{
1198 const Value *value = &((*this)[key]);
1199 return value != &null;
1200}
1201
1202
Tobias Grosser20532b82014-04-11 17:56:49 +00001203bool
Tobias Grosser75805372011-04-29 06:27:02 +00001204Value::isMember( const std::string &key ) const
1205{
1206 return isMember( key.c_str() );
1207}
1208
1209
1210# ifdef JSON_USE_CPPTL
Tobias Grosser20532b82014-04-11 17:56:49 +00001211bool
Tobias Grosser75805372011-04-29 06:27:02 +00001212Value::isMember( const CppTL::ConstString &key ) const
1213{
1214 return isMember( key.c_str() );
1215}
1216#endif
1217
Tobias Grosser20532b82014-04-11 17:56:49 +00001218Value::Members
Tobias Grosser75805372011-04-29 06:27:02 +00001219Value::getMemberNames() const
1220{
1221 JSON_ASSERT( type_ == nullValue || type_ == objectValue );
1222 if ( type_ == nullValue )
1223 return Value::Members();
1224 Members members;
1225 members.reserve( value_.map_->size() );
1226#ifndef JSON_VALUE_USE_INTERNAL_MAP
1227 ObjectValues::const_iterator it = value_.map_->begin();
1228 ObjectValues::const_iterator itEnd = value_.map_->end();
1229 for ( ; it != itEnd; ++it )
1230 members.push_back( std::string( (*it).first.c_str() ) );
1231#else
1232 ValueInternalMap::IteratorState it;
1233 ValueInternalMap::IteratorState itEnd;
1234 value_.map_->makeBeginIterator( it );
1235 value_.map_->makeEndIterator( itEnd );
1236 for ( ; !ValueInternalMap::equals( it, itEnd ); ValueInternalMap::increment(it) )
1237 members.push_back( std::string( ValueInternalMap::key( it ) ) );
1238#endif
1239 return members;
1240}
1241//
1242//# ifdef JSON_USE_CPPTL
1243//EnumMemberNames
1244//Value::enumMemberNames() const
1245//{
1246// if ( type_ == objectValue )
1247// {
1248// return CppTL::Enum::any( CppTL::Enum::transform(
1249// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
1250// MemberNamesTransform() ) );
1251// }
1252// return EnumMemberNames();
1253//}
1254//
1255//
Tobias Grosser20532b82014-04-11 17:56:49 +00001256//EnumValues
Tobias Grosser75805372011-04-29 06:27:02 +00001257//Value::enumValues() const
1258//{
1259// if ( type_ == objectValue || type_ == arrayValue )
Tobias Grosser20532b82014-04-11 17:56:49 +00001260// return CppTL::Enum::anyValues( *(value_.map_),
Tobias Grosser75805372011-04-29 06:27:02 +00001261// CppTL::Type<const Value &>() );
1262// return EnumValues();
1263//}
1264//
1265//# endif
1266
1267
1268bool
1269Value::isNull() const
1270{
1271 return type_ == nullValue;
1272}
1273
1274
Tobias Grosser20532b82014-04-11 17:56:49 +00001275bool
Tobias Grosser75805372011-04-29 06:27:02 +00001276Value::isBool() const
1277{
1278 return type_ == booleanValue;
1279}
1280
1281
Tobias Grosser20532b82014-04-11 17:56:49 +00001282bool
Tobias Grosser75805372011-04-29 06:27:02 +00001283Value::isInt() const
1284{
1285 return type_ == intValue;
1286}
1287
1288
Tobias Grosser20532b82014-04-11 17:56:49 +00001289bool
Tobias Grosser75805372011-04-29 06:27:02 +00001290Value::isUInt() const
1291{
1292 return type_ == uintValue;
1293}
1294
1295
Tobias Grosser20532b82014-04-11 17:56:49 +00001296bool
Tobias Grosser75805372011-04-29 06:27:02 +00001297Value::isIntegral() const
1298{
Tobias Grosser20532b82014-04-11 17:56:49 +00001299 return type_ == intValue
1300 || type_ == uintValue
Tobias Grosser75805372011-04-29 06:27:02 +00001301 || type_ == booleanValue;
1302}
1303
1304
Tobias Grosser20532b82014-04-11 17:56:49 +00001305bool
Tobias Grosser75805372011-04-29 06:27:02 +00001306Value::isDouble() const
1307{
1308 return type_ == realValue;
1309}
1310
1311
Tobias Grosser20532b82014-04-11 17:56:49 +00001312bool
Tobias Grosser75805372011-04-29 06:27:02 +00001313Value::isNumeric() const
1314{
1315 return isIntegral() || isDouble();
1316}
1317
1318
Tobias Grosser20532b82014-04-11 17:56:49 +00001319bool
Tobias Grosser75805372011-04-29 06:27:02 +00001320Value::isString() const
1321{
1322 return type_ == stringValue;
1323}
1324
1325
Tobias Grosser20532b82014-04-11 17:56:49 +00001326bool
Tobias Grosser75805372011-04-29 06:27:02 +00001327Value::isArray() const
1328{
1329 return type_ == nullValue || type_ == arrayValue;
1330}
1331
1332
Tobias Grosser20532b82014-04-11 17:56:49 +00001333bool
Tobias Grosser75805372011-04-29 06:27:02 +00001334Value::isObject() const
1335{
1336 return type_ == nullValue || type_ == objectValue;
1337}
1338
1339
Tobias Grosser20532b82014-04-11 17:56:49 +00001340void
Tobias Grosser75805372011-04-29 06:27:02 +00001341Value::setComment( const char *comment,
1342 CommentPlacement placement )
1343{
1344 if ( !comments_ )
1345 comments_ = new CommentInfo[numberOfCommentPlacement];
1346 comments_[placement].setComment( comment );
1347}
1348
1349
Tobias Grosser20532b82014-04-11 17:56:49 +00001350void
Tobias Grosser75805372011-04-29 06:27:02 +00001351Value::setComment( const std::string &comment,
1352 CommentPlacement placement )
1353{
1354 setComment( comment.c_str(), placement );
1355}
1356
1357
Tobias Grosser20532b82014-04-11 17:56:49 +00001358bool
Tobias Grosser75805372011-04-29 06:27:02 +00001359Value::hasComment( CommentPlacement placement ) const
1360{
1361 return comments_ != 0 && comments_[placement].comment_ != 0;
1362}
1363
Tobias Grosser20532b82014-04-11 17:56:49 +00001364std::string
Tobias Grosser75805372011-04-29 06:27:02 +00001365Value::getComment( CommentPlacement placement ) const
1366{
1367 if ( hasComment(placement) )
1368 return comments_[placement].comment_;
1369 return "";
1370}
1371
1372
Tobias Grosser20532b82014-04-11 17:56:49 +00001373std::string
Tobias Grosser75805372011-04-29 06:27:02 +00001374Value::toStyledString() const
1375{
1376 StyledWriter writer;
1377 return writer.write( *this );
1378}
1379
1380
Tobias Grosser20532b82014-04-11 17:56:49 +00001381Value::const_iterator
Tobias Grosser75805372011-04-29 06:27:02 +00001382Value::begin() const
1383{
1384 switch ( type_ )
1385 {
1386#ifdef JSON_VALUE_USE_INTERNAL_MAP
1387 case arrayValue:
1388 if ( value_.array_ )
1389 {
1390 ValueInternalArray::IteratorState it;
1391 value_.array_->makeBeginIterator( it );
1392 return const_iterator( it );
1393 }
1394 break;
1395 case objectValue:
1396 if ( value_.map_ )
1397 {
1398 ValueInternalMap::IteratorState it;
1399 value_.map_->makeBeginIterator( it );
1400 return const_iterator( it );
1401 }
1402 break;
1403#else
1404 case arrayValue:
1405 case objectValue:
1406 if ( value_.map_ )
1407 return const_iterator( value_.map_->begin() );
1408 break;
1409#endif
1410 default:
1411 break;
1412 }
1413 return const_iterator();
1414}
1415
Tobias Grosser20532b82014-04-11 17:56:49 +00001416Value::const_iterator
Tobias Grosser75805372011-04-29 06:27:02 +00001417Value::end() const
1418{
1419 switch ( type_ )
1420 {
1421#ifdef JSON_VALUE_USE_INTERNAL_MAP
1422 case arrayValue:
1423 if ( value_.array_ )
1424 {
1425 ValueInternalArray::IteratorState it;
1426 value_.array_->makeEndIterator( it );
1427 return const_iterator( it );
1428 }
1429 break;
1430 case objectValue:
1431 if ( value_.map_ )
1432 {
1433 ValueInternalMap::IteratorState it;
1434 value_.map_->makeEndIterator( it );
1435 return const_iterator( it );
1436 }
1437 break;
1438#else
1439 case arrayValue:
1440 case objectValue:
1441 if ( value_.map_ )
1442 return const_iterator( value_.map_->end() );
1443 break;
1444#endif
1445 default:
1446 break;
1447 }
1448 return const_iterator();
1449}
1450
1451
Tobias Grosser20532b82014-04-11 17:56:49 +00001452Value::iterator
Tobias Grosser75805372011-04-29 06:27:02 +00001453Value::begin()
1454{
1455 switch ( type_ )
1456 {
1457#ifdef JSON_VALUE_USE_INTERNAL_MAP
1458 case arrayValue:
1459 if ( value_.array_ )
1460 {
1461 ValueInternalArray::IteratorState it;
1462 value_.array_->makeBeginIterator( it );
1463 return iterator( it );
1464 }
1465 break;
1466 case objectValue:
1467 if ( value_.map_ )
1468 {
1469 ValueInternalMap::IteratorState it;
1470 value_.map_->makeBeginIterator( it );
1471 return iterator( it );
1472 }
1473 break;
1474#else
1475 case arrayValue:
1476 case objectValue:
1477 if ( value_.map_ )
1478 return iterator( value_.map_->begin() );
1479 break;
1480#endif
1481 default:
1482 break;
1483 }
1484 return iterator();
1485}
1486
Tobias Grosser20532b82014-04-11 17:56:49 +00001487Value::iterator
Tobias Grosser75805372011-04-29 06:27:02 +00001488Value::end()
1489{
1490 switch ( type_ )
1491 {
1492#ifdef JSON_VALUE_USE_INTERNAL_MAP
1493 case arrayValue:
1494 if ( value_.array_ )
1495 {
1496 ValueInternalArray::IteratorState it;
1497 value_.array_->makeEndIterator( it );
1498 return iterator( it );
1499 }
1500 break;
1501 case objectValue:
1502 if ( value_.map_ )
1503 {
1504 ValueInternalMap::IteratorState it;
1505 value_.map_->makeEndIterator( it );
1506 return iterator( it );
1507 }
1508 break;
1509#else
1510 case arrayValue:
1511 case objectValue:
1512 if ( value_.map_ )
1513 return iterator( value_.map_->end() );
1514 break;
1515#endif
1516 default:
1517 break;
1518 }
1519 return iterator();
1520}
1521
1522
1523// class PathArgument
1524// //////////////////////////////////////////////////////////////////
1525
1526PathArgument::PathArgument()
1527 : kind_( kindNone )
1528{
1529}
1530
1531
1532PathArgument::PathArgument( Value::UInt index )
1533 : index_( index )
1534 , kind_( kindIndex )
1535{
1536}
1537
1538
1539PathArgument::PathArgument( const char *key )
1540 : key_( key )
1541 , kind_( kindKey )
1542{
1543}
1544
1545
1546PathArgument::PathArgument( const std::string &key )
1547 : key_( key.c_str() )
1548 , kind_( kindKey )
1549{
1550}
1551
1552// class Path
1553// //////////////////////////////////////////////////////////////////
1554
1555Path::Path( const std::string &path,
1556 const PathArgument &a1,
1557 const PathArgument &a2,
1558 const PathArgument &a3,
1559 const PathArgument &a4,
1560 const PathArgument &a5 )
1561{
1562 InArgs in;
1563 in.push_back( &a1 );
1564 in.push_back( &a2 );
1565 in.push_back( &a3 );
1566 in.push_back( &a4 );
1567 in.push_back( &a5 );
1568 makePath( path, in );
1569}
1570
1571
Tobias Grosser20532b82014-04-11 17:56:49 +00001572void
Tobias Grosser75805372011-04-29 06:27:02 +00001573Path::makePath( const std::string &path,
1574 const InArgs &in )
1575{
1576 const char *current = path.c_str();
1577 const char *end = current + path.length();
1578 InArgs::const_iterator itInArg = in.begin();
1579 while ( current != end )
1580 {
1581 if ( *current == '[' )
1582 {
1583 ++current;
1584 if ( *current == '%' )
1585 addPathInArg( path, in, itInArg, PathArgument::kindIndex );
1586 else
1587 {
1588 Value::UInt index = 0;
1589 for ( ; current != end && *current >= '0' && *current <= '9'; ++current )
1590 index = index * 10 + Value::UInt(*current - '0');
1591 args_.push_back( index );
1592 }
1593 if ( current == end || *current++ != ']' )
1594 invalidPath( path, int(current - path.c_str()) );
1595 }
1596 else if ( *current == '%' )
1597 {
1598 addPathInArg( path, in, itInArg, PathArgument::kindKey );
1599 ++current;
1600 }
1601 else if ( *current == '.' )
1602 {
1603 ++current;
1604 }
1605 else
1606 {
1607 const char *beginName = current;
1608 while ( current != end && !strchr( "[.", *current ) )
1609 ++current;
1610 args_.push_back( std::string( beginName, current ) );
1611 }
1612 }
1613}
1614
1615
Tobias Grosser20532b82014-04-11 17:56:49 +00001616void
1617Path::addPathInArg( const std::string &path,
1618 const InArgs &in,
1619 InArgs::const_iterator &itInArg,
Tobias Grosser75805372011-04-29 06:27:02 +00001620 PathArgument::Kind kind )
1621{
1622 if ( itInArg == in.end() )
1623 {
1624 // Error: missing argument %d
1625 }
1626 else if ( (*itInArg)->kind_ != kind )
1627 {
1628 // Error: bad argument type
1629 }
1630 else
1631 {
1632 args_.push_back( **itInArg );
1633 }
1634}
1635
1636
Tobias Grosser20532b82014-04-11 17:56:49 +00001637void
1638Path::invalidPath( const std::string &path,
Tobias Grosser75805372011-04-29 06:27:02 +00001639 int location )
1640{
1641 // Error: invalid path.
1642}
1643
1644
1645const Value &
1646Path::resolve( const Value &root ) const
1647{
1648 const Value *node = &root;
1649 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1650 {
1651 const PathArgument &arg = *it;
1652 if ( arg.kind_ == PathArgument::kindIndex )
1653 {
1654 if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
1655 {
1656 // Error: unable to resolve path (array value expected at position...
1657 }
1658 node = &((*node)[arg.index_]);
1659 }
1660 else if ( arg.kind_ == PathArgument::kindKey )
1661 {
1662 if ( !node->isObject() )
1663 {
1664 // Error: unable to resolve path (object value expected at position...)
1665 }
1666 node = &((*node)[arg.key_]);
1667 if ( node == &Value::null )
1668 {
1669 // Error: unable to resolve path (object has no member named '' at position...)
1670 }
1671 }
1672 }
1673 return *node;
1674}
1675
1676
Tobias Grosser20532b82014-04-11 17:56:49 +00001677Value
1678Path::resolve( const Value &root,
Tobias Grosser75805372011-04-29 06:27:02 +00001679 const Value &defaultValue ) const
1680{
1681 const Value *node = &root;
1682 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1683 {
1684 const PathArgument &arg = *it;
1685 if ( arg.kind_ == PathArgument::kindIndex )
1686 {
1687 if ( !node->isArray() || node->isValidIndex( arg.index_ ) )
1688 return defaultValue;
1689 node = &((*node)[arg.index_]);
1690 }
1691 else if ( arg.kind_ == PathArgument::kindKey )
1692 {
1693 if ( !node->isObject() )
1694 return defaultValue;
1695 node = &((*node)[arg.key_]);
1696 if ( node == &Value::null )
1697 return defaultValue;
1698 }
1699 }
1700 return *node;
1701}
1702
1703
1704Value &
1705Path::make( Value &root ) const
1706{
1707 Value *node = &root;
1708 for ( Args::const_iterator it = args_.begin(); it != args_.end(); ++it )
1709 {
1710 const PathArgument &arg = *it;
1711 if ( arg.kind_ == PathArgument::kindIndex )
1712 {
1713 if ( !node->isArray() )
1714 {
1715 // Error: node is not an array at position ...
1716 }
1717 node = &((*node)[arg.index_]);
1718 }
1719 else if ( arg.kind_ == PathArgument::kindKey )
1720 {
1721 if ( !node->isObject() )
1722 {
1723 // Error: node is not an object at position...
1724 }
1725 node = &((*node)[arg.key_]);
1726 }
1727 }
1728 return *node;
1729}
1730
1731
1732} // namespace Json