blob: 5d1bc81e0e9fa7c1be19e6e43c9aa3320a6bc267 [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
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000516
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000517
518#ifdef JSON_VALUE_USE_INTERNAL_MAP
519 /** \brief Allocator to customize Value internal map.
520 * Below is an example of a simple implementation (default implementation actually
521 * use memory pool for speed).
522 * \code
523 class DefaultValueMapAllocator : public ValueMapAllocator
524 {
525 public: // overridden from ValueMapAllocator
526 virtual ValueInternalMap *newMap()
527 {
528 return new ValueInternalMap();
529 }
530
531 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
532 {
533 return new ValueInternalMap( other );
534 }
535
536 virtual void destructMap( ValueInternalMap *map )
537 {
538 delete map;
539 }
540
541 virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
542 {
543 return new ValueInternalLink[size];
544 }
545
546 virtual void releaseMapBuckets( ValueInternalLink *links )
547 {
548 delete [] links;
549 }
550
551 virtual ValueInternalLink *allocateMapLink()
552 {
553 return new ValueInternalLink();
554 }
555
556 virtual void releaseMapLink( ValueInternalLink *link )
557 {
558 delete link;
559 }
560 };
561 * \endcode
562 */
563 class JSON_API ValueMapAllocator
564 {
565 public:
566 virtual ~ValueMapAllocator();
567 virtual ValueInternalMap *newMap() = 0;
568 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0;
569 virtual void destructMap( ValueInternalMap *map ) = 0;
570 virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0;
571 virtual void releaseMapBuckets( ValueInternalLink *links ) = 0;
572 virtual ValueInternalLink *allocateMapLink() = 0;
573 virtual void releaseMapLink( ValueInternalLink *link ) = 0;
574 };
575
576 /** \brief ValueInternalMap hash-map bucket chain link (for internal use only).
577 * \internal previous_ & next_ allows for bidirectional traversal.
578 */
579 class JSON_API ValueInternalLink
580 {
581 public:
582 enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture.
583 enum InternalFlags {
584 flagAvailable = 0,
585 flagUsed = 1
586 };
587
588 ValueInternalLink();
589
590 ~ValueInternalLink();
591
592 Value items_[itemPerLink];
593 char *keys_[itemPerLink];
594 ValueInternalLink *previous_;
595 ValueInternalLink *next_;
596 };
597
598
599 /** \brief A linked page based hash-table implementation used internally by Value.
600 * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked
601 * list in each bucket to handle collision. There is an addional twist in that
602 * each node of the collision linked list is a page containing a fixed amount of
603 * value. This provides a better compromise between memory usage and speed.
604 *
605 * Each bucket is made up of a chained list of ValueInternalLink. The last
606 * link of a given bucket can be found in the 'previous_' field of the following bucket.
607 * The last link of the last bucket is stored in tailLink_ as it has no following bucket.
608 * Only the last link of a bucket may contains 'available' item. The last link always
609 * contains at least one element unless is it the bucket one very first link.
610 */
611 class JSON_API ValueInternalMap
612 {
613 friend class ValueIteratorBase;
614 friend class Value;
615 public:
616 typedef unsigned int HashKey;
617 typedef unsigned int BucketIndex;
618
619# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
620 struct IteratorState
621 {
Baptiste Lepilleur4a5e58c2010-01-15 14:56:59 +0000622 IteratorState()
623 : map_(0)
624 , link_(0)
625 , itemIndex_(0)
626 , bucketIndex_(0)
627 {
628 }
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000629 ValueInternalMap *map_;
630 ValueInternalLink *link_;
631 BucketIndex itemIndex_;
632 BucketIndex bucketIndex_;
633 };
634# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
635
636 ValueInternalMap();
637 ValueInternalMap( const ValueInternalMap &other );
638 ValueInternalMap &operator =( const ValueInternalMap &other );
639 ~ValueInternalMap();
640
641 void swap( ValueInternalMap &other );
642
643 BucketIndex size() const;
644
645 void clear();
646
647 bool reserveDelta( BucketIndex growth );
648
649 bool reserve( BucketIndex newItemCount );
650
651 const Value *find( const char *key ) const;
652
653 Value *find( const char *key );
654
655 Value &resolveReference( const char *key,
656 bool isStatic );
657
658 void remove( const char *key );
659
660 void doActualRemove( ValueInternalLink *link,
661 BucketIndex index,
662 BucketIndex bucketIndex );
663
664 ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex );
665
666 Value &setNewItem( const char *key,
667 bool isStatic,
668 ValueInternalLink *link,
669 BucketIndex index );
670
671 Value &unsafeAdd( const char *key,
672 bool isStatic,
673 HashKey hashedKey );
674
675 HashKey hash( const char *key ) const;
676
677 int compare( const ValueInternalMap &other ) const;
678
679 private:
680 void makeBeginIterator( IteratorState &it ) const;
681 void makeEndIterator( IteratorState &it ) const;
682 static bool equals( const IteratorState &x, const IteratorState &other );
683 static void increment( IteratorState &iterator );
684 static void incrementBucket( IteratorState &iterator );
685 static void decrement( IteratorState &iterator );
686 static const char *key( const IteratorState &iterator );
687 static const char *key( const IteratorState &iterator, bool &isStatic );
688 static Value &value( const IteratorState &iterator );
689 static int distance( const IteratorState &x, const IteratorState &y );
690
691 private:
692 ValueInternalLink *buckets_;
693 ValueInternalLink *tailLink_;
694 BucketIndex bucketsSize_;
695 BucketIndex itemCount_;
696 };
697
698 /** \brief A simplified deque implementation used internally by Value.
699 * \internal
700 * It is based on a list of fixed "page", each page contains a fixed number of items.
701 * Instead of using a linked-list, a array of pointer is used for fast item look-up.
702 * Look-up for an element is as follow:
703 * - compute page index: pageIndex = itemIndex / itemsPerPage
704 * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage]
705 *
706 * Insertion is amortized constant time (only the array containing the index of pointers
707 * need to be reallocated when items are appended).
708 */
709 class JSON_API ValueInternalArray
710 {
711 friend class Value;
712 friend class ValueIteratorBase;
713 public:
714 enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo.
715 typedef Value::ArrayIndex ArrayIndex;
716 typedef unsigned int PageIndex;
717
718# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
719 struct IteratorState // Must be a POD
720 {
Baptiste Lepilleur4a5e58c2010-01-15 14:56:59 +0000721 IteratorState()
722 : array_(0)
723 , currentPageIndex_(0)
724 , currentItemIndex_(0)
725 {
726 }
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000727 ValueInternalArray *array_;
728 Value **currentPageIndex_;
729 unsigned int currentItemIndex_;
730 };
731# endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
732
733 ValueInternalArray();
734 ValueInternalArray( const ValueInternalArray &other );
735 ValueInternalArray &operator =( const ValueInternalArray &other );
736 ~ValueInternalArray();
737 void swap( ValueInternalArray &other );
738
739 void clear();
740 void resize( ArrayIndex newSize );
741
742 Value &resolveReference( ArrayIndex index );
743
744 Value *find( ArrayIndex index ) const;
745
746 ArrayIndex size() const;
747
748 int compare( const ValueInternalArray &other ) const;
749
750 private:
751 static bool equals( const IteratorState &x, const IteratorState &other );
752 static void increment( IteratorState &iterator );
753 static void decrement( IteratorState &iterator );
754 static Value &dereference( const IteratorState &iterator );
755 static Value &unsafeDereference( const IteratorState &iterator );
756 static int distance( const IteratorState &x, const IteratorState &y );
757 static ArrayIndex indexOf( const IteratorState &iterator );
758 void makeBeginIterator( IteratorState &it ) const;
759 void makeEndIterator( IteratorState &it ) const;
760 void makeIterator( IteratorState &it, ArrayIndex index ) const;
761
762 void makeIndexValid( ArrayIndex index );
763
764 Value **pages_;
765 ArrayIndex size_;
766 PageIndex pageCount_;
767 };
768
Baptiste Lepilleur0c5fff12010-03-11 20:23:07 +0000769 /** \brief Experimental: do not use. Allocator to customize Value internal array.
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000770 * Below is an example of a simple implementation (actual implementation use
771 * memory pool).
772 \code
773class DefaultValueArrayAllocator : public ValueArrayAllocator
774{
775public: // overridden from ValueArrayAllocator
776 virtual ~DefaultValueArrayAllocator()
777 {
778 }
779
780 virtual ValueInternalArray *newArray()
781 {
782 return new ValueInternalArray();
783 }
784
785 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
786 {
787 return new ValueInternalArray( other );
788 }
789
790 virtual void destruct( ValueInternalArray *array )
791 {
792 delete array;
793 }
794
795 virtual void reallocateArrayPageIndex( Value **&indexes,
796 ValueInternalArray::PageIndex &indexCount,
797 ValueInternalArray::PageIndex minNewIndexCount )
798 {
799 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
800 if ( minNewIndexCount > newIndexCount )
801 newIndexCount = minNewIndexCount;
802 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
803 if ( !newIndexes )
804 throw std::bad_alloc();
805 indexCount = newIndexCount;
806 indexes = static_cast<Value **>( newIndexes );
807 }
808 virtual void releaseArrayPageIndex( Value **indexes,
809 ValueInternalArray::PageIndex indexCount )
810 {
811 if ( indexes )
812 free( indexes );
813 }
814
815 virtual Value *allocateArrayPage()
816 {
817 return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
818 }
819
820 virtual void releaseArrayPage( Value *value )
821 {
822 if ( value )
823 free( value );
824 }
825};
826 \endcode
827 */
828 class JSON_API ValueArrayAllocator
829 {
830 public:
831 virtual ~ValueArrayAllocator();
832 virtual ValueInternalArray *newArray() = 0;
833 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0;
834 virtual void destructArray( ValueInternalArray *array ) = 0;
835 /** \brief Reallocate array page index.
836 * Reallocates an array of pointer on each page.
837 * \param indexes [input] pointer on the current index. May be \c NULL.
838 * [output] pointer on the new index of at least
839 * \a minNewIndexCount pages.
840 * \param indexCount [input] current number of pages in the index.
841 * [output] number of page the reallocated index can handle.
842 * \b MUST be >= \a minNewIndexCount.
843 * \param minNewIndexCount Minimum number of page the new index must be able to
844 * handle.
845 */
846 virtual void reallocateArrayPageIndex( Value **&indexes,
847 ValueInternalArray::PageIndex &indexCount,
848 ValueInternalArray::PageIndex minNewIndexCount ) = 0;
849 virtual void releaseArrayPageIndex( Value **indexes,
850 ValueInternalArray::PageIndex indexCount ) = 0;
851 virtual Value *allocateArrayPage() = 0;
852 virtual void releaseArrayPage( Value *value ) = 0;
853 };
854#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
855
856
Baptiste Lepilleur0c5fff12010-03-11 20:23:07 +0000857 /** \brief base class for Value iterators.
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000858 *
859 */
860 class ValueIteratorBase
861 {
862 public:
863 typedef unsigned int size_t;
864 typedef int difference_type;
865 typedef ValueIteratorBase SelfType;
866
867 ValueIteratorBase();
868#ifndef JSON_VALUE_USE_INTERNAL_MAP
869 explicit ValueIteratorBase( const Value::ObjectValues::iterator &current );
870#else
871 ValueIteratorBase( const ValueInternalArray::IteratorState &state );
872 ValueIteratorBase( const ValueInternalMap::IteratorState &state );
873#endif
874
875 bool operator ==( const SelfType &other ) const
876 {
877 return isEqual( other );
878 }
879
880 bool operator !=( const SelfType &other ) const
881 {
882 return !isEqual( other );
883 }
884
885 difference_type operator -( const SelfType &other ) const
886 {
887 return computeDistance( other );
888 }
889
890 /// Return either the index or the member name of the referenced value as a Value.
891 Value key() const;
892
893 /// Return the index of the referenced Value. -1 if it is not an arrayValue.
Baptiste Lepilleur3a1b93b2010-02-21 14:08:17 +0000894 UInt index() const;
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000895
896 /// Return the member name of the referenced Value. "" if it is not an objectValue.
897 const char *memberName() const;
898
899 protected:
900 Value &deref() const;
901
902 void increment();
903
904 void decrement();
905
906 difference_type computeDistance( const SelfType &other ) const;
907
908 bool isEqual( const SelfType &other ) const;
909
910 void copy( const SelfType &other );
911
912 private:
913#ifndef JSON_VALUE_USE_INTERNAL_MAP
914 Value::ObjectValues::iterator current_;
Baptiste Lepilleura1d6c9e2009-11-23 22:33:30 +0000915 // Indicates that iterator is for a null value.
916 bool isNull_;
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000917#else
918 union
919 {
920 ValueInternalArray::IteratorState array_;
921 ValueInternalMap::IteratorState map_;
922 } iterator_;
923 bool isArray_;
924#endif
925 };
926
Baptiste Lepilleur0c5fff12010-03-11 20:23:07 +0000927 /** \brief const iterator for object and array value.
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000928 *
929 */
930 class ValueConstIterator : public ValueIteratorBase
931 {
932 friend class Value;
933 public:
934 typedef unsigned int size_t;
935 typedef int difference_type;
936 typedef const Value &reference;
937 typedef const Value *pointer;
938 typedef ValueConstIterator SelfType;
939
940 ValueConstIterator();
941 private:
942 /*! \internal Use by Value to create an iterator.
943 */
944#ifndef JSON_VALUE_USE_INTERNAL_MAP
945 explicit ValueConstIterator( const Value::ObjectValues::iterator &current );
946#else
947 ValueConstIterator( const ValueInternalArray::IteratorState &state );
948 ValueConstIterator( const ValueInternalMap::IteratorState &state );
949#endif
950 public:
951 SelfType &operator =( const ValueIteratorBase &other );
952
953 SelfType operator++( int )
954 {
955 SelfType temp( *this );
956 ++*this;
957 return temp;
958 }
959
960 SelfType operator--( int )
961 {
962 SelfType temp( *this );
963 --*this;
964 return temp;
965 }
966
967 SelfType &operator--()
968 {
969 decrement();
970 return *this;
971 }
972
973 SelfType &operator++()
974 {
975 increment();
976 return *this;
977 }
978
979 reference operator *() const
980 {
981 return deref();
982 }
983 };
984
985
Baptiste Lepilleur0c5fff12010-03-11 20:23:07 +0000986 /** \brief Iterator for object and array value.
Christopher Dunn6d135cb2007-06-13 15:51:04 +0000987 */
988 class ValueIterator : public ValueIteratorBase
989 {
990 friend class Value;
991 public:
992 typedef unsigned int size_t;
993 typedef int difference_type;
994 typedef Value &reference;
995 typedef Value *pointer;
996 typedef ValueIterator SelfType;
997
998 ValueIterator();
999 ValueIterator( const ValueConstIterator &other );
1000 ValueIterator( const ValueIterator &other );
1001 private:
1002 /*! \internal Use by Value to create an iterator.
1003 */
1004#ifndef JSON_VALUE_USE_INTERNAL_MAP
1005 explicit ValueIterator( const Value::ObjectValues::iterator &current );
1006#else
1007 ValueIterator( const ValueInternalArray::IteratorState &state );
1008 ValueIterator( const ValueInternalMap::IteratorState &state );
1009#endif
1010 public:
1011
1012 SelfType &operator =( const SelfType &other );
1013
1014 SelfType operator++( int )
1015 {
1016 SelfType temp( *this );
1017 ++*this;
1018 return temp;
1019 }
1020
1021 SelfType operator--( int )
1022 {
1023 SelfType temp( *this );
1024 --*this;
1025 return temp;
1026 }
1027
1028 SelfType &operator--()
1029 {
1030 decrement();
1031 return *this;
1032 }
1033
1034 SelfType &operator++()
1035 {
1036 increment();
1037 return *this;
1038 }
1039
1040 reference operator *() const
1041 {
1042 return deref();
1043 }
1044 };
1045
1046
1047} // namespace Json
1048
1049
1050#endif // CPPTL_JSON_H_INCLUDED