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