"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "include/rapidjson/document.h" between
rapidjson-1.0.2.tar.gz and rapidjson-1.1.0.tar.gz

About: RapidJSON is a fast JSON parser/generator for C++ with both SAX/DOM style API.

document.h  (rapidjson-1.0.2):document.h  (rapidjson-1.1.0)
skipping to change at line 23 skipping to change at line 23
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
#ifndef RAPIDJSON_DOCUMENT_H_ #ifndef RAPIDJSON_DOCUMENT_H_
#define RAPIDJSON_DOCUMENT_H_ #define RAPIDJSON_DOCUMENT_H_
/*! \file document.h */ /*! \file document.h */
#include "reader.h" #include "reader.h"
#include "internal/meta.h" #include "internal/meta.h"
#include "internal/strfunc.h" #include "internal/strfunc.h"
#include "memorystream.h"
#include "encodedstream.h"
#include <new> // placement new #include <new> // placement new
#include <limits>
#ifdef _MSC_VER
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
#ifdef _MSC_VER
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
#elif defined(__GNUC__) RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible lo
RAPIDJSON_DIAG_PUSH ss of data
RAPIDJSON_DIAG_OFF(effc++)
#endif #endif
/////////////////////////////////////////////////////////////////////////////// #ifdef __clang__
// RAPIDJSON_HAS_STDSTRING RAPIDJSON_DIAG_OFF(padded)
RAPIDJSON_DIAG_OFF(switch-enum)
#ifndef RAPIDJSON_HAS_STDSTRING RAPIDJSON_DIAG_OFF(c++98-compat)
#ifdef RAPIDJSON_DOXYGEN_RUNNING
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
#else
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
#endif #endif
/*! \def RAPIDJSON_HAS_STDSTRING
\ingroup RAPIDJSON_CONFIG
\brief Enable RapidJSON support for \c std::string
By defining this preprocessor symbol to \c 1, several convenience functions
for using
\ref rapidjson::GenericValue with \c std::string are enabled, especially
for construction and comparison.
\hideinitializer #ifdef __GNUC__
*/ RAPIDJSON_DIAG_OFF(effc++)
#endif // !defined(RAPIDJSON_HAS_STDSTRING) #if __GNUC__ >= 6
RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_N
#if RAPIDJSON_HAS_STDSTRING OEXCEPT functions
#include <string> #endif
#endif // RAPIDJSON_HAS_STDSTRING #endif // __GNUC__
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS #ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include <iterator> // std::iterator, std::random_access_iterator_tag #include <iterator> // std::iterator, std::random_access_iterator_tag
#endif #endif
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
#include <utility> // std::move #include <utility> // std::move
#endif #endif
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
// Forward declaration. // Forward declaration.
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericValue; class GenericValue;
template <typename Encoding, typename Allocator, typename StackAllocator>
class GenericDocument;
//! Name-value pair in a JSON object value. //! Name-value pair in a JSON object value.
/*! /*!
This class was internal to GenericValue. It used to be a inner struct. This class was internal to GenericValue. It used to be a inner struct.
But a compiler (IBM XL C/C++ for AIX) have reported to have problem with tha t so it moved as a namespace scope struct. But a compiler (IBM XL C/C++ for AIX) have reported to have problem with tha t so it moved as a namespace scope struct.
https://code.google.com/p/rapidjson/issues/detail?id=64 https://code.google.com/p/rapidjson/issues/detail?id=64
*/ */
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
struct GenericMember { struct GenericMember {
GenericValue<Encoding, Allocator> name; //!< name of member (must be a s tring) GenericValue<Encoding, Allocator> name; //!< name of member (must be a s tring)
GenericValue<Encoding, Allocator> value; //!< value of member. GenericValue<Encoding, Allocator> value; //!< value of member.
skipping to change at line 158 skipping to change at line 150
\li const -> non-const (not ok) \li const -> non-const (not ok)
\li const -> const (ok) \li const -> const (ok)
\li non-const -> const (ok) \li non-const -> const (ok)
\li non-const -> non-const (ok) \li non-const -> non-const (ok)
\note If the \c Const template parameter is already \c false, this \note If the \c Const template parameter is already \c false, this
constructor effectively defines a regular copy-constructor. constructor effectively defines a regular copy-constructor.
Otherwise, the copy constructor is implicitly defined. Otherwise, the copy constructor is implicitly defined.
*/ */
GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *t his; }
//! @name stepping //! @name stepping
//@{ //@{
Iterator& operator++(){ ++ptr_; return *this; } Iterator& operator++(){ ++ptr_; return *this; }
Iterator& operator--(){ --ptr_; return *this; } Iterator& operator--(){ --ptr_; return *this; }
Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
//@} //@}
//! @name increment/decrement //! @name increment/decrement
skipping to change at line 260 skipping to change at line 253
Value y(StringRef(bar, 3)); // ok, explicitly pass length Value y(StringRef(bar, 3)); // ok, explicitly pass length
\endcode \endcode
\see StringRef, GenericValue::SetString \see StringRef, GenericValue::SetString
*/ */
template<typename CharType> template<typename CharType>
struct GenericStringRef { struct GenericStringRef {
typedef CharType Ch; //!< character type of the string typedef CharType Ch; //!< character type of the string
//! Create string reference from \c const character array //! Create string reference from \c const character array
#ifndef __clang__ // -Wdocumentation
/*! /*!
This constructor implicitly creates a constant string reference from This constructor implicitly creates a constant string reference from
a \c const character array. It has better performance than a \c const character array. It has better performance than
\ref StringRef(const CharType*) by inferring the string \ref length \ref StringRef(const CharType*) by inferring the string \ref length
from the array length, and also supports strings containing null from the array length, and also supports strings containing null
characters. characters.
\tparam N length of the string, automatically inferred \tparam N length of the string, automatically inferred
\param str Constant character array, lifetime assumed to be longer \param str Constant character array, lifetime assumed to be longer
skipping to change at line 282 skipping to change at line 276
\post \ref s == str \post \ref s == str
\note Constant complexity. \note Constant complexity.
\note There is a hidden, private overload to disallow references to \note There is a hidden, private overload to disallow references to
non-const character arrays to be created via this constructor. non-const character arrays to be created via this constructor.
By this, e.g. function-scope arrays used to be filled via By this, e.g. function-scope arrays used to be filled via
\c snprintf are excluded from consideration. \c snprintf are excluded from consideration.
In such cases, the referenced string should be \b copied to the In such cases, the referenced string should be \b copied to the
GenericValue instead. GenericValue instead.
*/ */
#endif
template<SizeType N> template<SizeType N>
GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
: s(str), length(N-1) {} : s(str), length(N-1) {}
//! Explicitly create string reference from \c const character pointer //! Explicitly create string reference from \c const character pointer
#ifndef __clang__ // -Wdocumentation
/*! /*!
This constructor can be used to \b explicitly create a reference to This constructor can be used to \b explicitly create a reference to
a constant string pointer. a constant string pointer.
\see StringRef(const CharType*) \see StringRef(const CharType*)
\param str Constant character pointer, lifetime assumed to be longer \param str Constant character pointer, lifetime assumed to be longer
than the use of the string in e.g. a GenericValue than the use of the string in e.g. a GenericValue
\post \ref s == str \post \ref s == str
\note There is a hidden, private overload to disallow references to \note There is a hidden, private overload to disallow references to
non-const character arrays to be created via this constructor. non-const character arrays to be created via this constructor.
By this, e.g. function-scope arrays used to be filled via By this, e.g. function-scope arrays used to be filled via
\c snprintf are excluded from consideration. \c snprintf are excluded from consideration.
In such cases, the referenced string should be \b copied to the In such cases, the referenced string should be \b copied to the
GenericValue instead. GenericValue instead.
*/ */
#endif
explicit GenericStringRef(const CharType* str) explicit GenericStringRef(const CharType* str)
: s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != 0); }
//! Create constant string reference from pointer and length //! Create constant string reference from pointer and length
#ifndef __clang__ // -Wdocumentation
/*! \param str constant string, lifetime assumed to be longer than the use o f the string in e.g. a GenericValue /*! \param str constant string, lifetime assumed to be longer than the use o f the string in e.g. a GenericValue
\param len length of the string, excluding the trailing NULL terminator \param len length of the string, excluding the trailing NULL terminator
\post \ref s == str && \ref length == len \post \ref s == str && \ref length == len
\note Constant complexity. \note Constant complexity.
*/ */
#endif
GenericStringRef(const CharType* str, SizeType len) GenericStringRef(const CharType* str, SizeType len)
: s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); } : s(str), length(len) { RAPIDJSON_ASSERT(s != 0); }
GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length)
{}
GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length
= rhs.length; }
//! implicit conversion to plain CharType pointer //! implicit conversion to plain CharType pointer
operator const Ch *() const { return s; } operator const Ch *() const { return s; }
const Ch* const s; //!< plain CharType pointer const Ch* const s; //!< plain CharType pointer
const SizeType length; //!< length of the string (excluding the trailing NUL L terminator) const SizeType length; //!< length of the string (excluding the trailing NUL L terminator)
private: private:
//! Disallow copy-assignment
GenericStringRef operator=(const GenericStringRef&);
//! Disallow construction from non-const array //! Disallow construction from non-const array
template<SizeType N> template<SizeType N>
GenericStringRef(CharType (&str)[N]) /* = delete */; GenericStringRef(CharType (&str)[N]) /* = delete */;
}; };
//! Mark a character pointer as constant string //! Mark a character pointer as constant string
/*! Mark a plain character pointer as a "string literal". This function /*! Mark a plain character pointer as a "string literal". This function
can be used to avoid copying a character string to be referenced as a can be used to avoid copying a character string to be referenced as a
value in a JSON GenericValue object, if the string's lifetime is known value in a JSON GenericValue object, if the string's lifetime is known
to be valid long enough. to be valid long enough.
skipping to change at line 405 skipping to change at line 406
// select candidates according to nested encoding and allocator types // select candidates according to nested encoding and allocator types
template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::Enc odingType>::Type, typename Void<typename T::AllocatorType>::Type> template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::Enc odingType>::Type, typename Void<typename T::AllocatorType>::Type>
: IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType> , T>::Type {}; : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType> , T>::Type {};
// helper to match arbitrary GenericValue instantiations, including derived clas ses // helper to match arbitrary GenericValue instantiations, including derived clas ses
template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {}; template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
} // namespace internal } // namespace internal
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// TypeHelper
namespace internal {
template <typename ValueType, typename T>
struct TypeHelper {};
template<typename ValueType>
struct TypeHelper<ValueType, bool> {
static bool Is(const ValueType& v) { return v.IsBool(); }
static bool Get(const ValueType& v) { return v.GetBool(); }
static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); }
static ValueType& Set(ValueType& v, bool data, typename ValueType::Allocator
Type&) { return v.SetBool(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, int> {
static bool Is(const ValueType& v) { return v.IsInt(); }
static int Get(const ValueType& v) { return v.GetInt(); }
static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); }
static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorT
ype&) { return v.SetInt(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, unsigned> {
static bool Is(const ValueType& v) { return v.IsUint(); }
static unsigned Get(const ValueType& v) { return v.GetUint(); }
static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data);
}
static ValueType& Set(ValueType& v, unsigned data, typename ValueType::Alloc
atorType&) { return v.SetUint(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, int64_t> {
static bool Is(const ValueType& v) { return v.IsInt64(); }
static int64_t Get(const ValueType& v) { return v.GetInt64(); }
static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data);
}
static ValueType& Set(ValueType& v, int64_t data, typename ValueType::Alloca
torType&) { return v.SetInt64(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, uint64_t> {
static bool Is(const ValueType& v) { return v.IsUint64(); }
static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data
); }
static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::Alloc
atorType&) { return v.SetUint64(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, double> {
static bool Is(const ValueType& v) { return v.IsDouble(); }
static double Get(const ValueType& v) { return v.GetDouble(); }
static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data);
}
static ValueType& Set(ValueType& v, double data, typename ValueType::Allocat
orType&) { return v.SetDouble(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, float> {
static bool Is(const ValueType& v) { return v.IsFloat(); }
static float Get(const ValueType& v) { return v.GetFloat(); }
static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); }
static ValueType& Set(ValueType& v, float data, typename ValueType::Allocato
rType&) { return v.SetFloat(data); }
};
template<typename ValueType>
struct TypeHelper<ValueType, const typename ValueType::Ch*> {
typedef const typename ValueType::Ch* StringType;
static bool Is(const ValueType& v) { return v.IsString(); }
static StringType Get(const ValueType& v) { return v.GetString(); }
static ValueType& Set(ValueType& v, const StringType data) { return v.SetStr
ing(typename ValueType::StringRefType(data)); }
static ValueType& Set(ValueType& v, const StringType data, typename ValueTyp
e::AllocatorType& a) { return v.SetString(data, a); }
};
#if RAPIDJSON_HAS_STDSTRING
template<typename ValueType>
struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
typedef std::basic_string<typename ValueType::Ch> StringType;
static bool Is(const ValueType& v) { return v.IsString(); }
static StringType Get(const ValueType& v) { return StringType(v.GetString(),
v.GetStringLength()); }
static ValueType& Set(ValueType& v, const StringType& data, typename ValueTy
pe::AllocatorType& a) { return v.SetString(data, a); }
};
#endif
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::Array> {
typedef typename ValueType::Array ArrayType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArrayType Get(ValueType& v) { return v.GetArray(); }
static ValueType& Set(ValueType& v, ArrayType data) { return v = data; }
static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::Allo
catorType&) { return v = data; }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::ConstArray> {
typedef typename ValueType::ConstArray ArrayType;
static bool Is(const ValueType& v) { return v.IsArray(); }
static ArrayType Get(const ValueType& v) { return v.GetArray(); }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::Object> {
typedef typename ValueType::Object ObjectType;
static bool Is(const ValueType& v) { return v.IsObject(); }
static ObjectType Get(ValueType& v) { return v.GetObject(); }
static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::All
ocatorType&) { v = data; }
};
template<typename ValueType>
struct TypeHelper<ValueType, typename ValueType::ConstObject> {
typedef typename ValueType::ConstObject ObjectType;
static bool Is(const ValueType& v) { return v.IsObject(); }
static ObjectType Get(const ValueType& v) { return v.GetObject(); }
};
} // namespace internal
// Forward declarations
template <bool, typename> class GenericArray;
template <bool, typename> class GenericObject;
///////////////////////////////////////////////////////////////////////////////
// GenericValue // GenericValue
//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. //! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
/*! /*!
A JSON value can be one of 7 types. This class is a variant type supporting A JSON value can be one of 7 types. This class is a variant type supporting
these types. these types.
Use the Value if UTF8 and default allocator Use the Value if UTF8 and default allocator
\tparam Encoding Encoding of the value. (Even non-string values need to h ave the same encoding in a document) \tparam Encoding Encoding of the value. (Even non-string values need to h ave the same encoding in a document)
skipping to change at line 431 skipping to change at line 553
typedef GenericMember<Encoding, Allocator> Member; typedef GenericMember<Encoding, Allocator> Member;
typedef Encoding EncodingType; //!< Encoding type from temp late parameter. typedef Encoding EncodingType; //!< Encoding type from temp late parameter.
typedef Allocator AllocatorType; //!< Allocator type from tem plate parameter. typedef Allocator AllocatorType; //!< Allocator type from tem plate parameter.
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator M emberIterator; //!< Member iterator for iterating in object. typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator M emberIterator; //!< Member iterator for iterating in object.
typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator Co nstMemberIterator; //!< Constant member iterator for iterating in object. typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator Co nstMemberIterator; //!< Constant member iterator for iterating in object.
typedef GenericValue* ValueIterator; //!< Value iterator for iter ating in array. typedef GenericValue* ValueIterator; //!< Value iterator for iter ating in array.
typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of i tself. typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of i tself.
typedef GenericArray<false, ValueType> Array;
typedef GenericArray<true, ValueType> ConstArray;
typedef GenericObject<false, ValueType> Object;
typedef GenericObject<true, ValueType> ConstObject;
//!@name Constructors and destructor. //!@name Constructors and destructor.
//@{ //@{
//! Default constructor creates a null value. //! Default constructor creates a null value.
GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {} GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11 //! Move constructor in C++11
GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flag GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) {
s_(rhs.flags_) { rhs.data_.f.flags = kNullFlag; // give up contents
rhs.flags_ = kNullFlag; // give up contents
} }
#endif #endif
private: private:
//! Copy constructor is not permitted. //! Copy constructor is not permitted.
GenericValue(const GenericValue& rhs); GenericValue(const GenericValue& rhs);
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Moving from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue(GenericDocument<Encoding,Allocator,StackAllocator>&& rhs);
//! Move assignment from a GenericDocument is not permitted.
template <typename StackAllocator>
GenericValue& operator=(GenericDocument<Encoding,Allocator,StackAllocator>&&
rhs);
#endif
public: public:
//! Constructor with JSON value type. //! Constructor with JSON value type.
/*! This creates a Value of specified type with default content. /*! This creates a Value of specified type with default content.
\param type Type of the value. \param type Type of the value.
\note Default content for number is zero. \note Default content for number is zero.
*/ */
explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() {
static const unsigned defaultFlags[7] = { static const uint16_t defaultFlags[7] = {
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStr ingFlag, kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStr ingFlag,
kNumberAnyFlag kNumberAnyFlag
}; };
RAPIDJSON_ASSERT(type <= kNumberType); RAPIDJSON_ASSERT(type <= kNumberType);
flags_ = defaultFlags[type]; data_.f.flags = defaultFlags[type];
// Use ShortString to store empty string. // Use ShortString to store empty string.
if (type == kStringType) if (type == kStringType)
data_.ss.SetLength(0); data_.ss.SetLength(0);
} }
//! Explicit copy constructor (with allocator) //! Explicit copy constructor (with allocator)
/*! Creates a copy of a Value by using the given Allocator /*! Creates a copy of a Value by using the given Allocator
\tparam SourceAllocator allocator of \c rhs \tparam SourceAllocator allocator of \c rhs
\param rhs Value to copy from (read-only) \param rhs Value to copy from (read-only)
skipping to change at line 487 skipping to change at line 623
GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator); GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
//! Constructor for boolean value. //! Constructor for boolean value.
/*! \param b Boolean value /*! \param b Boolean value
\note This constructor is limited to \em real boolean values and rejects \note This constructor is limited to \em real boolean values and rejects
implicitly converted types like arbitrary pointers. Use an explicit cast implicitly converted types like arbitrary pointers. Use an explicit cast
to \c bool, if you want to construct a boolean JSON value in such ca ses. to \c bool, if you want to construct a boolean JSON value in such ca ses.
*/ */
#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen #ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
template <typename T> template <typename T>
explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) R APIDJSON_NOEXCEPT explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<bool, T>))) RAPIDJSON_NOEXCEPT // See #472
#else #else
explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
#endif #endif
: data_(), flags_(b ? kTrueFlag : kFalseFlag) { : data_() {
// safe-guard against failing SFINAE // safe-guard against failing SFINAE
RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value)); RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
data_.f.flags = b ? kTrueFlag : kFalseFlag;
} }
//! Constructor for int value. //! Constructor for int value.
explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt Flag) { explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i; data_.n.i64 = i;
if (i >= 0) data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) :
flags_ |= kUintFlag | kUint64Flag; kNumberIntFlag;
} }
//! Constructor for unsigned value. //! Constructor for unsigned value.
explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumb erUintFlag) { explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u; data_.n.u64 = u;
if (!(u & 0x80000000)) data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag |
flags_ |= kIntFlag | kInt64Flag; kIntFlag | kInt64Flag);
} }
//! Constructor for int64_t value. //! Constructor for int64_t value.
explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNum berInt64Flag) { explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.i64 = i64; data_.n.i64 = i64;
data_.f.flags = kNumberInt64Flag;
if (i64 >= 0) { if (i64 >= 0) {
flags_ |= kNumberUint64Flag; data_.f.flags |= kNumberUint64Flag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0 x00000000))) if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0 x00000000)))
flags_ |= kUintFlag; data_.f.flags |= kUintFlag;
if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0 x80000000))) if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0 x80000000)))
flags_ |= kIntFlag; data_.f.flags |= kIntFlag;
} }
else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x8 0000000))) else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x8 0000000)))
flags_ |= kIntFlag; data_.f.flags |= kIntFlag;
} }
//! Constructor for uint64_t value. //! Constructor for uint64_t value.
explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNu mberUint64Flag) { explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() {
data_.n.u64 = u64; data_.n.u64 = u64;
data_.f.flags = kNumberUint64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
flags_ |= kInt64Flag; data_.f.flags |= kInt64Flag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
flags_ |= kUintFlag; data_.f.flags |= kUintFlag;
if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
flags_ |= kIntFlag; data_.f.flags |= kIntFlag;
} }
//! Constructor for double value. //! Constructor for double value.
explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumber DoubleFlag) { data_.n.d = d; } explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d ; data_.f.flags = kNumberDoubleFlag; }
//! Constructor for constant string (i.e. do not make a copy of string) //! Constructor for constant string (i.e. do not make a copy of string)
GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), fla gs_() { SetStringRaw(StringRef(s, length)); } GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { Se tStringRaw(StringRef(s, length)); }
//! Constructor for constant string (i.e. do not make a copy of string) //! Constructor for constant string (i.e. do not make a copy of string)
explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_( ) { SetStringRaw(s); } explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStr ingRaw(s); }
//! Constructor for copy-string (i.e. do make a copy of string) //! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); } GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); }
//! Constructor for copy-string (i.e. do make a copy of string) //! Constructor for copy-string (i.e. do make a copy of string)
GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStri ngRaw(StringRef(s), allocator); } GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(Stri ngRef(s), allocator); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Constructor for copy-string from a string object (i.e. do make a copy of string) //! Constructor for copy-string from a string object (i.e. do make a copy of string)
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_ HAS_STDSTRING. /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_ HAS_STDSTRING.
*/ */
GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() , flags_() { SetStringRaw(StringRef(s), allocator); } GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); }
#endif #endif
//! Constructor for Array.
/*!
\param a An array obtained by \c GetArray().
\note \c Array is always pass-by-value.
\note the source array is moved into this value and the sourec array bec
omes empty.
*/
GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) {
a.value_.data_ = Data();
a.value_.data_.f.flags = kArrayFlag;
}
//! Constructor for Object.
/*!
\param o An object obtained by \c GetObject().
\note \c Object is always pass-by-value.
\note the source object is moved into this value and the sourec object b
ecomes empty.
*/
GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) {
o.value_.data_ = Data();
o.value_.data_.f.flags = kObjectFlag;
}
//! Destructor. //! Destructor.
/*! Need to destruct elements of array, members of object, or copy-string. /*! Need to destruct elements of array, members of object, or copy-string.
*/ */
~GenericValue() { ~GenericValue() {
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
switch(flags_) { switch(data_.f.flags) {
case kArrayFlag: case kArrayFlag:
for (GenericValue* v = data_.a.elements; v != data_.a.elements + {
data_.a.size; ++v) GenericValue* e = GetElementsPointer();
v->~GenericValue(); for (GenericValue* v = e; v != e + data_.a.size; ++v)
Allocator::Free(data_.a.elements); v->~GenericValue();
Allocator::Free(e);
}
break; break;
case kObjectFlag: case kObjectFlag:
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
m->~Member(); m->~Member();
Allocator::Free(data_.o.members); Allocator::Free(GetMembersPointer());
break; break;
case kCopyStringFlag: case kCopyStringFlag:
Allocator::Free(const_cast<Ch*>(data_.s.str)); Allocator::Free(const_cast<Ch*>(GetStringPointer()));
break; break;
default: default:
break; // Do nothing for other types. break; // Do nothing for other types.
} }
} }
} }
//@} //@}
skipping to change at line 644 skipping to change at line 806
} }
//! Deep-copy assignment from Value //! Deep-copy assignment from Value
/*! Assigns a \b copy of the Value to the current Value object /*! Assigns a \b copy of the Value to the current Value object
\tparam SourceAllocator Allocator type of \c rhs \tparam SourceAllocator Allocator type of \c rhs
\param rhs Value to copy from (read-only) \param rhs Value to copy from (read-only)
\param allocator Allocator to use for copying \param allocator Allocator to use for copying
*/ */
template <typename SourceAllocator> template <typename SourceAllocator>
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, A llocator& allocator) { GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, A llocator& allocator) {
RAPIDJSON_ASSERT((void*)this != (void const*)&rhs); RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&r hs));
this->~GenericValue(); this->~GenericValue();
new (this) GenericValue(rhs, allocator); new (this) GenericValue(rhs, allocator);
return *this; return *this;
} }
//! Exchange the contents of this value with those of other. //! Exchange the contents of this value with those of other.
/*! /*!
\param other Another value. \param other Another value.
\note Constant complexity. \note Constant complexity.
*/ */
GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
GenericValue temp; GenericValue temp;
temp.RawAssign(*this); temp.RawAssign(*this);
RawAssign(other); RawAssign(other);
other.RawAssign(temp); other.RawAssign(temp);
return *this; return *this;
} }
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern
based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.value, b.value);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT
{ a.Swap(b); }
//! Prepare Value for move semantics //! Prepare Value for move semantics
/*! \return *this */ /*! \return *this */
GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
//@} //@}
//!@name Equal-to and not-equal-to operators //!@name Equal-to and not-equal-to operators
//@{ //@{
//! Equal-to operator //! Equal-to operator
/*! /*!
\note If an object contains duplicated named member, comparing equality with any object is always \c false. \note If an object contains duplicated named member, comparing equality with any object is always \c false.
skipping to change at line 712 skipping to change at line 888
case kNumberType: case kNumberType:
if (IsDouble() || rhs.IsDouble()) { if (IsDouble() || rhs.IsDouble()) {
double a = GetDouble(); // May convert from integer to doubl e. double a = GetDouble(); // May convert from integer to doubl e.
double b = rhs.GetDouble(); // Ditto double b = rhs.GetDouble(); // Ditto
return a >= b && a <= b; // Prevent -Wfloat-equal return a >= b && a <= b; // Prevent -Wfloat-equal
} }
else else
return data_.n.u64 == rhs.data_.n.u64; return data_.n.u64 == rhs.data_.n.u64;
default: // kTrueType, kFalseType, kNullType default:
return true; return true;
} }
} }
//! Equal-to operator with const C-string pointer //! Equal-to operator with const C-string pointer
bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRe f(rhs)); } bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRe f(rhs)); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Equal-to operator with string object //! Equal-to operator with string object
/*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_ HAS_STDSTRING. /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_ HAS_STDSTRING.
skipping to change at line 760 skipping to change at line 936
//! Not-Equal-to operator with arbitrary types (symmetric version) //! Not-Equal-to operator with arbitrary types (symmetric version)
/*! \return !(rhs == lhs) /*! \return !(rhs == lhs)
*/ */
template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGeneric Value<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !( rhs == lhs); } template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGeneric Value<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !( rhs == lhs); }
//@} //@}
//!@name Type //!@name Type
//@{ //@{
Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); } Type GetType() const { return static_cast<Type>(data_.f.flags & kTypeMask);
bool IsNull() const { return flags_ == kNullFlag; } }
bool IsFalse() const { return flags_ == kFalseFlag; } bool IsNull() const { return data_.f.flags == kNullFlag; }
bool IsTrue() const { return flags_ == kTrueFlag; } bool IsFalse() const { return data_.f.flags == kFalseFlag; }
bool IsBool() const { return (flags_ & kBoolFlag) != 0; } bool IsTrue() const { return data_.f.flags == kTrueFlag; }
bool IsObject() const { return flags_ == kObjectFlag; } bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; }
bool IsArray() const { return flags_ == kArrayFlag; } bool IsObject() const { return data_.f.flags == kObjectFlag; }
bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } bool IsArray() const { return data_.f.flags == kArrayFlag; }
bool IsInt() const { return (flags_ & kIntFlag) != 0; } bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; }
bool IsUint() const { return (flags_ & kUintFlag) != 0; } bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; }
bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; }
bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; }
bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; }
bool IsString() const { return (flags_ & kStringFlag) != 0; } bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; }
bool IsString() const { return (data_.f.flags & kStringFlag) != 0; }
// Checks whether a number can be losslessly converted to a double.
bool IsLosslessDouble() const {
if (!IsNumber()) return false;
if (IsUint64()) {
uint64_t u = GetUint64();
volatile double d = static_cast<double>(u);
return (d >= 0.0)
&& (d < static_cast<double>(std::numeric_limits<uint64_t>::max()
))
&& (u == static_cast<uint64_t>(d));
}
if (IsInt64()) {
int64_t i = GetInt64();
volatile double d = static_cast<double>(i);
return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()
))
&& (d < static_cast<double>(std::numeric_limits<int64_t>::max())
)
&& (i == static_cast<int64_t>(d));
}
return true; // double, int, uint are always lossless
}
// Checks whether a number is a float (possible lossy).
bool IsFloat() const {
if ((data_.f.flags & kDoubleFlag) == 0)
return false;
double d = GetDouble();
return d >= -3.4028234e38 && d <= 3.4028234e38;
}
// Checks whether a number can be losslessly converted to a float.
bool IsLosslessFloat() const {
if (!IsNumber()) return false;
double a = GetDouble();
if (a < static_cast<double>(-std::numeric_limits<float>::max())
|| a > static_cast<double>(std::numeric_limits<float>::max()))
return false;
double b = static_cast<double>(static_cast<float>(a));
return a >= b && a <= b; // Prevent -Wfloat-equal
}
//@} //@}
//!@name Null //!@name Null
//@{ //@{
GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
//@} //@}
//!@name Bool //!@name Bool
//@{ //@{
bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFla g; } bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == k TrueFlag; }
//!< Set boolean value //!< Set boolean value
/*! \post IsBool() == true */ /*! \post IsBool() == true */
GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericVal ue(b); return *this; } GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericVal ue(b); return *this; }
//@} //@}
//!@name Object //!@name Object
//@{ //@{
//! Set this value as an empty object. //! Set this value as an empty object.
skipping to change at line 840 skipping to change at line 1054
\note Linear time complexity. \note Linear time complexity.
*/ */
template <typename SourceAllocator> template <typename SourceAllocator>
GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name ) { GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name ) {
MemberIterator member = FindMember(name); MemberIterator member = FindMember(name);
if (member != MemberEnd()) if (member != MemberEnd())
return member->value; return member->value;
else { else {
RAPIDJSON_ASSERT(false); // see above note RAPIDJSON_ASSERT(false); // see above note
static GenericValue NullValue;
return NullValue; // This will generate -Wexit-time-destructors in clang
// static GenericValue NullValue;
// return NullValue;
// Use static buffer and placement-new to prevent destruction
static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
} }
} }
template <typename SourceAllocator> template <typename SourceAllocator>
const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator> & name) const { return const_cast<GenericValue&>(*this)[name]; } const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator> & name) const { return const_cast<GenericValue&>(*this)[name]; }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Get a value from an object associated with name (string object). //! Get a value from an object associated with name (string object).
GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this) [GenericValue(StringRef(name))]; } GenericValue& operator[](const std::basic_string<Ch>& name) { return (*this) [GenericValue(StringRef(name))]; }
const GenericValue& operator[](const std::basic_string<Ch>& name) const { re turn (*this)[GenericValue(StringRef(name))]; } const GenericValue& operator[](const std::basic_string<Ch>& name) const { re turn (*this)[GenericValue(StringRef(name))]; }
#endif #endif
//! Const member iterator //! Const member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); retu rn ConstMemberIterator(data_.o.members); } ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); retu rn ConstMemberIterator(GetMembersPointer()); }
//! Const \em past-the-end member iterator //! Const \em past-the-end member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); retu rn ConstMemberIterator(data_.o.members + data_.o.size); } ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); retu rn ConstMemberIterator(GetMembersPointer() + data_.o.size); }
//! Member iterator //! Member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); retu rn MemberIterator(data_.o.members); } MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); retu rn MemberIterator(GetMembersPointer()); }
//! \em Past-the-end member iterator //! \em Past-the-end member iterator
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); retu rn MemberIterator(data_.o.members + data_.o.size); } MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); retu rn MemberIterator(GetMembersPointer() + data_.o.size); }
//! Check whether a member exists in the object. //! Check whether a member exists in the object.
/*! /*!
\param name Member name to be searched. \param name Member name to be searched.
\pre IsObject() == true \pre IsObject() == true
\return Whether a member with that name exists. \return Whether a member with that name exists.
\note It is better to use FindMember() directly if you need the obtain t he value as well. \note It is better to use FindMember() directly if you need the obtain t he value as well.
\note Linear time complexity. \note Linear time complexity.
*/ */
bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd( ); } bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd( ); }
skipping to change at line 952 skipping to change at line 1172
template <typename SourceAllocator> ConstMemberIterator FindMember(const Gen ericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericVal ue&>(*this).FindMember(name); } template <typename SourceAllocator> ConstMemberIterator FindMember(const Gen ericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericVal ue&>(*this).FindMember(name); }
#if RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Find member by string object name. //! Find member by string object name.
/*! /*!
\param name Member name to be searched. \param name Member name to be searched.
\pre IsObject() == true \pre IsObject() == true
\return Iterator to member, if it exists. \return Iterator to member, if it exists.
Otherwise returns \ref MemberEnd(). Otherwise returns \ref MemberEnd().
*/ */
MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMe MemberIterator FindMember(const std::basic_string<Ch>& name) { return FindMe
mber(StringRef(name)); } mber(GenericValue(StringRef(name))); }
ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { re ConstMemberIterator FindMember(const std::basic_string<Ch>& name) const { re
turn FindMember(StringRef(name)); } turn FindMember(GenericValue(StringRef(name))); }
#endif #endif
//! Add a member (name-value pair) to the object. //! Add a member (name-value pair) to the object.
/*! \param name A string value as name of member. /*! \param name A string value as name of member.
\param value Value of any type. \param value Value of any type.
\param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator(). \param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API. \return The value itself for fluent API.
\note The ownership of \c name and \c value will be transferred to this object on success. \note The ownership of \c name and \c value will be transferred to this object on success.
\pre IsObject() && name.IsString() \pre IsObject() && name.IsString()
\post name.IsNull() && value.IsNull() \post name.IsNull() && value.IsNull()
\note Amortized Constant time complexity. \note Amortized Constant time complexity.
*/ */
GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(name.IsString()); RAPIDJSON_ASSERT(name.IsString());
Object& o = data_.o; ObjectData& o = data_.o;
if (o.size >= o.capacity) { if (o.size >= o.capacity) {
if (o.capacity == 0) { if (o.capacity == 0) {
o.capacity = kDefaultObjectCapacity; o.capacity = kDefaultObjectCapacity;
o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacit y * sizeof(Member))); SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.c apacity * sizeof(Member))));
} }
else { else {
SizeType oldCapacity = o.capacity; SizeType oldCapacity = o.capacity;
o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
o.members = reinterpret_cast<Member*>(allocator.Realloc(o.member s, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(Ge tMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
} }
} }
o.members[o.size].name.RawAssign(name); Member* members = GetMembersPointer();
o.members[o.size].value.RawAssign(value); members[o.size].name.RawAssign(name);
members[o.size].value.RawAssign(value);
o.size++; o.size++;
return *this; return *this;
} }
//! Add a constant string value as member (name-value pair) to the object. //! Add a constant string value as member (name-value pair) to the object.
/*! \param name A string value as name of member. /*! \param name A string value as name of member.
\param value constant string reference as value of member. \param value constant string reference as value of member.
\param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator(). \param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API. \return The value itself for fluent API.
\pre IsObject() \pre IsObject()
skipping to change at line 1161 skipping to change at line 1382
/*! \param m member iterator (obtained by FindMember() or MemberBegin()). /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
\return the new iterator after removal. \return the new iterator after removal.
\note This function may reorder the object members. Use \ref \note This function may reorder the object members. Use \ref
EraseMember(ConstMemberIterator) if you need to preserve the EraseMember(ConstMemberIterator) if you need to preserve the
relative order of the remaining members. relative order of the remaining members.
\note Constant time complexity. \note Constant time complexity.
*/ */
MemberIterator RemoveMember(MemberIterator m) { MemberIterator RemoveMember(MemberIterator m) {
RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0); RAPIDJSON_ASSERT(data_.o.size > 0);
RAPIDJSON_ASSERT(data_.o.members != 0); RAPIDJSON_ASSERT(GetMembersPointer() != 0);
RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
MemberIterator last(data_.o.members + (data_.o.size - 1)); MemberIterator last(GetMembersPointer() + (data_.o.size - 1));
if (data_.o.size > 1 && m != last) { if (data_.o.size > 1 && m != last)
// Move the last one to this place *m = *last; // Move the last one to this place
*m = *last; else
} m->~Member(); // Only one left, just destroy
else {
// Only one left, just destroy
m->~Member();
}
--data_.o.size; --data_.o.size;
return m; return m;
} }
//! Remove a member from an object by iterator. //! Remove a member from an object by iterator.
/*! \param pos iterator to the member to remove /*! \param pos iterator to the member to remove
\pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd () \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd ()
\return Iterator following the removed element. \return Iterator following the removed element.
If the iterator \c pos refers to the last element, the \ref MemberEn d() iterator is returned. If the iterator \c pos refers to the last element, the \ref MemberEn d() iterator is returned.
\note This function preserves the relative order of the remaining object \note This function preserves the relative order of the remaining object
skipping to change at line 1202 skipping to change at line 1419
\param last iterator following the last member to remove \param last iterator following the last member to remove
\pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
\return Iterator following the last removed element. \return Iterator following the last removed element.
\note This function preserves the relative order of the remaining object \note This function preserves the relative order of the remaining object
members. members.
\note Linear time complexity. \note Linear time complexity.
*/ */
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator la st) { MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator la st) {
RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(IsObject());
RAPIDJSON_ASSERT(data_.o.size > 0); RAPIDJSON_ASSERT(data_.o.size > 0);
RAPIDJSON_ASSERT(data_.o.members != 0); RAPIDJSON_ASSERT(GetMembersPointer() != 0);
RAPIDJSON_ASSERT(first >= MemberBegin()); RAPIDJSON_ASSERT(first >= MemberBegin());
RAPIDJSON_ASSERT(first <= last); RAPIDJSON_ASSERT(first <= last);
RAPIDJSON_ASSERT(last <= MemberEnd()); RAPIDJSON_ASSERT(last <= MemberEnd());
MemberIterator pos = MemberBegin() + (first - MemberBegin()); MemberIterator pos = MemberBegin() + (first - MemberBegin());
for (MemberIterator itr = pos; itr != last; ++itr) for (MemberIterator itr = pos; itr != last; ++itr)
itr->~Member(); itr->~Member();
std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member)); std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * si
data_.o.size -= (last - first); zeof(Member));
data_.o.size -= static_cast<SizeType>(last - first);
return pos; return pos;
} }
//! Erase a member in object by its name.
/*! \param name Name of member to be removed.
\return Whether the member existed.
\note Linear time complexity.
*/
bool EraseMember(const Ch* name) {
GenericValue n(StringRef(name));
return EraseMember(n);
}
#if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) { return EraseMember(Gen
ericValue(StringRef(name))); }
#endif
template <typename SourceAllocator>
bool EraseMember(const GenericValue<Encoding, SourceAllocator>& name) {
MemberIterator m = FindMember(name);
if (m != MemberEnd()) {
EraseMember(m);
return true;
}
else
return false;
}
Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); }
ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstOb
ject(*this); }
//@} //@}
//!@name Array //!@name Array
//@{ //@{
//! Set this value as an empty array. //! Set this value as an empty array.
/*! \post IsArray == true */ /*! \post IsArray == true */
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(k ArrayType); return *this; } GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kA rrayType); return *this; }
//! Get the number of elements in array. //! Get the number of elements in array.
SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
//! Get the capacity of array. //! Get the capacity of array.
SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capa city; } SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capa city; }
//! Check whether the array is empty. //! Check whether the array is empty.
bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
//! Remove all elements in the array. //! Remove all elements in the array.
/*! This function do not deallocate memory in the array, i.e. the capacity i s unchanged. /*! This function do not deallocate memory in the array, i.e. the capacity i s unchanged.
\note Linear time complexity. \note Linear time complexity.
*/ */
void Clear() { void Clear() {
RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(IsArray());
for (SizeType i = 0; i < data_.a.size; ++i) GenericValue* e = GetElementsPointer();
data_.a.elements[i].~GenericValue(); for (GenericValue* v = e; v != e + data_.a.size; ++v)
v->~GenericValue();
data_.a.size = 0; data_.a.size = 0;
} }
//! Get an element from array by index. //! Get an element from array by index.
/*! \pre IsArray() == true /*! \pre IsArray() == true
\param index Zero-based index of element. \param index Zero-based index of element.
\see operator[](T*) \see operator[](T*)
*/ */
GenericValue& operator[](SizeType index) { GenericValue& operator[](SizeType index) {
RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(index < data_.a.size); RAPIDJSON_ASSERT(index < data_.a.size);
return data_.a.elements[index]; return GetElementsPointer()[index];
} }
const GenericValue& operator[](SizeType index) const { return const_cast<Gen ericValue&>(*this)[index]; } const GenericValue& operator[](SizeType index) const { return const_cast<Gen ericValue&>(*this)[index]; }
//! Element iterator //! Element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements ; } ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPoint er(); }
//! \em Past-the-end element iterator //! \em Past-the-end element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer () + data_.a.size; }
//! Constant element iterator //! Constant element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).B egin(); } ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).B egin(); }
//! Constant \em past-the-end element iterator //! Constant \em past-the-end element iterator
/*! \pre IsArray() == true */ /*! \pre IsArray() == true */
ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End (); } ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End (); }
//! Request the array to have enough capacity to store elements. //! Request the array to have enough capacity to store elements.
/*! \param newCapacity The capacity that the array at least need to have. /*! \param newCapacity The capacity that the array at least need to have.
\param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator(). \param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API. \return The value itself for fluent API.
\note Linear time complexity. \note Linear time complexity.
*/ */
GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(IsArray());
if (newCapacity > data_.a.capacity) { if (newCapacity > data_.a.capacity) {
data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements , data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); SetElementsPointer(reinterpret_cast<GenericValue*>(allocator.Realloc (GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * si zeof(GenericValue))));
data_.a.capacity = newCapacity; data_.a.capacity = newCapacity;
} }
return *this; return *this;
} }
//! Append a GenericValue at the end of the array. //! Append a GenericValue at the end of the array.
/*! \param value Value to be appended. /*! \param value Value to be appended.
\param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator(). \param allocator Allocator for reallocating memory. It must be the sa me one as used before. Commonly use GenericDocument::GetAllocator().
\pre IsArray() == true \pre IsArray() == true
\post value.IsNull() == true \post value.IsNull() == true
\return The value itself for fluent API. \return The value itself for fluent API.
\note The ownership of \c value will be transferred to this array on suc cess. \note The ownership of \c value will be transferred to this array on suc cess.
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
\note Amortized constant time complexity. \note Amortized constant time complexity.
*/ */
GenericValue& PushBack(GenericValue& value, Allocator& allocator) { GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(IsArray());
if (data_.a.size >= data_.a.capacity) if (data_.a.size >= data_.a.capacity)
Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.cap acity + (data_.a.capacity + 1) / 2), allocator); Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.cap acity + (data_.a.capacity + 1) / 2), allocator);
data_.a.elements[data_.a.size++].RawAssign(value); GetElementsPointer()[data_.a.size++].RawAssign(value);
return *this; return *this;
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
return PushBack(value, allocator); return PushBack(value, allocator);
} }
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Append a constant string reference at the end of the array. //! Append a constant string reference at the end of the array.
skipping to change at line 1352 skipping to change at line 1598
return PushBack(v, allocator); return PushBack(v, allocator);
} }
//! Remove the last element in the array. //! Remove the last element in the array.
/*! /*!
\note Constant time complexity. \note Constant time complexity.
*/ */
GenericValue& PopBack() { GenericValue& PopBack() {
RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(!Empty()); RAPIDJSON_ASSERT(!Empty());
data_.a.elements[--data_.a.size].~GenericValue(); GetElementsPointer()[--data_.a.size].~GenericValue();
return *this; return *this;
} }
//! Remove an element of array by iterator. //! Remove an element of array by iterator.
/*! /*!
\param pos iterator to the element to remove \param pos iterator to the element to remove
\pre IsArray() == true && \ref Begin() <= \c pos < \ref End() \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
\return Iterator following the removed element. If the iterator pos refe rs to the last element, the End() iterator is returned. \return Iterator following the removed element. If the iterator pos refe rs to the last element, the End() iterator is returned.
\note Linear time complexity. \note Linear time complexity.
*/ */
skipping to change at line 1378 skipping to change at line 1624
/*! /*!
\param first iterator to the first element to remove \param first iterator to the first element to remove
\param last iterator following the last element to remove \param last iterator following the last element to remove
\pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref En d() \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref En d()
\return Iterator following the last removed element. \return Iterator following the last removed element.
\note Linear time complexity. \note Linear time complexity.
*/ */
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(IsArray());
RAPIDJSON_ASSERT(data_.a.size > 0); RAPIDJSON_ASSERT(data_.a.size > 0);
RAPIDJSON_ASSERT(data_.a.elements != 0); RAPIDJSON_ASSERT(GetElementsPointer() != 0);
RAPIDJSON_ASSERT(first >= Begin()); RAPIDJSON_ASSERT(first >= Begin());
RAPIDJSON_ASSERT(first <= last); RAPIDJSON_ASSERT(first <= last);
RAPIDJSON_ASSERT(last <= End()); RAPIDJSON_ASSERT(last <= End());
ValueIterator pos = Begin() + (first - Begin()); ValueIterator pos = Begin() + (first - Begin());
for (ValueIterator itr = pos; itr != last; ++itr) for (ValueIterator itr = pos; itr != last; ++itr)
itr->~GenericValue(); itr->~GenericValue();
std::memmove(pos, last, (End() - last) * sizeof(GenericValue)); std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(Gener
data_.a.size -= (last - first); icValue));
data_.a.size -= static_cast<SizeType>(last - first);
return pos; return pos;
} }
Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); }
ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray
(*this); }
//@} //@}
//!@name Number //!@name Number
//@{ //@{
int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag);
data_.n.i.i; } return data_.n.i.i; }
unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag);
data_.n.u.u; } return data_.n.u.u; }
int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag);
data_.n.i64; } return data_.n.i64; }
uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag);
data_.n.u64; } return data_.n.u64; }
//! Get the value as double type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c
IsLosslessDouble() to check whether the converison is lossless.
*/
double GetDouble() const { double GetDouble() const {
RAPIDJSON_ASSERT(IsNumber()); RAPIDJSON_ASSERT(IsNumber());
if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // e if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d;
xact type, no conversion. // exact type, no conversion.
if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // i if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.
nt -> double i; // int -> double
if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // u if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.
nsigned -> double u; // unsigned -> double
if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i if ((data_.f.flags & kInt64Flag) != 0) return static_cas
64; // int64_t -> double (may lose precision) t<double>(data_.n.i64); // int64_t -> double (may lose precision)
RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cas
64; // uint64_t -> double (may lose precision) t<double>(data_.n.u64); // uint64_t -> double (may lose precision)
}
//! Get the value as float type.
/*! \note If the value is 64-bit integer type, it may lose precision. Use \c
IsLosslessFloat() to check whether the converison is lossless.
*/
float GetFloat() const {
return static_cast<float>(GetDouble());
} }
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
//@} //@}
//!@name String //!@name String
//@{ //@{
const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); } const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f. flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); }
//! Get the length of string. //! Get the length of string.
/*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString ()) may not equal to v.GetStringLength(). /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString ()) may not equal to v.GetStringLength().
*/ */
SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((fl ags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((da ta_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
//! Set this value as a string without copying source string. //! Set this value as a string without copying source string.
/*! This version has better performance with supplied length, and also suppo rt string containing null character. /*! This version has better performance with supplied length, and also suppo rt string containing null character.
\param s source string pointer. \param s source string pointer.
\param length The length of source string, excluding the trailing null t erminator. \param length The length of source string, excluding the trailing null t erminator.
\return The value itself for fluent API. \return The value itself for fluent API.
\post IsString() == true && GetString() == s && GetStringLength() == len gth \post IsString() == true && GetString() == s && GetStringLength() == len gth
\see SetString(StringRefType) \see SetString(StringRefType)
*/ */
GenericValue& SetString(const Ch* s, SizeType length) { return SetString(Str ingRef(s, length)); } GenericValue& SetString(const Ch* s, SizeType length) { return SetString(Str ingRef(s, length)); }
skipping to change at line 1475 skipping to change at line 1735
\param allocator Allocator for allocating copied buffer. Commonly use Ge nericDocument::GetAllocator(). \param allocator Allocator for allocating copied buffer. Commonly use Ge nericDocument::GetAllocator().
\return The value itself for fluent API. \return The value itself for fluent API.
\post IsString() == true && GetString() != s.data() && strcmp(GetString( ),s.data() == 0 && GetStringLength() == s.size() \post IsString() == true && GetString() != s.data() && strcmp(GetString( ),s.data() == 0 && GetStringLength() == s.size()
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_ HAS_STDSTRING. \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_ HAS_STDSTRING.
*/ */
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator ) { return SetString(s.data(), SizeType(s.size()), allocator); } GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator ) { return SetString(s.data(), SizeType(s.size()), allocator); }
#endif #endif
//@} //@}
//!@name Array
//@{
//! Templated version for checking whether this value is type T.
/*!
\tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t,
\c double, \c float, \c const \c char*, \c std::basic_string<Ch>
*/
template <typename T>
bool Is() const { return internal::TypeHelper<ValueType, T>::Is(*this); }
template <typename T>
T Get() const { return internal::TypeHelper<ValueType, T>::Get(*this); }
template <typename T>
T Get() { return internal::TypeHelper<ValueType, T>::Get(*this); }
template<typename T>
ValueType& Set(const T& data) { return internal::TypeHelper<ValueType, T>::S
et(*this, data); }
template<typename T>
ValueType& Set(const T& data, AllocatorType& allocator) { return internal::T
ypeHelper<ValueType, T>::Set(*this, data, allocator); }
//@}
//! Generate events of this value to a Handler. //! Generate events of this value to a Handler.
/*! This function adopts the GoF visitor pattern. /*! This function adopts the GoF visitor pattern.
Typical usage is to output this JSON value as JSON text via Writer, whic h is a Handler. Typical usage is to output this JSON value as JSON text via Writer, whic h is a Handler.
It can also be used to deep clone this value via GenericDocument, which is also a Handler. It can also be used to deep clone this value via GenericDocument, which is also a Handler.
\tparam Handler type of handler. \tparam Handler type of handler.
\param handler An object implementing concept Handler. \param handler An object implementing concept Handler.
*/ */
template <typename Handler> template <typename Handler>
bool Accept(Handler& handler) const { bool Accept(Handler& handler) const {
switch(GetType()) { switch(GetType()) {
case kNullType: return handler.Null(); case kNullType: return handler.Null();
case kFalseType: return handler.Bool(false); case kFalseType: return handler.Bool(false);
case kTrueType: return handler.Bool(true); case kTrueType: return handler.Bool(true);
case kObjectType: case kObjectType:
if (!handler.StartObject()) if (RAPIDJSON_UNLIKELY(!handler.StartObject()))
return false; return false;
for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
RAPIDJSON_ASSERT(m->name.IsString()); // User may change the typ e of name by MemberIterator. RAPIDJSON_ASSERT(m->name.IsString()); // User may change the typ e of name by MemberIterator.
if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name .GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0)))
return false; return false;
if (!m->value.Accept(handler)) if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler)))
return false; return false;
} }
return handler.EndObject(data_.o.size); return handler.EndObject(data_.o.size);
case kArrayType: case kArrayType:
if (!handler.StartArray()) if (RAPIDJSON_UNLIKELY(!handler.StartArray()))
return false; return false;
for (GenericValue* v = data_.a.elements; v != data_.a.elements + dat for (const GenericValue* v = Begin(); v != End(); ++v)
a_.a.size; ++v) if (RAPIDJSON_UNLIKELY(!v->Accept(handler)))
if (!v->Accept(handler))
return false; return false;
return handler.EndArray(data_.a.size); return handler.EndArray(data_.a.size);
case kStringType: case kStringType:
return handler.String(GetString(), GetStringLength(), (flags_ & kCop yFlag) != 0); return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
default: default:
RAPIDJSON_ASSERT(GetType() == kNumberType); RAPIDJSON_ASSERT(GetType() == kNumberType);
if (IsInt()) return handler.Int(data_.n.i.i); if (IsDouble()) return handler.Double(data_.n.d);
else if (IsInt()) return handler.Int(data_.n.i.i);
else if (IsUint()) return handler.Uint(data_.n.u.u); else if (IsUint()) return handler.Uint(data_.n.u.u);
else if (IsInt64()) return handler.Int64(data_.n.i64); else if (IsInt64()) return handler.Int64(data_.n.i64);
else if (IsUint64()) return handler.Uint64(data_.n.u64); else return handler.Uint64(data_.n.u64);
else return handler.Double(data_.n.d);
} }
} }
private: private:
template <typename, typename> friend class GenericValue; template <typename, typename> friend class GenericValue;
template <typename, typename, typename> friend class GenericDocument; template <typename, typename, typename> friend class GenericDocument;
enum { enum {
kBoolFlag = 0x100, kBoolFlag = 0x0008,
kNumberFlag = 0x200, kNumberFlag = 0x0010,
kIntFlag = 0x400, kIntFlag = 0x0020,
kUintFlag = 0x800, kUintFlag = 0x0040,
kInt64Flag = 0x1000, kInt64Flag = 0x0080,
kUint64Flag = 0x2000, kUint64Flag = 0x0100,
kDoubleFlag = 0x4000, kDoubleFlag = 0x0200,
kStringFlag = 0x100000, kStringFlag = 0x0400,
kCopyFlag = 0x200000, kCopyFlag = 0x0800,
kInlineStrFlag = 0x400000, kInlineStrFlag = 0x1000,
// Initial flags of different types. // Initial flags of different types.
kNullFlag = kNullType, kNullFlag = kNullType,
kTrueFlag = kTrueType | kBoolFlag, kTrueFlag = kTrueType | kBoolFlag,
kFalseFlag = kFalseType | kBoolFlag, kFalseFlag = kFalseType | kBoolFlag,
kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag, kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag, kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag, kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag, kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag, kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUi ntFlag | kUint64Flag | kDoubleFlag, kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUi ntFlag | kUint64Flag | kDoubleFlag,
kConstStringFlag = kStringType | kStringFlag, kConstStringFlag = kStringType | kStringFlag,
kCopyStringFlag = kStringType | kStringFlag | kCopyFlag, kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFla g, kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFla g,
kObjectFlag = kObjectType, kObjectFlag = kObjectType,
kArrayFlag = kArrayType, kArrayFlag = kArrayType,
kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler kTypeMask = 0x07
}; };
static const SizeType kDefaultArrayCapacity = 16; static const SizeType kDefaultArrayCapacity = 16;
static const SizeType kDefaultObjectCapacity = 16; static const SizeType kDefaultObjectCapacity = 16;
struct Flag {
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-b
it pointer
#elif RAPIDJSON_64BIT
char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding byt
es
#else
char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding byt
es
#endif
uint16_t flags;
};
struct String { struct String {
const Ch* str;
SizeType length; SizeType length;
unsigned hashcode; //!< reserved SizeType hashcode; //!< reserved
const Ch* str;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
// implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
// (excluding the terminating zero) and store a value to determine the lengt h of the contained // (excluding the terminating zero) and store a value to determine the lengt h of the contained
// string in the last character str[LenPos] by storing "MaxSize - length" th ere. If the string // string in the last character str[LenPos] by storing "MaxSize - length" th ere. If the string
// to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
// the string terminator as well. For getting the string length back from th at value just use // the string terminator as well. For getting the string length back from th at value just use
// "MaxSize - str[LenPos]". // "MaxSize - str[LenPos]".
// This allows to store 11-chars strings in 32-bit mode and 15-chars strings // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in
in 64-bit mode 64-bit mode,
// inline (for `UTF8`-encoded strings). // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `U
TF8`-encoded strings).
struct ShortString { struct ShortString {
enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, L enPos = MaxSize }; enum { MaxChars = sizeof(static_cast<Flag*>(0)->payload) / sizeof(Ch), M axSize = MaxChars - 1, LenPos = MaxSize };
Ch str[MaxChars]; Ch str[MaxChars];
inline static bool Usable(SizeType len) { return (MaxSize >= inline static bool Usable(SizeType len) { return (
len); } MaxSize >= len); }
inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - inline void SetLength(SizeType len) { str[LenPos] = static_cast<Ch>(
len); } MaxSize - len); }
inline SizeType GetLength() const { return (SizeType)(MaxSize - inline SizeType GetLength() const { return static_cast<SizeType>(
str[LenPos]); } MaxSize - str[LenPos]); }
}; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 1 6 bytes in 64-bit mode }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 1 6 bytes in 64-bit mode
// By using proper binary layout, retrieval of different integer types do no t need conversions. // By using proper binary layout, retrieval of different integer types do no t need conversions.
union Number { union Number {
#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN #if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
struct I { struct I {
int i; int i;
char padding[4]; char padding[4];
}i; }i;
struct U { struct U {
skipping to change at line 1609 skipping to change at line 1904
struct U { struct U {
char padding2[4]; char padding2[4];
unsigned u; unsigned u;
}u; }u;
#endif #endif
int64_t i64; int64_t i64;
uint64_t u64; uint64_t u64;
double d; double d;
}; // 8 bytes }; // 8 bytes
struct Object { struct ObjectData {
Member* members;
SizeType size; SizeType size;
SizeType capacity; SizeType capacity;
Member* members;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
struct Array { struct ArrayData {
GenericValue* elements;
SizeType size; SizeType size;
SizeType capacity; SizeType capacity;
GenericValue* elements;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
union Data { union Data {
String s; String s;
ShortString ss; ShortString ss;
Number n; Number n;
Object o; ObjectData o;
Array a; ArrayData a;
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode Flag f;
}; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit
with RAPIDJSON_48BITPOINTER_OPTIMIZATION
RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_
GETPOINTER(Ch, data_.s.str); }
RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAP
IDJSON_SETPOINTER(Ch, data_.s.str, str); }
RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPI
DJSON_GETPOINTER(GenericValue, data_.a.elements); }
RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* element
s) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); }
RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_G
ETPOINTER(Member, data_.o.members); }
RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RA
PIDJSON_SETPOINTER(Member, data_.o.members, members); }
// Initialize this value as array with initial data, without calling destruc tor. // Initialize this value as array with initial data, without calling destruc tor.
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
flags_ = kArrayFlag; data_.f.flags = kArrayFlag;
if (count) { if (count) {
data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(Ge GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count
nericValue)); * sizeof(GenericValue)));
std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); SetElementsPointer(e);
std::memcpy(e, values, count * sizeof(GenericValue));
} }
else else
data_.a.elements = NULL; SetElementsPointer(0);
data_.a.size = data_.a.capacity = count; data_.a.size = data_.a.capacity = count;
} }
//! Initialize this value as object with initial data, without calling destr uctor. //! Initialize this value as object with initial data, without calling destr uctor.
void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
flags_ = kObjectFlag; data_.f.flags = kObjectFlag;
if (count) { if (count) {
data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Mem
std::memcpy(data_.o.members, members, count * sizeof(Member)); ber)));
SetMembersPointer(m);
std::memcpy(m, members, count * sizeof(Member));
} }
else else
data_.o.members = NULL; SetMembersPointer(0);
data_.o.size = data_.o.capacity = count; data_.o.size = data_.o.capacity = count;
} }
//! Initialize this value as constant string, without calling destructor. //! Initialize this value as constant string, without calling destructor.
void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
flags_ = kConstStringFlag; data_.f.flags = kConstStringFlag;
data_.s.str = s; SetStringPointer(s);
data_.s.length = s.length; data_.s.length = s.length;
} }
//! Initialize this value as copy string with initial data, without calling destructor. //! Initialize this value as copy string with initial data, without calling destructor.
void SetStringRaw(StringRefType s, Allocator& allocator) { void SetStringRaw(StringRefType s, Allocator& allocator) {
Ch* str = NULL; Ch* str = 0;
if(ShortString::Usable(s.length)) { if (ShortString::Usable(s.length)) {
flags_ = kShortStringFlag; data_.f.flags = kShortStringFlag;
data_.ss.SetLength(s.length); data_.ss.SetLength(s.length);
str = data_.ss.str; str = data_.ss.str;
} else { } else {
flags_ = kCopyStringFlag; data_.f.flags = kCopyStringFlag;
data_.s.length = s.length; data_.s.length = s.length;
str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch)); str = static_cast<Ch *>(allocator.Malloc((s.length + 1) * sizeof(Ch)
data_.s.str = str; ));
SetStringPointer(str);
} }
std::memcpy(str, s, s.length * sizeof(Ch)); std::memcpy(str, s, s.length * sizeof(Ch));
str[s.length] = '\0'; str[s.length] = '\0';
} }
//! Assignment without calling destructor //! Assignment without calling destructor
void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
data_ = rhs.data_; data_ = rhs.data_;
flags_ = rhs.flags_; // data_.f.flags = rhs.data_.f.flags;
rhs.flags_ = kNullFlag; rhs.data_.f.flags = kNullFlag;
} }
template <typename SourceAllocator> template <typename SourceAllocator>
bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const { bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
RAPIDJSON_ASSERT(IsString()); RAPIDJSON_ASSERT(IsString());
RAPIDJSON_ASSERT(rhs.IsString()); RAPIDJSON_ASSERT(rhs.IsString());
const SizeType len1 = GetStringLength(); const SizeType len1 = GetStringLength();
const SizeType len2 = rhs.GetStringLength(); const SizeType len2 = rhs.GetStringLength();
if(len1 != len2) { return false; } if(len1 != len2) { return false; }
const Ch* const str1 = GetString(); const Ch* const str1 = GetString();
const Ch* const str2 = rhs.GetString(); const Ch* const str2 = rhs.GetString();
if(str1 == str2) { return true; } // fast path for constant string if(str1 == str2) { return true; } // fast path for constant string
return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
} }
Data data_; Data data_;
unsigned flags_;
}; };
//! GenericValue with UTF8 encoding //! GenericValue with UTF8 encoding
typedef GenericValue<UTF8<> > Value; typedef GenericValue<UTF8<> > Value;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GenericDocument // GenericDocument
//! A document for parsing JSON text as DOM. //! A document for parsing JSON text as DOM.
/*! /*!
skipping to change at line 1726 skipping to change at line 2030
\warning Although GenericDocument inherits from GenericValue, the API does \ b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a Gene ricValue. \warning Although GenericDocument inherits from GenericValue, the API does \ b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a Gene ricValue.
*/ */
template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typenam e StackAllocator = CrtAllocator> template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typenam e StackAllocator = CrtAllocator>
class GenericDocument : public GenericValue<Encoding, Allocator> { class GenericDocument : public GenericValue<Encoding, Allocator> {
public: public:
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of t he document. typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of t he document.
typedef Allocator AllocatorType; //!< Allocator type from template parameter. typedef Allocator AllocatorType; //!< Allocator type from template parameter.
//! Constructor //! Constructor
/*! \param allocator Optional allocator for allocating memory. /*! Creates an empty document of specified type.
\param type Mandatory type of object to create.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for sta
ck.
*/
explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCa
pacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllo
cator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{
if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
}
//! Constructor
/*! Creates an empty document which type is Null.
\param allocator Optional allocator for allocating memory.
\param stackCapacity Optional initial capacity of stack in bytes. \param stackCapacity Optional initial capacity of stack in bytes.
\param stackAllocator Optional allocator for allocating memory for sta ck. \param stackAllocator Optional allocator for allocating memory for sta ck.
*/ */
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultSta ckCapacity, StackAllocator* stackAllocator = 0) : GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultSta ckCapacity, StackAllocator* stackAllocator = 0) :
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCap acity), parseResult_() allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCap acity), parseResult_()
{ {
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11 //! Move constructor in C++11
GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
: ValueType(std::move(rhs)), : ValueType(std::forward<ValueType>(rhs)), // explicit cast to avoid pro hibited move from Document
allocator_(rhs.allocator_), allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_), ownAllocator_(rhs.ownAllocator_),
stack_(std::move(rhs.stack_)), stack_(std::move(rhs.stack_)),
parseResult_(rhs.parseResult_) parseResult_(rhs.parseResult_)
{ {
rhs.allocator_ = 0; rhs.allocator_ = 0;
rhs.ownAllocator_ = 0; rhs.ownAllocator_ = 0;
rhs.parseResult_ = ParseResult(); rhs.parseResult_ = ParseResult();
} }
#endif #endif
skipping to change at line 1780 skipping to change at line 2099
parseResult_ = rhs.parseResult_; parseResult_ = rhs.parseResult_;
rhs.allocator_ = 0; rhs.allocator_ = 0;
rhs.ownAllocator_ = 0; rhs.ownAllocator_ = 0;
rhs.parseResult_ = ParseResult(); rhs.parseResult_ = ParseResult();
return *this; return *this;
} }
#endif #endif
//! Exchange the contents of this document with those of another.
/*!
\param rhs Another document.
\note Constant complexity.
\see GenericValue::Swap
*/
GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
ValueType::Swap(rhs);
stack_.Swap(rhs.stack_);
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(parseResult_, rhs.parseResult_);
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern
based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.doc, b.doc);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NO
EXCEPT { a.Swap(b); }
//! Populate this document by a generator which produces SAX events.
/*! \tparam Generator A functor with <tt>bool f(Handler)</tt> prototype.
\param g Generator functor which sends SAX events to the parameter.
\return The document itself for fluent API.
*/
template <typename Generator>
GenericDocument& Populate(Generator& g) {
ClearStackOnExit scope(*this);
if (g(*this)) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one
and only one root object
ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move val
ue from stack to document
}
return *this;
}
//!@name Parse from stream //!@name Parse from stream
//!@{ //!@{
//! Parse JSON text from an input stream (with Encoding conversion) //! Parse JSON text from an input stream (with Encoding conversion)
/*! \tparam parseFlags Combination of \ref ParseFlag. /*! \tparam parseFlags Combination of \ref ParseFlag.
\tparam SourceEncoding Encoding of input stream \tparam SourceEncoding Encoding of input stream
\tparam InputStream Type of input stream, implementing Stream concept \tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed. \param is Input stream to be parsed.
\return The document itself for fluent API. \return The document itself for fluent API.
*/ */
template <unsigned parseFlags, typename SourceEncoding, typename InputStream > template <unsigned parseFlags, typename SourceEncoding, typename InputStream >
GenericDocument& ParseStream(InputStream& is) { GenericDocument& ParseStream(InputStream& is) {
ValueType::SetNull(); // Remove existing root if exist GenericReader<SourceEncoding, Encoding, StackAllocator> reader(
GenericReader<SourceEncoding, Encoding, StackAllocator> reader(&stack_.G stack_.HasAllocator() ? &stack_.GetAllocator() : 0);
etAllocator());
ClearStackOnExit scope(*this); ClearStackOnExit scope(*this);
parseResult_ = reader.template Parse<parseFlags>(is, *this); parseResult_ = reader.template Parse<parseFlags>(is, *this);
if (parseResult_) { if (parseResult_) {
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this- > to prevent issue 13. ValueType::operator=(*stack_.template Pop<ValueType>(1));// Move val ue from stack to document
} }
return *this; return *this;
} }
//! Parse JSON text from an input stream //! Parse JSON text from an input stream
/*! \tparam parseFlags Combination of \ref ParseFlag. /*! \tparam parseFlags Combination of \ref ParseFlag.
\tparam InputStream Type of input stream, implementing Stream concept \tparam InputStream Type of input stream, implementing Stream concept
\param is Input stream to be parsed. \param is Input stream to be parsed.
\return The document itself for fluent API. \return The document itself for fluent API.
*/ */
skipping to change at line 1857 skipping to change at line 2220
//!@name Parse from read-only string //!@name Parse from read-only string
//!@{ //!@{
//! Parse JSON text from a read-only string (with Encoding conversion) //! Parse JSON text from a read-only string (with Encoding conversion)
/*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
\tparam SourceEncoding Transcoding from input Encoding \tparam SourceEncoding Transcoding from input Encoding
\param str Read-only zero-terminated string to be parsed. \param str Read-only zero-terminated string to be parsed.
*/ */
template <unsigned parseFlags, typename SourceEncoding> template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const Ch* str) { GenericDocument& Parse(const typename SourceEncoding::Ch* str) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
GenericStringStream<SourceEncoding> s(str); GenericStringStream<SourceEncoding> s(str);
return ParseStream<parseFlags, SourceEncoding>(s); return ParseStream<parseFlags, SourceEncoding>(s);
} }
//! Parse JSON text from a read-only string //! Parse JSON text from a read-only string
/*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
\param str Read-only zero-terminated string to be parsed. \param str Read-only zero-terminated string to be parsed.
*/ */
template <unsigned parseFlags> template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) { GenericDocument& Parse(const Ch* str) {
return Parse<parseFlags, Encoding>(str); return Parse<parseFlags, Encoding>(str);
} }
//! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
/*! \param str Read-only zero-terminated string to be parsed. /*! \param str Read-only zero-terminated string to be parsed.
*/ */
GenericDocument& Parse(const Ch* str) { GenericDocument& Parse(const Ch* str) {
return Parse<kParseDefaultFlags>(str); return Parse<kParseDefaultFlags>(str);
} }
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length
) {
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename
SourceEncoding::Ch));
EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
ParseStream<parseFlags, SourceEncoding>(is);
return *this;
}
template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str, size_t length) {
return Parse<parseFlags, Encoding>(str, length);
}
GenericDocument& Parse(const Ch* str, size_t length) {
return Parse<kParseDefaultFlags>(str, length);
}
#if RAPIDJSON_HAS_STDSTRING
template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const std::basic_string<typename SourceEncoding::Ch>&
str) {
// c_str() is constant complexity according to standard. Should be faste
r than Parse(const char*, size_t)
return Parse<parseFlags, SourceEncoding>(str.c_str());
}
template <unsigned parseFlags>
GenericDocument& Parse(const std::basic_string<Ch>& str) {
return Parse<parseFlags, Encoding>(str.c_str());
}
GenericDocument& Parse(const std::basic_string<Ch>& str) {
return Parse<kParseDefaultFlags>(str);
}
#endif // RAPIDJSON_HAS_STDSTRING
//!@} //!@}
//!@name Handling parse errors //!@name Handling parse errors
//!@{ //!@{
//! Whether a parse error has occured in the last parsing. //! Whether a parse error has occured in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); } bool HasParseError() const { return parseResult_.IsError(); }
//! Get the \ref ParseErrorCode of last parsing. //! Get the \ref ParseErrorCode of last parsing.
ParseErrorCode GetParseError() const { return parseResult_.Code(); } ParseErrorCode GetParseError() const { return parseResult_.Code(); }
//! Get the position of last parsing error in input, 0 otherwise. //! Get the position of last parsing error in input, 0 otherwise.
size_t GetErrorOffset() const { return parseResult_.Offset(); } size_t GetErrorOffset() const { return parseResult_.Offset(); }
//! Implicit conversion to get the last parse result
#ifndef __clang // -Wdocumentation
/*! \return \ref ParseResult of the last parse operation
\code
Document doc;
ParseResult ok = doc.Parse(json);
if (!ok)
printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()),
ok.Offset());
\endcode
*/
#endif
operator ParseResult() const { return parseResult_; }
//!@} //!@}
//! Get the allocator of this document. //! Get the allocator of this document.
Allocator& GetAllocator() { return *allocator_; } Allocator& GetAllocator() {
RAPIDJSON_ASSERT(allocator_);
return *allocator_;
}
//! Get the capacity of stack in bytes. //! Get the capacity of stack in bytes.
size_t GetStackCapacity() const { return stack_.GetCapacity(); } size_t GetStackCapacity() const { return stack_.GetCapacity(); }
private: private:
// clear stack on any exit from ParseStream, e.g. due to exception // clear stack on any exit from ParseStream, e.g. due to exception
struct ClearStackOnExit { struct ClearStackOnExit {
explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
~ClearStackOnExit() { d_.ClearStack(); } ~ClearStackOnExit() { d_.ClearStack(); }
private: private:
ClearStackOnExit(const ClearStackOnExit&); ClearStackOnExit(const ClearStackOnExit&);
ClearStackOnExit& operator=(const ClearStackOnExit&); ClearStackOnExit& operator=(const ClearStackOnExit&);
GenericDocument& d_; GenericDocument& d_;
}; };
// callers of the following private Handler functions // callers of the following private Handler functions
template <typename,typename,typename> friend class GenericReader; // for par sing // template <typename,typename,typename> friend class GenericReader; // for parsing
template <typename, typename> friend class GenericValue; // for deep copying template <typename, typename> friend class GenericValue; // for deep copying
public:
// Implementation of Handler // Implementation of Handler
bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return tr ue; } bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return tr ue; }
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); re turn true; } bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); re turn true; }
bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); retu rn true; } bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); retu rn true; }
bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i) ; return true; } bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i) ; return true; }
bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i) ; return true; } bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i) ; return true; }
bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType( i); return true; } bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType( i); return true; }
bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d) ; return true; } bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d) ; return true; }
bool RawNumber(const Ch* str, SizeType length, bool copy) {
if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAl
locator());
else
new (stack_.template Push<ValueType>()) ValueType(str, length);
return true;
}
bool String(const Ch* str, SizeType length, bool copy) { bool String(const Ch* str, SizeType length, bool copy) {
if (copy) if (copy)
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAl locator()); new (stack_.template Push<ValueType>()) ValueType(str, length, GetAl locator());
else else
new (stack_.template Push<ValueType>()) ValueType(str, length); new (stack_.template Push<ValueType>()) ValueType(str, length);
return true; return true;
} }
bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObje ctType); return true; } bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObje ctType); return true; }
bool Key(const Ch* str, SizeType length, bool copy) { return String(str, len gth, copy); } bool Key(const Ch* str, SizeType length, bool copy) { return String(str, len gth, copy); }
bool EndObject(SizeType memberCount) { bool EndObject(SizeType memberCount) {
typename ValueType::Member* members = stack_.template Pop<typename Value Type::Member>(memberCount); typename ValueType::Member* members = stack_.template Pop<typename Value Type::Member>(memberCount);
stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)member Count, GetAllocator()); stack_.template Top<ValueType>()->SetObjectRaw(members, memberCount, Get Allocator());
return true; return true;
} }
bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArray Type); return true; } bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArray Type); return true; }
bool EndArray(SizeType elementCount) { bool EndArray(SizeType elementCount) {
ValueType* elements = stack_.template Pop<ValueType>(elementCount); ValueType* elements = stack_.template Pop<ValueType>(elementCount);
stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, Ge tAllocator()); stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, Ge tAllocator());
return true; return true;
} }
skipping to change at line 1994 skipping to change at line 2418
{ {
switch (rhs.GetType()) { switch (rhs.GetType()) {
case kObjectType: case kObjectType:
case kArrayType: { // perform deep copy via SAX Handler case kArrayType: { // perform deep copy via SAX Handler
GenericDocument<Encoding,Allocator> d(&allocator); GenericDocument<Encoding,Allocator> d(&allocator);
rhs.Accept(d); rhs.Accept(d);
RawAssign(*d.stack_.template Pop<GenericValue>(1)); RawAssign(*d.stack_.template Pop<GenericValue>(1));
} }
break; break;
case kStringType: case kStringType:
if (rhs.flags_ == kConstStringFlag) { if (rhs.data_.f.flags == kConstStringFlag) {
flags_ = rhs.flags_; data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_); data_ = *reinterpret_cast<const Data*>(&rhs.data_);
} else { } else {
SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allo cator); SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allo cator);
} }
break; break;
default: // kNumberType, kTrueType, kFalseType, kNullType default:
flags_ = rhs.flags_; data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_); data_ = *reinterpret_cast<const Data*>(&rhs.data_);
break;
} }
} }
RAPIDJSON_NAMESPACE_END //! Helper class for accessing Value of array type.
/*!
Instance of this helper class is obtained by \c GenericValue::GetArray().
In addition to all APIs for array type, it provides range-based for loop if
\c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
*/
template <bool Const, typename ValueT>
class GenericArray {
public:
typedef GenericArray<true, ValueT> ConstArray;
typedef GenericArray<false, ValueT> Array;
typedef ValueT PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef ValueType* ValueIterator; // This may be const or non-const iterato
r
typedef const ValueT* ConstValueIterator;
typedef typename ValueType::AllocatorType AllocatorType;
typedef typename ValueType::StringRefType StringRefType;
template <typename, typename>
friend class GenericValue;
GenericArray(const GenericArray& rhs) : value_(rhs.value_) {}
GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; retu
rn *this; }
~GenericArray() {}
SizeType Size() const { return value_.Size(); }
SizeType Capacity() const { return value_.Capacity(); }
bool Empty() const { return value_.Empty(); }
void Clear() const { value_.Clear(); }
ValueType& operator[](SizeType index) const { return value_[index]; }
ValueIterator Begin() const { return value_.Begin(); }
ValueIterator End() const { return value_.End(); }
GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const {
value_.Reserve(newCapacity, allocator); return *this; }
GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { va
lue_.PushBack(value, allocator); return *this; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { v
alue_.PushBack(value, allocator); return *this; }
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericArray PushBack(StringRefType value, AllocatorType& allocator) const {
value_.PushBack(value, allocator); return *this; }
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal:
:IsPointer<T>, internal::IsGenericValue<T> >), (const GenericArray&)) PushBack(T
value, AllocatorType& allocator) const { value_.PushBack(value, allocator); ret
urn *this; }
GenericArray PopBack() const { value_.PopBack(); return *this; }
ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos)
; }
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const
{ return value_.Erase(first, last); }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
ValueIterator begin() const { return value_.Begin(); }
ValueIterator end() const { return value_.End(); }
#endif
#if defined(_MSC_VER) || defined(__GNUC__) private:
RAPIDJSON_DIAG_POP GenericArray();
GenericArray(ValueType& value) : value_(value) {}
ValueType& value_;
};
//! Helper class for accessing Value of object type.
/*!
Instance of this helper class is obtained by \c GenericValue::GetObject().
In addition to all APIs for array type, it provides range-based for loop if
\c RAPIDJSON_HAS_CXX11_RANGE_FOR=1.
*/
template <bool Const, typename ValueT>
class GenericObject {
public:
typedef GenericObject<true, ValueT> ConstObject;
typedef GenericObject<false, ValueT> Object;
typedef ValueT PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef GenericMemberIterator<Const, typename ValueT::EncodingType, typename
ValueT::AllocatorType> MemberIterator; // This may be const or non-const itera
tor
typedef GenericMemberIterator<true, typename ValueT::EncodingType, typename
ValueT::AllocatorType> ConstMemberIterator;
typedef typename ValueType::AllocatorType AllocatorType;
typedef typename ValueType::StringRefType StringRefType;
typedef typename ValueType::EncodingType EncodingType;
typedef typename ValueType::Ch Ch;
template <typename, typename>
friend class GenericValue;
GenericObject(const GenericObject& rhs) : value_(rhs.value_) {}
GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; re
turn *this; }
~GenericObject() {}
SizeType MemberCount() const { return value_.MemberCount(); }
bool ObjectEmpty() const { return value_.ObjectEmpty(); }
template <typename T> ValueType& operator[](T* name) const { return value_[n
ame]; }
template <typename SourceAllocator> ValueType& operator[](const GenericValue
<EncodingType, SourceAllocator>& name) const { return value_[name]; }
#if RAPIDJSON_HAS_STDSTRING
ValueType& operator[](const std::basic_string<Ch>& name) const { return valu
e_[name]; }
#endif
MemberIterator MemberBegin() const { return value_.MemberBegin(); }
MemberIterator MemberEnd() const { return value_.MemberEnd(); }
bool HasMember(const Ch* name) const { return value_.HasMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasM
ember(name); }
#endif
template <typename SourceAllocator> bool HasMember(const GenericValue<Encodi
ngType, SourceAllocator>& name) const { return value_.HasMember(name); }
MemberIterator FindMember(const Ch* name) const { return value_.FindMember(n
ame); }
template <typename SourceAllocator> MemberIterator FindMember(const GenericV
alue<EncodingType, SourceAllocator>& name) const { return value_.FindMember(name
); }
#if RAPIDJSON_HAS_STDSTRING
MemberIterator FindMember(const std::basic_string<Ch>& name) const { return
value_.FindMember(name); }
#endif
GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& al
locator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType&
allocator) const { value_.AddMember(name, value, allocator); return *this; }
#if RAPIDJSON_HAS_STDSTRING
GenericObject AddMember(ValueType& name, std::basic_string<Ch>& value, Alloc
atorType& allocator) const { value_.AddMember(name, value, allocator); return *t
his; }
#endif #endif
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal:
:IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&)) AddMember(ValueType
& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value,
allocator); return *this; }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType&
allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& a
llocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& a
llocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType
& allocator) const { value_.AddMember(name, value, allocator); return *this; }
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType&
allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(StringRefType name, StringRefType value, AllocatorTy
pe& allocator) const { value_.AddMember(name, value, allocator); return *this; }
template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal:
:IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(String
RefType name, T value, AllocatorType& allocator) const { value_.AddMember(name,
value, allocator); return *this; }
void RemoveAllMembers() { return value_.RemoveAllMembers(); }
bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name);
}
#if RAPIDJSON_HAS_STDSTRING
bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.R
emoveMember(name); }
#endif
template <typename SourceAllocator> bool RemoveMember(const GenericValue<Enc
odingType, SourceAllocator>& name) const { return value_.RemoveMember(name); }
MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMe
mber(m); }
MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.Er
aseMember(pos); }
MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator la
st) const { return value_.EraseMember(first, last); }
bool EraseMember(const Ch* name) const { return value_.EraseMember(name); }
#if RAPIDJSON_HAS_STDSTRING
bool EraseMember(const std::basic_string<Ch>& name) const { return EraseMemb
er(ValueType(StringRef(name))); }
#endif
template <typename SourceAllocator> bool EraseMember(const GenericValue<Enco
dingType, SourceAllocator>& name) const { return value_.EraseMember(name); }
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
MemberIterator begin() const { return value_.MemberBegin(); }
MemberIterator end() const { return value_.MemberEnd(); }
#endif
private:
GenericObject();
GenericObject(ValueType& value) : value_(value) {}
ValueType& value_;
};
RAPIDJSON_NAMESPACE_END
RAPIDJSON_DIAG_POP
#endif // RAPIDJSON_DOCUMENT_H_ #endif // RAPIDJSON_DOCUMENT_H_
 End of changes. 145 change blocks. 
223 lines changed or deleted 897 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)