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