annotate json/value.h @ 49:178642d134a7 tip

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