mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-10-27 02:53:13 +01:00
Implemented C++11 move semantics for GenericDocument
This commit is contained in:
@@ -227,6 +227,186 @@ TEST(Document, UTF16_Document) {
|
||||
EXPECT_EQ(0, wcscmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString()));
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
|
||||
TEST(Document, MoveConstructor) {
|
||||
typedef GenericDocument<UTF8<>, CrtAllocator> Document;
|
||||
Document::AllocatorType allocator;
|
||||
|
||||
Document a(&allocator);
|
||||
a.Parse("[\"one\", \"two\", \"three\"]");
|
||||
EXPECT_FALSE(a.HasParseError());
|
||||
EXPECT_TRUE(a.IsArray());
|
||||
EXPECT_EQ(3u, a.Size());
|
||||
EXPECT_EQ(&a.GetAllocator(), &allocator);
|
||||
|
||||
// Document b(a); // should not compile
|
||||
Document b(std::move(a));
|
||||
EXPECT_TRUE(a.IsNull());
|
||||
EXPECT_TRUE(b.IsArray());
|
||||
EXPECT_EQ(3u, b.Size());
|
||||
EXPECT_EQ(&a.GetAllocator(), (void*)0);
|
||||
EXPECT_EQ(&b.GetAllocator(), &allocator);
|
||||
|
||||
b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
|
||||
EXPECT_FALSE(b.HasParseError());
|
||||
EXPECT_TRUE(b.IsObject());
|
||||
EXPECT_EQ(2u, b.MemberCount());
|
||||
|
||||
// Document c = a; // should not compile
|
||||
Document c = std::move(b);
|
||||
EXPECT_TRUE(b.IsNull());
|
||||
EXPECT_TRUE(c.IsObject());
|
||||
EXPECT_EQ(2u, c.MemberCount());
|
||||
EXPECT_EQ(&b.GetAllocator(), (void*)0);
|
||||
EXPECT_EQ(&c.GetAllocator(), &allocator);
|
||||
}
|
||||
|
||||
TEST(Document, MoveConstructorParseError) {
|
||||
typedef GenericDocument<UTF8<>, CrtAllocator> Document;
|
||||
|
||||
ParseResult noError;
|
||||
Document a;
|
||||
a.Parse("{ 4 = 4]");
|
||||
ParseResult error(a.GetParseError(), a.GetErrorOffset());
|
||||
EXPECT_TRUE(a.HasParseError());
|
||||
EXPECT_NE(error.Code(), noError.Code());
|
||||
EXPECT_NE(error.Offset(), noError.Offset());
|
||||
|
||||
Document b(std::move(a));
|
||||
EXPECT_FALSE(a.HasParseError());
|
||||
EXPECT_TRUE(b.HasParseError());
|
||||
EXPECT_EQ(a.GetParseError(), noError.Code());
|
||||
EXPECT_EQ(b.GetParseError(), error.Code());
|
||||
EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
|
||||
EXPECT_EQ(b.GetErrorOffset(), error.Offset());
|
||||
|
||||
Document c(std::move(b));
|
||||
EXPECT_FALSE(b.HasParseError());
|
||||
EXPECT_TRUE(c.HasParseError());
|
||||
EXPECT_EQ(b.GetParseError(), noError.Code());
|
||||
EXPECT_EQ(c.GetParseError(), error.Code());
|
||||
EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
|
||||
EXPECT_EQ(c.GetErrorOffset(), error.Offset());
|
||||
}
|
||||
|
||||
TEST(Document, MoveConstructorStack) {
|
||||
typedef UTF8<> Encoding;
|
||||
typedef GenericDocument<Encoding, CrtAllocator> Document;
|
||||
|
||||
Document a;
|
||||
size_t defaultCapacity = a.GetStackCapacity();
|
||||
|
||||
// Trick Document into getting GetStackCapacity() to return non-zero
|
||||
typedef GenericReader<Encoding, Encoding, Document::AllocatorType> Reader;
|
||||
Reader reader(&a.GetAllocator());
|
||||
GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
|
||||
reader.Parse<kParseDefaultFlags>(is, a);
|
||||
size_t capacity = a.GetStackCapacity();
|
||||
EXPECT_GT(capacity, 0);
|
||||
|
||||
Document b(std::move(a));
|
||||
EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
|
||||
EXPECT_EQ(b.GetStackCapacity(), capacity);
|
||||
|
||||
Document c = std::move(b);
|
||||
EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
|
||||
EXPECT_EQ(c.GetStackCapacity(), capacity);
|
||||
}
|
||||
|
||||
TEST(Document, MoveAssignment) {
|
||||
typedef GenericDocument<UTF8<>, CrtAllocator> Document;
|
||||
Document::AllocatorType allocator;
|
||||
|
||||
Document a(&allocator);
|
||||
a.Parse("[\"one\", \"two\", \"three\"]");
|
||||
EXPECT_FALSE(a.HasParseError());
|
||||
EXPECT_TRUE(a.IsArray());
|
||||
EXPECT_EQ(3u, a.Size());
|
||||
EXPECT_EQ(&a.GetAllocator(), &allocator);
|
||||
|
||||
// Document b; b = a; // should not compile
|
||||
Document b;
|
||||
b = std::move(a);
|
||||
EXPECT_TRUE(a.IsNull());
|
||||
EXPECT_TRUE(b.IsArray());
|
||||
EXPECT_EQ(3u, b.Size());
|
||||
EXPECT_EQ(&a.GetAllocator(), (void*)0);
|
||||
EXPECT_EQ(&b.GetAllocator(), &allocator);
|
||||
|
||||
b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}");
|
||||
EXPECT_FALSE(b.HasParseError());
|
||||
EXPECT_TRUE(b.IsObject());
|
||||
EXPECT_EQ(2u, b.MemberCount());
|
||||
|
||||
// Document c; c = a; // should not compile
|
||||
Document c;
|
||||
c = std::move(b);
|
||||
EXPECT_TRUE(b.IsNull());
|
||||
EXPECT_TRUE(c.IsObject());
|
||||
EXPECT_EQ(2u, c.MemberCount());
|
||||
EXPECT_EQ(&b.GetAllocator(), (void*)0);
|
||||
EXPECT_EQ(&c.GetAllocator(), &allocator);
|
||||
}
|
||||
|
||||
TEST(Document, MoveAssignmentParseError) {
|
||||
typedef GenericDocument<UTF8<>, CrtAllocator> Document;
|
||||
|
||||
ParseResult noError;
|
||||
Document a;
|
||||
a.Parse("{ 4 = 4]");
|
||||
ParseResult error(a.GetParseError(), a.GetErrorOffset());
|
||||
EXPECT_TRUE(a.HasParseError());
|
||||
EXPECT_NE(error.Code(), noError.Code());
|
||||
EXPECT_NE(error.Offset(), noError.Offset());
|
||||
|
||||
Document b;
|
||||
b = std::move(a);
|
||||
EXPECT_FALSE(a.HasParseError());
|
||||
EXPECT_TRUE(b.HasParseError());
|
||||
EXPECT_EQ(a.GetParseError(), noError.Code());
|
||||
EXPECT_EQ(b.GetParseError(), error.Code());
|
||||
EXPECT_EQ(a.GetErrorOffset(), noError.Offset());
|
||||
EXPECT_EQ(b.GetErrorOffset(), error.Offset());
|
||||
|
||||
Document c;
|
||||
c = std::move(b);
|
||||
EXPECT_FALSE(b.HasParseError());
|
||||
EXPECT_TRUE(c.HasParseError());
|
||||
EXPECT_EQ(b.GetParseError(), noError.Code());
|
||||
EXPECT_EQ(c.GetParseError(), error.Code());
|
||||
EXPECT_EQ(b.GetErrorOffset(), noError.Offset());
|
||||
EXPECT_EQ(c.GetErrorOffset(), error.Offset());
|
||||
}
|
||||
|
||||
TEST(Document, MoveAssignmentStack) {
|
||||
typedef UTF8<> Encoding;
|
||||
typedef GenericDocument<Encoding, CrtAllocator> Document;
|
||||
|
||||
Document a;
|
||||
size_t defaultCapacity = a.GetStackCapacity();
|
||||
|
||||
// Trick Document into getting GetStackCapacity() to return non-zero
|
||||
typedef GenericReader<Encoding, Encoding, Document::AllocatorType> Reader;
|
||||
Reader reader(&a.GetAllocator());
|
||||
GenericStringStream<Encoding> is("[\"one\", \"two\", \"three\"]");
|
||||
reader.Parse<kParseDefaultFlags>(is, a);
|
||||
size_t capacity = a.GetStackCapacity();
|
||||
EXPECT_GT(capacity, 0);
|
||||
|
||||
Document b;
|
||||
b = std::move(a);
|
||||
EXPECT_EQ(a.GetStackCapacity(), defaultCapacity);
|
||||
EXPECT_EQ(b.GetStackCapacity(), capacity);
|
||||
|
||||
Document c;
|
||||
c = std::move(b);
|
||||
EXPECT_EQ(b.GetStackCapacity(), defaultCapacity);
|
||||
EXPECT_EQ(c.GetStackCapacity(), capacity);
|
||||
}
|
||||
|
||||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
|
||||
// Issue 22: Memory corruption via operator=
|
||||
// Fixed by making unimplemented assignment operator private.
|
||||
//TEST(Document, Assignment) {
|
||||
|
||||
Reference in New Issue
Block a user