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