annotate third_party/json/value.h @ 0:add35537fdbb tip

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