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