blob: d575b707e2461a2cb1fcef789b0067fc51bcae76 [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;
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000124 typedef UInt ArrayIndex;
125
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 };
143 CZString( int index );
144 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;
150 int index() const;
151 const char *c_str() const;
152 bool isStaticString() const;
153 private:
154 void swap( CZString &other );
155 const char *cstr_;
156 int index_;
157 };
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 );
185 Value( Int value );
186 Value( UInt value );
187 Value( double value );
188 Value( const char *value );
Baptiste Lepilleur3a1b93b2010-02-21 14:08:17 +0000189 Value( const char *beginValue, const char *endValue );
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000190 /** \brief Constructs a value from a static string.
191
192 * Like other value string constructor but do not duplicate the string for
193 * internal storage. The given string must remain alive after the call to this
194 * constructor.
195 * Example of usage:
196 * \code
197 * Json::Value aValue( StaticString("some text") );
198 * \endcode
199 */
200 Value( const StaticString &value );
201 Value( const std::string &value );
202# ifdef JSON_USE_CPPTL
203 Value( const CppTL::ConstString &value );
204# endif
205 Value( bool value );
206 Value( const Value &other );
207 ~Value();
208
209 Value &operator=( const Value &other );
210 /// Swap values.
211 /// \note Currently, comments are intentionally not swapped, for
212 /// both logic and efficiency.
213 void swap( Value &other );
214
215 ValueType type() const;
216
217 bool operator <( const Value &other ) const;
218 bool operator <=( const Value &other ) const;
219 bool operator >=( const Value &other ) const;
220 bool operator >( const Value &other ) const;
221
222 bool operator ==( const Value &other ) const;
223 bool operator !=( const Value &other ) const;
224
225 int compare( const Value &other );
226
227 const char *asCString() const;
228 std::string asString() const;
229# ifdef JSON_USE_CPPTL
230 CppTL::ConstString asConstString() const;
231# endif
232 Int asInt() const;
233 UInt asUInt() const;
234 double asDouble() const;
235 bool asBool() const;
236
237 bool isNull() const;
238 bool isBool() const;
239 bool isInt() const;
240 bool isUInt() const;
241 bool isIntegral() const;
242 bool isDouble() const;
243 bool isNumeric() const;
244 bool isString() const;
245 bool isArray() const;
246 bool isObject() const;
247
248 bool isConvertibleTo( ValueType other ) const;
249
250 /// Number of values in array or object
251 UInt size() const;
252
253 /// \brief Return true if empty array, empty object, or null;
254 /// otherwise, false.
255 bool empty() const;
256
257 /// Return isNull()
258 bool operator!() const;
259
260 /// Remove all object members and array elements.
261 /// \pre type() is arrayValue, objectValue, or nullValue
262 /// \post type() is unchanged
263 void clear();
264
265 /// Resize the array to size elements.
266 /// New elements are initialized to null.
267 /// May only be called on nullValue or arrayValue.
268 /// \pre type() is arrayValue or nullValue
269 /// \post type() is arrayValue
270 void resize( UInt size );
271
272 /// Access an array element (zero based index ).
273 /// If the array contains less than index element, then null value are inserted
274 /// in the array so that its size is index+1.
Christopher Dunnf4b73932007-06-13 17:02:59 +0000275 /// (You may need to say 'value[0u]' to get your compiler to distinguish
276 /// this from the operator[] which takes a string.)
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000277 Value &operator[]( UInt index );
278 /// Access an array element (zero based index )
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.)
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000281 const Value &operator[]( UInt index ) const;
282 /// If the array contains at least index+1 elements, returns the element value,
283 /// otherwise returns defaultValue.
284 Value get( UInt index,
285 const Value &defaultValue ) const;
286 /// Return true if index < size().
287 bool isValidIndex( UInt index ) const;
288 /// \brief Append value to array at the end.
289 ///
290 /// Equivalent to jsonvalue[jsonvalue.size()] = value;
291 Value &append( const Value &value );
292
293 /// Access an object value by name, create a null member if it does not exist.
294 Value &operator[]( const char *key );
295 /// Access an object value by name, returns null if there is no member with that name.
296 const Value &operator[]( const char *key ) const;
297 /// Access an object value by name, create a null member if it does not exist.
298 Value &operator[]( const std::string &key );
299 /// Access an object value by name, returns null if there is no member with that name.
300 const Value &operator[]( const std::string &key ) const;
301 /** \brief Access an object value by name, create a null member if it does not exist.
302
303 * If the object as no entry for that name, then the member name used to store
304 * the new entry is not duplicated.
305 * Example of use:
306 * \code
307 * Json::Value object;
308 * static const StaticString code("code");
309 * object[code] = 1234;
310 * \endcode
311 */
312 Value &operator[]( const StaticString &key );
313# ifdef JSON_USE_CPPTL
314 /// Access an object value by name, create a null member if it does not exist.
315 Value &operator[]( const CppTL::ConstString &key );
316 /// Access an object value by name, returns null if there is no member with that name.
317 const Value &operator[]( const CppTL::ConstString &key ) const;
318# endif
319 /// Return the member named key if it exist, defaultValue otherwise.
320 Value get( const char *key,
321 const Value &defaultValue ) const;
322 /// Return the member named key if it exist, defaultValue otherwise.
323 Value get( const std::string &key,
324 const Value &defaultValue ) const;
325# ifdef JSON_USE_CPPTL
326 /// Return the member named key if it exist, defaultValue otherwise.
327 Value get( const CppTL::ConstString &key,
328 const Value &defaultValue ) const;
329# endif
330 /// \brief Remove and return the named member.
331 ///
332 /// Do nothing if it did not exist.
333 /// \return the removed Value, or null.
334 /// \pre type() is objectValue or nullValue
335 /// \post type() is unchanged
336 Value removeMember( const char* key );
337 /// Same as removeMember(const char*)
338 Value removeMember( const std::string &key );
339
340 /// Return true if the object has a member named key.
341 bool isMember( const char *key ) const;
342 /// Return true if the object has a member named key.
343 bool isMember( const std::string &key ) const;
344# ifdef JSON_USE_CPPTL
345 /// Return true if the object has a member named key.
346 bool isMember( const CppTL::ConstString &key ) const;
347# endif
348
349 /// \brief Return a list of the member names.
350 ///
351 /// If null, return an empty list.
352 /// \pre type() is objectValue or nullValue
353 /// \post if type() was nullValue, it remains nullValue
354 Members getMemberNames() const;
355
356//# ifdef JSON_USE_CPPTL
357// EnumMemberNames enumMemberNames() const;
358// EnumValues enumValues() const;
359//# endif
360
361 /// Comments must be //... or /* ... */
362 void setComment( const char *comment,
363 CommentPlacement placement );
364 /// Comments must be //... or /* ... */
365 void setComment( const std::string &comment,
366 CommentPlacement placement );
367 bool hasComment( CommentPlacement placement ) const;
368 /// Include delimiters and embedded newlines.
369 std::string getComment( CommentPlacement placement ) const;
370
371 std::string toStyledString() const;
372
373 const_iterator begin() const;
374 const_iterator end() const;
375
376 iterator begin();
377 iterator end();
378
379 private:
380 Value &resolveReference( const char *key,
381 bool isStatic );
382
383# ifdef JSON_VALUE_USE_INTERNAL_MAP
384 inline bool isItemAvailable() const
385 {
386 return itemIsUsed_ == 0;
387 }
388
389 inline void setItemUsed( bool isUsed = true )
390 {
391 itemIsUsed_ = isUsed ? 1 : 0;
392 }
393
394 inline bool isMemberNameStatic() const
395 {
396 return memberNameIsStatic_ == 0;
397 }
398
399 inline void setMemberNameIsStatic( bool isStatic )
400 {
401 memberNameIsStatic_ = isStatic ? 1 : 0;
402 }
403# endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP
404
405 private:
406 struct CommentInfo
407 {
408 CommentInfo();
409 ~CommentInfo();
410
411 void setComment( const char *text );
412
413 char *comment_;
414 };
415
416 //struct MemberNamesTransform
417 //{
418 // typedef const char *result_type;
419 // const char *operator()( const CZString &name ) const
420 // {
421 // return name.c_str();
422 // }
423 //};
424
425 union ValueHolder
426 {
427 Int int_;
428 UInt uint_;
429 double real_;
430 bool bool_;
431 char *string_;
432# ifdef JSON_VALUE_USE_INTERNAL_MAP
433 ValueInternalArray *array_;
434 ValueInternalMap *map_;
435#else
436 ObjectValues *map_;
437# endif
438 } value_;
439 ValueType type_ : 8;
440 int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
441# ifdef JSON_VALUE_USE_INTERNAL_MAP
442 unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container.
443 int memberNameIsStatic_ : 1; // used by the ValueInternalMap container.
444# endif
445 CommentInfo *comments_;
446 };
447
448
449 /** \brief Experimental and untested: represents an element of the "path" to access a node.
450 */
451 class PathArgument
452 {
453 public:
454 friend class Path;
455
456 PathArgument();
Baptiste Lepilleur3a1b93b2010-02-21 14:08:17 +0000457 PathArgument( UInt index );
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000458 PathArgument( const char *key );
459 PathArgument( const std::string &key );
460
461 private:
462 enum Kind
463 {
464 kindNone = 0,
465 kindIndex,
466 kindKey
467 };
468 std::string key_;
Baptiste Lepilleur3a1b93b2010-02-21 14:08:17 +0000469 UInt index_;
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000470 Kind kind_;
471 };
472
473 /** \brief Experimental and untested: represents a "path" to access a node.
474 *
475 * Syntax:
476 * - "." => root node
477 * - ".[n]" => elements at index 'n' of root node (an array value)
478 * - ".name" => member named 'name' of root node (an object value)
479 * - ".name1.name2.name3"
480 * - ".[0][1][2].name1[3]"
481 * - ".%" => member name is provided as parameter
482 * - ".[%]" => index is provied as parameter
483 */
484 class Path
485 {
486 public:
487 Path( const std::string &path,
488 const PathArgument &a1 = PathArgument(),
489 const PathArgument &a2 = PathArgument(),
490 const PathArgument &a3 = PathArgument(),
491 const PathArgument &a4 = PathArgument(),
492 const PathArgument &a5 = PathArgument() );
493
494 const Value &resolve( const Value &root ) const;
495 Value resolve( const Value &root,
496 const Value &defaultValue ) const;
497 /// Creates the "path" to access the specified node and returns a reference on the node.
498 Value &make( Value &root ) const;
499
500 private:
501 typedef std::vector<const PathArgument *> InArgs;
502 typedef std::vector<PathArgument> Args;
503
504 void makePath( const std::string &path,
505 const InArgs &in );
506 void addPathInArg( const std::string &path,
507 const InArgs &in,
508 InArgs::const_iterator &itInArg,
509 PathArgument::Kind kind );
510 void invalidPath( const std::string &path,
511 int location );
512
513 Args args_;
514 };
515
516 /** \brief Allocator to customize member name and string value memory management done by Value.
517 *
518 * - makeMemberName() and releaseMemberName() are called to respectively duplicate and
519 * free an Json::objectValue member name.
520 * - duplicateStringValue() and releaseStringValue() are called similarly to
521 * duplicate and free a Json::stringValue value.
522 */
523 class ValueAllocator
524 {
525 public:
526 enum { unknown = (unsigned)-1 };
527
528 virtual ~ValueAllocator();
529
530 virtual char *makeMemberName( const char *memberName ) = 0;
531 virtual void releaseMemberName( char *memberName ) = 0;
532 virtual char *duplicateStringValue( const char *value,
533 unsigned int length = unknown ) = 0;
534 virtual void releaseStringValue( char *value ) = 0;
535 };
536
537#ifdef JSON_VALUE_USE_INTERNAL_MAP
538 /** \brief Allocator to customize Value internal map.
539 * Below is an example of a simple implementation (default implementation actually
540 * use memory pool for speed).
541 * \code
542 class DefaultValueMapAllocator : public ValueMapAllocator
543 {
544 public: // overridden from ValueMapAllocator
545 virtual ValueInternalMap *newMap()
546 {
547 return new ValueInternalMap();
548 }
549
550 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
551 {
552 return new ValueInternalMap( other );
553 }
554
555 virtual void destructMap( ValueInternalMap *map )
556 {
557 delete map;
558 }
559
560 virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
561 {
562 return new ValueInternalLink[size];
563 }
564
565 virtual void releaseMapBuckets( ValueInternalLink *links )
566 {
567 delete [] links;
568 }
569
570 virtual ValueInternalLink *allocateMapLink()
571 {
572 return new ValueInternalLink();
573 }
574
575 virtual void releaseMapLink( ValueInternalLink *link )
576 {
577 delete link;
578 }
579 };
580 * \endcode
581 */
582 class JSON_API ValueMapAllocator
583 {
584 public:
585 virtual ~ValueMapAllocator();
586 virtual ValueInternalMap *newMap() = 0;
587 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
588 virtual void destructMap( ValueInternalMap *map ) = 0;
589 virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
590 virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
591 virtual ValueInternalLink *allocateMapLink() = 0;
592 virtual void releaseMapLink( ValueInternalLink *link ) = 0;
593 };
594
595 /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
596 * \internal previous_ & next_ allows for bidirectional traversal.
597 */
598 class JSON_API ValueInternalLink
599 {
600 public:
601 enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
602 enum InternalFlags {
603 flagAvailable = 0,
604 flagUsed = 1
605 };
606
607 ValueInternalLink();
608
609 ~ValueInternalLink();
610
611 Value items_[itemPerLink];
612 char *keys_[itemPerLink];
613 ValueInternalLink *previous_;
614 ValueInternalLink *next_;
615 };
616
617
618 /** \brief A linked page based hash-table implementation used internally by Value.
619 * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
620 * list in each bucket to handle collision. There is an addional twist in that
621 * each node of the collision linked list is a page containing a fixed amount of
622 * value. This provides a better compromise between memory usage and speed.
623 *
624 * Each bucket is made up of a chained list of ValueInternalLink. The last
625 * link of a given bucket can be found in the 'previous_' field of the following bucket.
626 * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
627 * Only the last link of a bucket may contains 'available' item. The last link always
628 * contains at least one element unless is it the bucket one very first link.
629 */
630 class JSON_API ValueInternalMap
631 {
632 friend class ValueIteratorBase;
633 friend class Value;
634 public:
635 typedef unsigned int HashKey;
636 typedef unsigned int BucketIndex;
637
638# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
639 struct IteratorState
640 {
Baptiste Lepilleur4a5e58c2010-01-15 14:56:59 +0000641 IteratorState()
642 : map_(0)
643 , link_(0)
644 , itemIndex_(0)
645 , bucketIndex_(0)
646 {
647 }
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000648 ValueInternalMap *map_;
649 ValueInternalLink *link_;
650 BucketIndex itemIndex_;
651 BucketIndex bucketIndex_;
652 };
653# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
654
655 ValueInternalMap();
656 ValueInternalMap( const ValueInternalMap &other );
657 ValueInternalMap &operator =( const ValueInternalMap &other );
658 ~ValueInternalMap();
659
660 void swap( ValueInternalMap &other );
661
662 BucketIndex size() const;
663
664 void clear();
665
666 bool reserveDelta( BucketIndex growth );
667
668 bool reserve( BucketIndex newItemCount );
669
670 const Value *find( const char *key ) const;
671
672 Value *find( const char *key );
673
674 Value &resolveReference( const char *key,
675 bool isStatic );
676
677 void remove( const char *key );
678
679 void doActualRemove( ValueInternalLink *link,
680 BucketIndex index,
681 BucketIndex bucketIndex );
682
683 ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
684
685 Value &setNewItem( const char *key,
686 bool isStatic,
687 ValueInternalLink *link,
688 BucketIndex index );
689
690 Value &unsafeAdd( const char *key,
691 bool isStatic,
692 HashKey hashedKey );
693
694 HashKey hash( const char *key ) const;
695
696 int compare( const ValueInternalMap &other ) const;
697
698 private:
699 void makeBeginIterator( IteratorState &it ) const;
700 void makeEndIterator( IteratorState &it ) const;
701 static bool equals( const IteratorState &x, const IteratorState &other );
702 static void increment( IteratorState &iterator );
703 static void incrementBucket( IteratorState &iterator );
704 static void decrement( IteratorState &iterator );
705 static const char *key( const IteratorState &iterator );
706 static const char *key( const IteratorState &iterator, bool &isStatic );
707 static Value &value( const IteratorState &iterator );
708 static int distance( const IteratorState &x, const IteratorState &y );
709
710 private:
711 ValueInternalLink *buckets_;
712 ValueInternalLink *tailLink_;
713 BucketIndex bucketsSize_;
714 BucketIndex itemCount_;
715 };
716
717 /** \brief A simplified deque implementation used internally by Value.
718 * \internal
719 * It is based on a list of fixed "page", each page contains a fixed number of items.
720 * Instead of using a linked-list, a array of pointer is used for fast item look-up.
721 * Look-up for an element is as follow:
722 * - compute page index: pageIndex = itemIndex / itemsPerPage
723 * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
724 *
725 * Insertion is amortized constant time (only the array containing the index of pointers
726 * need to be reallocated when items are appended).
727 */
728 class JSON_API ValueInternalArray
729 {
730 friend class Value;
731 friend class ValueIteratorBase;
732 public:
733 enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo.
734 typedef Value::ArrayIndex ArrayIndex;
735 typedef unsigned int PageIndex;
736
737# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
738 struct IteratorState // Must be a POD
739 {
Baptiste Lepilleur4a5e58c2010-01-15 14:56:59 +0000740 IteratorState()
741 : array_(0)
742 , currentPageIndex_(0)
743 , currentItemIndex_(0)
744 {
745 }
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000746 ValueInternalArray *array_;
747 Value **currentPageIndex_;
748 unsigned int currentItemIndex_;
749 };
750# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
751
752 ValueInternalArray();
753 ValueInternalArray( const ValueInternalArray &other );
754 ValueInternalArray &operator =( const ValueInternalArray &other );
755 ~ValueInternalArray();
756 void swap( ValueInternalArray &other );
757
758 void clear();
759 void resize( ArrayIndex newSize );
760
761 Value &resolveReference( ArrayIndex index );
762
763 Value *find( ArrayIndex index ) const;
764
765 ArrayIndex size() const;
766
767 int compare( const ValueInternalArray &other ) const;
768
769 private:
770 static bool equals( const IteratorState &x, const IteratorState &other );
771 static void increment( IteratorState &iterator );
772 static void decrement( IteratorState &iterator );
773 static Value &dereference( const IteratorState &iterator );
774 static Value &unsafeDereference( const IteratorState &iterator );
775 static int distance( const IteratorState &x, const IteratorState &y );
776 static ArrayIndex indexOf( const IteratorState &iterator );
777 void makeBeginIterator( IteratorState &it ) const;
778 void makeEndIterator( IteratorState &it ) const;
779 void makeIterator( IteratorState &it, ArrayIndex index ) const;
780
781 void makeIndexValid( ArrayIndex index );
782
783 Value **pages_;
784 ArrayIndex size_;
785 PageIndex pageCount_;
786 };
787
788 /** \brief Allocator to customize Value internal array.
789 * Below is an example of a simple implementation (actual implementation use
790 * memory pool).
791 \code
792class DefaultValueArrayAllocator : public ValueArrayAllocator
793{
794public: // overridden from ValueArrayAllocator
795 virtual ~DefaultValueArrayAllocator()
796 {
797 }
798
799 virtual ValueInternalArray *newArray()
800 {
801 return new ValueInternalArray();
802 }
803
804 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
805 {
806 return new ValueInternalArray( other );
807 }
808
809 virtual void destruct( ValueInternalArray *array )
810 {
811 delete array;
812 }
813
814 virtual void reallocateArrayPageIndex( Value **&indexes,
815 ValueInternalArray::PageIndex &indexCount,
816 ValueInternalArray::PageIndex minNewIndexCount )
817 {
818 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
819 if ( minNewIndexCount > newIndexCount )
820 newIndexCount = minNewIndexCount;
821 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
822 if ( !newIndexes )
823 throw std::bad_alloc();
824 indexCount = newIndexCount;
825 indexes = static_cast<Value **>( newIndexes );
826 }
827 virtual void releaseArrayPageIndex( Value **indexes,
828 ValueInternalArray::PageIndex indexCount )
829 {
830 if ( indexes )
831 free( indexes );
832 }
833
834 virtual Value *allocateArrayPage()
835 {
836 return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
837 }
838
839 virtual void releaseArrayPage( Value *value )
840 {
841 if ( value )
842 free( value );
843 }
844};
845 \endcode
846 */
847 class JSON_API ValueArrayAllocator
848 {
849 public:
850 virtual ~ValueArrayAllocator();
851 virtual ValueInternalArray *newArray() = 0;
852 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
853 virtual void destructArray( ValueInternalArray *array ) = 0;
854 /** \brief Reallocate array page index.
855 * Reallocates an array of pointer on each page.
856 * \param indexes [input] pointer on the current index. May be \c NULL.
857 * [output] pointer on the new index of at least
858 * \a minNewIndexCount pages.
859 * \param indexCount [input] current number of pages in the index.
860 * [output] number of page the reallocated index can handle.
861 * \b MUST be >= \a minNewIndexCount.
862 * \param minNewIndexCount Minimum number of page the new index must be able to
863 * handle.
864 */
865 virtual void reallocateArrayPageIndex( Value **&indexes,
866 ValueInternalArray::PageIndex &indexCount,
867 ValueInternalArray::PageIndex minNewIndexCount ) = 0;
868 virtual void releaseArrayPageIndex( Value **indexes,
869 ValueInternalArray::PageIndex indexCount ) = 0;
870 virtual Value *allocateArrayPage() = 0;
871 virtual void releaseArrayPage( Value *value ) = 0;
872 };
873#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
874
875
876 /** \brief Experimental and untested: base class for Value iterators.
877 *
878 */
879 class ValueIteratorBase
880 {
881 public:
882 typedef unsigned int size_t;
883 typedef int difference_type;
884 typedef ValueIteratorBase SelfType;
885
886 ValueIteratorBase();
887#ifndef JSON_VALUE_USE_INTERNAL_MAP
888 explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
889#else
890 ValueIteratorBase( const ValueInternalArray::IteratorState &state );
891 ValueIteratorBase( const ValueInternalMap::IteratorState &state );
892#endif
893
894 bool operator ==( const SelfType &other ) const
895 {
896 return isEqual( other );
897 }
898
899 bool operator !=( const SelfType &other ) const
900 {
901 return !isEqual( other );
902 }
903
904 difference_type operator -( const SelfType &other ) const
905 {
906 return computeDistance( other );
907 }
908
909 /// Return either the index or the member name of the referenced value as a Value.
910 Value key() const;
911
912 /// Return the index of the referenced Value. -1 if it is not an arrayValue.
Baptiste Lepilleur3a1b93b2010-02-21 14:08:17 +0000913 UInt index() const;
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000914
915 /// Return the member name of the referenced Value. "" if it is not an objectValue.
916 const char *memberName() const;
917
918 protected:
919 Value &deref() const;
920
921 void increment();
922
923 void decrement();
924
925 difference_type computeDistance( const SelfType &other ) const;
926
927 bool isEqual( const SelfType &other ) const;
928
929 void copy( const SelfType &other );
930
931 private:
932#ifndef JSON_VALUE_USE_INTERNAL_MAP
933 Value::ObjectValues::iterator current_;
Baptiste Lepilleura1d6c9e2009-11-23 22:33:30 +0000934 // Indicates that iterator is for a null value.
935 bool isNull_;
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000936#else
937 union
938 {
939 ValueInternalArray::IteratorState array_;
940 ValueInternalMap::IteratorState map_;
941 } iterator_;
942 bool isArray_;
943#endif
944 };
945
946 /** \brief Experimental and untested: const iterator for object and array value.
947 *
948 */
949 class ValueConstIterator : public ValueIteratorBase
950 {
951 friend class Value;
952 public:
953 typedef unsigned int size_t;
954 typedef int difference_type;
955 typedef const Value &reference;
956 typedef const Value *pointer;
957 typedef ValueConstIterator SelfType;
958
959 ValueConstIterator();
960 private:
961 /*! \internal Use by Value to create an iterator.
962 */
963#ifndef JSON_VALUE_USE_INTERNAL_MAP
964 explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
965#else
966 ValueConstIterator( const ValueInternalArray::IteratorState &state );
967 ValueConstIterator( const ValueInternalMap::IteratorState &state );
968#endif
969 public:
970 SelfType &operator =( const ValueIteratorBase &other );
971
972 SelfType operator++( int )
973 {
974 SelfType temp( *this );
975 ++*this;
976 return temp;
977 }
978
979 SelfType operator--( int )
980 {
981 SelfType temp( *this );
982 --*this;
983 return temp;
984 }
985
986 SelfType &operator--()
987 {
988 decrement();
989 return *this;
990 }
991
992 SelfType &operator++()
993 {
994 increment();
995 return *this;
996 }
997
998 reference operator *() const
999 {
1000 return deref();
1001 }
1002 };
1003
1004
1005 /** \brief Experimental and untested: iterator for object and array value.
1006 */
1007 class ValueIterator : public ValueIteratorBase
1008 {
1009 friend class Value;
1010 public:
1011 typedef unsigned int size_t;
1012 typedef int difference_type;
1013 typedef Value &reference;
1014 typedef Value *pointer;
1015 typedef ValueIterator SelfType;
1016
1017 ValueIterator();
1018 ValueIterator( const ValueConstIterator &other );
1019 ValueIterator( const ValueIterator &other );
1020 private:
1021 /*! \internal Use by Value to create an iterator.
1022 */
1023#ifndef JSON_VALUE_USE_INTERNAL_MAP
1024 explicit ValueIterator( const Value::ObjectValues::iterator &current );
1025#else
1026 ValueIterator( const ValueInternalArray::IteratorState &state );
1027 ValueIterator( const ValueInternalMap::IteratorState &state );
1028#endif
1029 public:
1030
1031 SelfType &operator =( const SelfType &other );
1032
1033 SelfType operator++( int )
1034 {
1035 SelfType temp( *this );
1036 ++*this;
1037 return temp;
1038 }
1039
1040 SelfType operator--( int )
1041 {
1042 SelfType temp( *this );
1043 --*this;
1044 return temp;
1045 }
1046
1047 SelfType &operator--()
1048 {
1049 decrement();
1050 return *this;
1051 }
1052
1053 SelfType &operator++()
1054 {
1055 increment();
1056 return *this;
1057 }
1058
1059 reference operator *() const
1060 {
1061 return deref();
1062 }
1063 };
1064
1065
1066} // namespace Json
1067
1068
1069#endif // CPPTL_JSON_H_INCLUDED