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