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