rt300@9: #ifndef CPPTL_JSON_H_INCLUDED rt300@9: # define CPPTL_JSON_H_INCLUDED rt300@9: rt300@9: # include "forwards.h" rt300@9: # include rt300@9: # include rt300@9: rt300@9: # ifndef JSON_USE_CPPTL_SMALLMAP rt300@9: # include rt300@9: # else rt300@9: # include rt300@9: # endif rt300@9: # ifdef JSON_USE_CPPTL rt300@9: # include rt300@9: # endif rt300@9: rt300@9: /** \brief JSON (JavaScript Object Notation). rt300@9: */ rt300@9: namespace Json { rt300@9: rt300@9: /** \brief Type of the value held by a Value object. rt300@9: */ rt300@9: enum ValueType rt300@9: { rt300@9: nullValue = 0, ///< 'null' value rt300@9: intValue, ///< signed integer value rt300@9: uintValue, ///< unsigned integer value rt300@9: realValue, ///< double value rt300@9: stringValue, ///< UTF-8 string value rt300@9: booleanValue, ///< bool value rt300@9: arrayValue, ///< array value (ordered list) rt300@9: objectValue ///< object value (collection of name/value pairs). rt300@9: }; rt300@9: rt300@9: enum CommentPlacement rt300@9: { rt300@9: commentBefore = 0, ///< a comment placed on the line before a value rt300@9: commentAfterOnSameLine, ///< a comment just after a value on the same line rt300@9: commentAfter, ///< a comment on the line after a value (only make sense for root value) rt300@9: numberOfCommentPlacement rt300@9: }; rt300@9: rt300@9: //# ifdef JSON_USE_CPPTL rt300@9: // typedef CppTL::AnyEnumerator EnumMemberNames; rt300@9: // typedef CppTL::AnyEnumerator EnumValues; rt300@9: //# endif rt300@9: rt300@9: /** \brief Lightweight wrapper to tag static string. rt300@9: * rt300@9: * Value constructor and objectValue member assignement takes advantage of the rt300@9: * StaticString and avoid the cost of string duplication when storing the rt300@9: * string or the member name. rt300@9: * rt300@9: * Example of usage: rt300@9: * \code rt300@9: * Json::Value aValue( StaticString("some text") ); rt300@9: * Json::Value object; rt300@9: * static const StaticString code("code"); rt300@9: * object[code] = 1234; rt300@9: * \endcode rt300@9: */ rt300@9: class JSON_API StaticString rt300@9: { rt300@9: public: rt300@9: explicit StaticString( const char *czstring ) rt300@9: : str_( czstring ) rt300@9: { rt300@9: } rt300@9: rt300@9: operator const char *() const rt300@9: { rt300@9: return str_; rt300@9: } rt300@9: rt300@9: const char *c_str() const rt300@9: { rt300@9: return str_; rt300@9: } rt300@9: rt300@9: private: rt300@9: const char *str_; rt300@9: }; rt300@9: rt300@9: /** \brief Represents a JSON value. rt300@9: * rt300@9: * This class is a discriminated union wrapper that can represents a: rt300@9: * - signed integer [range: Value::minInt - Value::maxInt] rt300@9: * - unsigned integer (range: 0 - Value::maxUInt) rt300@9: * - double rt300@9: * - UTF-8 string rt300@9: * - boolean rt300@9: * - 'null' rt300@9: * - an ordered list of Value rt300@9: * - collection of name/value pairs (javascript object) rt300@9: * rt300@9: * The type of the held value is represented by a #ValueType and rt300@9: * can be obtained using type(). rt300@9: * rt300@9: * values of an #objectValue or #arrayValue can be accessed using operator[]() methods. rt300@9: * Non const methods will automatically create the a #nullValue element rt300@9: * if it does not exist. rt300@9: * The sequence of an #arrayValue will be automatically resize and initialized rt300@9: * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue. rt300@9: * rt300@9: * The get() methods can be used to obtanis default value in the case the required element rt300@9: * does not exist. rt300@9: * rt300@9: * It is possible to iterate over the list of a #objectValue values using rt300@9: * the getMemberNames() method. rt300@9: */ rt300@9: class JSON_API Value rt300@9: { rt300@9: friend class ValueIteratorBase; rt300@9: # ifdef JSON_VALUE_USE_INTERNAL_MAP rt300@9: friend class ValueInternalLink; rt300@9: friend class ValueInternalMap; rt300@9: # endif rt300@9: public: rt300@9: typedef std::vector Members; rt300@9: typedef ValueIterator iterator; rt300@9: typedef ValueConstIterator const_iterator; rt300@9: typedef Json::UInt UInt; rt300@9: typedef Json::Int Int; rt300@9: typedef UInt ArrayIndex; rt300@9: rt300@9: static const Value null; rt300@9: static const Int minInt; rt300@9: static const Int maxInt; rt300@9: static const UInt maxUInt; rt300@9: rt300@9: private: rt300@9: #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION rt300@9: # ifndef JSON_VALUE_USE_INTERNAL_MAP rt300@9: class CZString rt300@9: { rt300@9: public: rt300@9: enum DuplicationPolicy rt300@9: { rt300@9: noDuplication = 0, rt300@9: duplicate, rt300@9: duplicateOnCopy rt300@9: }; rt300@9: CZString( int index ); rt300@9: CZString( const char *cstr, DuplicationPolicy allocate ); rt300@9: CZString( const CZString &other ); rt300@9: ~CZString(); rt300@9: CZString &operator =( const CZString &other ); rt300@9: bool operator<( const CZString &other ) const; rt300@9: bool operator==( const CZString &other ) const; rt300@9: int index() const; rt300@9: const char *c_str() const; rt300@9: bool isStaticString() const; rt300@9: private: rt300@9: void swap( CZString &other ); rt300@9: const char *cstr_; rt300@9: int index_; rt300@9: }; rt300@9: rt300@9: public: rt300@9: # ifndef JSON_USE_CPPTL_SMALLMAP rt300@9: typedef std::map ObjectValues; rt300@9: # else rt300@9: typedef CppTL::SmallMap ObjectValues; rt300@9: # endif // ifndef JSON_USE_CPPTL_SMALLMAP rt300@9: # endif // ifndef JSON_VALUE_USE_INTERNAL_MAP rt300@9: #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION rt300@9: rt300@9: public: rt300@9: /** \brief Create a default Value of the given type. rt300@9: rt300@9: This is a very useful constructor. rt300@9: To create an empty array, pass arrayValue. rt300@9: To create an empty object, pass objectValue. rt300@9: Another Value can then be set to this one by assignment. rt300@9: This is useful since clear() and resize() will not alter types. rt300@9: rt300@9: Examples: rt300@9: \code rt300@9: Json::Value null_value; // null rt300@9: Json::Value arr_value(Json::arrayValue); // [] rt300@9: Json::Value obj_value(Json::objectValue); // {} rt300@9: \endcode rt300@9: */ rt300@9: Value( ValueType type = nullValue ); rt300@9: Value( Int value ); rt300@9: Value( UInt value ); rt300@9: Value( double value ); rt300@9: Value( const char *value ); rt300@9: Value( const char *beginValue, const char *endValue ); rt300@9: /** \brief Constructs a value from a static string. rt300@9: rt300@9: * Like other value string constructor but do not duplicate the string for rt300@9: * internal storage. The given string must remain alive after the call to this rt300@9: * constructor. rt300@9: * Example of usage: rt300@9: * \code rt300@9: * Json::Value aValue( StaticString("some text") ); rt300@9: * \endcode rt300@9: */ rt300@9: Value( const StaticString &value ); rt300@9: Value( const std::string &value ); rt300@9: # ifdef JSON_USE_CPPTL rt300@9: Value( const CppTL::ConstString &value ); rt300@9: # endif rt300@9: Value( bool value ); rt300@9: Value( const Value &other ); rt300@9: ~Value(); rt300@9: rt300@9: Value &operator=( const Value &other ); rt300@9: /// Swap values. rt300@9: /// \note Currently, comments are intentionally not swapped, for rt300@9: /// both logic and efficiency. rt300@9: void swap( Value &other ); rt300@9: rt300@9: ValueType type() const; rt300@9: rt300@9: bool operator <( const Value &other ) const; rt300@9: bool operator <=( const Value &other ) const; rt300@9: bool operator >=( const Value &other ) const; rt300@9: bool operator >( const Value &other ) const; rt300@9: rt300@9: bool operator ==( const Value &other ) const; rt300@9: bool operator !=( const Value &other ) const; rt300@9: rt300@9: int compare( const Value &other ); rt300@9: rt300@9: const char *asCString() const; rt300@9: std::string asString() const; rt300@9: # ifdef JSON_USE_CPPTL rt300@9: CppTL::ConstString asConstString() const; rt300@9: # endif rt300@9: Int asInt() const; rt300@9: UInt asUInt() const; rt300@9: double asDouble() const; rt300@9: bool asBool() const; rt300@9: rt300@9: bool isNull() const; rt300@9: bool isBool() const; rt300@9: bool isInt() const; rt300@9: bool isUInt() const; rt300@9: bool isIntegral() const; rt300@9: bool isDouble() const; rt300@9: bool isNumeric() const; rt300@9: bool isString() const; rt300@9: bool isArray() const; rt300@9: bool isObject() const; rt300@9: rt300@9: bool isConvertibleTo( ValueType other ) const; rt300@9: rt300@9: /// Number of values in array or object rt300@9: UInt size() const; rt300@9: rt300@9: /// \brief Return true if empty array, empty object, or null; rt300@9: /// otherwise, false. rt300@9: bool empty() const; rt300@9: rt300@9: /// Return isNull() rt300@9: bool operator!() const; rt300@9: rt300@9: /// Remove all object members and array elements. rt300@9: /// \pre type() is arrayValue, objectValue, or nullValue rt300@9: /// \post type() is unchanged rt300@9: void clear(); rt300@9: rt300@9: /// Resize the array to size elements. rt300@9: /// New elements are initialized to null. rt300@9: /// May only be called on nullValue or arrayValue. rt300@9: /// \pre type() is arrayValue or nullValue rt300@9: /// \post type() is arrayValue rt300@9: void resize( UInt size ); rt300@9: rt300@9: /// Access an array element (zero based index ). rt300@9: /// If the array contains less than index element, then null value are inserted rt300@9: /// in the array so that its size is index+1. rt300@9: /// (You may need to say 'value[0u]' to get your compiler to distinguish rt300@9: /// this from the operator[] which takes a string.) rt300@9: Value &operator[]( UInt index ); rt300@9: /// Access an array element (zero based index ) rt300@9: /// (You may need to say 'value[0u]' to get your compiler to distinguish rt300@9: /// this from the operator[] which takes a string.) rt300@9: const Value &operator[]( UInt index ) const; rt300@9: /// If the array contains at least index+1 elements, returns the element value, rt300@9: /// otherwise returns defaultValue. rt300@9: Value get( UInt index, rt300@9: const Value &defaultValue ) const; rt300@9: /// Return true if index < size(). rt300@9: bool isValidIndex( UInt index ) const; rt300@9: /// \brief Append value to array at the end. rt300@9: /// rt300@9: /// Equivalent to jsonvalue[jsonvalue.size()] = value; rt300@9: Value &append( const Value &value ); rt300@9: rt300@9: /// Access an object value by name, create a null member if it does not exist. rt300@9: Value &operator[]( const char *key ); rt300@9: /// Access an object value by name, returns null if there is no member with that name. rt300@9: const Value &operator[]( const char *key ) const; rt300@9: /// Access an object value by name, create a null member if it does not exist. rt300@9: Value &operator[]( const std::string &key ); rt300@9: /// Access an object value by name, returns null if there is no member with that name. rt300@9: const Value &operator[]( const std::string &key ) const; rt300@9: /** \brief Access an object value by name, create a null member if it does not exist. rt300@9: rt300@9: * If the object as no entry for that name, then the member name used to store rt300@9: * the new entry is not duplicated. rt300@9: * Example of use: rt300@9: * \code rt300@9: * Json::Value object; rt300@9: * static const StaticString code("code"); rt300@9: * object[code] = 1234; rt300@9: * \endcode rt300@9: */ rt300@9: Value &operator[]( const StaticString &key ); rt300@9: # ifdef JSON_USE_CPPTL rt300@9: /// Access an object value by name, create a null member if it does not exist. rt300@9: Value &operator[]( const CppTL::ConstString &key ); rt300@9: /// Access an object value by name, returns null if there is no member with that name. rt300@9: const Value &operator[]( const CppTL::ConstString &key ) const; rt300@9: # endif rt300@9: /// Return the member named key if it exist, defaultValue otherwise. rt300@9: Value get( const char *key, rt300@9: const Value &defaultValue ) const; rt300@9: /// Return the member named key if it exist, defaultValue otherwise. rt300@9: Value get( const std::string &key, rt300@9: const Value &defaultValue ) const; rt300@9: # ifdef JSON_USE_CPPTL rt300@9: /// Return the member named key if it exist, defaultValue otherwise. rt300@9: Value get( const CppTL::ConstString &key, rt300@9: const Value &defaultValue ) const; rt300@9: # endif rt300@9: /// \brief Remove and return the named member. rt300@9: /// rt300@9: /// Do nothing if it did not exist. rt300@9: /// \return the removed Value, or null. rt300@9: /// \pre type() is objectValue or nullValue rt300@9: /// \post type() is unchanged rt300@9: Value removeMember( const char* key ); rt300@9: /// Same as removeMember(const char*) rt300@9: Value removeMember( const std::string &key ); rt300@9: rt300@9: /// Return true if the object has a member named key. rt300@9: bool isMember( const char *key ) const; rt300@9: /// Return true if the object has a member named key. rt300@9: bool isMember( const std::string &key ) const; rt300@9: # ifdef JSON_USE_CPPTL rt300@9: /// Return true if the object has a member named key. rt300@9: bool isMember( const CppTL::ConstString &key ) const; rt300@9: # endif rt300@9: rt300@9: /// \brief Return a list of the member names. rt300@9: /// rt300@9: /// If null, return an empty list. rt300@9: /// \pre type() is objectValue or nullValue rt300@9: /// \post if type() was nullValue, it remains nullValue rt300@9: Members getMemberNames() const; rt300@9: rt300@9: //# ifdef JSON_USE_CPPTL rt300@9: // EnumMemberNames enumMemberNames() const; rt300@9: // EnumValues enumValues() const; rt300@9: //# endif rt300@9: rt300@9: /// Comments must be //... or /* ... */ rt300@9: void setComment( const char *comment, rt300@9: CommentPlacement placement ); rt300@9: /// Comments must be //... or /* ... */ rt300@9: void setComment( const std::string &comment, rt300@9: CommentPlacement placement ); rt300@9: bool hasComment( CommentPlacement placement ) const; rt300@9: /// Include delimiters and embedded newlines. rt300@9: std::string getComment( CommentPlacement placement ) const; rt300@9: rt300@9: std::string toStyledString() const; rt300@9: rt300@9: const_iterator begin() const; rt300@9: const_iterator end() const; rt300@9: rt300@9: iterator begin(); rt300@9: iterator end(); rt300@9: rt300@9: private: rt300@9: Value &resolveReference( const char *key, rt300@9: bool isStatic ); rt300@9: rt300@9: # ifdef JSON_VALUE_USE_INTERNAL_MAP rt300@9: inline bool isItemAvailable() const rt300@9: { rt300@9: return itemIsUsed_ == 0; rt300@9: } rt300@9: rt300@9: inline void setItemUsed( bool isUsed = true ) rt300@9: { rt300@9: itemIsUsed_ = isUsed ? 1 : 0; rt300@9: } rt300@9: rt300@9: inline bool isMemberNameStatic() const rt300@9: { rt300@9: return memberNameIsStatic_ == 0; rt300@9: } rt300@9: rt300@9: inline void setMemberNameIsStatic( bool isStatic ) rt300@9: { rt300@9: memberNameIsStatic_ = isStatic ? 1 : 0; rt300@9: } rt300@9: # endif // # ifdef JSON_VALUE_USE_INTERNAL_MAP rt300@9: rt300@9: private: rt300@9: struct CommentInfo rt300@9: { rt300@9: CommentInfo(); rt300@9: ~CommentInfo(); rt300@9: rt300@9: void setComment( const char *text ); rt300@9: rt300@9: char *comment_; rt300@9: }; rt300@9: rt300@9: //struct MemberNamesTransform rt300@9: //{ rt300@9: // typedef const char *result_type; rt300@9: // const char *operator()( const CZString &name ) const rt300@9: // { rt300@9: // return name.c_str(); rt300@9: // } rt300@9: //}; rt300@9: rt300@9: union ValueHolder rt300@9: { rt300@9: Int int_; rt300@9: UInt uint_; rt300@9: double real_; rt300@9: bool bool_; rt300@9: char *string_; rt300@9: # ifdef JSON_VALUE_USE_INTERNAL_MAP rt300@9: ValueInternalArray *array_; rt300@9: ValueInternalMap *map_; rt300@9: #else rt300@9: ObjectValues *map_; rt300@9: # endif rt300@9: } value_; rt300@9: ValueType type_ : 8; rt300@9: int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. rt300@9: # ifdef JSON_VALUE_USE_INTERNAL_MAP rt300@9: unsigned int itemIsUsed_ : 1; // used by the ValueInternalMap container. rt300@9: int memberNameIsStatic_ : 1; // used by the ValueInternalMap container. rt300@9: # endif rt300@9: CommentInfo *comments_; rt300@9: }; rt300@9: rt300@9: rt300@9: /** \brief Experimental and untested: represents an element of the "path" to access a node. rt300@9: */ rt300@9: class PathArgument rt300@9: { rt300@9: public: rt300@9: friend class Path; rt300@9: rt300@9: PathArgument(); rt300@9: PathArgument( UInt index ); rt300@9: PathArgument( const char *key ); rt300@9: PathArgument( const std::string &key ); rt300@9: rt300@9: private: rt300@9: enum Kind rt300@9: { rt300@9: kindNone = 0, rt300@9: kindIndex, rt300@9: kindKey rt300@9: }; rt300@9: std::string key_; rt300@9: UInt index_; rt300@9: Kind kind_; rt300@9: }; rt300@9: rt300@9: /** \brief Experimental and untested: represents a "path" to access a node. rt300@9: * rt300@9: * Syntax: rt300@9: * - "." => root node rt300@9: * - ".[n]" => elements at index 'n' of root node (an array value) rt300@9: * - ".name" => member named 'name' of root node (an object value) rt300@9: * - ".name1.name2.name3" rt300@9: * - ".[0][1][2].name1[3]" rt300@9: * - ".%" => member name is provided as parameter rt300@9: * - ".[%]" => index is provied as parameter rt300@9: */ rt300@9: class Path rt300@9: { rt300@9: public: rt300@9: Path( const std::string &path, rt300@9: const PathArgument &a1 = PathArgument(), rt300@9: const PathArgument &a2 = PathArgument(), rt300@9: const PathArgument &a3 = PathArgument(), rt300@9: const PathArgument &a4 = PathArgument(), rt300@9: const PathArgument &a5 = PathArgument() ); rt300@9: rt300@9: const Value &resolve( const Value &root ) const; rt300@9: Value resolve( const Value &root, rt300@9: const Value &defaultValue ) const; rt300@9: /// Creates the "path" to access the specified node and returns a reference on the node. rt300@9: Value &make( Value &root ) const; rt300@9: rt300@9: private: rt300@9: typedef std::vector InArgs; rt300@9: typedef std::vector Args; rt300@9: rt300@9: void makePath( const std::string &path, rt300@9: const InArgs &in ); rt300@9: void addPathInArg( const std::string &path, rt300@9: const InArgs &in, rt300@9: InArgs::const_iterator &itInArg, rt300@9: PathArgument::Kind kind ); rt300@9: void invalidPath( const std::string &path, rt300@9: int location ); rt300@9: rt300@9: Args args_; rt300@9: }; rt300@9: rt300@9: /** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value. rt300@9: * rt300@9: * - makeMemberName() and releaseMemberName() are called to respectively duplicate and rt300@9: * free an Json::objectValue member name. rt300@9: * - duplicateStringValue() and releaseStringValue() are called similarly to rt300@9: * duplicate and free a Json::stringValue value. rt300@9: */ rt300@9: class ValueAllocator rt300@9: { rt300@9: public: rt300@9: enum { unknown = (unsigned)-1 }; rt300@9: rt300@9: virtual ~ValueAllocator(); rt300@9: rt300@9: virtual char *makeMemberName( const char *memberName ) = 0; rt300@9: virtual void releaseMemberName( char *memberName ) = 0; rt300@9: virtual char *duplicateStringValue( const char *value, rt300@9: unsigned int length = unknown ) = 0; rt300@9: virtual void releaseStringValue( char *value ) = 0; rt300@9: }; rt300@9: rt300@9: #ifdef JSON_VALUE_USE_INTERNAL_MAP rt300@9: /** \brief Allocator to customize Value internal map. rt300@9: * Below is an example of a simple implementation (default implementation actually rt300@9: * use memory pool for speed). rt300@9: * \code rt300@9: class DefaultValueMapAllocator : public ValueMapAllocator rt300@9: { rt300@9: public: // overridden from ValueMapAllocator rt300@9: virtual ValueInternalMap *newMap() rt300@9: { rt300@9: return new ValueInternalMap(); rt300@9: } rt300@9: rt300@9: virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) rt300@9: { rt300@9: return new ValueInternalMap( other ); rt300@9: } rt300@9: rt300@9: virtual void destructMap( ValueInternalMap *map ) rt300@9: { rt300@9: delete map; rt300@9: } rt300@9: rt300@9: virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) rt300@9: { rt300@9: return new ValueInternalLink[size]; rt300@9: } rt300@9: rt300@9: virtual void releaseMapBuckets( ValueInternalLink *links ) rt300@9: { rt300@9: delete [] links; rt300@9: } rt300@9: rt300@9: virtual ValueInternalLink *allocateMapLink() rt300@9: { rt300@9: return new ValueInternalLink(); rt300@9: } rt300@9: rt300@9: virtual void releaseMapLink( ValueInternalLink *link ) rt300@9: { rt300@9: delete link; rt300@9: } rt300@9: }; rt300@9: * \endcode rt300@9: */ rt300@9: class JSON_API ValueMapAllocator rt300@9: { rt300@9: public: rt300@9: virtual ~ValueMapAllocator(); rt300@9: virtual ValueInternalMap *newMap() = 0; rt300@9: virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other ) = 0; rt300@9: virtual void destructMap( ValueInternalMap *map ) = 0; rt300@9: virtual ValueInternalLink *allocateMapBuckets( unsigned int size ) = 0; rt300@9: virtual void releaseMapBuckets( ValueInternalLink *links ) = 0; rt300@9: virtual ValueInternalLink *allocateMapLink() = 0; rt300@9: virtual void releaseMapLink( ValueInternalLink *link ) = 0; rt300@9: }; rt300@9: rt300@9: /** \brief ValueInternalMap hash-map bucket chain link (for internal use only). rt300@9: * \internal previous_ & next_ allows for bidirectional traversal. rt300@9: */ rt300@9: class JSON_API ValueInternalLink rt300@9: { rt300@9: public: rt300@9: enum { itemPerLink = 6 }; // sizeof(ValueInternalLink) = 128 on 32 bits architecture. rt300@9: enum InternalFlags { rt300@9: flagAvailable = 0, rt300@9: flagUsed = 1 rt300@9: }; rt300@9: rt300@9: ValueInternalLink(); rt300@9: rt300@9: ~ValueInternalLink(); rt300@9: rt300@9: Value items_[itemPerLink]; rt300@9: char *keys_[itemPerLink]; rt300@9: ValueInternalLink *previous_; rt300@9: ValueInternalLink *next_; rt300@9: }; rt300@9: rt300@9: rt300@9: /** \brief A linked page based hash-table implementation used internally by Value. rt300@9: * \internal ValueInternalMap is a tradional bucket based hash-table, with a linked rt300@9: * list in each bucket to handle collision. There is an addional twist in that rt300@9: * each node of the collision linked list is a page containing a fixed amount of rt300@9: * value. This provides a better compromise between memory usage and speed. rt300@9: * rt300@9: * Each bucket is made up of a chained list of ValueInternalLink. The last rt300@9: * link of a given bucket can be found in the 'previous_' field of the following bucket. rt300@9: * The last link of the last bucket is stored in tailLink_ as it has no following bucket. rt300@9: * Only the last link of a bucket may contains 'available' item. The last link always rt300@9: * contains at least one element unless is it the bucket one very first link. rt300@9: */ rt300@9: class JSON_API ValueInternalMap rt300@9: { rt300@9: friend class ValueIteratorBase; rt300@9: friend class Value; rt300@9: public: rt300@9: typedef unsigned int HashKey; rt300@9: typedef unsigned int BucketIndex; rt300@9: rt300@9: # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION rt300@9: struct IteratorState rt300@9: { rt300@9: IteratorState() rt300@9: : map_(0) rt300@9: , link_(0) rt300@9: , itemIndex_(0) rt300@9: , bucketIndex_(0) rt300@9: { rt300@9: } rt300@9: ValueInternalMap *map_; rt300@9: ValueInternalLink *link_; rt300@9: BucketIndex itemIndex_; rt300@9: BucketIndex bucketIndex_; rt300@9: }; rt300@9: # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION rt300@9: rt300@9: ValueInternalMap(); rt300@9: ValueInternalMap( const ValueInternalMap &other ); rt300@9: ValueInternalMap &operator =( const ValueInternalMap &other ); rt300@9: ~ValueInternalMap(); rt300@9: rt300@9: void swap( ValueInternalMap &other ); rt300@9: rt300@9: BucketIndex size() const; rt300@9: rt300@9: void clear(); rt300@9: rt300@9: bool reserveDelta( BucketIndex growth ); rt300@9: rt300@9: bool reserve( BucketIndex newItemCount ); rt300@9: rt300@9: const Value *find( const char *key ) const; rt300@9: rt300@9: Value *find( const char *key ); rt300@9: rt300@9: Value &resolveReference( const char *key, rt300@9: bool isStatic ); rt300@9: rt300@9: void remove( const char *key ); rt300@9: rt300@9: void doActualRemove( ValueInternalLink *link, rt300@9: BucketIndex index, rt300@9: BucketIndex bucketIndex ); rt300@9: rt300@9: ValueInternalLink *&getLastLinkInBucket( BucketIndex bucketIndex ); rt300@9: rt300@9: Value &setNewItem( const char *key, rt300@9: bool isStatic, rt300@9: ValueInternalLink *link, rt300@9: BucketIndex index ); rt300@9: rt300@9: Value &unsafeAdd( const char *key, rt300@9: bool isStatic, rt300@9: HashKey hashedKey ); rt300@9: rt300@9: HashKey hash( const char *key ) const; rt300@9: rt300@9: int compare( const ValueInternalMap &other ) const; rt300@9: rt300@9: private: rt300@9: void makeBeginIterator( IteratorState &it ) const; rt300@9: void makeEndIterator( IteratorState &it ) const; rt300@9: static bool equals( const IteratorState &x, const IteratorState &other ); rt300@9: static void increment( IteratorState &iterator ); rt300@9: static void incrementBucket( IteratorState &iterator ); rt300@9: static void decrement( IteratorState &iterator ); rt300@9: static const char *key( const IteratorState &iterator ); rt300@9: static const char *key( const IteratorState &iterator, bool &isStatic ); rt300@9: static Value &value( const IteratorState &iterator ); rt300@9: static int distance( const IteratorState &x, const IteratorState &y ); rt300@9: rt300@9: private: rt300@9: ValueInternalLink *buckets_; rt300@9: ValueInternalLink *tailLink_; rt300@9: BucketIndex bucketsSize_; rt300@9: BucketIndex itemCount_; rt300@9: }; rt300@9: rt300@9: /** \brief A simplified deque implementation used internally by Value. rt300@9: * \internal rt300@9: * It is based on a list of fixed "page", each page contains a fixed number of items. rt300@9: * Instead of using a linked-list, a array of pointer is used for fast item look-up. rt300@9: * Look-up for an element is as follow: rt300@9: * - compute page index: pageIndex = itemIndex / itemsPerPage rt300@9: * - look-up item in page: pages_[pageIndex][itemIndex % itemsPerPage] rt300@9: * rt300@9: * Insertion is amortized constant time (only the array containing the index of pointers rt300@9: * need to be reallocated when items are appended). rt300@9: */ rt300@9: class JSON_API ValueInternalArray rt300@9: { rt300@9: friend class Value; rt300@9: friend class ValueIteratorBase; rt300@9: public: rt300@9: enum { itemsPerPage = 8 }; // should be a power of 2 for fast divide and modulo. rt300@9: typedef Value::ArrayIndex ArrayIndex; rt300@9: typedef unsigned int PageIndex; rt300@9: rt300@9: # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION rt300@9: struct IteratorState // Must be a POD rt300@9: { rt300@9: IteratorState() rt300@9: : array_(0) rt300@9: , currentPageIndex_(0) rt300@9: , currentItemIndex_(0) rt300@9: { rt300@9: } rt300@9: ValueInternalArray *array_; rt300@9: Value **currentPageIndex_; rt300@9: unsigned int currentItemIndex_; rt300@9: }; rt300@9: # endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION rt300@9: rt300@9: ValueInternalArray(); rt300@9: ValueInternalArray( const ValueInternalArray &other ); rt300@9: ValueInternalArray &operator =( const ValueInternalArray &other ); rt300@9: ~ValueInternalArray(); rt300@9: void swap( ValueInternalArray &other ); rt300@9: rt300@9: void clear(); rt300@9: void resize( ArrayIndex newSize ); rt300@9: rt300@9: Value &resolveReference( ArrayIndex index ); rt300@9: rt300@9: Value *find( ArrayIndex index ) const; rt300@9: rt300@9: ArrayIndex size() const; rt300@9: rt300@9: int compare( const ValueInternalArray &other ) const; rt300@9: rt300@9: private: rt300@9: static bool equals( const IteratorState &x, const IteratorState &other ); rt300@9: static void increment( IteratorState &iterator ); rt300@9: static void decrement( IteratorState &iterator ); rt300@9: static Value &dereference( const IteratorState &iterator ); rt300@9: static Value &unsafeDereference( const IteratorState &iterator ); rt300@9: static int distance( const IteratorState &x, const IteratorState &y ); rt300@9: static ArrayIndex indexOf( const IteratorState &iterator ); rt300@9: void makeBeginIterator( IteratorState &it ) const; rt300@9: void makeEndIterator( IteratorState &it ) const; rt300@9: void makeIterator( IteratorState &it, ArrayIndex index ) const; rt300@9: rt300@9: void makeIndexValid( ArrayIndex index ); rt300@9: rt300@9: Value **pages_; rt300@9: ArrayIndex size_; rt300@9: PageIndex pageCount_; rt300@9: }; rt300@9: rt300@9: /** \brief Experimental: do not use. Allocator to customize Value internal array. rt300@9: * Below is an example of a simple implementation (actual implementation use rt300@9: * memory pool). rt300@9: \code rt300@9: class DefaultValueArrayAllocator : public ValueArrayAllocator rt300@9: { rt300@9: public: // overridden from ValueArrayAllocator rt300@9: virtual ~DefaultValueArrayAllocator() rt300@9: { rt300@9: } rt300@9: rt300@9: virtual ValueInternalArray *newArray() rt300@9: { rt300@9: return new ValueInternalArray(); rt300@9: } rt300@9: rt300@9: virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) rt300@9: { rt300@9: return new ValueInternalArray( other ); rt300@9: } rt300@9: rt300@9: virtual void destruct( ValueInternalArray *array ) rt300@9: { rt300@9: delete array; rt300@9: } rt300@9: rt300@9: virtual void reallocateArrayPageIndex( Value **&indexes, rt300@9: ValueInternalArray::PageIndex &indexCount, rt300@9: ValueInternalArray::PageIndex minNewIndexCount ) rt300@9: { rt300@9: ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1; rt300@9: if ( minNewIndexCount > newIndexCount ) rt300@9: newIndexCount = minNewIndexCount; rt300@9: void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount ); rt300@9: if ( !newIndexes ) rt300@9: throw std::bad_alloc(); rt300@9: indexCount = newIndexCount; rt300@9: indexes = static_cast( newIndexes ); rt300@9: } rt300@9: virtual void releaseArrayPageIndex( Value **indexes, rt300@9: ValueInternalArray::PageIndex indexCount ) rt300@9: { rt300@9: if ( indexes ) rt300@9: free( indexes ); rt300@9: } rt300@9: rt300@9: virtual Value *allocateArrayPage() rt300@9: { rt300@9: return static_cast( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) ); rt300@9: } rt300@9: rt300@9: virtual void releaseArrayPage( Value *value ) rt300@9: { rt300@9: if ( value ) rt300@9: free( value ); rt300@9: } rt300@9: }; rt300@9: \endcode rt300@9: */ rt300@9: class JSON_API ValueArrayAllocator rt300@9: { rt300@9: public: rt300@9: virtual ~ValueArrayAllocator(); rt300@9: virtual ValueInternalArray *newArray() = 0; rt300@9: virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other ) = 0; rt300@9: virtual void destructArray( ValueInternalArray *array ) = 0; rt300@9: /** \brief Reallocate array page index. rt300@9: * Reallocates an array of pointer on each page. rt300@9: * \param indexes [input] pointer on the current index. May be \c NULL. rt300@9: * [output] pointer on the new index of at least rt300@9: * \a minNewIndexCount pages. rt300@9: * \param indexCount [input] current number of pages in the index. rt300@9: * [output] number of page the reallocated index can handle. rt300@9: * \b MUST be >= \a minNewIndexCount. rt300@9: * \param minNewIndexCount Minimum number of page the new index must be able to rt300@9: * handle. rt300@9: */ rt300@9: virtual void reallocateArrayPageIndex( Value **&indexes, rt300@9: ValueInternalArray::PageIndex &indexCount, rt300@9: ValueInternalArray::PageIndex minNewIndexCount ) = 0; rt300@9: virtual void releaseArrayPageIndex( Value **indexes, rt300@9: ValueInternalArray::PageIndex indexCount ) = 0; rt300@9: virtual Value *allocateArrayPage() = 0; rt300@9: virtual void releaseArrayPage( Value *value ) = 0; rt300@9: }; rt300@9: #endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP rt300@9: rt300@9: rt300@9: /** \brief base class for Value iterators. rt300@9: * rt300@9: */ rt300@9: class ValueIteratorBase rt300@9: { rt300@9: public: rt300@9: typedef unsigned int size_t; rt300@9: typedef int difference_type; rt300@9: typedef ValueIteratorBase SelfType; rt300@9: rt300@9: ValueIteratorBase(); rt300@9: #ifndef JSON_VALUE_USE_INTERNAL_MAP rt300@9: explicit ValueIteratorBase( const Value::ObjectValues::iterator ¤t ); rt300@9: #else rt300@9: ValueIteratorBase( const ValueInternalArray::IteratorState &state ); rt300@9: ValueIteratorBase( const ValueInternalMap::IteratorState &state ); rt300@9: #endif rt300@9: rt300@9: bool operator ==( const SelfType &other ) const rt300@9: { rt300@9: return isEqual( other ); rt300@9: } rt300@9: rt300@9: bool operator !=( const SelfType &other ) const rt300@9: { rt300@9: return !isEqual( other ); rt300@9: } rt300@9: rt300@9: difference_type operator -( const SelfType &other ) const rt300@9: { rt300@9: return computeDistance( other ); rt300@9: } rt300@9: rt300@9: /// Return either the index or the member name of the referenced value as a Value. rt300@9: Value key() const; rt300@9: rt300@9: /// Return the index of the referenced Value. -1 if it is not an arrayValue. rt300@9: UInt index() const; rt300@9: rt300@9: /// Return the member name of the referenced Value. "" if it is not an objectValue. rt300@9: const char *memberName() const; rt300@9: rt300@9: protected: rt300@9: Value &deref() const; rt300@9: rt300@9: void increment(); rt300@9: rt300@9: void decrement(); rt300@9: rt300@9: difference_type computeDistance( const SelfType &other ) const; rt300@9: rt300@9: bool isEqual( const SelfType &other ) const; rt300@9: rt300@9: void copy( const SelfType &other ); rt300@9: rt300@9: private: rt300@9: #ifndef JSON_VALUE_USE_INTERNAL_MAP rt300@9: Value::ObjectValues::iterator current_; rt300@9: // Indicates that iterator is for a null value. rt300@9: bool isNull_; rt300@9: #else rt300@9: union rt300@9: { rt300@9: ValueInternalArray::IteratorState array_; rt300@9: ValueInternalMap::IteratorState map_; rt300@9: } iterator_; rt300@9: bool isArray_; rt300@9: #endif rt300@9: }; rt300@9: rt300@9: /** \brief const iterator for object and array value. rt300@9: * rt300@9: */ rt300@9: class ValueConstIterator : public ValueIteratorBase rt300@9: { rt300@9: friend class Value; rt300@9: public: rt300@9: typedef unsigned int size_t; rt300@9: typedef int difference_type; rt300@9: typedef const Value &reference; rt300@9: typedef const Value *pointer; rt300@9: typedef ValueConstIterator SelfType; rt300@9: rt300@9: ValueConstIterator(); rt300@9: private: rt300@9: /*! \internal Use by Value to create an iterator. rt300@9: */ rt300@9: #ifndef JSON_VALUE_USE_INTERNAL_MAP rt300@9: explicit ValueConstIterator( const Value::ObjectValues::iterator ¤t ); rt300@9: #else rt300@9: ValueConstIterator( const ValueInternalArray::IteratorState &state ); rt300@9: ValueConstIterator( const ValueInternalMap::IteratorState &state ); rt300@9: #endif rt300@9: public: rt300@9: SelfType &operator =( const ValueIteratorBase &other ); rt300@9: rt300@9: SelfType operator++( int ) rt300@9: { rt300@9: SelfType temp( *this ); rt300@9: ++*this; rt300@9: return temp; rt300@9: } rt300@9: rt300@9: SelfType operator--( int ) rt300@9: { rt300@9: SelfType temp( *this ); rt300@9: --*this; rt300@9: return temp; rt300@9: } rt300@9: rt300@9: SelfType &operator--() rt300@9: { rt300@9: decrement(); rt300@9: return *this; rt300@9: } rt300@9: rt300@9: SelfType &operator++() rt300@9: { rt300@9: increment(); rt300@9: return *this; rt300@9: } rt300@9: rt300@9: reference operator *() const rt300@9: { rt300@9: return deref(); rt300@9: } rt300@9: }; rt300@9: rt300@9: rt300@9: /** \brief Iterator for object and array value. rt300@9: */ rt300@9: class ValueIterator : public ValueIteratorBase rt300@9: { rt300@9: friend class Value; rt300@9: public: rt300@9: typedef unsigned int size_t; rt300@9: typedef int difference_type; rt300@9: typedef Value &reference; rt300@9: typedef Value *pointer; rt300@9: typedef ValueIterator SelfType; rt300@9: rt300@9: ValueIterator(); rt300@9: ValueIterator( const ValueConstIterator &other ); rt300@9: ValueIterator( const ValueIterator &other ); rt300@9: private: rt300@9: /*! \internal Use by Value to create an iterator. rt300@9: */ rt300@9: #ifndef JSON_VALUE_USE_INTERNAL_MAP rt300@9: explicit ValueIterator( const Value::ObjectValues::iterator ¤t ); rt300@9: #else rt300@9: ValueIterator( const ValueInternalArray::IteratorState &state ); rt300@9: ValueIterator( const ValueInternalMap::IteratorState &state ); rt300@9: #endif rt300@9: public: rt300@9: rt300@9: SelfType &operator =( const SelfType &other ); rt300@9: rt300@9: SelfType operator++( int ) rt300@9: { rt300@9: SelfType temp( *this ); rt300@9: ++*this; rt300@9: return temp; rt300@9: } rt300@9: rt300@9: SelfType operator--( int ) rt300@9: { rt300@9: SelfType temp( *this ); rt300@9: --*this; rt300@9: return temp; rt300@9: } rt300@9: rt300@9: SelfType &operator--() rt300@9: { rt300@9: decrement(); rt300@9: return *this; rt300@9: } rt300@9: rt300@9: SelfType &operator++() rt300@9: { rt300@9: increment(); rt300@9: return *this; rt300@9: } rt300@9: rt300@9: reference operator *() const rt300@9: { rt300@9: return deref(); rt300@9: } rt300@9: }; rt300@9: rt300@9: rt300@9: } // namespace Json rt300@9: rt300@9: rt300@9: #endif // CPPTL_JSON_H_INCLUDED