Mercurial > hg > gpsynth
comparison third_party/json/value.h @ 0:add35537fdbb tip
Initial import
author | irh <ian.r.hobson@gmail.com> |
---|---|
date | Thu, 25 Aug 2011 11:05:55 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:add35537fdbb |
---|---|
1 // Copyright 2007-2010 Baptiste Lepilleur | |
2 // Distributed under MIT license, or public domain if desired and | |
3 // recognized in your jurisdiction. | |
4 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE | |
5 | |
6 #ifndef CPPTL_JSON_H_INCLUDED | |
7 # define CPPTL_JSON_H_INCLUDED | |
8 | |
9 #if !defined(JSON_IS_AMALGAMATION) | |
10 # include "forwards.h" | |
11 #endif // if !defined(JSON_IS_AMALGAMATION) | |
12 # include <string> | |
13 # include <vector> | |
14 | |
15 # ifndef JSON_USE_CPPTL_SMALLMAP | |
16 # include <map> | |
17 # else | |
18 # include <cpptl/smallmap.h> | |
19 # endif | |
20 # ifdef JSON_USE_CPPTL | |
21 # include <cpptl/forwards.h> | |
22 # endif | |
23 | |
24 /** \brief JSON (JavaScript Object Notation). | |
25 */ | |
26 namespace Json { | |
27 | |
28 /** \brief Type of the value held by a Value object. | |
29 */ | |
30 enum ValueType | |
31 { | |
32 nullValue = 0, ///< 'null' value | |
33 intValue, ///< signed integer value | |
34 uintValue, ///< unsigned integer value | |
35 realValue, ///< double value | |
36 stringValue, ///< UTF-8 string value | |
37 booleanValue, ///< bool value | |
38 arrayValue, ///< array value (ordered list) | |
39 objectValue ///< object value (collection of name/value pairs). | |
40 }; | |
41 | |
42 enum CommentPlacement | |
43 { | |
44 commentBefore = 0, ///< a comment placed on the line before a value | |
45 commentAfterOnSameLine, ///< a comment just after a value on the same line | |
46 commentAfter, ///< a comment on the line after a value (only make sense for root value) | |
47 numberOfCommentPlacement | |
48 }; | |
49 | |
50 //# ifdef JSON_USE_CPPTL | |
51 // typedef CppTL::AnyEnumerator<const char *> EnumMemberNames; | |
52 // typedef CppTL::AnyEnumerator<const Value &> EnumValues; | |
53 //# endif | |
54 | |
55 /** \brief Lightweight wrapper to tag static string. | |
56 * | |
57 * Value constructor and objectValue member assignement takes advantage of the | |
58 * StaticString and avoid the cost of string duplication when storing the | |
59 * string or the member name. | |
60 * | |
61 * Example of usage: | |
62 * \code | |
63 * Json::Value aValue( StaticString("some text") ); | |
64 * Json::Value object; | |
65 * static const StaticString code("code"); | |
66 * object[code] = 1234; | |
67 * \endcode | |
68 */ | |
69 class JSON_API StaticString | |
70 { | |
71 public: | |
72 explicit StaticString( const char *czstring ) | |
73 : str_( czstring ) | |
74 { | |
75 } | |
76 | |
77 operator const char *() const | |
78 { | |
79 return str_; | |
80 } | |
81 | |
82 const char *c_str() const | |
83 { | |
84 return str_; | |
85 } | |
86 | |
87 private: | |
88 const char *str_; | |
89 }; | |
90 | |
91 /** \brief Represents a <a HREF="http://www.json.org">JSON</a> value. | |
92 * | |
93 * This class is a discriminated union wrapper that can represents a: | |
94 * - signed integer [range: Value::minInt - Value::maxInt] | |
95 * - unsigned integer (range: 0 - Value::maxUInt) | |
96 * - double | |
97 * - UTF-8 string | |
98 * - boolean | |
99 * - 'null' | |
100 * - an ordered list of Value | |
101 * - collection of name/value pairs (javascript object) | |
102 * | |
103 * The type of the held value is represented by a #ValueType and | |
104 * can be obtained using type(). | |
105 * | |
106 * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. | |
107 * Non const methods will automatically create the a #nullValue element | |
108 * if it does not exist. | |
109 * The sequence of an #arrayValue will be automatically resize and initialized | |
110 * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. | |
111 * | |
112 * The get() methods can be used to obtanis default value in the case the required element | |
113 * does not exist. | |
114 * | |
115 * It is possible to iterate over the list of a #objectValue values using | |
116 * the getMemberNames() method. | |
117 */ | |
118 class JSON_API Value | |
119 { | |
120 friend class ValueIteratorBase; | |
121 # ifdef JSON_VALUE_USE_INTERNAL_MAP | |
122 friend class ValueInternalLink; | |
123 friend class ValueInternalMap; | |
124 # endif | |
125 public: | |
126 typedef std::vector<std::string> Members; | |
127 typedef ValueIterator iterator; | |
128 typedef ValueConstIterator const_iterator; | |
129 typedef Json::UInt UInt; | |
130 typedef Json::Int Int; | |
131 # if defined(JSON_HAS_INT64) | |
132 typedef Json::UInt64 UInt64; | |
133 typedef Json::Int64 Int64; | |
134 #endif // defined(JSON_HAS_INT64) | |
135 typedef Json::LargestInt LargestInt; | |
136 typedef Json::LargestUInt LargestUInt; | |
137 typedef Json::ArrayIndex ArrayIndex; | |
138 | |
139 static const Value null; | |
140 /// Minimum signed integer value that can be stored in a Json::Value. | |
141 static const LargestInt minLargestInt; | |
142 /// Maximum signed integer value that can be stored in a Json::Value. | |
143 static const LargestInt maxLargestInt; | |
144 /// Maximum unsigned integer value that can be stored in a Json::Value. | |
145 static const LargestUInt maxLargestUInt; | |
146 | |
147 /// Minimum signed int value that can be stored in a Json::Value. | |
148 static const Int minInt; | |
149 /// Maximum signed int value that can be stored in a Json::Value. | |
150 static const Int maxInt; | |
151 /// Maximum unsigned int value that can be stored in a Json::Value. | |
152 static const UInt maxUInt; | |
153 | |
154 # if defined(JSON_HAS_INT64) | |
155 /// Minimum signed 64 bits int value that can be stored in a Json::Value. | |
156 static const Int64 minInt64; | |
157 /// Maximum signed 64 bits int value that can be stored in a Json::Value. | |
158 static const Int64 maxInt64; | |
159 /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. | |
160 static const UInt64 maxUInt64; | |
161 #endif // defined(JSON_HAS_INT64) | |
162 | |
163 private: | |
164 #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
165 # ifndef JSON_VALUE_USE_INTERNAL_MAP | |
166 class CZString | |
167 { | |
168 public: | |
169 enum DuplicationPolicy | |
170 { | |
171 noDuplication = 0, | |
172 duplicate, | |
173 duplicateOnCopy | |
174 }; | |
175 CZString( ArrayIndex index ); | |
176 CZString( const char *cstr, DuplicationPolicy allocate ); | |
177 CZString( const CZString &other ); | |
178 ~CZString(); | |
179 CZString &operator =( const CZString &other ); | |
180 bool operator<( const CZString &other ) const; | |
181 bool operator==( const CZString &other ) const; | |
182 ArrayIndex index() const; | |
183 const char *c_str() const; | |
184 bool isStaticString() const; | |
185 private: | |
186 void swap( CZString &other ); | |
187 const char *cstr_; | |
188 ArrayIndex index_; | |
189 }; | |
190 | |
191 public: | |
192 # ifndef JSON_USE_CPPTL_SMALLMAP | |
193 typedef std::map<CZString, Value> ObjectValues; | |
194 # else | |
195 typedef CppTL::SmallMap<CZString, Value> ObjectValues; | |
196 # endif // ifndef JSON_USE_CPPTL_SMALLMAP | |
197 # endif // ifndef JSON_VALUE_USE_INTERNAL_MAP | |
198 #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
199 | |
200 public: | |
201 /** \brief Create a default Value of the given type. | |
202 | |
203 This is a very useful constructor. | |
204 To create an empty array, pass arrayValue. | |
205 To create an empty object, pass objectValue. | |
206 Another Value can then be set to this one by assignment. | |
207 This is useful since clear() and resize() will not alter types. | |
208 | |
209 Examples: | |
210 \code | |
211 Json::Value null_value; // null | |
212 Json::Value arr_value(Json::arrayValue); // [] | |
213 Json::Value obj_value(Json::objectValue); // {} | |
214 \endcode | |
215 */ | |
216 Value( ValueType type = nullValue ); | |
217 Value( Int value ); | |
218 Value( UInt value ); | |
219 #if defined(JSON_HAS_INT64) | |
220 Value( Int64 value ); | |
221 Value( UInt64 value ); | |
222 #endif // if defined(JSON_HAS_INT64) | |
223 Value( double value ); | |
224 Value( const char *value ); | |
225 Value( const char *beginValue, const char *endValue ); | |
226 /** \brief Constructs a value from a static string. | |
227 | |
228 * Like other value string constructor but do not duplicate the string for | |
229 * internal storage. The given string must remain alive after the call to this | |
230 * constructor. | |
231 * Example of usage: | |
232 * \code | |
233 * Json::Value aValue( StaticString("some text") ); | |
234 * \endcode | |
235 */ | |
236 Value( const StaticString &value ); | |
237 Value( const std::string &value ); | |
238 # ifdef JSON_USE_CPPTL | |
239 Value( const CppTL::ConstString &value ); | |
240 # endif | |
241 Value( bool value ); | |
242 Value( const Value &other ); | |
243 ~Value(); | |
244 | |
245 Value &operator=( const Value &other ); | |
246 /// Swap values. | |
247 /// \note Currently, comments are intentionally not swapped, for | |
248 /// both logic and efficiency. | |
249 void swap( Value &other ); | |
250 | |
251 ValueType type() const; | |
252 | |
253 bool operator <( const Value &other ) const; | |
254 bool operator <=( const Value &other ) const; | |
255 bool operator >=( const Value &other ) const; | |
256 bool operator >( const Value &other ) const; | |
257 | |
258 bool operator ==( const Value &other ) const; | |
259 bool operator !=( const Value &other ) const; | |
260 | |
261 int compare( const Value &other ) const; | |
262 | |
263 const char *asCString() const; | |
264 std::string asString() const; | |
265 # ifdef JSON_USE_CPPTL | |
266 CppTL::ConstString asConstString() const; | |
267 # endif | |
268 Int asInt() const; | |
269 UInt asUInt() const; | |
270 #if defined(JSON_HAS_INT64) | |
271 Int64 asInt64() const; | |
272 UInt64 asUInt64() const; | |
273 #endif // if defined(JSON_HAS_INT64) | |
274 LargestInt asLargestInt() const; | |
275 LargestUInt asLargestUInt() const; | |
276 float asFloat() const; | |
277 double asDouble() const; | |
278 bool asBool() const; | |
279 | |
280 bool isNull() const; | |
281 bool isBool() const; | |
282 bool isInt() const; | |
283 bool isInt64() const; | |
284 bool isUInt() const; | |
285 bool isUInt64() const; | |
286 bool isIntegral() const; | |
287 bool isDouble() const; | |
288 bool isNumeric() const; | |
289 bool isString() const; | |
290 bool isArray() const; | |
291 bool isObject() const; | |
292 | |
293 bool isConvertibleTo( ValueType other ) const; | |
294 | |
295 /// Number of values in array or object | |
296 ArrayIndex size() const; | |
297 | |
298 /// \brief Return true if empty array, empty object, or null; | |
299 /// otherwise, false. | |
300 bool empty() const; | |
301 | |
302 /// Return isNull() | |
303 bool operator!() const; | |
304 | |
305 /// Remove all object members and array elements. | |
306 /// \pre type() is arrayValue, objectValue, or nullValue | |
307 /// \post type() is unchanged | |
308 void clear(); | |
309 | |
310 /// Resize the array to size elements. | |
311 /// New elements are initialized to null. | |
312 /// May only be called on nullValue or arrayValue. | |
313 /// \pre type() is arrayValue or nullValue | |
314 /// \post type() is arrayValue | |
315 void resize( ArrayIndex size ); | |
316 | |
317 /// Access an array element (zero based index ). | |
318 /// If the array contains less than index element, then null value are inserted | |
319 /// in the array so that its size is index+1. | |
320 /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
321 /// this from the operator[] which takes a string.) | |
322 Value &operator[]( ArrayIndex index ); | |
323 | |
324 /// Access an array element (zero based index ). | |
325 /// If the array contains less than index element, then null value are inserted | |
326 /// in the array so that its size is index+1. | |
327 /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
328 /// this from the operator[] which takes a string.) | |
329 Value &operator[]( int index ); | |
330 | |
331 /// Access an array element (zero based index ) | |
332 /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
333 /// this from the operator[] which takes a string.) | |
334 const Value &operator[]( ArrayIndex index ) const; | |
335 | |
336 /// Access an array element (zero based index ) | |
337 /// (You may need to say 'value[0u]' to get your compiler to distinguish | |
338 /// this from the operator[] which takes a string.) | |
339 const Value &operator[]( int index ) const; | |
340 | |
341 /// If the array contains at least index+1 elements, returns the element value, | |
342 /// otherwise returns defaultValue. | |
343 Value get( ArrayIndex index, | |
344 const Value &defaultValue ) const; | |
345 /// Return true if index < size(). | |
346 bool isValidIndex( ArrayIndex index ) const; | |
347 /// \brief Append value to array at the end. | |
348 /// | |
349 /// Equivalent to jsonvalue[jsonvalue.size()] = value; | |
350 Value &append( const Value &value ); | |
351 | |
352 /// Access an object value by name, create a null member if it does not exist. | |
353 Value &operator[]( const char *key ); | |
354 /// Access an object value by name, returns null if there is no member with that name. | |
355 const Value &operator[]( const char *key ) const; | |
356 /// Access an object value by name, create a null member if it does not exist. | |
357 Value &operator[]( const std::string &key ); | |
358 /// Access an object value by name, returns null if there is no member with that name. | |
359 const Value &operator[]( const std::string &key ) const; | |
360 /** \brief Access an object value by name, create a null member if it does not exist. | |
361 | |
362 * If the object as no entry for that name, then the member name used to store | |
363 * the new entry is not duplicated. | |
364 * Example of use: | |
365 * \code | |
366 * Json::Value object; | |
367 * static const StaticString code("code"); | |
368 * object[code] = 1234; | |
369 * \endcode | |
370 */ | |
371 Value &operator[]( const StaticString &key ); | |
372 # ifdef JSON_USE_CPPTL | |
373 /// Access an object value by name, create a null member if it does not exist. | |
374 Value &operator[]( const CppTL::ConstString &key ); | |
375 /// Access an object value by name, returns null if there is no member with that name. | |
376 const Value &operator[]( const CppTL::ConstString &key ) const; | |
377 # endif | |
378 /// Return the member named key if it exist, defaultValue otherwise. | |
379 Value get( const char *key, | |
380 const Value &defaultValue ) const; | |
381 /// Return the member named key if it exist, defaultValue otherwise. | |
382 Value get( const std::string &key, | |
383 const Value &defaultValue ) const; | |
384 # ifdef JSON_USE_CPPTL | |
385 /// Return the member named key if it exist, defaultValue otherwise. | |
386 Value get( const CppTL::ConstString &key, | |
387 const Value &defaultValue ) const; | |
388 # endif | |
389 /// \brief Remove and return the named member. | |
390 /// | |
391 /// Do nothing if it did not exist. | |
392 /// \return the removed Value, or null. | |
393 /// \pre type() is objectValue or nullValue | |
394 /// \post type() is unchanged | |
395 Value removeMember( const char* key ); | |
396 /// Same as removeMember(const char*) | |
397 Value removeMember( const std::string &key ); | |
398 | |
399 /// Return true if the object has a member named key. | |
400 bool isMember( const char *key ) const; | |
401 /// Return true if the object has a member named key. | |
402 bool isMember( const std::string &key ) const; | |
403 # ifdef JSON_USE_CPPTL | |
404 /// Return true if the object has a member named key. | |
405 bool isMember( const CppTL::ConstString &key ) const; | |
406 # endif | |
407 | |
408 /// \brief Return a list of the member names. | |
409 /// | |
410 /// If null, return an empty list. | |
411 /// \pre type() is objectValue or nullValue | |
412 /// \post if type() was nullValue, it remains nullValue | |
413 Members getMemberNames() const; | |
414 | |
415 //# ifdef JSON_USE_CPPTL | |
416 // EnumMemberNames enumMemberNames() const; | |
417 // EnumValues enumValues() const; | |
418 //# endif | |
419 | |
420 /// Comments must be //... or /* ... */ | |
421 void setComment( const char *comment, | |
422 CommentPlacement placement ); | |
423 /// Comments must be //... or /* ... */ | |
424 void setComment( const std::string &comment, | |
425 CommentPlacement placement ); | |
426 bool hasComment( CommentPlacement placement ) const; | |
427 /// Include delimiters and embedded newlines. | |
428 std::string getComment( CommentPlacement placement ) const; | |
429 | |
430 std::string toStyledString() const; | |
431 | |
432 const_iterator begin() const; | |
433 const_iterator end() const; | |
434 | |
435 iterator begin(); | |
436 iterator end(); | |
437 | |
438 private: | |
439 Value &resolveReference( const char *key, | |
440 bool isStatic ); | |
441 | |
442 # ifdef JSON_VALUE_USE_INTERNAL_MAP | |
443 inline bool isItemAvailable() const | |
444 { | |
445 return itemIsUsed_ == 0; | |
446 } | |
447 | |
448 inline void setItemUsed( bool isUsed = true ) | |
449 { | |
450 itemIsUsed_ = isUsed ? 1 : 0; | |
451 } | |
452 | |
453 inline bool isMemberNameStatic() const | |
454 { | |
455 return memberNameIsStatic_ == 0; | |
456 } | |
457 | |
458 inline void setMemberNameIsStatic( bool isStatic ) | |
459 { | |
460 memberNameIsStatic_ = isStatic ? 1 : 0; | |
461 } | |
462 # endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP | |
463 | |
464 private: | |
465 struct CommentInfo | |
466 { | |
467 CommentInfo(); | |
468 ~CommentInfo(); | |
469 | |
470 void setComment( const char *text ); | |
471 | |
472 char *comment_; | |
473 }; | |
474 | |
475 //struct MemberNamesTransform | |
476 //{ | |
477 // typedef const char *result_type; | |
478 // const char *operator()( const CZString &name ) const | |
479 // { | |
480 // return name.c_str(); | |
481 // } | |
482 //}; | |
483 | |
484 union ValueHolder | |
485 { | |
486 LargestInt int_; | |
487 LargestUInt uint_; | |
488 double real_; | |
489 bool bool_; | |
490 char *string_; | |
491 # ifdef JSON_VALUE_USE_INTERNAL_MAP | |
492 ValueInternalArray *array_; | |
493 ValueInternalMap *map_; | |
494 #else | |
495 ObjectValues *map_; | |
496 # endif | |
497 } value_; | |
498 ValueType type_ : 8; | |
499 int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. | |
500 # ifdef JSON_VALUE_USE_INTERNAL_MAP | |
501 unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. | |
502 int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. | |
503 # endif | |
504 CommentInfo *comments_; | |
505 }; | |
506 | |
507 | |
508 /** \brief Experimental and untested: represents an element of the "path" to access a node. | |
509 */ | |
510 class PathArgument | |
511 { | |
512 public: | |
513 friend class Path; | |
514 | |
515 PathArgument(); | |
516 PathArgument( ArrayIndex index ); | |
517 PathArgument( const char *key ); | |
518 PathArgument( const std::string &key ); | |
519 | |
520 private: | |
521 enum Kind | |
522 { | |
523 kindNone = 0, | |
524 kindIndex, | |
525 kindKey | |
526 }; | |
527 std::string key_; | |
528 ArrayIndex index_; | |
529 Kind kind_; | |
530 }; | |
531 | |
532 /** \brief Experimental and untested: represents a "path" to access a node. | |
533 * | |
534 * Syntax: | |
535 * - "." => root node | |
536 * - ".[n]" => elements at index 'n' of root node (an array value) | |
537 * - ".name" => member named 'name' of root node (an object value) | |
538 * - ".name1.name2.name3" | |
539 * - ".[0][1][2].name1[3]" | |
540 * - ".%" => member name is provided as parameter | |
541 * - ".[%]" => index is provied as parameter | |
542 */ | |
543 class Path | |
544 { | |
545 public: | |
546 Path( const std::string &path, | |
547 const PathArgument &a1 = PathArgument(), | |
548 const PathArgument &a2 = PathArgument(), | |
549 const PathArgument &a3 = PathArgument(), | |
550 const PathArgument &a4 = PathArgument(), | |
551 const PathArgument &a5 = PathArgument() ); | |
552 | |
553 const Value &resolve( const Value &root ) const; | |
554 Value resolve( const Value &root, | |
555 const Value &defaultValue ) const; | |
556 /// Creates the "path" to access the specified node and returns a reference on the node. | |
557 Value &make( Value &root ) const; | |
558 | |
559 private: | |
560 typedef std::vector<const PathArgument *> InArgs; | |
561 typedef std::vector<PathArgument> Args; | |
562 | |
563 void makePath( const std::string &path, | |
564 const InArgs &in ); | |
565 void addPathInArg( const std::string &path, | |
566 const InArgs &in, | |
567 InArgs::const_iterator &itInArg, | |
568 PathArgument::Kind kind ); | |
569 void invalidPath( const std::string &path, | |
570 int location ); | |
571 | |
572 Args args_; | |
573 }; | |
574 | |
575 | |
576 | |
577 #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
578 /** \brief Allocator to customize Value internal map. | |
579 * Below is an example of a simple implementation (default implementation actually | |
580 * use memory pool for speed). | |
581 * \code | |
582 class DefaultValueMapAllocator : public ValueMapAllocator | |
583 { | |
584 public: // overridden from ValueMapAllocator | |
585 virtual ValueInternalMap *newMap() | |
586 { | |
587 return new ValueInternalMap(); | |
588 } | |
589 | |
590 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) | |
591 { | |
592 return new ValueInternalMap( other ); | |
593 } | |
594 | |
595 virtual void destructMap( ValueInternalMap *map ) | |
596 { | |
597 delete map; | |
598 } | |
599 | |
600 virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) | |
601 { | |
602 return new ValueInternalLink[size]; | |
603 } | |
604 | |
605 virtual void releaseMapBuckets( ValueInternalLink *links ) | |
606 { | |
607 delete [] links; | |
608 } | |
609 | |
610 virtual ValueInternalLink *allocateMapLink() | |
611 { | |
612 return new ValueInternalLink(); | |
613 } | |
614 | |
615 virtual void releaseMapLink( ValueInternalLink *link ) | |
616 { | |
617 delete link; | |
618 } | |
619 }; | |
620 * \endcode | |
621 */ | |
622 class JSON_API ValueMapAllocator | |
623 { | |
624 public: | |
625 virtual ~ValueMapAllocator(); | |
626 virtual ValueInternalMap *newMap() = 0; | |
627 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; | |
628 virtual void destructMap( ValueInternalMap *map ) = 0; | |
629 virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; | |
630 virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; | |
631 virtual ValueInternalLink *allocateMapLink() = 0; | |
632 virtual void releaseMapLink( ValueInternalLink *link ) = 0; | |
633 }; | |
634 | |
635 /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). | |
636 * \internal previous_ & next_ allows for bidirectional traversal. | |
637 */ | |
638 class JSON_API ValueInternalLink | |
639 { | |
640 public: | |
641 enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. | |
642 enum InternalFlags { | |
643 flagAvailable = 0, | |
644 flagUsed = 1 | |
645 }; | |
646 | |
647 ValueInternalLink(); | |
648 | |
649 ~ValueInternalLink(); | |
650 | |
651 Value items_[itemPerLink]; | |
652 char *keys_[itemPerLink]; | |
653 ValueInternalLink *previous_; | |
654 ValueInternalLink *next_; | |
655 }; | |
656 | |
657 | |
658 /** \brief A linked page based hash-table implementation used internally by Value. | |
659 * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked | |
660 * list in each bucket to handle collision. There is an addional twist in that | |
661 * each node of the collision linked list is a page containing a fixed amount of | |
662 * value. This provides a better compromise between memory usage and speed. | |
663 * | |
664 * Each bucket is made up of a chained list of ValueInternalLink. The last | |
665 * link of a given bucket can be found in the 'previous_' field of the following bucket. | |
666 * The last link of the last bucket is stored in tailLink_ as it has no following bucket. | |
667 * Only the last link of a bucket may contains 'available' item. The last link always | |
668 * contains at least one element unless is it the bucket one very first link. | |
669 */ | |
670 class JSON_API ValueInternalMap | |
671 { | |
672 friend class ValueIteratorBase; | |
673 friend class Value; | |
674 public: | |
675 typedef unsigned int HashKey; | |
676 typedef unsigned int BucketIndex; | |
677 | |
678 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
679 struct IteratorState | |
680 { | |
681 IteratorState() | |
682 : map_(0) | |
683 , link_(0) | |
684 , itemIndex_(0) | |
685 , bucketIndex_(0) | |
686 { | |
687 } | |
688 ValueInternalMap *map_; | |
689 ValueInternalLink *link_; | |
690 BucketIndex itemIndex_; | |
691 BucketIndex bucketIndex_; | |
692 }; | |
693 # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
694 | |
695 ValueInternalMap(); | |
696 ValueInternalMap( const ValueInternalMap &other ); | |
697 ValueInternalMap &operator =( const ValueInternalMap &other ); | |
698 ~ValueInternalMap(); | |
699 | |
700 void swap( ValueInternalMap &other ); | |
701 | |
702 BucketIndex size() const; | |
703 | |
704 void clear(); | |
705 | |
706 bool reserveDelta( BucketIndex growth ); | |
707 | |
708 bool reserve( BucketIndex newItemCount ); | |
709 | |
710 const Value *find( const char *key ) const; | |
711 | |
712 Value *find( const char *key ); | |
713 | |
714 Value &resolveReference( const char *key, | |
715 bool isStatic ); | |
716 | |
717 void remove( const char *key ); | |
718 | |
719 void doActualRemove( ValueInternalLink *link, | |
720 BucketIndex index, | |
721 BucketIndex bucketIndex ); | |
722 | |
723 ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); | |
724 | |
725 Value &setNewItem( const char *key, | |
726 bool isStatic, | |
727 ValueInternalLink *link, | |
728 BucketIndex index ); | |
729 | |
730 Value &unsafeAdd( const char *key, | |
731 bool isStatic, | |
732 HashKey hashedKey ); | |
733 | |
734 HashKey hash( const char *key ) const; | |
735 | |
736 int compare( const ValueInternalMap &other ) const; | |
737 | |
738 private: | |
739 void makeBeginIterator( IteratorState &it ) const; | |
740 void makeEndIterator( IteratorState &it ) const; | |
741 static bool equals( const IteratorState &x, const IteratorState &other ); | |
742 static void increment( IteratorState &iterator ); | |
743 static void incrementBucket( IteratorState &iterator ); | |
744 static void decrement( IteratorState &iterator ); | |
745 static const char *key( const IteratorState &iterator ); | |
746 static const char *key( const IteratorState &iterator, bool &isStatic ); | |
747 static Value &value( const IteratorState &iterator ); | |
748 static int distance( const IteratorState &x, const IteratorState &y ); | |
749 | |
750 private: | |
751 ValueInternalLink *buckets_; | |
752 ValueInternalLink *tailLink_; | |
753 BucketIndex bucketsSize_; | |
754 BucketIndex itemCount_; | |
755 }; | |
756 | |
757 /** \brief A simplified deque implementation used internally by Value. | |
758 * \internal | |
759 * It is based on a list of fixed "page", each page contains a fixed number of items. | |
760 * Instead of using a linked-list, a array of pointer is used for fast item look-up. | |
761 * Look-up for an element is as follow: | |
762 * - compute page index: pageIndex = itemIndex / itemsPerPage | |
763 * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] | |
764 * | |
765 * Insertion is amortized constant time (only the array containing the index of pointers | |
766 * need to be reallocated when items are appended). | |
767 */ | |
768 class JSON_API ValueInternalArray | |
769 { | |
770 friend class Value; | |
771 friend class ValueIteratorBase; | |
772 public: | |
773 enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. | |
774 typedef Value::ArrayIndex ArrayIndex; | |
775 typedef unsigned int PageIndex; | |
776 | |
777 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
778 struct IteratorState // Must be a POD | |
779 { | |
780 IteratorState() | |
781 : array_(0) | |
782 , currentPageIndex_(0) | |
783 , currentItemIndex_(0) | |
784 { | |
785 } | |
786 ValueInternalArray *array_; | |
787 Value **currentPageIndex_; | |
788 unsigned int currentItemIndex_; | |
789 }; | |
790 # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION | |
791 | |
792 ValueInternalArray(); | |
793 ValueInternalArray( const ValueInternalArray &other ); | |
794 ValueInternalArray &operator =( const ValueInternalArray &other ); | |
795 ~ValueInternalArray(); | |
796 void swap( ValueInternalArray &other ); | |
797 | |
798 void clear(); | |
799 void resize( ArrayIndex newSize ); | |
800 | |
801 Value &resolveReference( ArrayIndex index ); | |
802 | |
803 Value *find( ArrayIndex index ) const; | |
804 | |
805 ArrayIndex size() const; | |
806 | |
807 int compare( const ValueInternalArray &other ) const; | |
808 | |
809 private: | |
810 static bool equals( const IteratorState &x, const IteratorState &other ); | |
811 static void increment( IteratorState &iterator ); | |
812 static void decrement( IteratorState &iterator ); | |
813 static Value &dereference( const IteratorState &iterator ); | |
814 static Value &unsafeDereference( const IteratorState &iterator ); | |
815 static int distance( const IteratorState &x, const IteratorState &y ); | |
816 static ArrayIndex indexOf( const IteratorState &iterator ); | |
817 void makeBeginIterator( IteratorState &it ) const; | |
818 void makeEndIterator( IteratorState &it ) const; | |
819 void makeIterator( IteratorState &it, ArrayIndex index ) const; | |
820 | |
821 void makeIndexValid( ArrayIndex index ); | |
822 | |
823 Value **pages_; | |
824 ArrayIndex size_; | |
825 PageIndex pageCount_; | |
826 }; | |
827 | |
828 /** \brief Experimental: do not use. Allocator to customize Value internal array. | |
829 * Below is an example of a simple implementation (actual implementation use | |
830 * memory pool). | |
831 \code | |
832 class DefaultValueArrayAllocator : public ValueArrayAllocator | |
833 { | |
834 public: // overridden from ValueArrayAllocator | |
835 virtual ~DefaultValueArrayAllocator() | |
836 { | |
837 } | |
838 | |
839 virtual ValueInternalArray *newArray() | |
840 { | |
841 return new ValueInternalArray(); | |
842 } | |
843 | |
844 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) | |
845 { | |
846 return new ValueInternalArray( other ); | |
847 } | |
848 | |
849 virtual void destruct( ValueInternalArray *array ) | |
850 { | |
851 delete array; | |
852 } | |
853 | |
854 virtual void reallocateArrayPageIndex( Value **&indexes, | |
855 ValueInternalArray::PageIndex &indexCount, | |
856 ValueInternalArray::PageIndex minNewIndexCount ) | |
857 { | |
858 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; | |
859 if ( minNewIndexCount > newIndexCount ) | |
860 newIndexCount = minNewIndexCount; | |
861 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); | |
862 if ( !newIndexes ) | |
863 throw std::bad_alloc(); | |
864 indexCount = newIndexCount; | |
865 indexes = static_cast<Value **>( newIndexes ); | |
866 } | |
867 virtual void releaseArrayPageIndex( Value **indexes, | |
868 ValueInternalArray::PageIndex indexCount ) | |
869 { | |
870 if ( indexes ) | |
871 free( indexes ); | |
872 } | |
873 | |
874 virtual Value *allocateArrayPage() | |
875 { | |
876 return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); | |
877 } | |
878 | |
879 virtual void releaseArrayPage( Value *value ) | |
880 { | |
881 if ( value ) | |
882 free( value ); | |
883 } | |
884 }; | |
885 \endcode | |
886 */ | |
887 class JSON_API ValueArrayAllocator | |
888 { | |
889 public: | |
890 virtual ~ValueArrayAllocator(); | |
891 virtual ValueInternalArray *newArray() = 0; | |
892 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; | |
893 virtual void destructArray( ValueInternalArray *array ) = 0; | |
894 /** \brief Reallocate array page index. | |
895 * Reallocates an array of pointer on each page. | |
896 * \param indexes [input] pointer on the current index. May be \c NULL. | |
897 * [output] pointer on the new index of at least | |
898 * \a minNewIndexCount pages. | |
899 * \param indexCount [input] current number of pages in the index. | |
900 * [output] number of page the reallocated index can handle. | |
901 * \b MUST be >= \a minNewIndexCount. | |
902 * \param minNewIndexCount Minimum number of page the new index must be able to | |
903 * handle. | |
904 */ | |
905 virtual void reallocateArrayPageIndex( Value **&indexes, | |
906 ValueInternalArray::PageIndex &indexCount, | |
907 ValueInternalArray::PageIndex minNewIndexCount ) = 0; | |
908 virtual void releaseArrayPageIndex( Value **indexes, | |
909 ValueInternalArray::PageIndex indexCount ) = 0; | |
910 virtual Value *allocateArrayPage() = 0; | |
911 virtual void releaseArrayPage( Value *value ) = 0; | |
912 }; | |
913 #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP | |
914 | |
915 | |
916 /** \brief base class for Value iterators. | |
917 * | |
918 */ | |
919 class ValueIteratorBase | |
920 { | |
921 public: | |
922 typedef unsigned int size_t; | |
923 typedef int difference_type; | |
924 typedef ValueIteratorBase SelfType; | |
925 | |
926 ValueIteratorBase(); | |
927 #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
928 explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); | |
929 #else | |
930 ValueIteratorBase( const ValueInternalArray::IteratorState &state ); | |
931 ValueIteratorBase( const ValueInternalMap::IteratorState &state ); | |
932 #endif | |
933 | |
934 bool operator ==( const SelfType &other ) const | |
935 { | |
936 return isEqual( other ); | |
937 } | |
938 | |
939 bool operator !=( const SelfType &other ) const | |
940 { | |
941 return !isEqual( other ); | |
942 } | |
943 | |
944 difference_type operator -( const SelfType &other ) const | |
945 { | |
946 return computeDistance( other ); | |
947 } | |
948 | |
949 /// Return either the index or the member name of the referenced value as a Value. | |
950 Value key() const; | |
951 | |
952 /// Return the index of the referenced Value. -1 if it is not an arrayValue. | |
953 UInt index() const; | |
954 | |
955 /// Return the member name of the referenced Value. "" if it is not an objectValue. | |
956 const char *memberName() const; | |
957 | |
958 protected: | |
959 Value &deref() const; | |
960 | |
961 void increment(); | |
962 | |
963 void decrement(); | |
964 | |
965 difference_type computeDistance( const SelfType &other ) const; | |
966 | |
967 bool isEqual( const SelfType &other ) const; | |
968 | |
969 void copy( const SelfType &other ); | |
970 | |
971 private: | |
972 #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
973 Value::ObjectValues::iterator current_; | |
974 // Indicates that iterator is for a null value. | |
975 bool isNull_; | |
976 #else | |
977 union | |
978 { | |
979 ValueInternalArray::IteratorState array_; | |
980 ValueInternalMap::IteratorState map_; | |
981 } iterator_; | |
982 bool isArray_; | |
983 #endif | |
984 }; | |
985 | |
986 /** \brief const iterator for object and array value. | |
987 * | |
988 */ | |
989 class ValueConstIterator : public ValueIteratorBase | |
990 { | |
991 friend class Value; | |
992 public: | |
993 typedef unsigned int size_t; | |
994 typedef int difference_type; | |
995 typedef const Value &reference; | |
996 typedef const Value *pointer; | |
997 typedef ValueConstIterator SelfType; | |
998 | |
999 ValueConstIterator(); | |
1000 private: | |
1001 /*! \internal Use by Value to create an iterator. | |
1002 */ | |
1003 #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
1004 explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); | |
1005 #else | |
1006 ValueConstIterator( const ValueInternalArray::IteratorState &state ); | |
1007 ValueConstIterator( const ValueInternalMap::IteratorState &state ); | |
1008 #endif | |
1009 public: | |
1010 SelfType &operator =( const ValueIteratorBase &other ); | |
1011 | |
1012 SelfType operator++( int ) | |
1013 { | |
1014 SelfType temp( *this ); | |
1015 ++*this; | |
1016 return temp; | |
1017 } | |
1018 | |
1019 SelfType operator--( int ) | |
1020 { | |
1021 SelfType temp( *this ); | |
1022 --*this; | |
1023 return temp; | |
1024 } | |
1025 | |
1026 SelfType &operator--() | |
1027 { | |
1028 decrement(); | |
1029 return *this; | |
1030 } | |
1031 | |
1032 SelfType &operator++() | |
1033 { | |
1034 increment(); | |
1035 return *this; | |
1036 } | |
1037 | |
1038 reference operator *() const | |
1039 { | |
1040 return deref(); | |
1041 } | |
1042 }; | |
1043 | |
1044 | |
1045 /** \brief Iterator for object and array value. | |
1046 */ | |
1047 class ValueIterator : public ValueIteratorBase | |
1048 { | |
1049 friend class Value; | |
1050 public: | |
1051 typedef unsigned int size_t; | |
1052 typedef int difference_type; | |
1053 typedef Value &reference; | |
1054 typedef Value *pointer; | |
1055 typedef ValueIterator SelfType; | |
1056 | |
1057 ValueIterator(); | |
1058 ValueIterator( const ValueConstIterator &other ); | |
1059 ValueIterator( const ValueIterator &other ); | |
1060 private: | |
1061 /*! \internal Use by Value to create an iterator. | |
1062 */ | |
1063 #ifndef JSON_VALUE_USE_INTERNAL_MAP | |
1064 explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); | |
1065 #else | |
1066 ValueIterator( const ValueInternalArray::IteratorState &state ); | |
1067 ValueIterator( const ValueInternalMap::IteratorState &state ); | |
1068 #endif | |
1069 public: | |
1070 | |
1071 SelfType &operator =( const SelfType &other ); | |
1072 | |
1073 SelfType operator++( int ) | |
1074 { | |
1075 SelfType temp( *this ); | |
1076 ++*this; | |
1077 return temp; | |
1078 } | |
1079 | |
1080 SelfType operator--( int ) | |
1081 { | |
1082 SelfType temp( *this ); | |
1083 --*this; | |
1084 return temp; | |
1085 } | |
1086 | |
1087 SelfType &operator--() | |
1088 { | |
1089 decrement(); | |
1090 return *this; | |
1091 } | |
1092 | |
1093 SelfType &operator++() | |
1094 { | |
1095 increment(); | |
1096 return *this; | |
1097 } | |
1098 | |
1099 reference operator *() const | |
1100 { | |
1101 return deref(); | |
1102 } | |
1103 }; | |
1104 | |
1105 | |
1106 } // namespace Json | |
1107 | |
1108 | |
1109 #endif // CPPTL_JSON_H_INCLUDED |