Commit bc9d7866 authored by Milo Yip's avatar Milo Yip

Merge pull request #128 from pah/feature/cxx11-move

Initial C++11 move support
parents 15d70d6a 8ae2266c
...@@ -2004,7 +2004,8 @@ PREDEFINED = \ ...@@ -2004,7 +2004,8 @@ PREDEFINED = \
# definition found in the source code. # definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED = EXPAND_AS_DEFINED = \
RAPIDJSON_NOEXCEPT
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have # remove all references to function-like macros that are alone on a line, have
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
/*! \file document.h */ /*! \file document.h */
#include "reader.h" #include "reader.h"
#include "internal/meta.h"
#include "internal/strfunc.h" #include "internal/strfunc.h"
#include <new> // placement new #include <new> // placement new
...@@ -38,15 +39,17 @@ RAPIDJSON_DIAG_OFF(effc++) ...@@ -38,15 +39,17 @@ RAPIDJSON_DIAG_OFF(effc++)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_HAS_STDSTRING // RAPIDJSON_HAS_STDSTRING
#ifndef RAPIDJSON_HAS_STDSTRING
#ifdef RAPIDJSON_DOXYGEN_RUNNING #ifdef RAPIDJSON_DOXYGEN_RUNNING
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation #define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
#else
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
#endif #endif
#ifdef RAPIDJSON_HAS_STDSTRING
/*! \def RAPIDJSON_HAS_STDSTRING /*! \def RAPIDJSON_HAS_STDSTRING
\ingroup RAPIDJSON_CONFIG \ingroup RAPIDJSON_CONFIG
\brief Enable RapidJSON support for \c std::string \brief Enable RapidJSON support for \c std::string
By defining this preprocessor symbol, several convenience functions for using By defining this preprocessor symbol to \c 1, several convenience functions for using
\ref rapidjson::GenericValue with \c std::string are enabled, especially \ref rapidjson::GenericValue with \c std::string are enabled, especially
for construction and comparison. for construction and comparison.
...@@ -56,7 +59,6 @@ RAPIDJSON_DIAG_OFF(effc++) ...@@ -56,7 +59,6 @@ RAPIDJSON_DIAG_OFF(effc++)
#endif // RAPIDJSON_HAS_STDSTRING #endif // RAPIDJSON_HAS_STDSTRING
#ifndef RAPIDJSON_NOMEMBERITERATORCLASS #ifndef RAPIDJSON_NOMEMBERITERATORCLASS
#include "internal/meta.h"
#include <iterator> // std::iterator, std::random_access_iterator_tag #include <iterator> // std::iterator, std::random_access_iterator_tag
#endif #endif
...@@ -277,7 +279,7 @@ struct GenericStringRef { ...@@ -277,7 +279,7 @@ struct GenericStringRef {
GenericValue instead. GenericValue instead.
*/ */
template<SizeType N> template<SizeType N>
GenericStringRef(const CharType (&str)[N]) 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
...@@ -300,7 +302,7 @@ struct GenericStringRef { ...@@ -300,7 +302,7 @@ struct GenericStringRef {
GenericValue instead. GenericValue instead.
*/ */
explicit GenericStringRef(const CharType* str) explicit GenericStringRef(const CharType* str)
: s(str), length(internal::StrLen(str)){} : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
//! Create constant string reference from pointer and length //! Create constant string reference from pointer and length
/*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
...@@ -363,7 +365,7 @@ inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) ...@@ -363,7 +365,7 @@ inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length)
return GenericStringRef<CharType>(str, SizeType(length)); return GenericStringRef<CharType>(str, SizeType(length));
} }
#ifdef RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Mark a string object as constant string //! Mark a string object as constant string
/*! Mark a string object (e.g. \c std::string) as a "string literal". /*! Mark a string object (e.g. \c std::string) as a "string literal".
This function can be used to avoid copying a string to be referenced as a This function can be used to avoid copying a string to be referenced as a
...@@ -430,7 +432,14 @@ public: ...@@ -430,7 +432,14 @@ public:
//@{ //@{
//! Default constructor creates a null value. //! Default constructor creates a null value.
GenericValue() : data_(), flags_(kNullFlag) {} GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move constructor in C++11
GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
rhs.flags_ = kNullFlag; // give up contents
}
#endif
private: private:
//! Copy constructor is not permitted. //! Copy constructor is not permitted.
...@@ -443,7 +452,7 @@ public: ...@@ -443,7 +452,7 @@ public:
\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.
*/ */
GenericValue(Type type) : data_(), flags_() { GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
static const unsigned defaultFlags[7] = { static const unsigned defaultFlags[7] = {
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag, kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
kNumberAnyFlag kNumberAnyFlag
...@@ -470,9 +479,9 @@ public: ...@@ -470,9 +479,9 @@ public:
*/ */
#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>))) explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
#else #else
explicit GenericValue(bool b) explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
#endif #endif
: data_(), flags_(b ? kTrueFlag : kFalseFlag) { : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
// safe-guard against failing SFINAE // safe-guard against failing SFINAE
...@@ -480,21 +489,21 @@ public: ...@@ -480,21 +489,21 @@ public:
} }
//! Constructor for int value. //! Constructor for int value.
explicit GenericValue(int i) : data_(), flags_(kNumberIntFlag) { explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
data_.n.i64 = i; data_.n.i64 = i;
if (i >= 0) if (i >= 0)
flags_ |= kUintFlag | kUint64Flag; flags_ |= kUintFlag | kUint64Flag;
} }
//! Constructor for unsigned value. //! Constructor for unsigned value.
explicit GenericValue(unsigned u) : data_(), flags_(kNumberUintFlag) { explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
data_.n.u64 = u; data_.n.u64 = u;
if (!(u & 0x80000000)) if (!(u & 0x80000000))
flags_ |= kIntFlag | kInt64Flag; flags_ |= kIntFlag | kInt64Flag;
} }
//! Constructor for int64_t value. //! Constructor for int64_t value.
explicit GenericValue(int64_t i64) : data_(), flags_(kNumberInt64Flag) { explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
data_.n.i64 = i64; data_.n.i64 = i64;
if (i64 >= 0) { if (i64 >= 0) {
flags_ |= kNumberUint64Flag; flags_ |= kNumberUint64Flag;
...@@ -508,7 +517,7 @@ public: ...@@ -508,7 +517,7 @@ public:
} }
//! Constructor for uint64_t value. //! Constructor for uint64_t value.
explicit GenericValue(uint64_t u64) : data_(), flags_(kNumberUint64Flag) { explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
data_.n.u64 = u64; data_.n.u64 = u64;
if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
flags_ |= kInt64Flag; flags_ |= kInt64Flag;
...@@ -519,13 +528,13 @@ public: ...@@ -519,13 +528,13 @@ public:
} }
//! Constructor for double value. //! Constructor for double value.
explicit GenericValue(double d) : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
//! 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) : data_(), flags_() { SetStringRaw(StringRef(s, length)); } GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(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) : data_(), flags_() { SetStringRaw(s); } explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(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_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
...@@ -533,7 +542,7 @@ public: ...@@ -533,7 +542,7 @@ public:
//! 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_() { SetStringRaw(StringRef(s), allocator); } GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
#ifdef 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.
*/ */
...@@ -576,19 +585,26 @@ public: ...@@ -576,19 +585,26 @@ public:
//! Assignment with move semantics. //! Assignment with move semantics.
/*! \param rhs Source of the assignment. It will become a null value after assignment. /*! \param rhs Source of the assignment. It will become a null value after assignment.
*/ */
GenericValue& operator=(GenericValue& rhs) { GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
RAPIDJSON_ASSERT(this != &rhs); RAPIDJSON_ASSERT(this != &rhs);
this->~GenericValue(); this->~GenericValue();
RawAssign(rhs); RawAssign(rhs);
return *this; return *this;
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Move assignment in C++11
GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
return *this = rhs.Move();
}
#endif
//! Assignment of constant string reference (no copy) //! Assignment of constant string reference (no copy)
/*! \param str Constant string reference to be assigned /*! \param str Constant string reference to be assigned
\note This overload is needed to avoid clashes with the generic primitive type assignment overload below. \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
\see GenericStringRef, operator=(T) \see GenericStringRef, operator=(T)
*/ */
GenericValue& operator=(StringRefType str) { GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
GenericValue s(str); GenericValue s(str);
return *this = s; return *this = s;
} }
...@@ -631,7 +647,7 @@ public: ...@@ -631,7 +647,7 @@ public:
\param other Another value. \param other Another value.
\note Constant complexity. \note Constant complexity.
*/ */
GenericValue& Swap(GenericValue& other) { GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
GenericValue temp; GenericValue temp;
temp.RawAssign(*this); temp.RawAssign(*this);
RawAssign(other); RawAssign(other);
...@@ -641,7 +657,7 @@ public: ...@@ -641,7 +657,7 @@ public:
//! Prepare Value for move semantics //! Prepare Value for move semantics
/*! \return *this */ /*! \return *this */
GenericValue& Move() { return *this; } GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
//@} //@}
//!@name Equal-to and not-equal-to operators //!@name Equal-to and not-equal-to operators
...@@ -693,7 +709,7 @@ public: ...@@ -693,7 +709,7 @@ public:
//! 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(StringRef(rhs)); } bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
#ifdef 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.
*/ */
...@@ -921,6 +937,23 @@ public: ...@@ -921,6 +937,23 @@ public:
return *this; return *this;
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
return AddMember(name, value, allocator);
}
GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
GenericValue n(name);
return AddMember(n, value, allocator);
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
//! Add a member (name-value pair) to the object. //! Add a member (name-value pair) to the object.
/*! \param name A constant string reference as name of member. /*! \param name A constant string reference as name of member.
\param value Value of any type. \param value Value of any type.
...@@ -1162,6 +1195,12 @@ int z = a[0u].GetInt(); // This works too. ...@@ -1162,6 +1195,12 @@ int z = a[0u].GetInt(); // This works too.
return *this; return *this;
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
return PushBack(value, allocator);
}
#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.
/*! \param value Constant string reference to be appended. /*! \param value Constant string reference to be appended.
\param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
...@@ -1316,7 +1355,7 @@ int z = a[0u].GetInt(); // This works too. ...@@ -1316,7 +1355,7 @@ int z = a[0u].GetInt(); // This works too.
*/ */
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
#ifdef RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string. //! Set this value as a string by copying from source string.
/*! \param s source string. /*! \param s source string.
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
...@@ -1502,7 +1541,7 @@ private: ...@@ -1502,7 +1541,7 @@ private:
} }
//! Initialize this value as constant string, without calling destructor. //! Initialize this value as constant string, without calling destructor.
void SetStringRaw(StringRefType s) { void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
flags_ = kConstStringFlag; flags_ = kConstStringFlag;
data_.s.str = s; data_.s.str = s;
data_.s.length = s.length; data_.s.length = s.length;
...@@ -1526,7 +1565,7 @@ private: ...@@ -1526,7 +1565,7 @@ private:
} }
//! Assignment without calling destructor //! Assignment without calling destructor
void RawAssign(GenericValue& rhs) { void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
data_ = rhs.data_; data_ = rhs.data_;
flags_ = rhs.flags_; flags_ = rhs.flags_;
rhs.flags_ = kNullFlag; rhs.flags_ = kNullFlag;
......
...@@ -21,6 +21,10 @@ ...@@ -21,6 +21,10 @@
#ifndef RAPIDJSON_INTERNAL_META_H_ #ifndef RAPIDJSON_INTERNAL_META_H_
#define RAPIDJSON_INTERNAL_META_H_ #define RAPIDJSON_INTERNAL_META_H_
#ifndef RAPIDJSON_RAPIDJSON_H_
#error <rapidjson.h> not yet included. Do not include this file directly.
#endif
#ifdef __GNUC__ #ifdef __GNUC__
RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++) RAPIDJSON_DIAG_OFF(effc++)
...@@ -30,7 +34,7 @@ RAPIDJSON_DIAG_PUSH ...@@ -30,7 +34,7 @@ RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(6334) RAPIDJSON_DIAG_OFF(6334)
#endif #endif
#ifdef RAPIDJSON_HAS_CXX11_TYPETRAITS #if RAPIDJSON_HAS_CXX11_TYPETRAITS
#include <type_traits> #include <type_traits>
#endif #endif
...@@ -100,7 +104,7 @@ template <typename T> struct IsPointer<T*> : TrueType {}; ...@@ -100,7 +104,7 @@ template <typename T> struct IsPointer<T*> : TrueType {};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// IsBaseOf // IsBaseOf
// //
#ifdef RAPIDJSON_HAS_CXX11_TYPETRAITS #if RAPIDJSON_HAS_CXX11_TYPETRAITS
template <typename B, typename D> struct IsBaseOf template <typename B, typename D> struct IsBaseOf
: BoolType< ::std::is_base_of<B,D>::value> {}; : BoolType< ::std::is_base_of<B,D>::value> {};
......
...@@ -318,7 +318,12 @@ template<int x> struct StaticAssertTest {}; ...@@ -318,7 +318,12 @@ template<int x> struct StaticAssertTest {};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF // RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
#if defined(__clang__) || (defined(__GNUC__) && RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) >= RAPIDJSON_VERSION_CODE(4,2,0)) #if defined(__GNUC__)
#define RAPIDJSON_GNUC \
RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
#endif
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) #define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) #define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
...@@ -326,7 +331,7 @@ template<int x> struct StaticAssertTest {}; ...@@ -326,7 +331,7 @@ template<int x> struct StaticAssertTest {};
RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
// push/pop support in Clang and GCC>=4.6 // push/pop support in Clang and GCC>=4.6
#if defined(__clang__) || (defined(__GNUC__) && RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) >= RAPIDJSON_VERSION_CODE(4,6,0)) #if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) #define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) #define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
#else // GCC >= 4.2, < 4.6 #else // GCC >= 4.2, < 4.6
...@@ -352,6 +357,42 @@ template<int x> struct StaticAssertTest {}; ...@@ -352,6 +357,42 @@ template<int x> struct StaticAssertTest {};
#endif // RAPIDJSON_DIAG_* #endif // RAPIDJSON_DIAG_*
///////////////////////////////////////////////////////////////////////////////
// C++11 features
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if defined(__clang__)
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1600)
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#else
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
#endif
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
#if defined(__clang__)
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
#else
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
#endif
#endif
#if RAPIDJSON_HAS_CXX11_NOEXCEPT
#define RAPIDJSON_NOEXCEPT noexcept
#else
#define RAPIDJSON_NOEXCEPT /* noexcept */
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
// no automatic detection, yet
#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
#endif
//!@endcond //!@endcond
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
using namespace rapidjson; using namespace rapidjson;
TEST(Value, default_constructor) { TEST(Value, DefaultConstructor) {
Value x; Value x;
EXPECT_EQ(kNullType, x.GetType()); EXPECT_EQ(kNullType, x.GetType());
EXPECT_TRUE(x.IsNull()); EXPECT_TRUE(x.IsNull());
...@@ -38,7 +38,32 @@ TEST(Value, default_constructor) { ...@@ -38,7 +38,32 @@ TEST(Value, default_constructor) {
// Value y = x; // Value y = x;
//} //}
TEST(Value, assignment_operator) { #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
TEST(Value, MoveConstructor) {
typedef GenericValue<UTF8<>, CrtAllocator> Value;
Value::AllocatorType allocator;
Value x((Value(kArrayType)));
x.Reserve(4u, allocator);
x.PushBack(1, allocator).PushBack(2, allocator).PushBack(3, allocator).PushBack(4, allocator);
EXPECT_TRUE(x.IsArray());
EXPECT_EQ(4u, x.Size());
// Value y(x); // should not compile
Value y(std::move(x));
EXPECT_TRUE(x.IsNull());
EXPECT_TRUE(y.IsArray());
EXPECT_EQ(4u, y.Size());
// Value z = y; // should not compile
Value z = std::move(y);
EXPECT_TRUE(y.IsNull());
EXPECT_TRUE(z.IsArray());
EXPECT_EQ(4u, z.Size());
}
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
TEST(Value, AssignmentOperator) {
Value x(1234); Value x(1234);
Value y; Value y;
y = x; y = x;
...@@ -63,6 +88,22 @@ TEST(Value, assignment_operator) { ...@@ -63,6 +88,22 @@ TEST(Value, assignment_operator) {
y = StringRef(mstr); y = StringRef(mstr);
EXPECT_TRUE(y.IsString()); EXPECT_TRUE(y.IsString());
EXPECT_EQ(y.GetString(),mstr); EXPECT_EQ(y.GetString(),mstr);
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
// C++11 move assignment
x = Value("World");
EXPECT_TRUE(x.IsString());
EXPECT_STREQ("World", x.GetString());
x = std::move(y);
EXPECT_TRUE(y.IsNull());
EXPECT_TRUE(x.IsString());
EXPECT_EQ(x.GetString(), mstr);
y = std::move(Value().SetInt(1234));
EXPECT_TRUE(y.IsInt());
EXPECT_EQ(1234, y);
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
} }
template <typename A, typename B> template <typename A, typename B>
...@@ -81,7 +122,7 @@ void TestUnequal(const A& a, const B& b) { ...@@ -81,7 +122,7 @@ void TestUnequal(const A& a, const B& b) {
EXPECT_TRUE (b != a); EXPECT_TRUE (b != a);
} }
TEST(Value, equalto_operator) { TEST(Value, EqualtoOperator) {
Value::AllocatorType allocator; Value::AllocatorType allocator;
Value x(kObjectType); Value x(kObjectType);
x.AddMember("hello", "world", allocator) x.AddMember("hello", "world", allocator)
...@@ -555,7 +596,7 @@ TEST(Value, String) { ...@@ -555,7 +596,7 @@ TEST(Value, String) {
EXPECT_STREQ("World", w.GetString()); EXPECT_STREQ("World", w.GetString());
EXPECT_EQ(5u, w.GetStringLength()); EXPECT_EQ(5u, w.GetStringLength());
#ifdef RAPIDJSON_HAS_STDSTRING #if RAPIDJSON_HAS_STDSTRING
{ {
std::string str = "Hello World"; std::string str = "Hello World";
str[5] = '\0'; str[5] = '\0';
...@@ -643,6 +684,21 @@ TEST(Value, Array) { ...@@ -643,6 +684,21 @@ TEST(Value, Array) {
EXPECT_TRUE(y[4u].IsString()); EXPECT_TRUE(y[4u].IsString());
EXPECT_STREQ("foo", y[4u].GetString()); EXPECT_STREQ("foo", y[4u].GetString());
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
// PushBack(GenericValue&&, Allocator&);
{
Value y(kArrayType);
y.PushBack(Value(true), allocator);
y.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).PushBack("foo", allocator)), allocator);
EXPECT_EQ(2u, y.Size());
EXPECT_TRUE(y[0u].IsTrue());
EXPECT_TRUE(y[1u].IsArray());
EXPECT_EQ(2u, y[1u].Size());
EXPECT_TRUE(y[1u][0u].IsInt());
EXPECT_TRUE(y[1u][1u].IsString());
}
#endif
// iterator // iterator
Value::ValueIterator itr = x.Begin(); Value::ValueIterator itr = x.Begin();
EXPECT_TRUE(itr != x.End()); EXPECT_TRUE(itr != x.End());
...@@ -751,7 +807,6 @@ TEST(Value, Array) { ...@@ -751,7 +807,6 @@ TEST(Value, Array) {
} }
// Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed. // Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.
#if 0
// http://en.wikipedia.org/wiki/Erase-remove_idiom // http://en.wikipedia.org/wiki/Erase-remove_idiom
x.Clear(); x.Clear();
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
...@@ -760,11 +815,11 @@ TEST(Value, Array) { ...@@ -760,11 +815,11 @@ TEST(Value, Array) {
else else
x.PushBack(Value(kNullType).Move(), allocator); x.PushBack(Value(kNullType).Move(), allocator);
x.Erase(std::remove(x.Begin(), x.End(), Value(kNullType)), x.End()); const Value null(kNullType);
x.Erase(std::remove(x.Begin(), x.End(), null), x.End());
EXPECT_EQ(5u, x.Size()); EXPECT_EQ(5u, x.Size());
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
EXPECT_EQ(i * 2, x[i]); EXPECT_EQ(i * 2, x[i]);
#endif
// SetArray() // SetArray()
Value z; Value z;
...@@ -818,6 +873,22 @@ TEST(Value, Object) { ...@@ -818,6 +873,22 @@ TEST(Value, Object) {
EXPECT_EQ(8u, o.MemberCount()); EXPECT_EQ(8u, o.MemberCount());
} }
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
// AddMember(GenericValue&&, ...) variants
{
Value o(kObjectType);
o.AddMember(Value("true"), Value(true), allocator);
o.AddMember(Value("false"), Value(false).Move(), allocator); // value is lvalue ref
o.AddMember(Value("int").Move(), Value(-1), allocator); // name is lvalue ref
o.AddMember("uint", std::move(Value().SetUint(1u)), allocator); // name is literal, value is rvalue
EXPECT_TRUE(o["true"].GetBool());
EXPECT_FALSE(o["false"].GetBool());
EXPECT_EQ(-1, o["int"].GetInt());
EXPECT_EQ(1u, o["uint"].GetUint());
EXPECT_EQ(4u, o.MemberCount());
}
#endif
// Tests a member with null character // Tests a member with null character
Value name; Value name;
const Value C0D("C\0D", 3); const Value C0D("C\0D", 3);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment