Commit 881c91d6 authored by Milo Yip's avatar Milo Yip

Merge master and implement kParseFullPrecision

parents d875f16a 5e03cbf1
...@@ -1993,7 +1993,9 @@ INCLUDE_FILE_PATTERNS = ...@@ -1993,7 +1993,9 @@ INCLUDE_FILE_PATTERNS =
PREDEFINED = \ PREDEFINED = \
RAPIDJSON_DOXYGEN_RUNNING \ RAPIDJSON_DOXYGEN_RUNNING \
RAPIDJSON_DISABLEIF_RETURN(cond,returntype)=returntype RAPIDJSON_REMOVEFPTR_(x)=x \
RAPIDJSON_ENABLEIF_RETURN(cond,returntype)="RAPIDJSON_REMOVEFPTR_ returntype" \
RAPIDJSON_DISABLEIF_RETURN(cond,returntype)="RAPIDJSON_REMOVEFPTR_ returntype"
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The # tag can be used to specify a list of macro names that should be expanded. The
...@@ -2002,7 +2004,8 @@ PREDEFINED = \ ...@@ -2002,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
......
...@@ -31,6 +31,7 @@ struct CapitalizeFilter { ...@@ -31,6 +31,7 @@ struct CapitalizeFilter {
return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string
} }
bool StartObject() { return out_.StartObject(); } bool StartObject() { return out_.StartObject(); }
bool Key(const char* str, SizeType length, bool copy) { return String(str, length, copy); }
bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); } bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); }
bool StartArray() { return out_.StartArray(); } bool StartArray() { return out_.StartArray(); }
bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); } bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); }
......
...@@ -17,6 +17,10 @@ struct MyHandler { ...@@ -17,6 +17,10 @@ struct MyHandler {
return true; return true;
} }
bool StartObject() { cout << "StartObject()" << endl; return true; } bool StartObject() { cout << "StartObject()" << endl; return true; }
bool Key(const char* str, SizeType length, bool copy) {
cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
return true;
}
bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; } bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; }
bool StartArray() { cout << "StartArray()" << endl; return true; } bool StartArray() { cout << "StartArray()" << endl; return true; }
bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; } bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; }
......
This diff is collapsed.
...@@ -21,57 +21,129 @@ ...@@ -21,57 +21,129 @@
#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++)
#endif #endif
#if defined(_MSC_VER)
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(6334)
#endif
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
#include <type_traits>
#endif
//@cond RAPIDJSON_INTERNAL //@cond RAPIDJSON_INTERNAL
namespace rapidjson { namespace rapidjson {
namespace internal { namespace internal {
template <int N> struct IntegralC { enum { Value = N }; }; // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
template <bool Cond> struct BoolType : IntegralC<Cond> {}; template <typename T> struct Void { typedef void Type; };
struct TrueType : BoolType<true> {};
struct FalseType : BoolType<false> {}; ///////////////////////////////////////////////////////////////////////////////
// BoolType, TrueType, FalseType
//
template <bool Cond> struct BoolType {
static const bool Value = Cond;
typedef BoolType Type;
};
typedef BoolType<true> TrueType;
typedef BoolType<false> FalseType;
///////////////////////////////////////////////////////////////////////////////
// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
//
template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
template <> struct AndExprCond<true, true> : TrueType {};
template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
template <> struct OrExprCond<false, false> : FalseType {};
template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
///////////////////////////////////////////////////////////////////////////////
// AddConst, MaybeAddConst, RemoveConst
template <typename T> struct AddConst { typedef const T Type; }; template <typename T> struct AddConst { typedef const T Type; };
template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
template <typename T> struct RemoveConst { typedef T Type; }; template <typename T> struct RemoveConst { typedef T Type; };
template <typename T> struct RemoveConst<const T> { typedef T Type; }; template <typename T> struct RemoveConst<const T> { typedef T Type; };
template <bool Condition, typename T1, typename T2> struct SelectIfCond;
template <typename T1, typename T2> struct SelectIfCond<true,T1,T2> { typedef T1 Type; };
template <typename T1, typename T2> struct SelectIfCond<false,T1,T2> { typedef T2 Type; };
template <typename Condition, typename T1, typename T2>
struct SelectIf : SelectIfCond<Condition::Value,T1,T2> {};
template <bool Constify, typename T>
struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
template <typename T, typename U> struct IsSame : FalseType {}; ///////////////////////////////////////////////////////////////////////////////
template <typename T> struct IsSame<T,T> : TrueType {}; // IsSame, IsConst, IsMoreConst, IsPointer
//
template <typename T, typename U> struct IsSame : FalseType {};
template <typename T> struct IsSame<T, T> : TrueType {};
template <typename T> struct IsConst : FalseType {}; template <typename T> struct IsConst : FalseType {};
template <typename T> struct IsConst<const T> : TrueType {}; template <typename T> struct IsConst<const T> : TrueType {};
template <typename CT, typename T>
struct IsMoreConst
: AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
template <typename T> struct IsPointer : FalseType {}; template <typename T> struct IsPointer : FalseType {};
template <typename T> struct IsPointer<T*> : TrueType {}; template <typename T> struct IsPointer<T*> : TrueType {};
template <typename CT, typename T> ///////////////////////////////////////////////////////////////////////////////
struct IsMoreConst { // IsBaseOf
enum { Value = //
( IsSame< typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>::Value #if RAPIDJSON_HAS_CXX11_TYPETRAITS
&& ( IsConst<CT>::Value >= IsConst<T>::Value ) )
template <typename B, typename D> struct IsBaseOf
: BoolType< ::std::is_base_of<B,D>::value> {};
#else // simplified version adopted from Boost
template<typename B, typename D> struct IsBaseOfImpl {
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
typedef char (&Yes)[1];
typedef char (&No) [2];
template <typename T>
static Yes Check(const D*, T);
static No Check(const B*, int);
struct Host {
operator const B*() const;
operator const D*();
}; };
enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
}; };
template <bool Condition, typename T = void> struct EnableIfCond; template <typename B, typename D> struct IsBaseOf
template <typename T> struct EnableIfCond<true, T> { typedef T Type; }; : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
//////////////////////////////////////////////////////////////////////////
// EnableIf / DisableIf
//
template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
template <typename T> struct EnableIfCond<false, T> { /* empty */ }; template <typename T> struct EnableIfCond<false, T> { /* empty */ };
template <bool Condition, typename T = void> template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
struct DisableIfCond : EnableIfCond<!Condition, T> {}; template <typename T> struct DisableIfCond<true, T> { /* empty */ };
template <typename Condition, typename T = void> template <typename Condition, typename T = void>
struct EnableIf : EnableIfCond<Condition::Value, T> {}; struct EnableIf : EnableIfCond<Condition::Value, T> {};
...@@ -80,26 +152,37 @@ template <typename Condition, typename T = void> ...@@ -80,26 +152,37 @@ template <typename Condition, typename T = void>
struct DisableIf : DisableIfCond<Condition::Value, T> {}; struct DisableIf : DisableIfCond<Condition::Value, T> {};
// SFINAE helpers // SFINAE helpers
struct SfinaeResultTag {}; struct SfinaeTag {};
template <typename T> struct RemoveSfinaeFptr {}; template <typename T> struct RemoveSfinaeTag;
template <typename T> struct RemoveSfinaeFptr<SfinaeResultTag&(*)(T)> { typedef T Type; }; template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
#define RAPIDJSON_REMOVEFPTR_(type) \ #define RAPIDJSON_REMOVEFPTR_(type) \
typename ::rapidjson::internal::RemoveSfinaeFptr \ typename ::rapidjson::internal::RemoveSfinaeTag \
< ::rapidjson::internal::SfinaeResultTag&(*) type>::Type < ::rapidjson::internal::SfinaeTag&(*) type>::Type
#define RAPIDJSON_ENABLEIF(cond) \ #define RAPIDJSON_ENABLEIF(cond) \
typename ::rapidjson::internal::EnableIf \ typename ::rapidjson::internal::EnableIf \
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
#define RAPIDJSON_DISABLEIF(cond) \
typename ::rapidjson::internal::DisableIf \
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
typename ::rapidjson::internal::EnableIf \
<RAPIDJSON_REMOVEFPTR_(cond), \
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
typename ::rapidjson::internal::DisableIf<cond,returntype>::Type typename ::rapidjson::internal::DisableIf \
<RAPIDJSON_REMOVEFPTR_(cond), \
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
} // namespace internal } // namespace internal
} // namespace rapidjson } // namespace rapidjson
//@endcond //@endcond
#ifdef __GNUC__ #if defined(__GNUC__) || defined(_MSC_VER)
RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_POP
#endif #endif
......
...@@ -88,6 +88,8 @@ public: ...@@ -88,6 +88,8 @@ public:
return Base::WriteStartObject(); return Base::WriteStartObject();
} }
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
bool EndObject(SizeType memberCount = 0) { bool EndObject(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
...@@ -135,6 +137,7 @@ public: ...@@ -135,6 +137,7 @@ public:
//! Simpler but slower overload. //! Simpler but slower overload.
bool String(const Ch* str) { return String(str, internal::StrLen(str)); } bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
//@} //@}
protected: protected:
......
...@@ -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
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
......
This diff is collapsed.
...@@ -131,6 +131,8 @@ public: ...@@ -131,6 +131,8 @@ public:
return WriteStartObject(); return WriteStartObject();
} }
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
bool EndObject(SizeType memberCount = 0) { bool EndObject(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
...@@ -165,6 +167,7 @@ public: ...@@ -165,6 +167,7 @@ public:
//! Simpler but slower overload. //! Simpler but slower overload.
bool String(const Ch* str) { return String(str, internal::StrLen(str)); } bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
//@} //@}
......
This diff is collapsed.
...@@ -89,15 +89,9 @@ inline FILE* TempFile(char *filename) { ...@@ -89,15 +89,9 @@ inline FILE* TempFile(char *filename) {
#pragma warning(disable : 4127) #pragma warning(disable : 4127)
#endif #endif
class AssertException : public std::exception { class AssertException : public std::logic_error {
public: public:
AssertException(const char* w) : what_(w) {} AssertException(const char* w) : std::logic_error(w) {}
AssertException(const AssertException& other) : what_(other.what_) {}
AssertException& operator=(const AssertException& rhs) { what_ = rhs.what_; return *this; }
virtual const char* what() const throw() { return what_; }
private:
const char* what_;
}; };
#define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x)) #define RAPIDJSON_ASSERT(x) if (!(x)) throw AssertException(RAPIDJSON_STRINGIFY(x))
......
...@@ -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)
...@@ -105,16 +146,33 @@ TEST(Value, equalto_operator) { ...@@ -105,16 +146,33 @@ TEST(Value, equalto_operator) {
TestEqual(x["i"], 123); TestEqual(x["i"], 123);
TestEqual(x["pi"], 3.14); TestEqual(x["pi"], 3.14);
// Test operator==() // Test operator==() (including different allocators)
Value y; CrtAllocator crtAllocator;
y.CopyFrom(x, allocator); GenericValue<UTF8<>, CrtAllocator> y;
GenericDocument<UTF8<>, CrtAllocator> z(&crtAllocator);
y.CopyFrom(x, crtAllocator);
z.CopyFrom(y, z.GetAllocator());
TestEqual(x, y); TestEqual(x, y);
TestEqual(y, z);
TestEqual(z, x);
// Swapping member order should be fine. // Swapping member order should be fine.
y.RemoveMember("t"); EXPECT_TRUE(y.RemoveMember("t"));
TestUnequal(x, y); TestUnequal(x, y);
y.AddMember("t", Value(true).Move(), allocator); TestUnequal(z, y);
EXPECT_TRUE(z.RemoveMember("t"));
TestUnequal(x, z);
TestEqual(y, z);
y.AddMember("t", true, crtAllocator);
z.AddMember("t", true, z.GetAllocator());
TestEqual(x, y); TestEqual(x, y);
TestEqual(y, z);
TestEqual(z, x);
// Issue #129: compare Uint64
x.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0));
y.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF));
TestUnequal(x, y);
} }
template <typename Value> template <typename Value>
...@@ -538,7 +596,7 @@ TEST(Value, String) { ...@@ -538,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';
...@@ -626,6 +684,21 @@ TEST(Value, Array) { ...@@ -626,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());
...@@ -734,7 +807,6 @@ TEST(Value, Array) { ...@@ -734,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++)
...@@ -743,11 +815,11 @@ TEST(Value, Array) { ...@@ -743,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;
...@@ -801,6 +873,22 @@ TEST(Value, Object) { ...@@ -801,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);
...@@ -818,10 +906,18 @@ TEST(Value, Object) { ...@@ -818,10 +906,18 @@ TEST(Value, Object) {
EXPECT_TRUE(x.HasMember(name)); EXPECT_TRUE(x.HasMember(name));
EXPECT_TRUE(y.HasMember(name)); EXPECT_TRUE(y.HasMember(name));
GenericValue<UTF8<>, CrtAllocator> othername("A");
EXPECT_TRUE(x.HasMember(othername));
EXPECT_TRUE(y.HasMember(othername));
othername.SetString("C\0D");
EXPECT_TRUE(x.HasMember(othername));
EXPECT_TRUE(y.HasMember(othername));
// operator[] // operator[]
EXPECT_STREQ("Apple", x["A"].GetString()); EXPECT_STREQ("Apple", x["A"].GetString());
EXPECT_STREQ("Banana", x["B"].GetString()); EXPECT_STREQ("Banana", x["B"].GetString());
EXPECT_STREQ("CherryD", x[C0D].GetString()); EXPECT_STREQ("CherryD", x[C0D].GetString());
EXPECT_STREQ("CherryD", x[othername].GetString());
// const operator[] // const operator[]
EXPECT_STREQ("Apple", y["A"].GetString()); EXPECT_STREQ("Apple", y["A"].GetString());
...@@ -892,7 +988,7 @@ TEST(Value, Object) { ...@@ -892,7 +988,7 @@ TEST(Value, Object) {
x.RemoveMember("B"); x.RemoveMember("B");
EXPECT_FALSE(x.HasMember("B")); EXPECT_FALSE(x.HasMember("B"));
x.RemoveMember(name); x.RemoveMember(othername);
EXPECT_FALSE(x.HasMember(name)); EXPECT_FALSE(x.HasMember(name));
EXPECT_TRUE(x.MemberBegin() == x.MemberEnd()); EXPECT_TRUE(x.MemberBegin() == x.MemberEnd());
...@@ -905,11 +1001,14 @@ TEST(Value, Object) { ...@@ -905,11 +1001,14 @@ TEST(Value, Object) {
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator); x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator);
// MemberCount, iterator difference
EXPECT_EQ(x.MemberCount(), SizeType(x.MemberEnd() - x.MemberBegin()));
// Erase the first // Erase the first
itr = x.EraseMember(x.MemberBegin()); itr = x.EraseMember(x.MemberBegin());
EXPECT_FALSE(x.HasMember(keys[0])); EXPECT_FALSE(x.HasMember(keys[0]));
EXPECT_EQ(x.MemberBegin(), itr); EXPECT_EQ(x.MemberBegin(), itr);
EXPECT_EQ(9, x.MemberEnd() - x.MemberBegin()); EXPECT_EQ(9u, x.MemberCount());
for (; itr != x.MemberEnd(); ++itr) { for (; itr != x.MemberEnd(); ++itr) {
int i = (itr - x.MemberBegin()) + 1; int i = (itr - x.MemberBegin()) + 1;
EXPECT_STREQ(itr->name.GetString(), keys[i]); EXPECT_STREQ(itr->name.GetString(), keys[i]);
...@@ -920,7 +1019,7 @@ TEST(Value, Object) { ...@@ -920,7 +1019,7 @@ TEST(Value, Object) {
itr = x.EraseMember(x.MemberEnd() - 1); itr = x.EraseMember(x.MemberEnd() - 1);
EXPECT_FALSE(x.HasMember(keys[9])); EXPECT_FALSE(x.HasMember(keys[9]));
EXPECT_EQ(x.MemberEnd(), itr); EXPECT_EQ(x.MemberEnd(), itr);
EXPECT_EQ(8, x.MemberEnd() - x.MemberBegin()); EXPECT_EQ(8u, x.MemberCount());
for (; itr != x.MemberEnd(); ++itr) { for (; itr != x.MemberEnd(); ++itr) {
int i = (itr - x.MemberBegin()) + 1; int i = (itr - x.MemberBegin()) + 1;
EXPECT_STREQ(itr->name.GetString(), keys[i]); EXPECT_STREQ(itr->name.GetString(), keys[i]);
...@@ -931,7 +1030,7 @@ TEST(Value, Object) { ...@@ -931,7 +1030,7 @@ TEST(Value, Object) {
itr = x.EraseMember(x.MemberBegin() + 4); itr = x.EraseMember(x.MemberBegin() + 4);
EXPECT_FALSE(x.HasMember(keys[5])); EXPECT_FALSE(x.HasMember(keys[5]));
EXPECT_EQ(x.MemberBegin() + 4, itr); EXPECT_EQ(x.MemberBegin() + 4, itr);
EXPECT_EQ(7, x.MemberEnd() - x.MemberBegin()); EXPECT_EQ(7u, x.MemberCount());
for (; itr != x.MemberEnd(); ++itr) { for (; itr != x.MemberEnd(); ++itr) {
int i = (itr - x.MemberBegin()); int i = (itr - x.MemberBegin());
i += (i<4) ? 1 : 2; i += (i<4) ? 1 : 2;
...@@ -955,7 +1054,7 @@ TEST(Value, Object) { ...@@ -955,7 +1054,7 @@ TEST(Value, Object) {
EXPECT_EQ(x.MemberBegin() + first, itr); EXPECT_EQ(x.MemberBegin() + first, itr);
size_t removeCount = last - first; size_t removeCount = last - first;
EXPECT_EQ(n - removeCount, size_t(x.MemberEnd() - x.MemberBegin())); EXPECT_EQ(n - removeCount, x.MemberCount());
for (unsigned i = 0; i < first; i++) for (unsigned i = 0; i < first; i++)
EXPECT_EQ(i, x[keys[i]][0u].GetUint()); EXPECT_EQ(i, x[keys[i]][0u].GetUint());
for (unsigned i = first; i < n - removeCount; i++) for (unsigned i = first; i < n - removeCount; i++)
...@@ -1059,3 +1158,23 @@ TEST(Document, CrtAllocator) { ...@@ -1059,3 +1158,23 @@ TEST(Document, CrtAllocator) {
V a(kArrayType); V a(kArrayType);
a.PushBack(1, allocator); // Should not call destructor on uninitialized Value of newly allocated elements. a.PushBack(1, allocator); // Should not call destructor on uninitialized Value of newly allocated elements.
} }
static void TestShortStringOptimization(const char* str) {
const rapidjson::SizeType len = (rapidjson::SizeType)strlen(str);
rapidjson::Document doc;
rapidjson::Value val;
val.SetString(str, len, doc.GetAllocator());
EXPECT_EQ(val.GetStringLength(), len);
EXPECT_STREQ(val.GetString(), str);
}
TEST(Value, AllocateShortString) {
TestShortStringOptimization(""); // edge case: empty string
TestShortStringOptimization("12345678"); // regular case for short strings: 8 chars
TestShortStringOptimization("12345678901"); // edge case: 11 chars in 32-bit mode (=> short string)
TestShortStringOptimization("123456789012"); // edge case: 12 chars in 32-bit mode (=> regular string)
TestShortStringOptimization("123456789012345"); // edge case: 15 chars in 64-bit mode (=> short string)
TestShortStringOptimization("1234567890123456"); // edge case: 16 chars in 64-bit mode (=> regular string)
}
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