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