OLD | NEW |
(Empty) | |
| 1 // 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 |
| 6 #ifndef CPPTL_JSON_H_INCLUDED |
| 7 # define CPPTL_JSON_H_INCLUDED |
| 8 |
| 9 #if !defined(JSON_IS_AMALGAMATION) |
| 10 # include "json/forwards.h" |
| 11 #endif // if !defined(JSON_IS_AMALGAMATION) |
| 12 # 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 */ |
| 26 namespace 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 li
ne |
| 46 commentAfter, ///< a comment on the line after a value (only m
ake 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 th
e |
| 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 initialize
d |
| 110 * with #nullValue. resize() can be used to enlarge or truncate an #arrayValu
e. |
| 111 * |
| 112 * The get() methods can be used to obtanis default value in the case the req
uired 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; |
| 127 typedef ValueIterator iterator; |
| 128 typedef ValueConstIterator const_iterator; |
| 129 typedef Json::UInt UInt; |
| 130 typedef Json::Int Int; |
| 131 # if defined(JSON_HAS_INT64) |
| 132 typedef Json::UInt64 UInt64; |
| 133 typedef Json::Int64 Int64; |
| 134 #endif // defined(JSON_HAS_INT64) |
| 135 typedef Json::LargestInt LargestInt; |
| 136 typedef Json::LargestUInt LargestUInt; |
| 137 typedef Json::ArrayIndex ArrayIndex; |
| 138 |
| 139 static const Value& null; |
| 140 /// 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. |
| 143 static const LargestInt maxLargestInt; |
| 144 /// Maximum unsigned integer value that can be stored in a Json::Value. |
| 145 static const LargestUInt maxLargestUInt; |
| 146 |
| 147 /// 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. |
| 150 static const Int maxInt; |
| 151 /// Maximum unsigned int value that can be stored in a Json::Value. |
| 152 static const UInt maxUInt; |
| 153 |
| 154 # if defined(JSON_HAS_INT64) |
| 155 /// 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. |
| 158 static const Int64 maxInt64; |
| 159 /// Maximum unsigned 64 bits int value that can be stored in a Json::Value
. |
| 160 static const UInt64 maxUInt64; |
| 161 #endif // defined(JSON_HAS_INT64) |
| 162 |
| 163 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 }; |
| 175 CZString( ArrayIndex index ); |
| 176 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; |
| 182 ArrayIndex index() const; |
| 183 const char *c_str() const; |
| 184 bool isStaticString() const; |
| 185 private: |
| 186 void swap( CZString &other ); |
| 187 const char *cstr_; |
| 188 ArrayIndex index_; |
| 189 }; |
| 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. |
| 207 This is useful since clear() and resize() will not alter types. |
| 208 |
| 209 Examples: |
| 210 \code |
| 211 Json::Value null_value; // null |
| 212 Json::Value arr_value(Json::arrayValue); // [] |
| 213 Json::Value obj_value(Json::objectValue); // {} |
| 214 \endcode |
| 215 */ |
| 216 Value( ValueType type = nullValue ); |
| 217 Value( Int value ); |
| 218 Value( UInt value ); |
| 219 #if defined(JSON_HAS_INT64) |
| 220 Value( Int64 value ); |
| 221 Value( UInt64 value ); |
| 222 #endif // if defined(JSON_HAS_INT64) |
| 223 Value( double value ); |
| 224 Value( const char *value ); |
| 225 Value( const char *beginValue, const char *endValue ); |
| 226 /** \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 |
| 261 int compare( const Value &other ) const; |
| 262 |
| 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; |
| 270 #if defined(JSON_HAS_INT64) |
| 271 Int64 asInt64() const; |
| 272 UInt64 asUInt64() const; |
| 273 #endif // if defined(JSON_HAS_INT64) |
| 274 LargestInt asLargestInt() const; |
| 275 LargestUInt asLargestUInt() const; |
| 276 float asFloat() const; |
| 277 double asDouble() const; |
| 278 bool asBool() const; |
| 279 |
| 280 bool isNull() const; |
| 281 bool isBool() const; |
| 282 bool isInt() const; |
| 283 bool isInt64() const; |
| 284 bool isUInt() const; |
| 285 bool isUInt64() const; |
| 286 bool isIntegral() const; |
| 287 bool isDouble() const; |
| 288 bool isNumeric() const; |
| 289 bool isString() const; |
| 290 bool isArray() const; |
| 291 bool isObject() const; |
| 292 |
| 293 bool isConvertibleTo( ValueType other ) const; |
| 294 |
| 295 /// Number of values in array or object |
| 296 ArrayIndex size() const; |
| 297 |
| 298 /// \brief Return true if empty array, empty object, or null; |
| 299 /// otherwise, false. |
| 300 bool empty() const; |
| 301 |
| 302 /// Return isNull() |
| 303 bool operator!() const; |
| 304 |
| 305 /// Remove all object members and array elements. |
| 306 /// \pre type() is arrayValue, objectValue, or nullValue |
| 307 /// \post type() is unchanged |
| 308 void clear(); |
| 309 |
| 310 /// Resize the array to size elements. |
| 311 /// New elements are initialized to null. |
| 312 /// May only be called on nullValue or arrayValue. |
| 313 /// \pre type() is arrayValue or nullValue |
| 314 /// \post type() is arrayValue |
| 315 void resize( ArrayIndex size ); |
| 316 |
| 317 /// Access an array element (zero based index ). |
| 318 /// If the array contains less than index element, then null value are ins
erted |
| 319 /// in the array so that its size is index+1. |
| 320 /// (You may need to say 'value[0u]' to get your compiler to distinguish |
| 321 /// this from the operator[] which takes a string.) |
| 322 Value &operator[]( ArrayIndex index ); |
| 323 |
| 324 /// Access an array element (zero based index ). |
| 325 /// If the array contains less than index element, then null value are ins
erted |
| 326 /// in the array so that its size is index+1. |
| 327 /// (You may need to say 'value[0u]' to get your compiler to distinguish |
| 328 /// this from the operator[] which takes a string.) |
| 329 Value &operator[]( int index ); |
| 330 |
| 331 /// Access an array element (zero based index ) |
| 332 /// (You may need to say 'value[0u]' to get your compiler to distinguish |
| 333 /// this from the operator[] which takes a string.) |
| 334 const Value &operator[]( ArrayIndex index ) const; |
| 335 |
| 336 /// Access an array element (zero based index ) |
| 337 /// (You may need to say 'value[0u]' to get your compiler to distinguish |
| 338 /// this from the operator[] which takes a string.) |
| 339 const Value &operator[]( int index ) const; |
| 340 |
| 341 /// If the array contains at least index+1 elements, returns the element v
alue, |
| 342 /// otherwise returns defaultValue. |
| 343 Value get( ArrayIndex index, |
| 344 const Value &defaultValue ) const; |
| 345 /// Return true if index < size(). |
| 346 bool isValidIndex( ArrayIndex index ) const; |
| 347 /// \brief Append value to array at the end. |
| 348 /// |
| 349 /// Equivalent to jsonvalue[jsonvalue.size()] = value; |
| 350 Value &append( const Value &value ); |
| 351 |
| 352 /// Access an object value by name, create a null member if it does not ex
ist. |
| 353 Value &operator[]( const char *key ); |
| 354 /// Access an object value by name, returns null if there is no member wit
h that name. |
| 355 const Value &operator[]( const char *key ) const; |
| 356 /// Access an object value by name, create a null member if it does not ex
ist. |
| 357 Value &operator[]( const std::string &key ); |
| 358 /// Access an object value by name, returns null if there is no member wit
h that name. |
| 359 const Value &operator[]( const std::string &key ) const; |
| 360 /** \brief Access an object value by name, create a null member if it does
not exist. |
| 361 |
| 362 * If the object as no entry for that name, then the member name used to s
tore |
| 363 * the new entry is not duplicated. |
| 364 * Example of use: |
| 365 * \code |
| 366 * Json::Value object; |
| 367 * static const StaticString code("code"); |
| 368 * object[code] = 1234; |
| 369 * \endcode |
| 370 */ |
| 371 Value &operator[]( const StaticString &key ); |
| 372 # ifdef JSON_USE_CPPTL |
| 373 /// Access an object value by name, create a null member if it does not ex
ist. |
| 374 Value &operator[]( const CppTL::ConstString &key ); |
| 375 /// Access an object value by name, returns null if there is no member wit
h that name. |
| 376 const Value &operator[]( const CppTL::ConstString &key ) const; |
| 377 # endif |
| 378 /// Return the member named key if it exist, defaultValue otherwise. |
| 379 Value get( const char *key, |
| 380 const Value &defaultValue ) const; |
| 381 /// Return the member named key if it exist, defaultValue otherwise. |
| 382 Value get( const std::string &key, |
| 383 const Value &defaultValue ) const; |
| 384 # ifdef JSON_USE_CPPTL |
| 385 /// Return the member named key if it exist, defaultValue otherwise. |
| 386 Value get( const CppTL::ConstString &key, |
| 387 const Value &defaultValue ) const; |
| 388 # endif |
| 389 /// \brief Remove and return the named member. |
| 390 /// |
| 391 /// Do nothing if it did not exist. |
| 392 /// \return the removed Value, or null. |
| 393 /// \pre type() is objectValue or nullValue |
| 394 /// \post type() is unchanged |
| 395 Value removeMember( const char* key ); |
| 396 /// Same as removeMember(const char*) |
| 397 Value removeMember( const std::string &key ); |
| 398 |
| 399 /// Return true if the object has a member named key. |
| 400 bool isMember( const char *key ) const; |
| 401 /// Return true if the object has a member named key. |
| 402 bool isMember( const std::string &key ) const; |
| 403 # ifdef JSON_USE_CPPTL |
| 404 /// Return true if the object has a member named key. |
| 405 bool isMember( const CppTL::ConstString &key ) const; |
| 406 # endif |
| 407 |
| 408 /// \brief Return a list of the member names. |
| 409 /// |
| 410 /// If null, return an empty list. |
| 411 /// \pre type() is objectValue or nullValue |
| 412 /// \post if type() was nullValue, it remains nullValue |
| 413 Members getMemberNames() const; |
| 414 |
| 415 //# ifdef JSON_USE_CPPTL |
| 416 // EnumMemberNames enumMemberNames() const; |
| 417 // EnumValues enumValues() const; |
| 418 //# endif |
| 419 |
| 420 /// Comments must be //... or /* ... */ |
| 421 void setComment( const char *comment, |
| 422 CommentPlacement placement ); |
| 423 /// Comments must be //... or /* ... */ |
| 424 void setComment( const std::string &comment, |
| 425 CommentPlacement placement ); |
| 426 bool hasComment( CommentPlacement placement ) const; |
| 427 /// Include delimiters and embedded newlines. |
| 428 std::string getComment( CommentPlacement placement ) const; |
| 429 |
| 430 std::string toStyledString() const; |
| 431 |
| 432 const_iterator begin() const; |
| 433 const_iterator end() const; |
| 434 |
| 435 iterator begin(); |
| 436 iterator end(); |
| 437 |
| 438 private: |
| 439 Value &resolveReference( const char *key, |
| 440 bool isStatic ); |
| 441 |
| 442 # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 443 inline bool isItemAvailable() const |
| 444 { |
| 445 return itemIsUsed_ == 0; |
| 446 } |
| 447 |
| 448 inline void setItemUsed( bool isUsed = true ) |
| 449 { |
| 450 itemIsUsed_ = isUsed ? 1 : 0; |
| 451 } |
| 452 |
| 453 inline bool isMemberNameStatic() const |
| 454 { |
| 455 return memberNameIsStatic_ == 0; |
| 456 } |
| 457 |
| 458 inline void setMemberNameIsStatic( bool isStatic ) |
| 459 { |
| 460 memberNameIsStatic_ = isStatic ? 1 : 0; |
| 461 } |
| 462 # endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 463 |
| 464 private: |
| 465 struct CommentInfo |
| 466 { |
| 467 CommentInfo(); |
| 468 ~CommentInfo(); |
| 469 |
| 470 void setComment( const char *text ); |
| 471 |
| 472 char *comment_; |
| 473 }; |
| 474 |
| 475 //struct MemberNamesTransform |
| 476 //{ |
| 477 // typedef const char *result_type; |
| 478 // const char *operator()( const CZString &name ) const |
| 479 // { |
| 480 // return name.c_str(); |
| 481 // } |
| 482 //}; |
| 483 |
| 484 union ValueHolder |
| 485 { |
| 486 LargestInt int_; |
| 487 LargestUInt uint_; |
| 488 double real_; |
| 489 bool bool_; |
| 490 char *string_; |
| 491 # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 492 ValueInternalArray *array_; |
| 493 ValueInternalMap *map_; |
| 494 #else |
| 495 ObjectValues *map_; |
| 496 # endif |
| 497 } value_; |
| 498 ValueType type_ : 8; |
| 499 int allocated_ : 1; // Notes: if declared as bool, bitfield is useless
. |
| 500 # ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 501 unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap contain
er. |
| 502 int memberNameIsStatic_ : 1; // used by the ValueInternalMap contain
er. |
| 503 # endif |
| 504 CommentInfo *comments_; |
| 505 }; |
| 506 |
| 507 |
| 508 /** \brief Experimental and untested: represents an element of the "path" to
access a node. |
| 509 */ |
| 510 class PathArgument |
| 511 { |
| 512 public: |
| 513 friend class Path; |
| 514 |
| 515 PathArgument(); |
| 516 PathArgument( ArrayIndex index ); |
| 517 PathArgument( const char *key ); |
| 518 PathArgument( const std::string &key ); |
| 519 |
| 520 private: |
| 521 enum Kind |
| 522 { |
| 523 kindNone = 0, |
| 524 kindIndex, |
| 525 kindKey |
| 526 }; |
| 527 std::string key_; |
| 528 ArrayIndex index_; |
| 529 Kind kind_; |
| 530 }; |
| 531 |
| 532 /** \brief Experimental and untested: represents a "path" to access a node. |
| 533 * |
| 534 * Syntax: |
| 535 * - "." => root node |
| 536 * - ".[n]" => elements at index 'n' of root node (an array value) |
| 537 * - ".name" => member named 'name' of root node (an object value) |
| 538 * - ".name1.name2.name3" |
| 539 * - ".[0][1][2].name1[3]" |
| 540 * - ".%" => member name is provided as parameter |
| 541 * - ".[%]" => index is provied as parameter |
| 542 */ |
| 543 class Path |
| 544 { |
| 545 public: |
| 546 Path( const std::string &path, |
| 547 const PathArgument &a1 = PathArgument(), |
| 548 const PathArgument &a2 = PathArgument(), |
| 549 const PathArgument &a3 = PathArgument(), |
| 550 const PathArgument &a4 = PathArgument(), |
| 551 const PathArgument &a5 = PathArgument() ); |
| 552 |
| 553 const Value &resolve( const Value &root ) const; |
| 554 Value resolve( const Value &root, |
| 555 const Value &defaultValue ) const; |
| 556 /// Creates the "path" to access the specified node and returns a referenc
e on the node. |
| 557 Value &make( Value &root ) const; |
| 558 |
| 559 private: |
| 560 typedef std::vector<const PathArgument *> InArgs; |
| 561 typedef std::vector<PathArgument> Args; |
| 562 |
| 563 void makePath( const std::string &path, |
| 564 const InArgs &in ); |
| 565 void addPathInArg( const std::string &path, |
| 566 const InArgs &in, |
| 567 InArgs::const_iterator &itInArg, |
| 568 PathArgument::Kind kind ); |
| 569 void invalidPath( const std::string &path, |
| 570 int location ); |
| 571 |
| 572 Args args_; |
| 573 }; |
| 574 |
| 575 |
| 576 |
| 577 #ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 578 /** \brief Allocator to customize Value internal map. |
| 579 * Below is an example of a simple implementation (default implementation act
ually |
| 580 * use memory pool for speed). |
| 581 * \code |
| 582 class DefaultValueMapAllocator : public ValueMapAllocator |
| 583 { |
| 584 public: // overridden from ValueMapAllocator |
| 585 virtual ValueInternalMap *newMap() |
| 586 { |
| 587 return new ValueInternalMap(); |
| 588 } |
| 589 |
| 590 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) |
| 591 { |
| 592 return new ValueInternalMap( other ); |
| 593 } |
| 594 |
| 595 virtual void destructMap( ValueInternalMap *map ) |
| 596 { |
| 597 delete map; |
| 598 } |
| 599 |
| 600 virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) |
| 601 { |
| 602 return new ValueInternalLink[size]; |
| 603 } |
| 604 |
| 605 virtual void releaseMapBuckets( ValueInternalLink *links ) |
| 606 { |
| 607 delete [] links; |
| 608 } |
| 609 |
| 610 virtual ValueInternalLink *allocateMapLink() |
| 611 { |
| 612 return new ValueInternalLink(); |
| 613 } |
| 614 |
| 615 virtual void releaseMapLink( ValueInternalLink *link ) |
| 616 { |
| 617 delete link; |
| 618 } |
| 619 }; |
| 620 * \endcode |
| 621 */ |
| 622 class JSON_API ValueMapAllocator |
| 623 { |
| 624 public: |
| 625 virtual ~ValueMapAllocator(); |
| 626 virtual ValueInternalMap *newMap() = 0; |
| 627 virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; |
| 628 virtual void destructMap( ValueInternalMap *map ) = 0; |
| 629 virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; |
| 630 virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; |
| 631 virtual ValueInternalLink *allocateMapLink() = 0; |
| 632 virtual void releaseMapLink( ValueInternalLink *link ) = 0; |
| 633 }; |
| 634 |
| 635 /** \brief ValueInternalMap hash-map bucket chain link (for internal use only
). |
| 636 * \internal previous_ & next_ allows for bidirectional traversal. |
| 637 */ |
| 638 class JSON_API ValueInternalLink |
| 639 { |
| 640 public: |
| 641 enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits a
rchitecture. |
| 642 enum InternalFlags { |
| 643 flagAvailable = 0, |
| 644 flagUsed = 1 |
| 645 }; |
| 646 |
| 647 ValueInternalLink(); |
| 648 |
| 649 ~ValueInternalLink(); |
| 650 |
| 651 Value items_[itemPerLink]; |
| 652 char *keys_[itemPerLink]; |
| 653 ValueInternalLink *previous_; |
| 654 ValueInternalLink *next_; |
| 655 }; |
| 656 |
| 657 |
| 658 /** \brief A linked page based hash-table implementation used internally by V
alue. |
| 659 * \internal ValueInternalMap is a tradional bucket based hash-table, with a
linked |
| 660 * list in each bucket to handle collision. There is an addional twist in tha
t |
| 661 * each node of the collision linked list is a page containing a fixed amount
of |
| 662 * value. This provides a better compromise between memory usage and speed. |
| 663 * |
| 664 * Each bucket is made up of a chained list of ValueInternalLink. The last |
| 665 * link of a given bucket can be found in the 'previous_' field of the follow
ing bucket. |
| 666 * The last link of the last bucket is stored in tailLink_ as it has no follo
wing bucket. |
| 667 * Only the last link of a bucket may contains 'available' item. The last lin
k always |
| 668 * contains at least one element unless is it the bucket one very first link. |
| 669 */ |
| 670 class JSON_API ValueInternalMap |
| 671 { |
| 672 friend class ValueIteratorBase; |
| 673 friend class Value; |
| 674 public: |
| 675 typedef unsigned int HashKey; |
| 676 typedef unsigned int BucketIndex; |
| 677 |
| 678 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 679 struct IteratorState |
| 680 { |
| 681 IteratorState() |
| 682 : map_(0) |
| 683 , link_(0) |
| 684 , itemIndex_(0) |
| 685 , bucketIndex_(0) |
| 686 { |
| 687 } |
| 688 ValueInternalMap *map_; |
| 689 ValueInternalLink *link_; |
| 690 BucketIndex itemIndex_; |
| 691 BucketIndex bucketIndex_; |
| 692 }; |
| 693 # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 694 |
| 695 ValueInternalMap(); |
| 696 ValueInternalMap( const ValueInternalMap &other ); |
| 697 ValueInternalMap &operator =( const ValueInternalMap &other ); |
| 698 ~ValueInternalMap(); |
| 699 |
| 700 void swap( ValueInternalMap &other ); |
| 701 |
| 702 BucketIndex size() const; |
| 703 |
| 704 void clear(); |
| 705 |
| 706 bool reserveDelta( BucketIndex growth ); |
| 707 |
| 708 bool reserve( BucketIndex newItemCount ); |
| 709 |
| 710 const Value *find( const char *key ) const; |
| 711 |
| 712 Value *find( const char *key ); |
| 713 |
| 714 Value &resolveReference( const char *key, |
| 715 bool isStatic ); |
| 716 |
| 717 void remove( const char *key ); |
| 718 |
| 719 void doActualRemove( ValueInternalLink *link, |
| 720 BucketIndex index, |
| 721 BucketIndex bucketIndex ); |
| 722 |
| 723 ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); |
| 724 |
| 725 Value &setNewItem( const char *key, |
| 726 bool isStatic, |
| 727 ValueInternalLink *link, |
| 728 BucketIndex index ); |
| 729 |
| 730 Value &unsafeAdd( const char *key, |
| 731 bool isStatic, |
| 732 HashKey hashedKey ); |
| 733 |
| 734 HashKey hash( const char *key ) const; |
| 735 |
| 736 int compare( const ValueInternalMap &other ) const; |
| 737 |
| 738 private: |
| 739 void makeBeginIterator( IteratorState &it ) const; |
| 740 void makeEndIterator( IteratorState &it ) const; |
| 741 static bool equals( const IteratorState &x, const IteratorState &other ); |
| 742 static void increment( IteratorState &iterator ); |
| 743 static void incrementBucket( IteratorState &iterator ); |
| 744 static void decrement( IteratorState &iterator ); |
| 745 static const char *key( const IteratorState &iterator ); |
| 746 static const char *key( const IteratorState &iterator, bool &isStatic ); |
| 747 static Value &value( const IteratorState &iterator ); |
| 748 static int distance( const IteratorState &x, const IteratorState &y ); |
| 749 |
| 750 private: |
| 751 ValueInternalLink *buckets_; |
| 752 ValueInternalLink *tailLink_; |
| 753 BucketIndex bucketsSize_; |
| 754 BucketIndex itemCount_; |
| 755 }; |
| 756 |
| 757 /** \brief A simplified deque implementation used internally by Value. |
| 758 * \internal |
| 759 * It is based on a list of fixed "page", each page contains a fixed number of
items. |
| 760 * Instead of using a linked-list, a array of pointer is used for fast item lo
ok-up. |
| 761 * Look-up for an element is as follow: |
| 762 * - compute page index: pageIndex = itemIndex / itemsPerPage |
| 763 * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] |
| 764 * |
| 765 * Insertion is amortized constant time (only the array containing the index o
f pointers |
| 766 * need to be reallocated when items are appended). |
| 767 */ |
| 768 class JSON_API ValueInternalArray |
| 769 { |
| 770 friend class Value; |
| 771 friend class ValueIteratorBase; |
| 772 public: |
| 773 enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide an
d modulo. |
| 774 typedef Value::ArrayIndex ArrayIndex; |
| 775 typedef unsigned int PageIndex; |
| 776 |
| 777 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 778 struct IteratorState // Must be a POD |
| 779 { |
| 780 IteratorState() |
| 781 : array_(0) |
| 782 , currentPageIndex_(0) |
| 783 , currentItemIndex_(0) |
| 784 { |
| 785 } |
| 786 ValueInternalArray *array_; |
| 787 Value **currentPageIndex_; |
| 788 unsigned int currentItemIndex_; |
| 789 }; |
| 790 # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION |
| 791 |
| 792 ValueInternalArray(); |
| 793 ValueInternalArray( const ValueInternalArray &other ); |
| 794 ValueInternalArray &operator =( const ValueInternalArray &other ); |
| 795 ~ValueInternalArray(); |
| 796 void swap( ValueInternalArray &other ); |
| 797 |
| 798 void clear(); |
| 799 void resize( ArrayIndex newSize ); |
| 800 |
| 801 Value &resolveReference( ArrayIndex index ); |
| 802 |
| 803 Value *find( ArrayIndex index ) const; |
| 804 |
| 805 ArrayIndex size() const; |
| 806 |
| 807 int compare( const ValueInternalArray &other ) const; |
| 808 |
| 809 private: |
| 810 static bool equals( const IteratorState &x, const IteratorState &other ); |
| 811 static void increment( IteratorState &iterator ); |
| 812 static void decrement( IteratorState &iterator ); |
| 813 static Value &dereference( const IteratorState &iterator ); |
| 814 static Value &unsafeDereference( const IteratorState &iterator ); |
| 815 static int distance( const IteratorState &x, const IteratorState &y ); |
| 816 static ArrayIndex indexOf( const IteratorState &iterator ); |
| 817 void makeBeginIterator( IteratorState &it ) const; |
| 818 void makeEndIterator( IteratorState &it ) const; |
| 819 void makeIterator( IteratorState &it, ArrayIndex index ) const; |
| 820 |
| 821 void makeIndexValid( ArrayIndex index ); |
| 822 |
| 823 Value **pages_; |
| 824 ArrayIndex size_; |
| 825 PageIndex pageCount_; |
| 826 }; |
| 827 |
| 828 /** \brief Experimental: do not use. Allocator to customize Value internal ar
ray. |
| 829 * Below is an example of a simple implementation (actual implementation use |
| 830 * memory pool). |
| 831 \code |
| 832 class DefaultValueArrayAllocator : public ValueArrayAllocator |
| 833 { |
| 834 public: // overridden from ValueArrayAllocator |
| 835 virtual ~DefaultValueArrayAllocator() |
| 836 { |
| 837 } |
| 838 |
| 839 virtual ValueInternalArray *newArray() |
| 840 { |
| 841 return new ValueInternalArray(); |
| 842 } |
| 843 |
| 844 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) |
| 845 { |
| 846 return new ValueInternalArray( other ); |
| 847 } |
| 848 |
| 849 virtual void destruct( ValueInternalArray *array ) |
| 850 { |
| 851 delete array; |
| 852 } |
| 853 |
| 854 virtual void reallocateArrayPageIndex( Value **&indexes, |
| 855 ValueInternalArray::PageIndex &indexCo
unt, |
| 856 ValueInternalArray::PageIndex minNewIn
dexCount ) |
| 857 { |
| 858 ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; |
| 859 if ( minNewIndexCount > newIndexCount ) |
| 860 newIndexCount = minNewIndexCount; |
| 861 void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); |
| 862 if ( !newIndexes ) |
| 863 throw std::bad_alloc(); |
| 864 indexCount = newIndexCount; |
| 865 indexes = static_cast<Value **>( newIndexes ); |
| 866 } |
| 867 virtual void releaseArrayPageIndex( Value **indexes, |
| 868 ValueInternalArray::PageIndex indexCount
) |
| 869 { |
| 870 if ( indexes ) |
| 871 free( indexes ); |
| 872 } |
| 873 |
| 874 virtual Value *allocateArrayPage() |
| 875 { |
| 876 return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::i
temsPerPage ) ); |
| 877 } |
| 878 |
| 879 virtual void releaseArrayPage( Value *value ) |
| 880 { |
| 881 if ( value ) |
| 882 free( value ); |
| 883 } |
| 884 }; |
| 885 \endcode |
| 886 */ |
| 887 class JSON_API ValueArrayAllocator |
| 888 { |
| 889 public: |
| 890 virtual ~ValueArrayAllocator(); |
| 891 virtual ValueInternalArray *newArray() = 0; |
| 892 virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other
) = 0; |
| 893 virtual void destructArray( ValueInternalArray *array ) = 0; |
| 894 /** \brief Reallocate array page index. |
| 895 * Reallocates an array of pointer on each page. |
| 896 * \param indexes [input] pointer on the current index. May be \c NULL. |
| 897 * [output] pointer on the new index of at least |
| 898 * \a minNewIndexCount pages. |
| 899 * \param indexCount [input] current number of pages in the index. |
| 900 * [output] number of page the reallocated index can han
dle. |
| 901 * \b MUST be >= \a minNewIndexCount. |
| 902 * \param minNewIndexCount Minimum number of page the new index must be ab
le to |
| 903 * handle. |
| 904 */ |
| 905 virtual void reallocateArrayPageIndex( Value **&indexes, |
| 906 ValueInternalArray::PageIndex &inde
xCount, |
| 907 ValueInternalArray::PageIndex minNe
wIndexCount ) = 0; |
| 908 virtual void releaseArrayPageIndex( Value **indexes, |
| 909 ValueInternalArray::PageIndex indexCou
nt ) = 0; |
| 910 virtual Value *allocateArrayPage() = 0; |
| 911 virtual void releaseArrayPage( Value *value ) = 0; |
| 912 }; |
| 913 #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP |
| 914 |
| 915 |
| 916 /** \brief base class for Value iterators. |
| 917 * |
| 918 */ |
| 919 class ValueIteratorBase |
| 920 { |
| 921 public: |
| 922 typedef unsigned int size_t; |
| 923 typedef int difference_type; |
| 924 typedef ValueIteratorBase SelfType; |
| 925 |
| 926 ValueIteratorBase(); |
| 927 #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 928 explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t )
; |
| 929 #else |
| 930 ValueIteratorBase( const ValueInternalArray::IteratorState &state ); |
| 931 ValueIteratorBase( const ValueInternalMap::IteratorState &state ); |
| 932 #endif |
| 933 |
| 934 bool operator ==( const SelfType &other ) const |
| 935 { |
| 936 return isEqual( other ); |
| 937 } |
| 938 |
| 939 bool operator !=( const SelfType &other ) const |
| 940 { |
| 941 return !isEqual( other ); |
| 942 } |
| 943 |
| 944 difference_type operator -( const SelfType &other ) const |
| 945 { |
| 946 return computeDistance( other ); |
| 947 } |
| 948 |
| 949 /// Return either the index or the member name of the referenced value as
a Value. |
| 950 Value key() const; |
| 951 |
| 952 /// Return the index of the referenced Value. -1 if it is not an arrayValu
e. |
| 953 UInt index() const; |
| 954 |
| 955 /// Return the member name of the referenced Value. "" if it is not an obj
ectValue. |
| 956 const char *memberName() const; |
| 957 |
| 958 protected: |
| 959 Value &deref() const; |
| 960 |
| 961 void increment(); |
| 962 |
| 963 void decrement(); |
| 964 |
| 965 difference_type computeDistance( const SelfType &other ) const; |
| 966 |
| 967 bool isEqual( const SelfType &other ) const; |
| 968 |
| 969 void copy( const SelfType &other ); |
| 970 |
| 971 private: |
| 972 #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 973 Value::ObjectValues::iterator current_; |
| 974 // Indicates that iterator is for a null value. |
| 975 bool isNull_; |
| 976 #else |
| 977 union |
| 978 { |
| 979 ValueInternalArray::IteratorState array_; |
| 980 ValueInternalMap::IteratorState map_; |
| 981 } iterator_; |
| 982 bool isArray_; |
| 983 #endif |
| 984 }; |
| 985 |
| 986 /** \brief const iterator for object and array value. |
| 987 * |
| 988 */ |
| 989 class ValueConstIterator : public ValueIteratorBase |
| 990 { |
| 991 friend class Value; |
| 992 public: |
| 993 typedef unsigned int size_t; |
| 994 typedef int difference_type; |
| 995 typedef const Value &reference; |
| 996 typedef const Value *pointer; |
| 997 typedef ValueConstIterator SelfType; |
| 998 |
| 999 ValueConstIterator(); |
| 1000 private: |
| 1001 /*! \internal Use by Value to create an iterator. |
| 1002 */ |
| 1003 #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 1004 explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t
); |
| 1005 #else |
| 1006 ValueConstIterator( const ValueInternalArray::IteratorState &state ); |
| 1007 ValueConstIterator( const ValueInternalMap::IteratorState &state ); |
| 1008 #endif |
| 1009 public: |
| 1010 SelfType &operator =( const ValueIteratorBase &other ); |
| 1011 |
| 1012 SelfType operator++( int ) |
| 1013 { |
| 1014 SelfType temp( *this ); |
| 1015 ++*this; |
| 1016 return temp; |
| 1017 } |
| 1018 |
| 1019 SelfType operator--( int ) |
| 1020 { |
| 1021 SelfType temp( *this ); |
| 1022 --*this; |
| 1023 return temp; |
| 1024 } |
| 1025 |
| 1026 SelfType &operator--() |
| 1027 { |
| 1028 decrement(); |
| 1029 return *this; |
| 1030 } |
| 1031 |
| 1032 SelfType &operator++() |
| 1033 { |
| 1034 increment(); |
| 1035 return *this; |
| 1036 } |
| 1037 |
| 1038 reference operator *() const |
| 1039 { |
| 1040 return deref(); |
| 1041 } |
| 1042 }; |
| 1043 |
| 1044 |
| 1045 /** \brief Iterator for object and array value. |
| 1046 */ |
| 1047 class ValueIterator : public ValueIteratorBase |
| 1048 { |
| 1049 friend class Value; |
| 1050 public: |
| 1051 typedef unsigned int size_t; |
| 1052 typedef int difference_type; |
| 1053 typedef Value &reference; |
| 1054 typedef Value *pointer; |
| 1055 typedef ValueIterator SelfType; |
| 1056 |
| 1057 ValueIterator(); |
| 1058 ValueIterator( const ValueConstIterator &other ); |
| 1059 ValueIterator( const ValueIterator &other ); |
| 1060 private: |
| 1061 /*! \internal Use by Value to create an iterator. |
| 1062 */ |
| 1063 #ifndef JSON_VALUE_USE_INTERNAL_MAP |
| 1064 explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); |
| 1065 #else |
| 1066 ValueIterator( const ValueInternalArray::IteratorState &state ); |
| 1067 ValueIterator( const ValueInternalMap::IteratorState &state ); |
| 1068 #endif |
| 1069 public: |
| 1070 |
| 1071 SelfType &operator =( const SelfType &other ); |
| 1072 |
| 1073 SelfType operator++( int ) |
| 1074 { |
| 1075 SelfType temp( *this ); |
| 1076 ++*this; |
| 1077 return temp; |
| 1078 } |
| 1079 |
| 1080 SelfType operator--( int ) |
| 1081 { |
| 1082 SelfType temp( *this ); |
| 1083 --*this; |
| 1084 return temp; |
| 1085 } |
| 1086 |
| 1087 SelfType &operator--() |
| 1088 { |
| 1089 decrement(); |
| 1090 return *this; |
| 1091 } |
| 1092 |
| 1093 SelfType &operator++() |
| 1094 { |
| 1095 increment(); |
| 1096 return *this; |
| 1097 } |
| 1098 |
| 1099 reference operator *() const |
| 1100 { |
| 1101 return deref(); |
| 1102 } |
| 1103 }; |
| 1104 |
| 1105 |
| 1106 } // namespace Json |
| 1107 |
| 1108 |
| 1109 #endif // CPPTL_JSON_H_INCLUDED |
OLD | NEW |