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