// Tencent is pleased to support the open source community by making RapidJSON available.// // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.//// Licensed under the MIT License (the "License"); you may not use this file except// in compliance with the License. You may obtain a copy of the License at//// http://opensource.org/licenses/MIT//// Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License.#include"unittest.h"#include"rapidjson/document.h"#include<algorithm>#ifdef __clang__RAPIDJSON_DIAG_PUSHRAPIDJSON_DIAG_OFF(c++98-compat)#endifusingnamespacerapidjson;TEST(Value,Size){if(sizeof(SizeType)==4){#if RAPIDJSON_48BITPOINTER_OPTIMIZATIONEXPECT_EQ(16,sizeof(Value));#elif RAPIDJSON_64BITEXPECT_EQ(24,sizeof(Value));#elseEXPECT_EQ(16,sizeof(Value));#endif}}TEST(Value,DefaultConstructor){Valuex;EXPECT_EQ(kNullType,x.GetType());EXPECT_TRUE(x.IsNull());//std::cout << "sizeof(Value): " << sizeof(x) << std::endl;}// Should not pass compilation//TEST(Value, copy_constructor) {// Value x(1234);// Value y = x;//}#if RAPIDJSON_HAS_CXX11_RVALUE_REFS#if 0 // Many old compiler does not support these. Turn it off temporaily.#include <type_traits>TEST(Value, Traits) { typedef GenericValue<UTF8<>, CrtAllocator> Value; static_assert(std::is_constructible<Value>::value, ""); static_assert(std::is_default_constructible<Value>::value, "");#ifndef _MSC_VER static_assert(!std::is_copy_constructible<Value>::value, "");#endif static_assert(std::is_move_constructible<Value>::value, "");#ifndef _MSC_VER static_assert(std::is_nothrow_constructible<Value>::value, ""); static_assert(std::is_nothrow_default_constructible<Value>::value, ""); static_assert(!std::is_nothrow_copy_constructible<Value>::value, ""); static_assert(std::is_nothrow_move_constructible<Value>::value, "");#endif static_assert(std::is_assignable<Value,Value>::value, "");#ifndef _MSC_VER static_assert(!std::is_copy_assignable<Value>::value, "");#endif static_assert(std::is_move_assignable<Value>::value, "");#ifndef _MSC_VER static_assert(std::is_nothrow_assignable<Value, Value>::value, "");#endif static_assert(!std::is_nothrow_copy_assignable<Value>::value, "");#ifndef _MSC_VER static_assert(std::is_nothrow_move_assignable<Value>::value, "");#endif static_assert(std::is_destructible<Value>::value, "");#ifndef _MSC_VER static_assert(std::is_nothrow_destructible<Value>::value, "");#endif}#endifTEST(Value,MoveConstructor){typedefGenericValue<UTF8<>,CrtAllocator>V;V::AllocatorTypeallocator;Vx((V(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); // does not compile (!is_copy_constructible)Vy(std::move(x));EXPECT_TRUE(x.IsNull());EXPECT_TRUE(y.IsArray());EXPECT_EQ(4u,y.Size());// Value z = y; // does not compile (!is_copy_assignable)Vz=std::move(y);EXPECT_TRUE(y.IsNull());EXPECT_TRUE(z.IsArray());EXPECT_EQ(4u,z.Size());}#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFSTEST(Value,AssignmentOperator){Valuex(1234);Valuey;y=x;EXPECT_TRUE(x.IsNull());// move semanticEXPECT_EQ(1234,y.GetInt());y=5678;EXPECT_TRUE(y.IsInt());EXPECT_EQ(5678,y.GetInt());x="Hello";EXPECT_TRUE(x.IsString());EXPECT_STREQ(x.GetString(),"Hello");y=StringRef(x.GetString(),x.GetStringLength());EXPECT_TRUE(y.IsString());EXPECT_EQ(y.GetString(),x.GetString());EXPECT_EQ(y.GetStringLength(),x.GetStringLength());staticcharmstr[]="mutable";// y = mstr; // should not compiley=StringRef(mstr);EXPECT_TRUE(y.IsString());EXPECT_EQ(y.GetString(),mstr);#if RAPIDJSON_HAS_CXX11_RVALUE_REFS// C++11 move assignmentx=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<typenameA,typenameB>voidTestEqual(constA&a,constB&b){EXPECT_TRUE(a==b);EXPECT_FALSE(a!=b);EXPECT_TRUE(b==a);EXPECT_FALSE(b!=a);}template<typenameA,typenameB>voidTestUnequal(constA&a,constB&b){EXPECT_FALSE(a==b);EXPECT_TRUE(a!=b);EXPECT_FALSE(b==a);EXPECT_TRUE(b!=a);}TEST(Value,EqualtoOperator){Value::AllocatorTypeallocator;Valuex(kObjectType);x.AddMember("hello","world",allocator).AddMember("t",Value(true).Move(),allocator).AddMember("f",Value(false).Move(),allocator).AddMember("n",Value(kNullType).Move(),allocator).AddMember("i",123,allocator).AddMember("pi",3.14,allocator).AddMember("a",Value(kArrayType).Move().PushBack(1,allocator).PushBack(2,allocator).PushBack(3,allocator),allocator);// Test templated operator==() and operator!=()TestEqual(x["hello"],"world");constchar*cc="world";TestEqual(x["hello"],cc);char*c=strdup("world");TestEqual(x["hello"],c);free(c);TestEqual(x["t"],true);TestEqual(x["f"],false);TestEqual(x["i"],123);TestEqual(x["pi"],3.14);// Test operator==() (including different allocators)CrtAllocatorcrtAllocator;GenericValue<UTF8<>,CrtAllocator>y;GenericDocument<UTF8<>,CrtAllocator>z(&crtAllocator);y.CopyFrom(x,crtAllocator);z.CopyFrom(y,z.GetAllocator());TestEqual(x,y);TestEqual(y,z);TestEqual(z,x);// Swapping member order should be fine.EXPECT_TRUE(y.RemoveMember("t"));TestUnequal(x,y);TestUnequal(z,y);EXPECT_TRUE(z.RemoveMember("t"));TestUnequal(x,z);TestEqual(y,z);y.AddMember("t",false,crtAllocator);z.AddMember("t",false,z.GetAllocator());TestUnequal(x,y);TestUnequal(z,x);y["t"]=true;z["t"]=true;TestEqual(x,y);TestEqual(y,z);TestEqual(z,x);// Swapping element order is not OKx["a"][0].Swap(x["a"][1]);TestUnequal(x,y);x["a"][0].Swap(x["a"][1]);TestEqual(x,y);// Array of different sizex["a"].PushBack(4,allocator);TestUnequal(x,y);x["a"].PopBack();TestEqual(x,y);// Issue #129: compare Uint64x.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF,0xFFFFFFF0));y.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF,0xFFFFFFFF));TestUnequal(x,y);}template<typenameValue>voidTestCopyFrom(){typenameValue::AllocatorTypea;Valuev1(1234);Valuev2(v1,a);// deep copy constructorEXPECT_TRUE(v1.GetType()==v2.GetType());EXPECT_EQ(v1.GetInt(),v2.GetInt());v1.SetString("foo");v2.CopyFrom(v1,a);EXPECT_TRUE(v1.GetType()==v2.GetType());EXPECT_STREQ(v1.GetString(),v2.GetString());EXPECT_EQ(v1.GetString(),v2.GetString());// string NOT copiedv1.SetString("bar",a);// copy stringv2.CopyFrom(v1,a);EXPECT_TRUE(v1.GetType()==v2.GetType());EXPECT_STREQ(v1.GetString(),v2.GetString());EXPECT_NE(v1.GetString(),v2.GetString());// string copiedv1.SetArray().PushBack(1234,a);v2.CopyFrom(v1,a);EXPECT_TRUE(v2.IsArray());EXPECT_EQ(v1.Size(),v2.Size());v1.PushBack(Value().SetString("foo",a),a);// push string copyEXPECT_TRUE(v1.Size()!=v2.Size());v2.CopyFrom(v1,a);EXPECT_TRUE(v1.Size()==v2.Size());EXPECT_STREQ(v1[1].GetString(),v2[1].GetString());EXPECT_NE(v1[1].GetString(),v2[1].GetString());// string got copied}TEST(Value,CopyFrom){TestCopyFrom<Value>();TestCopyFrom<GenericValue<UTF8<>,CrtAllocator>>();}TEST(Value,Swap){Valuev1(1234);Valuev2(kObjectType);EXPECT_EQ(&v1,&v1.Swap(v2));EXPECT_TRUE(v1.IsObject());EXPECT_TRUE(v2.IsInt());EXPECT_EQ(1234,v2.GetInt());// testing std::swap compatibilityusingstd::swap;swap(v1,v2);EXPECT_TRUE(v1.IsInt());EXPECT_TRUE(v2.IsObject());}TEST(Value,Null){// Default constructorValuex;EXPECT_EQ(kNullType,x.GetType());EXPECT_TRUE(x.IsNull());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsNumber());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());// Constructor with typeValuey(kNullType);EXPECT_TRUE(y.IsNull());// SetNull();Valuez(true);z.SetNull();EXPECT_TRUE(z.IsNull());}TEST(Value,True){// Constructor with boolValuex(true);EXPECT_EQ(kTrueType,x.GetType());EXPECT_TRUE(x.GetBool());EXPECT_TRUE(x.IsBool());EXPECT_TRUE(x.IsTrue());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsNumber());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());// Constructor with typeValuey(kTrueType);EXPECT_TRUE(y.IsTrue());// SetBool()Valuez;z.SetBool(true);EXPECT_TRUE(z.IsTrue());// Templated functionsEXPECT_TRUE(z.Is<bool>());EXPECT_TRUE(z.Get<bool>());EXPECT_FALSE(z.Set<bool>(false).Get<bool>());EXPECT_TRUE(z.Set(true).Get<bool>());}TEST(Value,False){// Constructor with boolValuex(false);EXPECT_EQ(kFalseType,x.GetType());EXPECT_TRUE(x.IsBool());EXPECT_TRUE(x.IsFalse());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.GetBool());//EXPECT_FALSE((bool)x);EXPECT_FALSE(x.IsNumber());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());// Constructor with typeValuey(kFalseType);EXPECT_TRUE(y.IsFalse());// SetBool()Valuez;z.SetBool(false);EXPECT_TRUE(z.IsFalse());}TEST(Value,Int){// Constructor with intValuex(1234);EXPECT_EQ(kNumberType,x.GetType());EXPECT_EQ(1234,x.GetInt());EXPECT_EQ(1234u,x.GetUint());EXPECT_EQ(1234,x.GetInt64());EXPECT_EQ(1234u,x.GetUint64());EXPECT_NEAR(1234.0,x.GetDouble(),0.0);//EXPECT_EQ(1234, (int)x);//EXPECT_EQ(1234, (unsigned)x);//EXPECT_EQ(1234, (int64_t)x);//EXPECT_EQ(1234, (uint64_t)x);//EXPECT_EQ(1234, (double)x);EXPECT_TRUE(x.IsNumber());EXPECT_TRUE(x.IsInt());EXPECT_TRUE(x.IsUint());EXPECT_TRUE(x.IsInt64());EXPECT_TRUE(x.IsUint64());EXPECT_FALSE(x.IsDouble());EXPECT_FALSE(x.IsFloat());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());Valuenx(-1234);EXPECT_EQ(-1234,nx.GetInt());EXPECT_EQ(-1234,nx.GetInt64());EXPECT_TRUE(nx.IsInt());EXPECT_TRUE(nx.IsInt64());EXPECT_FALSE(nx.IsUint());EXPECT_FALSE(nx.IsUint64());// Constructor with typeValuey(kNumberType);EXPECT_TRUE(y.IsNumber());EXPECT_TRUE(y.IsInt());EXPECT_EQ(0,y.GetInt());// SetInt()Valuez;z.SetInt(1234);EXPECT_EQ(1234,z.GetInt());// operator=(int)z=5678;EXPECT_EQ(5678,z.GetInt());// Templated functionsEXPECT_TRUE(z.Is<int>());EXPECT_EQ(5678,z.Get<int>());EXPECT_EQ(5679,z.Set(5679).Get<int>());EXPECT_EQ(5680,z.Set<int>(5680).Get<int>());}TEST(Value,Uint){// Constructor with intValuex(1234u);EXPECT_EQ(kNumberType,x.GetType());EXPECT_EQ(1234,x.GetInt());EXPECT_EQ(1234u,x.GetUint());EXPECT_EQ(1234,x.GetInt64());EXPECT_EQ(1234u,x.GetUint64());EXPECT_TRUE(x.IsNumber());EXPECT_TRUE(x.IsInt());EXPECT_TRUE(x.IsUint());EXPECT_TRUE(x.IsInt64());EXPECT_TRUE(x.IsUint64());EXPECT_NEAR(1234.0,x.GetDouble(),0.0);// Number can always be cast as double but !IsDouble().EXPECT_FALSE(x.IsDouble());EXPECT_FALSE(x.IsFloat());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());// SetUint()Valuez;z.SetUint(1234);EXPECT_EQ(1234u,z.GetUint());// operator=(unsigned)z=5678u;EXPECT_EQ(5678u,z.GetUint());z=2147483648u;// 2^31, cannot cast as intEXPECT_EQ(2147483648u,z.GetUint());EXPECT_FALSE(z.IsInt());EXPECT_TRUE(z.IsInt64());// Issue 41: Incorrect parsing of unsigned int number types// Templated functionsEXPECT_TRUE(z.Is<unsigned>());EXPECT_EQ(2147483648u,z.Get<unsigned>());EXPECT_EQ(2147483649u,z.Set(2147483649u).Get<unsigned>());EXPECT_EQ(2147483650u,z.Set<unsigned>(2147483650u).Get<unsigned>());}TEST(Value,Int64){// Constructor with intValuex(int64_t(1234));EXPECT_EQ(kNumberType,x.GetType());EXPECT_EQ(1234,x.GetInt());EXPECT_EQ(1234u,x.GetUint());EXPECT_EQ(1234,x.GetInt64());EXPECT_EQ(1234u,x.GetUint64());EXPECT_TRUE(x.IsNumber());EXPECT_TRUE(x.IsInt());EXPECT_TRUE(x.IsUint());EXPECT_TRUE(x.IsInt64());EXPECT_TRUE(x.IsUint64());EXPECT_FALSE(x.IsDouble());EXPECT_FALSE(x.IsFloat());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());Valuenx(int64_t(-1234));EXPECT_EQ(-1234,nx.GetInt());EXPECT_EQ(-1234,nx.GetInt64());EXPECT_TRUE(nx.IsInt());EXPECT_TRUE(nx.IsInt64());EXPECT_FALSE(nx.IsUint());EXPECT_FALSE(nx.IsUint64());// SetInt64()Valuez;z.SetInt64(1234);EXPECT_EQ(1234,z.GetInt64());z.SetInt64(2147483648u);// 2^31, cannot cast as intEXPECT_FALSE(z.IsInt());EXPECT_TRUE(z.IsUint());EXPECT_NEAR(2147483648.0,z.GetDouble(),0.0);z.SetInt64(int64_t(4294967295u)+1);// 2^32, cannot cast as uintEXPECT_FALSE(z.IsInt());EXPECT_FALSE(z.IsUint());EXPECT_NEAR(4294967296.0,z.GetDouble(),0.0);z.SetInt64(-int64_t(2147483648u)-1);// -2^31-1, cannot cast as intEXPECT_FALSE(z.IsInt());EXPECT_NEAR(-2147483649.0,z.GetDouble(),0.0);int64_ti=static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000,00000000));z.SetInt64(i);EXPECT_DOUBLE_EQ(-9223372036854775808.0,z.GetDouble());// Templated functionsEXPECT_TRUE(z.Is<int64_t>());EXPECT_EQ(i,z.Get<int64_t>());EXPECT_EQ(i-1,z.Set(i-1).Get<int64_t>());EXPECT_EQ(i-2,z.Set<int64_t>(i-2).Get<int64_t>());}TEST(Value,Uint64){// Constructor with intValuex(uint64_t(1234));EXPECT_EQ(kNumberType,x.GetType());EXPECT_EQ(1234,x.GetInt());EXPECT_EQ(1234u,x.GetUint());EXPECT_EQ(1234,x.GetInt64());EXPECT_EQ(1234u,x.GetUint64());EXPECT_TRUE(x.IsNumber());EXPECT_TRUE(x.IsInt());EXPECT_TRUE(x.IsUint());EXPECT_TRUE(x.IsInt64());EXPECT_TRUE(x.IsUint64());EXPECT_FALSE(x.IsDouble());EXPECT_FALSE(x.IsFloat());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());// SetUint64()Valuez;z.SetUint64(1234);EXPECT_EQ(1234u,z.GetUint64());z.SetUint64(uint64_t(2147483648u));// 2^31, cannot cast as intEXPECT_FALSE(z.IsInt());EXPECT_TRUE(z.IsUint());EXPECT_TRUE(z.IsInt64());z.SetUint64(uint64_t(4294967295u)+1);// 2^32, cannot cast as uintEXPECT_FALSE(z.IsInt());EXPECT_FALSE(z.IsUint());EXPECT_TRUE(z.IsInt64());uint64_tu=RAPIDJSON_UINT64_C2(0x80000000,0x00000000);z.SetUint64(u);// 2^63 cannot cast as int64EXPECT_FALSE(z.IsInt64());EXPECT_EQ(u,z.GetUint64());// Issue 48EXPECT_DOUBLE_EQ(9223372036854775808.0,z.GetDouble());// Templated functionsEXPECT_TRUE(z.Is<uint64_t>());EXPECT_EQ(u,z.Get<uint64_t>());EXPECT_EQ(u+1,z.Set(u+1).Get<uint64_t>());EXPECT_EQ(u+2,z.Set<uint64_t>(u+2).Get<uint64_t>());}TEST(Value,Double){// Constructor with doubleValuex(12.34);EXPECT_EQ(kNumberType,x.GetType());EXPECT_NEAR(12.34,x.GetDouble(),0.0);EXPECT_TRUE(x.IsNumber());EXPECT_TRUE(x.IsDouble());EXPECT_FALSE(x.IsInt());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());// SetDouble()Valuez;z.SetDouble(12.34);EXPECT_NEAR(12.34,z.GetDouble(),0.0);z=56.78;EXPECT_NEAR(56.78,z.GetDouble(),0.0);// Templated functionsEXPECT_TRUE(z.Is<double>());EXPECT_EQ(56.78,z.Get<double>());EXPECT_EQ(57.78,z.Set(57.78).Get<double>());EXPECT_EQ(58.78,z.Set<double>(58.78).Get<double>());}TEST(Value,Float){// Constructor with doubleValuex(12.34f);EXPECT_EQ(kNumberType,x.GetType());EXPECT_NEAR(12.34f,x.GetFloat(),0.0);EXPECT_TRUE(x.IsNumber());EXPECT_TRUE(x.IsDouble());EXPECT_TRUE(x.IsFloat());EXPECT_FALSE(x.IsInt());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());// SetFloat()Valuez;z.SetFloat(12.34f);EXPECT_NEAR(12.34f,z.GetFloat(),0.0f);// Issue 573z.SetInt(0);EXPECT_EQ(0.0f,z.GetFloat());z=56.78f;EXPECT_NEAR(56.78f,z.GetFloat(),0.0f);// Templated functionsEXPECT_TRUE(z.Is<float>());EXPECT_EQ(56.78f,z.Get<float>());EXPECT_EQ(57.78f,z.Set(57.78f).Get<float>());EXPECT_EQ(58.78f,z.Set<float>(58.78f).Get<float>());}TEST(Value,IsLosslessDouble){EXPECT_TRUE(Value(12.34).IsLosslessDouble());EXPECT_TRUE(Value(-123).IsLosslessDouble());EXPECT_TRUE(Value(2147483648u).IsLosslessDouble());EXPECT_TRUE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x40000000,0x00000000))).IsLosslessDouble());#if !(defined(_MSC_VER) && _MSC_VER < 1800) // VC2010 has problemEXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000,0x00000000)).IsLosslessDouble());#endifEXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF,0xFFFFFFFF))).IsLosslessDouble());EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF,0xFFFFFFFF)).IsLosslessDouble());}TEST(Value,IsLosslessFloat){EXPECT_TRUE(Value(12.25).IsLosslessFloat());EXPECT_TRUE(Value(-123).IsLosslessFloat());EXPECT_TRUE(Value(2147483648u).IsLosslessFloat());EXPECT_TRUE(Value(3.4028234e38f).IsLosslessFloat());EXPECT_TRUE(Value(-3.4028234e38f).IsLosslessFloat());EXPECT_FALSE(Value(3.4028235e38).IsLosslessFloat());EXPECT_FALSE(Value(0.3).IsLosslessFloat());}TEST(Value,String){// Construction with const stringValuex("Hello",5);// literalEXPECT_EQ(kStringType,x.GetType());EXPECT_TRUE(x.IsString());EXPECT_STREQ("Hello",x.GetString());EXPECT_EQ(5u,x.GetStringLength());EXPECT_FALSE(x.IsNumber());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsObject());EXPECT_FALSE(x.IsArray());staticconstcharcstr[]="World";// const arrayValue(cstr).Swap(x);EXPECT_TRUE(x.IsString());EXPECT_EQ(x.GetString(),cstr);EXPECT_EQ(x.GetStringLength(),sizeof(cstr)-1);staticcharmstr[]="Howdy";// non-const array// Value(mstr).Swap(x); // should not compileValue(StringRef(mstr)).Swap(x);EXPECT_TRUE(x.IsString());EXPECT_EQ(x.GetString(),mstr);EXPECT_EQ(x.GetStringLength(),sizeof(mstr)-1);strncpy(mstr,"Hello",sizeof(mstr));EXPECT_STREQ(x.GetString(),"Hello");constchar*pstr=cstr;//Value(pstr).Swap(x); // should not compileValue(StringRef(pstr)).Swap(x);EXPECT_TRUE(x.IsString());EXPECT_EQ(x.GetString(),cstr);EXPECT_EQ(x.GetStringLength(),sizeof(cstr)-1);char*mpstr=mstr;Value(StringRef(mpstr,sizeof(mstr)-1)).Swap(x);EXPECT_TRUE(x.IsString());EXPECT_EQ(x.GetString(),mstr);EXPECT_EQ(x.GetStringLength(),5u);EXPECT_STREQ(x.GetString(),"Hello");// Constructor with copy stringMemoryPoolAllocator<>allocator;Valuec(x.GetString(),x.GetStringLength(),allocator);EXPECT_NE(x.GetString(),c.GetString());EXPECT_EQ(x.GetStringLength(),c.GetStringLength());EXPECT_STREQ(x.GetString(),c.GetString());//x.SetString("World");x.SetString("World",5);EXPECT_STREQ("Hello",c.GetString());EXPECT_EQ(5u,c.GetStringLength());// Constructor with typeValuey(kStringType);EXPECT_TRUE(y.IsString());EXPECT_STREQ("",y.GetString());// Empty string should be "" instead of 0 (issue 226)EXPECT_EQ(0u,y.GetStringLength());// SetConsttring()Valuez;z.SetString("Hello");EXPECT_TRUE(x.IsString());z.SetString("Hello",5);EXPECT_STREQ("Hello",z.GetString());EXPECT_STREQ("Hello",z.GetString());EXPECT_EQ(5u,z.GetStringLength());z.SetString("Hello");EXPECT_TRUE(z.IsString());EXPECT_STREQ("Hello",z.GetString());//z.SetString(mstr); // should not compile//z.SetString(pstr); // should not compilez.SetString(StringRef(mstr));EXPECT_TRUE(z.IsString());EXPECT_STREQ(z.GetString(),mstr);z.SetString(cstr);EXPECT_TRUE(z.IsString());EXPECT_EQ(cstr,z.GetString());z=cstr;EXPECT_TRUE(z.IsString());EXPECT_EQ(cstr,z.GetString());// SetString()chars[]="World";Valuew;w.SetString(s,static_cast<SizeType>(strlen(s)),allocator);s[0]='\0';EXPECT_STREQ("World",w.GetString());EXPECT_EQ(5u,w.GetStringLength());// templated functionsEXPECT_TRUE(z.Is<constchar*>());EXPECT_STREQ(cstr,z.Get<constchar*>());EXPECT_STREQ("Apple",z.Set<constchar*>("Apple").Get<constchar*>());#if RAPIDJSON_HAS_STDSTRING{std::stringstr="Hello World";str[5]='\0';EXPECT_STREQ(str.data(),"Hello");// embedded '\0'EXPECT_EQ(str.size(),11u);// no copyValuevs0(StringRef(str));EXPECT_TRUE(vs0.IsString());EXPECT_EQ(vs0.GetString(),str.data());EXPECT_EQ(vs0.GetStringLength(),str.size());TestEqual(vs0,str);// do copyValuevs1(str,allocator);EXPECT_TRUE(vs1.IsString());EXPECT_NE(vs1.GetString(),str.data());EXPECT_NE(vs1.GetString(),str);// not equal due to embedded '\0'EXPECT_EQ(vs1.GetStringLength(),str.size());TestEqual(vs1,str);// SetStringstr="World";vs0.SetNull().SetString(str,allocator);EXPECT_TRUE(vs0.IsString());EXPECT_STREQ(vs0.GetString(),str.c_str());EXPECT_EQ(vs0.GetStringLength(),str.size());TestEqual(str,vs0);TestUnequal(str,vs1);// vs1 = str; // should not compilevs1=StringRef(str);TestEqual(str,vs1);TestEqual(vs0,vs1);// Templated function.EXPECT_TRUE(vs0.Is<std::string>());EXPECT_EQ(str,vs0.Get<std::string>());vs0.Set<std::string>(std::string("Apple"),allocator);EXPECT_EQ(std::string("Apple"),vs0.Get<std::string>());vs0.Set(std::string("Orange"),allocator);EXPECT_EQ(std::string("Orange"),vs0.Get<std::string>());}#endif // RAPIDJSON_HAS_STDSTRING}// Issue 226: Value of string type should not point to NULLTEST(Value,SetStringNullException){Valuev;EXPECT_THROW(v.SetString(0,0),AssertException);}template<typenameT,typenameAllocator>staticvoidTestArray(T&x,Allocator&allocator){constT&y=x;// PushBack()Valuev;x.PushBack(v,allocator);v.SetBool(true);x.PushBack(v,allocator);v.SetBool(false);x.PushBack(v,allocator);v.SetInt(123);x.PushBack(v,allocator);//x.PushBack((const char*)"foo", allocator); // should not compilex.PushBack("foo",allocator);EXPECT_FALSE(x.Empty());EXPECT_EQ(5u,x.Size());EXPECT_FALSE(y.Empty());EXPECT_EQ(5u,y.Size());EXPECT_TRUE(x[SizeType(0)].IsNull());EXPECT_TRUE(x[1].IsTrue());EXPECT_TRUE(x[2].IsFalse());EXPECT_TRUE(x[3].IsInt());EXPECT_EQ(123,x[3].GetInt());EXPECT_TRUE(y[SizeType(0)].IsNull());EXPECT_TRUE(y[1].IsTrue());EXPECT_TRUE(y[2].IsFalse());EXPECT_TRUE(y[3].IsInt());EXPECT_EQ(123,y[3].GetInt());EXPECT_TRUE(y[4].IsString());EXPECT_STREQ("foo",y[4].GetString());#if RAPIDJSON_HAS_CXX11_RVALUE_REFS// PushBack(GenericValue&&, Allocator&);{Valuey2(kArrayType);y2.PushBack(Value(true),allocator);y2.PushBack(std::move(Value(kArrayType).PushBack(Value(1),allocator).PushBack("foo",allocator)),allocator);EXPECT_EQ(2u,y2.Size());EXPECT_TRUE(y2[0].IsTrue());EXPECT_TRUE(y2[1].IsArray());EXPECT_EQ(2u,y2[1].Size());EXPECT_TRUE(y2[1][0].IsInt());EXPECT_TRUE(y2[1][1].IsString());}#endif// iteratortypenameT::ValueIteratoritr=x.Begin();EXPECT_TRUE(itr!=x.End());EXPECT_TRUE(itr->IsNull());++itr;EXPECT_TRUE(itr!=x.End());EXPECT_TRUE(itr->IsTrue());++itr;EXPECT_TRUE(itr!=x.End());EXPECT_TRUE(itr->IsFalse());++itr;EXPECT_TRUE(itr!=x.End());EXPECT_TRUE(itr->IsInt());EXPECT_EQ(123,itr->GetInt());++itr;EXPECT_TRUE(itr!=x.End());EXPECT_TRUE(itr->IsString());EXPECT_STREQ("foo",itr->GetString());// const iteratortypenameT::ConstValueIteratorcitr=y.Begin();EXPECT_TRUE(citr!=y.End());EXPECT_TRUE(citr->IsNull());++citr;EXPECT_TRUE(citr!=y.End());EXPECT_TRUE(citr->IsTrue());++citr;EXPECT_TRUE(citr!=y.End());EXPECT_TRUE(citr->IsFalse());++citr;EXPECT_TRUE(citr!=y.End());EXPECT_TRUE(citr->IsInt());EXPECT_EQ(123,citr->GetInt());++citr;EXPECT_TRUE(citr!=y.End());EXPECT_TRUE(citr->IsString());EXPECT_STREQ("foo",citr->GetString());// PopBack()x.PopBack();EXPECT_EQ(4u,x.Size());EXPECT_TRUE(y[SizeType(0)].IsNull());EXPECT_TRUE(y[1].IsTrue());EXPECT_TRUE(y[2].IsFalse());EXPECT_TRUE(y[3].IsInt());// Clear()x.Clear();EXPECT_TRUE(x.Empty());EXPECT_EQ(0u,x.Size());EXPECT_TRUE(y.Empty());EXPECT_EQ(0u,y.Size());// Erase(ValueIterator)// Use array of array to ensure removed elements' destructor is called.// [[0],[1],[2],...]for(inti=0;i<10;i++)x.PushBack(Value(kArrayType).PushBack(i,allocator).Move(),allocator);// Erase the firstitr=x.Erase(x.Begin());EXPECT_EQ(x.Begin(),itr);EXPECT_EQ(9u,x.Size());for(inti=0;i<9;i++)EXPECT_EQ(i+1,x[static_cast<SizeType>(i)][0].GetInt());// Ease the lastitr=x.Erase(x.End()-1);EXPECT_EQ(x.End(),itr);EXPECT_EQ(8u,x.Size());for(inti=0;i<8;i++)EXPECT_EQ(i+1,x[static_cast<SizeType>(i)][0].GetInt());// Erase the middleitr=x.Erase(x.Begin()+4);EXPECT_EQ(x.Begin()+4,itr);EXPECT_EQ(7u,x.Size());for(inti=0;i<4;i++)EXPECT_EQ(i+1,x[static_cast<SizeType>(i)][0].GetInt());for(inti=4;i<7;i++)EXPECT_EQ(i+2,x[static_cast<SizeType>(i)][0].GetInt());// Erase(ValueIterator, ValueIterator)// Exhaustive test with all 0 <= first < n, first <= last <= n casesconstunsignedn=10;for(unsignedfirst=0;first<n;first++){for(unsignedlast=first;last<=n;last++){x.Clear();for(unsignedi=0;i<n;i++)x.PushBack(Value(kArrayType).PushBack(i,allocator).Move(),allocator);itr=x.Erase(x.Begin()+first,x.Begin()+last);if(last==n)EXPECT_EQ(x.End(),itr);elseEXPECT_EQ(x.Begin()+first,itr);size_tremoveCount=last-first;EXPECT_EQ(n-removeCount,x.Size());for(unsignedi=0;i<first;i++)EXPECT_EQ(i,x[i][0].GetUint());for(unsignedi=first;i<n-removeCount;i++)EXPECT_EQ(i+removeCount,x[static_cast<SizeType>(i)][0].GetUint());}}}TEST(Value,Array){Valuex(kArrayType);constValue&y=x;Value::AllocatorTypeallocator;EXPECT_EQ(kArrayType,x.GetType());EXPECT_TRUE(x.IsArray());EXPECT_TRUE(x.Empty());EXPECT_EQ(0u,x.Size());EXPECT_TRUE(y.IsArray());EXPECT_TRUE(y.Empty());EXPECT_EQ(0u,y.Size());EXPECT_FALSE(x.IsNull());EXPECT_FALSE(x.IsBool());EXPECT_FALSE(x.IsFalse());EXPECT_FALSE(x.IsTrue());EXPECT_FALSE(x.IsString());EXPECT_FALSE(x.IsObject());TestArray(x,allocator);// Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.// http://en.wikipedia.org/wiki/Erase-remove_idiomx.Clear();for(inti=0;i<10;i++)if(i%2==0)x.PushBack(i,allocator);elsex.PushBack(Value(kNullType).Move(),allocator);constValuenull(kNullType);x.Erase(std::remove(x.Begin(),x.End(),null),x.End());EXPECT_EQ(5u,x.Size());for(inti=0;i<5;i++)EXPECT_EQ(i*2,x[static_cast<SizeType>(i)]);// SetArray()Valuez;z.SetArray();EXPECT_TRUE(z.IsArray());EXPECT_TRUE(z.Empty());}TEST(Value,ArrayHelper){Value::AllocatorTypeallocator;{Valuex(kArrayType);Value::Arraya=x.GetArray();TestArray(a,allocator);}{Valuex(kArrayType);Value::Arraya=x.GetArray();a.PushBack(1,allocator);Value::Arraya2(a);// copy constructorEXPECT_EQ(1,a2.Size());Value::Arraya3=a;EXPECT_EQ(1,a3.Size());Value::ConstArrayy=static_cast<constValue&>(x).GetArray();(void)y;// y.PushBack(1, allocator); // should not compile// Templated functionsx.Clear();EXPECT_TRUE(x.Is<Value::Array>());EXPECT_TRUE(x.Is<Value::ConstArray>());a.PushBack(1,allocator);EXPECT_EQ(1,x.Get<Value::Array>()[0].GetInt());EXPECT_EQ(1,x.Get<Value::ConstArray>()[0].GetInt());Valuex2;x2.Set<Value::Array>(a);EXPECT_TRUE(x.IsArray());// IsArray() is invariant after moving.EXPECT_EQ(1,x2.Get<Value::Array>()[0].GetInt());}{Valuey(kArrayType);y.PushBack(123,allocator);Valuex(y.GetArray());// Construct value form array.EXPECT_TRUE(x.IsArray());EXPECT_EQ(123,x[0].GetInt());EXPECT_TRUE(y.IsArray());// InvariantEXPECT_TRUE(y.Empty());}{Valuex(kArrayType);Valuey(kArrayType);y.PushBack(123,allocator);x.PushBack(y.GetArray(),allocator);// Implicit constructor to convert Array to GenericValueEXPECT_EQ(1,x.Size());EXPECT_EQ(123,x[0][0].GetInt());EXPECT_TRUE(y.IsArray());EXPECT_TRUE(y.Empty());}}#if RAPIDJSON_HAS_CXX11_RANGE_FORTEST(Value,ArrayHelperRangeFor){Value::AllocatorTypeallocator;Valuex(kArrayType);for(inti=0;i<10;i++)x.PushBack(i,allocator);{inti=0;for(auto&v:x.GetArray())EXPECT_EQ(i++,v.GetInt());EXPECT_EQ(i,10);}{inti=0;for(constauto&v:const_cast<constValue&>(x).GetArray())EXPECT_EQ(i++,v.GetInt());EXPECT_EQ(i,10);}// Array a = x.GetArray();// Array ca = const_cast<const Value&>(x).GetArray();}#endiftemplate<typenameT,typenameAllocator>staticvoidTestObject(T&x,Allocator&allocator){constT&y=x;// const version// AddMember()x.AddMember("A","Apple",allocator);EXPECT_FALSE(x.ObjectEmpty());EXPECT_EQ(1u,x.MemberCount());Valuevalue("Banana",6);x.AddMember("B","Banana",allocator);EXPECT_EQ(2u,x.MemberCount());// AddMember<T>(StringRefType, T, Allocator){Valueo(kObjectType);o.AddMember("true",true,allocator);o.AddMember("false",false,allocator);o.AddMember("int",-1,allocator);o.AddMember("uint",1u,allocator);o.AddMember("int64",int64_t(-4294967296),allocator);o.AddMember("uint64",uint64_t(4294967296),allocator);o.AddMember("double",3.14,allocator);o.AddMember("string","Jelly",allocator);EXPECT_TRUE(o["true"].GetBool());EXPECT_FALSE(o["false"].GetBool());EXPECT_EQ(-1,o["int"].GetInt());EXPECT_EQ(1u,o["uint"].GetUint());EXPECT_EQ(int64_t(-4294967296),o["int64"].GetInt64());EXPECT_EQ(uint64_t(4294967296),o["uint64"].GetUint64());EXPECT_STREQ("Jelly",o["string"].GetString());EXPECT_EQ(8u,o.MemberCount());}// AddMember<T>(Value&, T, Allocator){Valueo(kObjectType);Valuen("s");o.AddMember(n,"string",allocator);EXPECT_EQ(1u,o.MemberCount());Valuecount("#");o.AddMember(count,o.MemberCount(),allocator);EXPECT_EQ(2u,o.MemberCount());}#if RAPIDJSON_HAS_STDSTRING{// AddMember(StringRefType, const std::string&, Allocator)Valueo(kObjectType);o.AddMember("b",std::string("Banana"),allocator);EXPECT_STREQ("Banana",o["b"].GetString());// RemoveMember(const std::string&)o.RemoveMember(std::string("b"));EXPECT_TRUE(o.ObjectEmpty());}#endif#if RAPIDJSON_HAS_CXX11_RVALUE_REFS// AddMember(GenericValue&&, ...) variants{Valueo(kObjectType);o.AddMember(Value("true"),Value(true),allocator);o.AddMember(Value("false"),Value(false).Move(),allocator);// value is lvalue refo.AddMember(Value("int").Move(),Value(-1),allocator);// name is lvalue refo.AddMember("uint",std::move(Value().SetUint(1u)),allocator);// name is literal, value is rvalueEXPECT_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 characterValuename;constValueC0D("C\0D",3);name.SetString(C0D.GetString(),3);value.SetString("CherryD",7);x.AddMember(name,value,allocator);// HasMember()EXPECT_TRUE(x.HasMember("A"));EXPECT_TRUE(x.HasMember("B"));EXPECT_TRUE(y.HasMember("A"));EXPECT_TRUE(y.HasMember("B"));#if RAPIDJSON_HAS_STDSTRINGEXPECT_TRUE(x.HasMember(std::string("A")));#endifname.SetString("C\0D");EXPECT_TRUE(x.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[]EXPECT_STREQ("Apple",x["A"].GetString());EXPECT_STREQ("Banana",x["B"].GetString());EXPECT_STREQ("CherryD",x[C0D].GetString());EXPECT_STREQ("CherryD",x[othername].GetString());EXPECT_THROW(x["nonexist"],AssertException);// const operator[]EXPECT_STREQ("Apple",y["A"].GetString());EXPECT_STREQ("Banana",y["B"].GetString());EXPECT_STREQ("CherryD",y[C0D].GetString());#if RAPIDJSON_HAS_STDSTRINGEXPECT_STREQ("Apple",x["A"].GetString());EXPECT_STREQ("Apple",y[std::string("A")].GetString());#endif// member iteratorValue::MemberIteratoritr=x.MemberBegin();EXPECT_TRUE(itr!=x.MemberEnd());EXPECT_STREQ("A",itr->name.GetString());EXPECT_STREQ("Apple",itr->value.GetString());++itr;EXPECT_TRUE(itr!=x.MemberEnd());EXPECT_STREQ("B",itr->name.GetString());EXPECT_STREQ("Banana",itr->value.GetString());++itr;EXPECT_TRUE(itr!=x.MemberEnd());EXPECT_TRUE(memcmp(itr->name.GetString(),"C\0D",4)==0);EXPECT_STREQ("CherryD",itr->value.GetString());++itr;EXPECT_FALSE(itr!=x.MemberEnd());// const member iteratorValue::ConstMemberIteratorcitr=y.MemberBegin();EXPECT_TRUE(citr!=y.MemberEnd());EXPECT_STREQ("A",citr->name.GetString());EXPECT_STREQ("Apple",citr->value.GetString());++citr;EXPECT_TRUE(citr!=y.MemberEnd());EXPECT_STREQ("B",citr->name.GetString());EXPECT_STREQ("Banana",citr->value.GetString());++citr;EXPECT_TRUE(citr!=y.MemberEnd());EXPECT_TRUE(memcmp(citr->name.GetString(),"C\0D",4)==0);EXPECT_STREQ("CherryD",citr->value.GetString());++citr;EXPECT_FALSE(citr!=y.MemberEnd());// member iterator conversions/relationsitr=x.MemberBegin();citr=x.MemberBegin();// const conversionTestEqual(itr,citr);EXPECT_TRUE(itr<x.MemberEnd());EXPECT_FALSE(itr>y.MemberEnd());EXPECT_TRUE(citr<x.MemberEnd());EXPECT_FALSE(citr>y.MemberEnd());++citr;TestUnequal(itr,citr);EXPECT_FALSE(itr<itr);EXPECT_TRUE(itr<citr);EXPECT_FALSE(itr>itr);EXPECT_TRUE(citr>itr);EXPECT_EQ(1,citr-x.MemberBegin());EXPECT_EQ(0,itr-y.MemberBegin());itr+=citr-x.MemberBegin();EXPECT_EQ(1,itr-y.MemberBegin());TestEqual(citr,itr);EXPECT_TRUE(itr<=citr);EXPECT_TRUE(citr<=itr);itr++;EXPECT_TRUE(itr>=citr);EXPECT_FALSE(citr>=itr);// RemoveMember()EXPECT_TRUE(x.RemoveMember("A"));EXPECT_FALSE(x.HasMember("A"));EXPECT_TRUE(x.RemoveMember("B"));EXPECT_FALSE(x.HasMember("B"));EXPECT_FALSE(x.RemoveMember("nonexist"));EXPECT_TRUE(x.RemoveMember(othername));EXPECT_FALSE(x.HasMember(name));EXPECT_TRUE(x.MemberBegin()==x.MemberEnd());// EraseMember(ConstMemberIterator)// Use array members to ensure removed elements' destructor is called.// { "a": [0], "b": [1],[2],...]constcharkeys[][2]={"a","b","c","d","e","f","g","h","i","j"};for(inti=0;i<10;i++)x.AddMember(keys[i],Value(kArrayType).PushBack(i,allocator),allocator);// MemberCount, iterator differenceEXPECT_EQ(x.MemberCount(),SizeType(x.MemberEnd()-x.MemberBegin()));// Erase the firstitr=x.EraseMember(x.MemberBegin());EXPECT_FALSE(x.HasMember(keys[0]));EXPECT_EQ(x.MemberBegin(),itr);EXPECT_EQ(9u,x.MemberCount());for(;itr!=x.MemberEnd();++itr){size_ti=static_cast<size_t>((itr-x.MemberBegin()))+1;EXPECT_STREQ(itr->name.GetString(),keys[i]);EXPECT_EQ(i,itr->value[0].GetInt());}// Erase the lastitr=x.EraseMember(x.MemberEnd()-1);EXPECT_FALSE(x.HasMember(keys[9]));EXPECT_EQ(x.MemberEnd(),itr);EXPECT_EQ(8u,x.MemberCount());for(;itr!=x.MemberEnd();++itr){size_ti=static_cast<size_t>(itr-x.MemberBegin())+1;EXPECT_STREQ(itr->name.GetString(),keys[i]);EXPECT_EQ(i,itr->value[0].GetInt());}// Erase the middleitr=x.EraseMember(x.MemberBegin()+4);EXPECT_FALSE(x.HasMember(keys[5]));EXPECT_EQ(x.MemberBegin()+4,itr);EXPECT_EQ(7u,x.MemberCount());for(;itr!=x.MemberEnd();++itr){size_ti=static_cast<size_t>(itr-x.MemberBegin());i+=(i<4)?1:2;EXPECT_STREQ(itr->name.GetString(),keys[i]);EXPECT_EQ(i,itr->value[0].GetInt());}// EraseMember(ConstMemberIterator, ConstMemberIterator)// Exhaustive test with all 0 <= first < n, first <= last <= n casesconstunsignedn=10;for(unsignedfirst=0;first<n;first++){for(unsignedlast=first;last<=n;last++){x.RemoveAllMembers();for(unsignedi=0;i<n;i++)x.AddMember(keys[i],Value(kArrayType).PushBack(i,allocator),allocator);itr=x.EraseMember(x.MemberBegin()+static_cast<int>(first),x.MemberBegin()+static_cast<int>(last));if(last==n)EXPECT_EQ(x.MemberEnd(),itr);elseEXPECT_EQ(x.MemberBegin()+static_cast<int>(first),itr);size_tremoveCount=last-first;EXPECT_EQ(n-removeCount,x.MemberCount());for(unsignedi=0;i<first;i++)EXPECT_EQ(i,x[keys[i]][0].GetUint());for(unsignedi=first;i<n-removeCount;i++)EXPECT_EQ(i+removeCount,x[keys[i+removeCount]][0].GetUint());}}// RemoveAllMembers()x.RemoveAllMembers();EXPECT_TRUE(x.ObjectEmpty());EXPECT_EQ(0u,x.MemberCount());}TEST(Value,Object){Valuex(kObjectType);constValue&y=x;// const versionValue::AllocatorTypeallocator;EXPECT_EQ(kObjectType,x.GetType());EXPECT_TRUE(x.IsObject());EXPECT_TRUE(x.ObjectEmpty());EXPECT_EQ(0u,x.MemberCount());EXPECT_EQ(kObjectType,y.GetType());EXPECT_TRUE(y.IsObject());EXPECT_TRUE(y.ObjectEmpty());EXPECT_EQ(0u,y.MemberCount());TestObject(x,allocator);// SetObject()Valuez;z.SetObject();EXPECT_TRUE(z.IsObject());}TEST(Value,ObjectHelper){Value::AllocatorTypeallocator;{Valuex(kObjectType);Value::Objecto=x.GetObject();TestObject(o,allocator);}{Valuex(kObjectType);Value::Objecto=x.GetObject();o.AddMember("1",1,allocator);Value::Objecto2(o);// copy constructorEXPECT_EQ(1,o2.MemberCount());Value::Objecto3=o;EXPECT_EQ(1,o3.MemberCount());Value::ConstObjecty=static_cast<constValue&>(x).GetObject();(void)y;// y.AddMember("1", 1, allocator); // should not compile// Templated functionsx.RemoveAllMembers();EXPECT_TRUE(x.Is<Value::Object>());EXPECT_TRUE(x.Is<Value::ConstObject>());o.AddMember("1",1,allocator);EXPECT_EQ(1,x.Get<Value::Object>()["1"].GetInt());EXPECT_EQ(1,x.Get<Value::ConstObject>()["1"].GetInt());Valuex2;x2.Set<Value::Object>(o);EXPECT_TRUE(x.IsObject());// IsObject() is invariant after movingEXPECT_EQ(1,x2.Get<Value::Object>()["1"].GetInt());}{Valuex(kObjectType);x.AddMember("a","apple",allocator);Valuey(x.GetObject());EXPECT_STREQ("apple",y["a"].GetString());EXPECT_TRUE(x.IsObject());// Invariant}{Valuex(kObjectType);x.AddMember("a","apple",allocator);Valuey(kObjectType);y.AddMember("fruits",x.GetObject(),allocator);EXPECT_STREQ("apple",y["fruits"]["a"].GetString());EXPECT_TRUE(x.IsObject());// Invariant}}#if RAPIDJSON_HAS_CXX11_RANGE_FORTEST(Value,ObjectHelperRangeFor){Value::AllocatorTypeallocator;Valuex(kObjectType);for(inti=0;i<10;i++){charname[10];Valuen(name,static_cast<SizeType>(sprintf(name,"%d",i)),allocator);x.AddMember(n,i,allocator);}{inti=0;for(auto&m:x.GetObject()){charname[10];sprintf(name,"%d",i);EXPECT_STREQ(name,m.name.GetString());EXPECT_EQ(i,m.value.GetInt());i++;}EXPECT_EQ(i,10);}{inti=0;for(constauto&m:const_cast<constValue&>(x).GetObject()){charname[10];sprintf(name,"%d",i);EXPECT_STREQ(name,m.name.GetString());EXPECT_EQ(i,m.value.GetInt());i++;}EXPECT_EQ(i,10);}// Object a = x.GetObject();// Object ca = const_cast<const Value&>(x).GetObject();}#endifTEST(Value,EraseMember_String){Value::AllocatorTypeallocator;Valuex(kObjectType);x.AddMember("A","Apple",allocator);x.AddMember("B","Banana",allocator);EXPECT_TRUE(x.EraseMember("B"));EXPECT_FALSE(x.HasMember("B"));EXPECT_FALSE(x.EraseMember("nonexist"));GenericValue<UTF8<>,CrtAllocator>othername("A");EXPECT_TRUE(x.EraseMember(othername));EXPECT_FALSE(x.HasMember("A"));EXPECT_TRUE(x.MemberBegin()==x.MemberEnd());}TEST(Value,BigNestedArray){MemoryPoolAllocator<>allocator;Valuex(kArrayType);staticconstSizeTypen=200;for(SizeTypei=0;i<n;i++){Valuey(kArrayType);for(SizeTypej=0;j<n;j++){Valuenumber(static_cast<int>(i*n+j));y.PushBack(number,allocator);}x.PushBack(y,allocator);}for(SizeTypei=0;i<n;i++)for(SizeTypej=0;j<n;j++){EXPECT_TRUE(x[i][j].IsInt());EXPECT_EQ(static_cast<int>(i*n+j),x[i][j].GetInt());}}TEST(Value,BigNestedObject){MemoryPoolAllocator<>allocator;Valuex(kObjectType);staticconstSizeTypen=200;for(SizeTypei=0;i<n;i++){charname1[10];sprintf(name1,"%d",i);// Value name(name1); // should not compileValuename(name1,static_cast<SizeType>(strlen(name1)),allocator);Valueobject(kObjectType);for(SizeTypej=0;j<n;j++){charname2[10];sprintf(name2,"%d",j);Valuename3(name2,static_cast<SizeType>(strlen(name2)),allocator);Valuenumber(static_cast<int>(i*n+j));object.AddMember(name3,number,allocator);}// x.AddMember(name1, object, allocator); // should not compilex.AddMember(name,object,allocator);}for(SizeTypei=0;i<n;i++){charname1[10];sprintf(name1,"%d",i);for(SizeTypej=0;j<n;j++){charname2[10];sprintf(name2,"%d",j);x[name1];EXPECT_EQ(static_cast<int>(i*n+j),x[name1][name2].GetInt());}}}// Issue 18: Error removing last element of object// http://code.google.com/p/rapidjson/issues/detail?id=18TEST(Value,RemoveLastElement){rapidjson::Documentdoc;rapidjson::Document::AllocatorType&allocator=doc.GetAllocator();rapidjson::ValueobjVal(rapidjson::kObjectType);objVal.AddMember("var1",123,allocator);objVal.AddMember("var2","444",allocator);objVal.AddMember("var3",555,allocator);EXPECT_TRUE(objVal.HasMember("var3"));objVal.RemoveMember("var3");// Assertion here in r61EXPECT_FALSE(objVal.HasMember("var3"));}// Issue 38: Segmentation fault with CrtAllocatorTEST(Document,CrtAllocator){typedefGenericValue<UTF8<>,CrtAllocator>V;V::AllocatorTypeallocator;Vo(kObjectType);o.AddMember("x",1,allocator);// Should not call destructor on uninitialized name/value of newly allocated members.Va(kArrayType);a.PushBack(1,allocator);// Should not call destructor on uninitialized Value of newly allocated elements.}staticvoidTestShortStringOptimization(constchar*str){constrapidjson::SizeTypelen=static_cast<rapidjson::SizeType>(strlen(str));rapidjson::Documentdoc;rapidjson::Valueval;val.SetString(str,len,doc.GetAllocator());EXPECT_EQ(val.GetStringLength(),len);EXPECT_STREQ(val.GetString(),str);}TEST(Value,AllocateShortString){TestShortStringOptimization("");// edge case: empty stringTestShortStringOptimization("12345678");// regular case for short strings: 8 charsTestShortStringOptimization("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)}template<inte>structTerminateHandler{boolNull(){returne!=0;}boolBool(bool){returne!=1;}boolInt(int){returne!=2;}boolUint(unsigned){returne!=3;}boolInt64(int64_t){returne!=4;}boolUint64(uint64_t){returne!=5;}boolDouble(double){returne!=6;}boolRawNumber(constchar*,SizeType,bool){returne!=7;}boolString(constchar*,SizeType,bool){returne!=8;}boolStartObject(){returne!=9;}boolKey(constchar*,SizeType,bool){returne!=10;}boolEndObject(SizeType){returne!=11;}boolStartArray(){returne!=12;}boolEndArray(SizeType){returne!=13;}};#define TEST_TERMINATION(e, json)\{\ Document d; \ EXPECT_FALSE(d.Parse(json).HasParseError()); \ Reader reader; \ TerminateHandler<e> h;\ EXPECT_FALSE(d.Accept(h));\}TEST(Value,AcceptTerminationByHandler){TEST_TERMINATION(0,"[null]");TEST_TERMINATION(1,"[true]");TEST_TERMINATION(1,"[false]");TEST_TERMINATION(2,"[-1]");TEST_TERMINATION(3,"[2147483648]");TEST_TERMINATION(4,"[-1234567890123456789]");TEST_TERMINATION(5,"[9223372036854775808]");TEST_TERMINATION(6,"[0.5]");// RawNumber() is never calledTEST_TERMINATION(8,"[\"a\"]");TEST_TERMINATION(9,"[{}]");TEST_TERMINATION(10,"[{\"a\":1}]");TEST_TERMINATION(11,"[{}]");TEST_TERMINATION(12,"{\"a\":[]}");TEST_TERMINATION(13,"{\"a\":[]}");}structValueIntComparer{booloperator()(constValue&lhs,constValue&rhs)const{returnlhs.GetInt()<rhs.GetInt();}};#if RAPIDJSON_HAS_CXX11_RVALUE_REFSTEST(Value,Sorting){Value::AllocatorTypeallocator;Valuea(kArrayType);a.PushBack(5,allocator);a.PushBack(1,allocator);a.PushBack(3,allocator);std::sort(a.Begin(),a.End(),ValueIntComparer());EXPECT_EQ(1,a[0].GetInt());EXPECT_EQ(3,a[1].GetInt());EXPECT_EQ(5,a[2].GetInt());}#endif// http://stackoverflow.com/questions/35222230/staticvoidMergeDuplicateKey(Value&v,Value::AllocatorType&a){if(v.IsObject()){// Convert all key:value into key:[value]for(Value::MemberIteratoritr=v.MemberBegin();itr!=v.MemberEnd();++itr)itr->value=Value(kArrayType).Move().PushBack(itr->value,a);// Merge arrays if key is duplicatedfor(Value::MemberIteratoritr=v.MemberBegin();itr!=v.MemberEnd();){Value::MemberIteratoritr2=v.FindMember(itr->name);if(itr!=itr2){itr2->value.PushBack(itr->value[0],a);itr=v.EraseMember(itr);}else++itr;}// Convert key:[values] back to key:value if there is only one valuefor(Value::MemberIteratoritr=v.MemberBegin();itr!=v.MemberEnd();++itr){if(itr->value.Size()==1)itr->value=itr->value[0];MergeDuplicateKey(itr->value,a);// Recursion on the value}}elseif(v.IsArray())for(Value::ValueIteratoritr=v.Begin();itr!=v.End();++itr)MergeDuplicateKey(*itr,a);}TEST(Value,MergeDuplicateKey){Documentd;d.Parse("{"" \"key1\": {"" \"a\": \"asdf\","" \"b\": \"foo\","" \"b\": \"bar\","" \"c\": \"fdas\""" }""}");Documentd2;d2.Parse("{"" \"key1\": {"" \"a\": \"asdf\","" \"b\": ["" \"foo\","" \"bar\""" ],"" \"c\": \"fdas\""" }""}");EXPECT_NE(d2,d);MergeDuplicateKey(d,d.GetAllocator());EXPECT_EQ(d2,d);}#ifdef __clang__RAPIDJSON_DIAG_POP#endif