valuetest.cpp (rapidjson-1.0.2) | : | valuetest.cpp (rapidjson-1.1.0) | ||
---|---|---|---|---|
skipping to change at line 19 | skipping to change at line 19 | |||
// | // | |||
// Unless required by applicable law or agreed to in writing, software distribut ed | // Unless required by applicable law or agreed to in writing, software distribut ed | |||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR | // 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 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the | |||
// specific language governing permissions and limitations under the License. | // specific language governing permissions and limitations under the License. | |||
#include "unittest.h" | #include "unittest.h" | |||
#include "rapidjson/document.h" | #include "rapidjson/document.h" | |||
#include <algorithm> | #include <algorithm> | |||
#ifdef __clang__ | ||||
RAPIDJSON_DIAG_PUSH | ||||
RAPIDJSON_DIAG_OFF(c++98-compat) | ||||
#endif | ||||
using namespace rapidjson; | using namespace rapidjson; | |||
TEST(Value, Size) { | ||||
if (sizeof(SizeType) == 4) { | ||||
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION | ||||
EXPECT_EQ(16, sizeof(Value)); | ||||
#elif RAPIDJSON_64BIT | ||||
EXPECT_EQ(24, sizeof(Value)); | ||||
#else | ||||
EXPECT_EQ(16, sizeof(Value)); | ||||
#endif | ||||
} | ||||
} | ||||
TEST(Value, DefaultConstructor) { | 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()); | |||
//std::cout << "sizeof(Value): " << sizeof(x) << std::endl; | //std::cout << "sizeof(Value): " << sizeof(x) << std::endl; | |||
} | } | |||
// Should not pass compilation | // Should not pass compilation | |||
//TEST(Value, copy_constructor) { | //TEST(Value, copy_constructor) { | |||
// Value x(1234); | // Value x(1234); | |||
// Value y = x; | // Value y = x; | |||
//} | //} | |||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | |||
#if 0 // Many old compiler does not support these. Turn it off temporaily. | ||||
#include <type_traits> | #include <type_traits> | |||
TEST(Value, Traits) { | TEST(Value, Traits) { | |||
typedef GenericValue<UTF8<>, CrtAllocator> Value; | typedef GenericValue<UTF8<>, CrtAllocator> Value; | |||
static_assert(std::is_constructible<Value>::value, ""); | static_assert(std::is_constructible<Value>::value, ""); | |||
static_assert(std::is_default_constructible<Value>::value, ""); | static_assert(std::is_default_constructible<Value>::value, ""); | |||
#ifndef _MSC_VER | #ifndef _MSC_VER | |||
static_assert(!std::is_copy_constructible<Value>::value, ""); | static_assert(!std::is_copy_constructible<Value>::value, ""); | |||
#endif | #endif | |||
static_assert(std::is_move_constructible<Value>::value, ""); | static_assert(std::is_move_constructible<Value>::value, ""); | |||
skipping to change at line 75 | skipping to change at line 94 | |||
#ifndef _MSC_VER | #ifndef _MSC_VER | |||
static_assert(std::is_nothrow_move_assignable<Value>::value, ""); | static_assert(std::is_nothrow_move_assignable<Value>::value, ""); | |||
#endif | #endif | |||
static_assert(std::is_destructible<Value>::value, ""); | static_assert(std::is_destructible<Value>::value, ""); | |||
#ifndef _MSC_VER | #ifndef _MSC_VER | |||
static_assert(std::is_nothrow_destructible<Value>::value, ""); | static_assert(std::is_nothrow_destructible<Value>::value, ""); | |||
#endif | #endif | |||
} | } | |||
#endif | ||||
TEST(Value, MoveConstructor) { | TEST(Value, MoveConstructor) { | |||
typedef GenericValue<UTF8<>, CrtAllocator> Value; | typedef GenericValue<UTF8<>, CrtAllocator> V; | |||
Value::AllocatorType allocator; | V::AllocatorType allocator; | |||
Value x((Value(kArrayType))); | V x((V(kArrayType))); | |||
x.Reserve(4u, allocator); | x.Reserve(4u, allocator); | |||
x.PushBack(1, allocator).PushBack(2, allocator).PushBack(3, allocator).PushB ack(4, allocator); | x.PushBack(1, allocator).PushBack(2, allocator).PushBack(3, allocator).PushB ack(4, allocator); | |||
EXPECT_TRUE(x.IsArray()); | EXPECT_TRUE(x.IsArray()); | |||
EXPECT_EQ(4u, x.Size()); | EXPECT_EQ(4u, x.Size()); | |||
// Value y(x); // does not compile (!is_copy_constructible) | // Value y(x); // does not compile (!is_copy_constructible) | |||
Value y(std::move(x)); | V y(std::move(x)); | |||
EXPECT_TRUE(x.IsNull()); | EXPECT_TRUE(x.IsNull()); | |||
EXPECT_TRUE(y.IsArray()); | EXPECT_TRUE(y.IsArray()); | |||
EXPECT_EQ(4u, y.Size()); | EXPECT_EQ(4u, y.Size()); | |||
// Value z = y; // does not compile (!is_copy_assignable) | // Value z = y; // does not compile (!is_copy_assignable) | |||
Value z = std::move(y); | V z = std::move(y); | |||
EXPECT_TRUE(y.IsNull()); | EXPECT_TRUE(y.IsNull()); | |||
EXPECT_TRUE(z.IsArray()); | EXPECT_TRUE(z.IsArray()); | |||
EXPECT_EQ(4u, z.Size()); | EXPECT_EQ(4u, z.Size()); | |||
} | } | |||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS | #endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS | |||
TEST(Value, AssignmentOperator) { | TEST(Value, AssignmentOperator) { | |||
Value x(1234); | Value x(1234); | |||
Value y; | Value y; | |||
skipping to change at line 274 | skipping to change at line 295 | |||
} | } | |||
TEST(Value, Swap) { | TEST(Value, Swap) { | |||
Value v1(1234); | Value v1(1234); | |||
Value v2(kObjectType); | Value v2(kObjectType); | |||
EXPECT_EQ(&v1, &v1.Swap(v2)); | EXPECT_EQ(&v1, &v1.Swap(v2)); | |||
EXPECT_TRUE(v1.IsObject()); | EXPECT_TRUE(v1.IsObject()); | |||
EXPECT_TRUE(v2.IsInt()); | EXPECT_TRUE(v2.IsInt()); | |||
EXPECT_EQ(1234, v2.GetInt()); | EXPECT_EQ(1234, v2.GetInt()); | |||
// testing std::swap compatibility | ||||
using std::swap; | ||||
swap(v1, v2); | ||||
EXPECT_TRUE(v1.IsInt()); | ||||
EXPECT_TRUE(v2.IsObject()); | ||||
} | } | |||
TEST(Value, Null) { | TEST(Value, Null) { | |||
// Default constructor | // Default constructor | |||
Value x; | Value x; | |||
EXPECT_EQ(kNullType, x.GetType()); | EXPECT_EQ(kNullType, x.GetType()); | |||
EXPECT_TRUE(x.IsNull()); | EXPECT_TRUE(x.IsNull()); | |||
EXPECT_FALSE(x.IsTrue()); | EXPECT_FALSE(x.IsTrue()); | |||
EXPECT_FALSE(x.IsFalse()); | EXPECT_FALSE(x.IsFalse()); | |||
skipping to change at line 322 | skipping to change at line 349 | |||
EXPECT_FALSE(x.IsArray()); | EXPECT_FALSE(x.IsArray()); | |||
// Constructor with type | // Constructor with type | |||
Value y(kTrueType); | Value y(kTrueType); | |||
EXPECT_TRUE(y.IsTrue()); | EXPECT_TRUE(y.IsTrue()); | |||
// SetBool() | // SetBool() | |||
Value z; | Value z; | |||
z.SetBool(true); | z.SetBool(true); | |||
EXPECT_TRUE(z.IsTrue()); | EXPECT_TRUE(z.IsTrue()); | |||
// Templated functions | ||||
EXPECT_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) { | TEST(Value, False) { | |||
// Constructor with bool | // Constructor with bool | |||
Value x(false); | Value x(false); | |||
EXPECT_EQ(kFalseType, x.GetType()); | EXPECT_EQ(kFalseType, x.GetType()); | |||
EXPECT_TRUE(x.IsBool()); | EXPECT_TRUE(x.IsBool()); | |||
EXPECT_TRUE(x.IsFalse()); | EXPECT_TRUE(x.IsFalse()); | |||
EXPECT_FALSE(x.IsNull()); | EXPECT_FALSE(x.IsNull()); | |||
skipping to change at line 371 | skipping to change at line 404 | |||
//EXPECT_EQ(1234, (int64_t)x); | //EXPECT_EQ(1234, (int64_t)x); | |||
//EXPECT_EQ(1234, (uint64_t)x); | //EXPECT_EQ(1234, (uint64_t)x); | |||
//EXPECT_EQ(1234, (double)x); | //EXPECT_EQ(1234, (double)x); | |||
EXPECT_TRUE(x.IsNumber()); | EXPECT_TRUE(x.IsNumber()); | |||
EXPECT_TRUE(x.IsInt()); | EXPECT_TRUE(x.IsInt()); | |||
EXPECT_TRUE(x.IsUint()); | EXPECT_TRUE(x.IsUint()); | |||
EXPECT_TRUE(x.IsInt64()); | EXPECT_TRUE(x.IsInt64()); | |||
EXPECT_TRUE(x.IsUint64()); | EXPECT_TRUE(x.IsUint64()); | |||
EXPECT_FALSE(x.IsDouble()); | EXPECT_FALSE(x.IsDouble()); | |||
EXPECT_FALSE(x.IsFloat()); | ||||
EXPECT_FALSE(x.IsNull()); | EXPECT_FALSE(x.IsNull()); | |||
EXPECT_FALSE(x.IsBool()); | EXPECT_FALSE(x.IsBool()); | |||
EXPECT_FALSE(x.IsFalse()); | EXPECT_FALSE(x.IsFalse()); | |||
EXPECT_FALSE(x.IsTrue()); | EXPECT_FALSE(x.IsTrue()); | |||
EXPECT_FALSE(x.IsString()); | EXPECT_FALSE(x.IsString()); | |||
EXPECT_FALSE(x.IsObject()); | EXPECT_FALSE(x.IsObject()); | |||
EXPECT_FALSE(x.IsArray()); | EXPECT_FALSE(x.IsArray()); | |||
Value nx(-1234); | Value nx(-1234); | |||
EXPECT_EQ(-1234, nx.GetInt()); | EXPECT_EQ(-1234, nx.GetInt()); | |||
skipping to change at line 401 | skipping to change at line 435 | |||
EXPECT_EQ(0, y.GetInt()); | EXPECT_EQ(0, y.GetInt()); | |||
// SetInt() | // SetInt() | |||
Value z; | Value z; | |||
z.SetInt(1234); | z.SetInt(1234); | |||
EXPECT_EQ(1234, z.GetInt()); | EXPECT_EQ(1234, z.GetInt()); | |||
// operator=(int) | // operator=(int) | |||
z = 5678; | z = 5678; | |||
EXPECT_EQ(5678, z.GetInt()); | EXPECT_EQ(5678, z.GetInt()); | |||
// Templated functions | ||||
EXPECT_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) { | TEST(Value, Uint) { | |||
// Constructor with int | // Constructor with int | |||
Value x(1234u); | Value x(1234u); | |||
EXPECT_EQ(kNumberType, x.GetType()); | EXPECT_EQ(kNumberType, x.GetType()); | |||
EXPECT_EQ(1234, x.GetInt()); | EXPECT_EQ(1234, x.GetInt()); | |||
EXPECT_EQ(1234u, x.GetUint()); | EXPECT_EQ(1234u, x.GetUint()); | |||
EXPECT_EQ(1234, x.GetInt64()); | EXPECT_EQ(1234, x.GetInt64()); | |||
EXPECT_EQ(1234u, x.GetUint64()); | EXPECT_EQ(1234u, x.GetUint64()); | |||
EXPECT_TRUE(x.IsNumber()); | EXPECT_TRUE(x.IsNumber()); | |||
EXPECT_TRUE(x.IsInt()); | EXPECT_TRUE(x.IsInt()); | |||
EXPECT_TRUE(x.IsUint()); | EXPECT_TRUE(x.IsUint()); | |||
EXPECT_TRUE(x.IsInt64()); | EXPECT_TRUE(x.IsInt64()); | |||
EXPECT_TRUE(x.IsUint64()); | EXPECT_TRUE(x.IsUint64()); | |||
EXPECT_NEAR(1234.0, x.GetDouble(), 0.0); // Number can always be cast as d ouble but !IsDouble(). | EXPECT_NEAR(1234.0, x.GetDouble(), 0.0); // Number can always be cast as d ouble but !IsDouble(). | |||
EXPECT_FALSE(x.IsDouble()); | EXPECT_FALSE(x.IsDouble()); | |||
EXPECT_FALSE(x.IsFloat()); | ||||
EXPECT_FALSE(x.IsNull()); | EXPECT_FALSE(x.IsNull()); | |||
EXPECT_FALSE(x.IsBool()); | EXPECT_FALSE(x.IsBool()); | |||
EXPECT_FALSE(x.IsFalse()); | EXPECT_FALSE(x.IsFalse()); | |||
EXPECT_FALSE(x.IsTrue()); | EXPECT_FALSE(x.IsTrue()); | |||
EXPECT_FALSE(x.IsString()); | EXPECT_FALSE(x.IsString()); | |||
EXPECT_FALSE(x.IsObject()); | EXPECT_FALSE(x.IsObject()); | |||
EXPECT_FALSE(x.IsArray()); | EXPECT_FALSE(x.IsArray()); | |||
// SetUint() | // SetUint() | |||
Value z; | Value z; | |||
skipping to change at line 440 | skipping to change at line 481 | |||
EXPECT_EQ(1234u, z.GetUint()); | EXPECT_EQ(1234u, z.GetUint()); | |||
// operator=(unsigned) | // operator=(unsigned) | |||
z = 5678u; | z = 5678u; | |||
EXPECT_EQ(5678u, z.GetUint()); | EXPECT_EQ(5678u, z.GetUint()); | |||
z = 2147483648u; // 2^31, cannot cast as int | z = 2147483648u; // 2^31, cannot cast as int | |||
EXPECT_EQ(2147483648u, z.GetUint()); | EXPECT_EQ(2147483648u, z.GetUint()); | |||
EXPECT_FALSE(z.IsInt()); | EXPECT_FALSE(z.IsInt()); | |||
EXPECT_TRUE(z.IsInt64()); // Issue 41: Incorrect parsing of unsigned int n umber types | EXPECT_TRUE(z.IsInt64()); // Issue 41: Incorrect parsing of unsigned int n umber types | |||
// Templated functions | ||||
EXPECT_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) { | TEST(Value, Int64) { | |||
// Constructor with int | // Constructor with int | |||
Value x(int64_t(1234LL)); | Value x(int64_t(1234)); | |||
EXPECT_EQ(kNumberType, x.GetType()); | EXPECT_EQ(kNumberType, x.GetType()); | |||
EXPECT_EQ(1234, x.GetInt()); | EXPECT_EQ(1234, x.GetInt()); | |||
EXPECT_EQ(1234u, x.GetUint()); | EXPECT_EQ(1234u, x.GetUint()); | |||
EXPECT_EQ(1234, x.GetInt64()); | EXPECT_EQ(1234, x.GetInt64()); | |||
EXPECT_EQ(1234u, x.GetUint64()); | EXPECT_EQ(1234u, x.GetUint64()); | |||
EXPECT_TRUE(x.IsNumber()); | EXPECT_TRUE(x.IsNumber()); | |||
EXPECT_TRUE(x.IsInt()); | EXPECT_TRUE(x.IsInt()); | |||
EXPECT_TRUE(x.IsUint()); | EXPECT_TRUE(x.IsUint()); | |||
EXPECT_TRUE(x.IsInt64()); | EXPECT_TRUE(x.IsInt64()); | |||
EXPECT_TRUE(x.IsUint64()); | EXPECT_TRUE(x.IsUint64()); | |||
EXPECT_FALSE(x.IsDouble()); | EXPECT_FALSE(x.IsDouble()); | |||
EXPECT_FALSE(x.IsFloat()); | ||||
EXPECT_FALSE(x.IsNull()); | EXPECT_FALSE(x.IsNull()); | |||
EXPECT_FALSE(x.IsBool()); | EXPECT_FALSE(x.IsBool()); | |||
EXPECT_FALSE(x.IsFalse()); | EXPECT_FALSE(x.IsFalse()); | |||
EXPECT_FALSE(x.IsTrue()); | EXPECT_FALSE(x.IsTrue()); | |||
EXPECT_FALSE(x.IsString()); | EXPECT_FALSE(x.IsString()); | |||
EXPECT_FALSE(x.IsObject()); | EXPECT_FALSE(x.IsObject()); | |||
EXPECT_FALSE(x.IsArray()); | EXPECT_FALSE(x.IsArray()); | |||
Value nx(int64_t(-1234LL)); | Value nx(int64_t(-1234)); | |||
EXPECT_EQ(-1234, nx.GetInt()); | EXPECT_EQ(-1234, nx.GetInt()); | |||
EXPECT_EQ(-1234, nx.GetInt64()); | EXPECT_EQ(-1234, nx.GetInt64()); | |||
EXPECT_TRUE(nx.IsInt()); | EXPECT_TRUE(nx.IsInt()); | |||
EXPECT_TRUE(nx.IsInt64()); | EXPECT_TRUE(nx.IsInt64()); | |||
EXPECT_FALSE(nx.IsUint()); | EXPECT_FALSE(nx.IsUint()); | |||
EXPECT_FALSE(nx.IsUint64()); | EXPECT_FALSE(nx.IsUint64()); | |||
// SetInt64() | // SetInt64() | |||
Value z; | Value z; | |||
z.SetInt64(1234); | z.SetInt64(1234); | |||
EXPECT_EQ(1234, z.GetInt64()); | EXPECT_EQ(1234, z.GetInt64()); | |||
z.SetInt64(2147483648LL); // 2^31, cannot cast as int | z.SetInt64(2147483648u); // 2^31, cannot cast as int | |||
EXPECT_FALSE(z.IsInt()); | EXPECT_FALSE(z.IsInt()); | |||
EXPECT_TRUE(z.IsUint()); | EXPECT_TRUE(z.IsUint()); | |||
EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0); | EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0); | |||
z.SetInt64(4294967296LL); // 2^32, cannot cast as uint | z.SetInt64(int64_t(4294967295u) + 1); // 2^32, cannot cast as uint | |||
EXPECT_FALSE(z.IsInt()); | EXPECT_FALSE(z.IsInt()); | |||
EXPECT_FALSE(z.IsUint()); | EXPECT_FALSE(z.IsUint()); | |||
EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0); | EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0); | |||
z.SetInt64(-2147483649LL); // -2^31-1, cannot cast as int | z.SetInt64(-int64_t(2147483648u) - 1); // -2^31-1, cannot cast as int | |||
EXPECT_FALSE(z.IsInt()); | EXPECT_FALSE(z.IsInt()); | |||
EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0); | EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0); | |||
z.SetInt64(static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 00000000))); | int64_t i = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 00000000)); | |||
z.SetInt64(i); | ||||
EXPECT_DOUBLE_EQ(-9223372036854775808.0, z.GetDouble()); | EXPECT_DOUBLE_EQ(-9223372036854775808.0, z.GetDouble()); | |||
// Templated functions | ||||
EXPECT_TRUE(z.Is<int64_t>()); | ||||
EXPECT_EQ(i, z.Get<int64_t>()); | ||||
#if 0 // signed integer underflow is undefined behaviour | ||||
EXPECT_EQ(i - 1, z.Set(i - 1).Get<int64_t>()); | ||||
EXPECT_EQ(i - 2, z.Set<int64_t>(i - 2).Get<int64_t>()); | ||||
#endif | ||||
} | } | |||
TEST(Value, Uint64) { | TEST(Value, Uint64) { | |||
// Constructor with int | // Constructor with int | |||
Value x(uint64_t(1234LL)); | Value x(uint64_t(1234)); | |||
EXPECT_EQ(kNumberType, x.GetType()); | EXPECT_EQ(kNumberType, x.GetType()); | |||
EXPECT_EQ(1234, x.GetInt()); | EXPECT_EQ(1234, x.GetInt()); | |||
EXPECT_EQ(1234u, x.GetUint()); | EXPECT_EQ(1234u, x.GetUint()); | |||
EXPECT_EQ(1234, x.GetInt64()); | EXPECT_EQ(1234, x.GetInt64()); | |||
EXPECT_EQ(1234u, x.GetUint64()); | EXPECT_EQ(1234u, x.GetUint64()); | |||
EXPECT_TRUE(x.IsNumber()); | EXPECT_TRUE(x.IsNumber()); | |||
EXPECT_TRUE(x.IsInt()); | EXPECT_TRUE(x.IsInt()); | |||
EXPECT_TRUE(x.IsUint()); | EXPECT_TRUE(x.IsUint()); | |||
EXPECT_TRUE(x.IsInt64()); | EXPECT_TRUE(x.IsInt64()); | |||
EXPECT_TRUE(x.IsUint64()); | EXPECT_TRUE(x.IsUint64()); | |||
EXPECT_FALSE(x.IsDouble()); | EXPECT_FALSE(x.IsDouble()); | |||
EXPECT_FALSE(x.IsFloat()); | ||||
EXPECT_FALSE(x.IsNull()); | EXPECT_FALSE(x.IsNull()); | |||
EXPECT_FALSE(x.IsBool()); | EXPECT_FALSE(x.IsBool()); | |||
EXPECT_FALSE(x.IsFalse()); | EXPECT_FALSE(x.IsFalse()); | |||
EXPECT_FALSE(x.IsTrue()); | EXPECT_FALSE(x.IsTrue()); | |||
EXPECT_FALSE(x.IsString()); | EXPECT_FALSE(x.IsString()); | |||
EXPECT_FALSE(x.IsObject()); | EXPECT_FALSE(x.IsObject()); | |||
EXPECT_FALSE(x.IsArray()); | EXPECT_FALSE(x.IsArray()); | |||
// SetUint64() | // SetUint64() | |||
Value z; | Value z; | |||
z.SetUint64(1234); | z.SetUint64(1234); | |||
EXPECT_EQ(1234u, z.GetUint64()); | EXPECT_EQ(1234u, z.GetUint64()); | |||
z.SetUint64(2147483648LL); // 2^31, cannot cast as int | z.SetUint64(uint64_t(2147483648u)); // 2^31, cannot cast as int | |||
EXPECT_FALSE(z.IsInt()); | EXPECT_FALSE(z.IsInt()); | |||
EXPECT_TRUE(z.IsUint()); | EXPECT_TRUE(z.IsUint()); | |||
EXPECT_TRUE(z.IsInt64()); | EXPECT_TRUE(z.IsInt64()); | |||
z.SetUint64(4294967296LL); // 2^32, cannot cast as uint | z.SetUint64(uint64_t(4294967295u) + 1); // 2^32, cannot cast as uint | |||
EXPECT_FALSE(z.IsInt()); | EXPECT_FALSE(z.IsInt()); | |||
EXPECT_FALSE(z.IsUint()); | EXPECT_FALSE(z.IsUint()); | |||
EXPECT_TRUE(z.IsInt64()); | EXPECT_TRUE(z.IsInt64()); | |||
z.SetUint64(9223372036854775808uLL); // 2^63 cannot cast as int64 | uint64_t u = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); | |||
z.SetUint64(u); // 2^63 cannot cast as int64 | ||||
EXPECT_FALSE(z.IsInt64()); | EXPECT_FALSE(z.IsInt64()); | |||
EXPECT_EQ(9223372036854775808uLL, z.GetUint64()); // Issue 48 | EXPECT_EQ(u, z.GetUint64()); // Issue 48 | |||
EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble()); | EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble()); | |||
// Templated functions | ||||
EXPECT_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) { | TEST(Value, Double) { | |||
// Constructor with double | // Constructor with double | |||
Value x(12.34); | Value x(12.34); | |||
EXPECT_EQ(kNumberType, x.GetType()); | EXPECT_EQ(kNumberType, x.GetType()); | |||
EXPECT_NEAR(12.34, x.GetDouble(), 0.0); | EXPECT_NEAR(12.34, x.GetDouble(), 0.0); | |||
EXPECT_TRUE(x.IsNumber()); | EXPECT_TRUE(x.IsNumber()); | |||
EXPECT_TRUE(x.IsDouble()); | EXPECT_TRUE(x.IsDouble()); | |||
skipping to change at line 564 | skipping to change at line 629 | |||
EXPECT_FALSE(x.IsObject()); | EXPECT_FALSE(x.IsObject()); | |||
EXPECT_FALSE(x.IsArray()); | EXPECT_FALSE(x.IsArray()); | |||
// SetDouble() | // SetDouble() | |||
Value z; | Value z; | |||
z.SetDouble(12.34); | z.SetDouble(12.34); | |||
EXPECT_NEAR(12.34, z.GetDouble(), 0.0); | EXPECT_NEAR(12.34, z.GetDouble(), 0.0); | |||
z = 56.78; | z = 56.78; | |||
EXPECT_NEAR(56.78, z.GetDouble(), 0.0); | EXPECT_NEAR(56.78, z.GetDouble(), 0.0); | |||
// Templated functions | ||||
EXPECT_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 double | ||||
Value x(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() | ||||
Value z; | ||||
z.SetFloat(12.34f); | ||||
EXPECT_NEAR(12.34f, z.GetFloat(), 0.0f); | ||||
// Issue 573 | ||||
z.SetInt(0); | ||||
EXPECT_EQ(0.0f, z.GetFloat()); | ||||
z = 56.78f; | ||||
EXPECT_NEAR(56.78f, z.GetFloat(), 0.0f); | ||||
// Templated functions | ||||
EXPECT_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(0.0).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, 0x00 | ||||
000000))).IsLosslessDouble()); | ||||
#if !(defined(_MSC_VER) && _MSC_VER < 1800) // VC2010 has problem | ||||
EXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000, 0x00000000)).IsLosslessDou | ||||
ble()); | ||||
#endif | ||||
EXPECT_FALSE(Value(static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFF | ||||
FFFFFF))).IsLosslessDouble()); // INT64_MAX | ||||
EXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xF | ||||
FFFFFFF))).IsLosslessDouble()); // -INT64_MAX | ||||
EXPECT_TRUE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFF | ||||
FFFFFF)) - 1).IsLosslessDouble()); // INT64_MIN | ||||
EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDo | ||||
uble()); // UINT64_MAX | ||||
EXPECT_TRUE(Value(3.4028234e38f).IsLosslessDouble()); // FLT_MAX | ||||
EXPECT_TRUE(Value(-3.4028234e38f).IsLosslessDouble()); // -FLT_MAX | ||||
EXPECT_TRUE(Value(1.17549435e-38f).IsLosslessDouble()); // FLT_MIN | ||||
EXPECT_TRUE(Value(-1.17549435e-38f).IsLosslessDouble()); // -FLT_MIN | ||||
EXPECT_TRUE(Value(1.7976931348623157e+308).IsLosslessDouble()); // DBL_MAX | ||||
EXPECT_TRUE(Value(-1.7976931348623157e+308).IsLosslessDouble()); // -DBL_MAX | ||||
EXPECT_TRUE(Value(2.2250738585072014e-308).IsLosslessDouble()); // DBL_MIN | ||||
EXPECT_TRUE(Value(-2.2250738585072014e-308).IsLosslessDouble()); // -DBL_MIN | ||||
} | ||||
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) { | TEST(Value, String) { | |||
// Construction with const string | // Construction with const string | |||
Value x("Hello", 5); // literal | Value x("Hello", 5); // literal | |||
EXPECT_EQ(kStringType, x.GetType()); | EXPECT_EQ(kStringType, x.GetType()); | |||
EXPECT_TRUE(x.IsString()); | EXPECT_TRUE(x.IsString()); | |||
EXPECT_STREQ("Hello", x.GetString()); | EXPECT_STREQ("Hello", x.GetString()); | |||
EXPECT_EQ(5u, x.GetStringLength()); | EXPECT_EQ(5u, x.GetStringLength()); | |||
skipping to change at line 658 | skipping to change at line 801 | |||
EXPECT_TRUE(z.IsString()); | EXPECT_TRUE(z.IsString()); | |||
EXPECT_EQ(cstr, z.GetString()); | EXPECT_EQ(cstr, z.GetString()); | |||
z = cstr; | z = cstr; | |||
EXPECT_TRUE(z.IsString()); | EXPECT_TRUE(z.IsString()); | |||
EXPECT_EQ(cstr, z.GetString()); | EXPECT_EQ(cstr, z.GetString()); | |||
// SetString() | // SetString() | |||
char s[] = "World"; | char s[] = "World"; | |||
Value w; | Value w; | |||
w.SetString(s, (SizeType)strlen(s), allocator); | w.SetString(s, static_cast<SizeType>(strlen(s)), allocator); | |||
s[0] = '\0'; | s[0] = '\0'; | |||
EXPECT_STREQ("World", w.GetString()); | EXPECT_STREQ("World", w.GetString()); | |||
EXPECT_EQ(5u, w.GetStringLength()); | EXPECT_EQ(5u, w.GetStringLength()); | |||
// templated functions | ||||
EXPECT_TRUE(z.Is<const char*>()); | ||||
EXPECT_STREQ(cstr, z.Get<const char*>()); | ||||
EXPECT_STREQ("Apple", z.Set<const char*>("Apple").Get<const char*>()); | ||||
#if RAPIDJSON_HAS_STDSTRING | #if RAPIDJSON_HAS_STDSTRING | |||
{ | { | |||
std::string str = "Hello World"; | std::string str = "Hello World"; | |||
str[5] = '\0'; | str[5] = '\0'; | |||
EXPECT_STREQ(str.data(),"Hello"); // embedded '\0' | EXPECT_STREQ(str.data(),"Hello"); // embedded '\0' | |||
EXPECT_EQ(str.size(), 11u); | EXPECT_EQ(str.size(), 11u); | |||
// no copy | // no copy | |||
Value vs0(StringRef(str)); | Value vs0(StringRef(str)); | |||
EXPECT_TRUE(vs0.IsString()); | EXPECT_TRUE(vs0.IsString()); | |||
skipping to change at line 698 | skipping to change at line 846 | |||
EXPECT_TRUE(vs0.IsString()); | EXPECT_TRUE(vs0.IsString()); | |||
EXPECT_STREQ(vs0.GetString(), str.c_str()); | EXPECT_STREQ(vs0.GetString(), str.c_str()); | |||
EXPECT_EQ(vs0.GetStringLength(), str.size()); | EXPECT_EQ(vs0.GetStringLength(), str.size()); | |||
TestEqual(str, vs0); | TestEqual(str, vs0); | |||
TestUnequal(str, vs1); | TestUnequal(str, vs1); | |||
// vs1 = str; // should not compile | // vs1 = str; // should not compile | |||
vs1 = StringRef(str); | vs1 = StringRef(str); | |||
TestEqual(str, vs1); | TestEqual(str, vs1); | |||
TestEqual(vs0, 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 | #endif // RAPIDJSON_HAS_STDSTRING | |||
} | } | |||
// Issue 226: Value of string type should not point to NULL | // Issue 226: Value of string type should not point to NULL | |||
TEST(Value, SetStringNullException) { | TEST(Value, SetStringNullException) { | |||
Value v; | Value v; | |||
EXPECT_THROW(v.SetString(0, 0), AssertException); | EXPECT_THROW(v.SetString(0, 0), AssertException); | |||
} | } | |||
TEST(Value, Array) { | template <typename T, typename Allocator> | |||
Value x(kArrayType); | static void TestArray(T& x, Allocator& allocator) { | |||
const Value& y = x; | const T& y = x; | |||
Value::AllocatorType allocator; | ||||
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()); | ||||
// PushBack() | // PushBack() | |||
Value v; | Value v; | |||
x.PushBack(v, allocator); | x.PushBack(v, allocator); | |||
v.SetBool(true); | v.SetBool(true); | |||
x.PushBack(v, allocator); | x.PushBack(v, allocator); | |||
v.SetBool(false); | v.SetBool(false); | |||
x.PushBack(v, allocator); | x.PushBack(v, allocator); | |||
v.SetInt(123); | v.SetInt(123); | |||
x.PushBack(v, allocator); | x.PushBack(v, allocator); | |||
skipping to change at line 760 | skipping to change at line 900 | |||
EXPECT_TRUE(y[1].IsTrue()); | EXPECT_TRUE(y[1].IsTrue()); | |||
EXPECT_TRUE(y[2].IsFalse()); | EXPECT_TRUE(y[2].IsFalse()); | |||
EXPECT_TRUE(y[3].IsInt()); | EXPECT_TRUE(y[3].IsInt()); | |||
EXPECT_EQ(123, y[3].GetInt()); | EXPECT_EQ(123, y[3].GetInt()); | |||
EXPECT_TRUE(y[4].IsString()); | EXPECT_TRUE(y[4].IsString()); | |||
EXPECT_STREQ("foo", y[4].GetString()); | EXPECT_STREQ("foo", y[4].GetString()); | |||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS | #if RAPIDJSON_HAS_CXX11_RVALUE_REFS | |||
// PushBack(GenericValue&&, Allocator&); | // PushBack(GenericValue&&, Allocator&); | |||
{ | { | |||
Value y(kArrayType); | Value y2(kArrayType); | |||
y.PushBack(Value(true), allocator); | y2.PushBack(Value(true), allocator); | |||
y.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).Pus | y2.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).Pu | |||
hBack("foo", allocator)), allocator); | shBack("foo", allocator)), allocator); | |||
EXPECT_EQ(2u, y.Size()); | EXPECT_EQ(2u, y2.Size()); | |||
EXPECT_TRUE(y[0].IsTrue()); | EXPECT_TRUE(y2[0].IsTrue()); | |||
EXPECT_TRUE(y[1].IsArray()); | EXPECT_TRUE(y2[1].IsArray()); | |||
EXPECT_EQ(2u, y[1].Size()); | EXPECT_EQ(2u, y2[1].Size()); | |||
EXPECT_TRUE(y[1][0].IsInt()); | EXPECT_TRUE(y2[1][0].IsInt()); | |||
EXPECT_TRUE(y[1][1].IsString()); | EXPECT_TRUE(y2[1][1].IsString()); | |||
} | } | |||
#endif | #endif | |||
// iterator | // iterator | |||
Value::ValueIterator itr = x.Begin(); | typename T::ValueIterator itr = x.Begin(); | |||
EXPECT_TRUE(itr != x.End()); | EXPECT_TRUE(itr != x.End()); | |||
EXPECT_TRUE(itr->IsNull()); | EXPECT_TRUE(itr->IsNull()); | |||
++itr; | ++itr; | |||
EXPECT_TRUE(itr != x.End()); | EXPECT_TRUE(itr != x.End()); | |||
EXPECT_TRUE(itr->IsTrue()); | EXPECT_TRUE(itr->IsTrue()); | |||
++itr; | ++itr; | |||
EXPECT_TRUE(itr != x.End()); | EXPECT_TRUE(itr != x.End()); | |||
EXPECT_TRUE(itr->IsFalse()); | EXPECT_TRUE(itr->IsFalse()); | |||
++itr; | ++itr; | |||
EXPECT_TRUE(itr != x.End()); | EXPECT_TRUE(itr != x.End()); | |||
EXPECT_TRUE(itr->IsInt()); | EXPECT_TRUE(itr->IsInt()); | |||
EXPECT_EQ(123, itr->GetInt()); | EXPECT_EQ(123, itr->GetInt()); | |||
++itr; | ++itr; | |||
EXPECT_TRUE(itr != x.End()); | EXPECT_TRUE(itr != x.End()); | |||
EXPECT_TRUE(itr->IsString()); | EXPECT_TRUE(itr->IsString()); | |||
EXPECT_STREQ("foo", itr->GetString()); | EXPECT_STREQ("foo", itr->GetString()); | |||
// const iterator | // const iterator | |||
Value::ConstValueIterator citr = y.Begin(); | typename T::ConstValueIterator citr = y.Begin(); | |||
EXPECT_TRUE(citr != y.End()); | EXPECT_TRUE(citr != y.End()); | |||
EXPECT_TRUE(citr->IsNull()); | EXPECT_TRUE(citr->IsNull()); | |||
++citr; | ++citr; | |||
EXPECT_TRUE(citr != y.End()); | EXPECT_TRUE(citr != y.End()); | |||
EXPECT_TRUE(citr->IsTrue()); | EXPECT_TRUE(citr->IsTrue()); | |||
++citr; | ++citr; | |||
EXPECT_TRUE(citr != y.End()); | EXPECT_TRUE(citr != y.End()); | |||
EXPECT_TRUE(citr->IsFalse()); | EXPECT_TRUE(citr->IsFalse()); | |||
++citr; | ++citr; | |||
EXPECT_TRUE(citr != y.End()); | EXPECT_TRUE(citr != y.End()); | |||
skipping to change at line 837 | skipping to change at line 977 | |||
// Use array of array to ensure removed elements' destructor is called. | // Use array of array to ensure removed elements' destructor is called. | |||
// [[0],[1],[2],...] | // [[0],[1],[2],...] | |||
for (int i = 0; i < 10; i++) | for (int i = 0; i < 10; i++) | |||
x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allocator); | x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allocator); | |||
// Erase the first | // Erase the first | |||
itr = x.Erase(x.Begin()); | itr = x.Erase(x.Begin()); | |||
EXPECT_EQ(x.Begin(), itr); | EXPECT_EQ(x.Begin(), itr); | |||
EXPECT_EQ(9u, x.Size()); | EXPECT_EQ(9u, x.Size()); | |||
for (int i = 0; i < 9; i++) | for (int i = 0; i < 9; i++) | |||
EXPECT_EQ(i + 1, x[i][0].GetInt()); | EXPECT_EQ(i + 1, x[static_cast<SizeType>(i)][0].GetInt()); | |||
// Ease the last | // Ease the last | |||
itr = x.Erase(x.End() - 1); | itr = x.Erase(x.End() - 1); | |||
EXPECT_EQ(x.End(), itr); | EXPECT_EQ(x.End(), itr); | |||
EXPECT_EQ(8u, x.Size()); | EXPECT_EQ(8u, x.Size()); | |||
for (int i = 0; i < 8; i++) | for (int i = 0; i < 8; i++) | |||
EXPECT_EQ(i + 1, x[i][0].GetInt()); | EXPECT_EQ(i + 1, x[static_cast<SizeType>(i)][0].GetInt()); | |||
// Erase the middle | // Erase the middle | |||
itr = x.Erase(x.Begin() + 4); | itr = x.Erase(x.Begin() + 4); | |||
EXPECT_EQ(x.Begin() + 4, itr); | EXPECT_EQ(x.Begin() + 4, itr); | |||
EXPECT_EQ(7u, x.Size()); | EXPECT_EQ(7u, x.Size()); | |||
for (int i = 0; i < 4; i++) | for (int i = 0; i < 4; i++) | |||
EXPECT_EQ(i + 1, x[i][0].GetInt()); | EXPECT_EQ(i + 1, x[static_cast<SizeType>(i)][0].GetInt()); | |||
for (int i = 4; i < 7; i++) | for (int i = 4; i < 7; i++) | |||
EXPECT_EQ(i + 2, x[i][0].GetInt()); | EXPECT_EQ(i + 2, x[static_cast<SizeType>(i)][0].GetInt()); | |||
// Erase(ValueIterator, ValueIterator) | // Erase(ValueIterator, ValueIterator) | |||
// Exhaustive test with all 0 <= first < n, first <= last <= n cases | // Exhaustive test with all 0 <= first < n, first <= last <= n cases | |||
const unsigned n = 10; | const unsigned n = 10; | |||
for (unsigned first = 0; first < n; first++) { | for (unsigned first = 0; first < n; first++) { | |||
for (unsigned last = first; last <= n; last++) { | for (unsigned last = first; last <= n; last++) { | |||
x.Clear(); | x.Clear(); | |||
for (unsigned i = 0; i < n; i++) | for (unsigned i = 0; i < n; i++) | |||
x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allo cator); | x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allo cator); | |||
skipping to change at line 875 | skipping to change at line 1015 | |||
if (last == n) | if (last == n) | |||
EXPECT_EQ(x.End(), itr); | EXPECT_EQ(x.End(), itr); | |||
else | else | |||
EXPECT_EQ(x.Begin() + first, itr); | EXPECT_EQ(x.Begin() + first, itr); | |||
size_t removeCount = last - first; | size_t removeCount = last - first; | |||
EXPECT_EQ(n - removeCount, x.Size()); | EXPECT_EQ(n - removeCount, x.Size()); | |||
for (unsigned i = 0; i < first; i++) | for (unsigned i = 0; i < first; i++) | |||
EXPECT_EQ(i, x[i][0].GetUint()); | EXPECT_EQ(i, x[i][0].GetUint()); | |||
for (unsigned i = first; i < n - removeCount; i++) | for (unsigned i = first; i < n - removeCount; i++) | |||
EXPECT_EQ(i + removeCount, x[i][0].GetUint()); | EXPECT_EQ(i + removeCount, x[static_cast<SizeType>(i)][0].GetUin t()); | |||
} | } | |||
} | } | |||
} | ||||
TEST(Value, Array) { | ||||
Value x(kArrayType); | ||||
const Value& y = x; | ||||
Value::AllocatorType allocator; | ||||
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. | // Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed. | |||
// 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++) | |||
if (i % 2 == 0) | if (i % 2 == 0) | |||
x.PushBack(i, allocator); | x.PushBack(i, allocator); | |||
else | else | |||
x.PushBack(Value(kNullType).Move(), allocator); | x.PushBack(Value(kNullType).Move(), allocator); | |||
const Value null(kNullType); | const Value null(kNullType); | |||
x.Erase(std::remove(x.Begin(), x.End(), null), x.End()); | 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[static_cast<SizeType>(i)]); | |||
// SetArray() | // SetArray() | |||
Value z; | Value z; | |||
z.SetArray(); | z.SetArray(); | |||
EXPECT_TRUE(z.IsArray()); | EXPECT_TRUE(z.IsArray()); | |||
EXPECT_TRUE(z.Empty()); | EXPECT_TRUE(z.Empty()); | |||
} | } | |||
TEST(Value, Object) { | TEST(Value, ArrayHelper) { | |||
Value x(kObjectType); | ||||
const Value& y = x; // const version | ||||
Value::AllocatorType allocator; | Value::AllocatorType allocator; | |||
{ | ||||
Value x(kArrayType); | ||||
Value::Array a = x.GetArray(); | ||||
TestArray(a, allocator); | ||||
} | ||||
EXPECT_EQ(kObjectType, x.GetType()); | { | |||
EXPECT_TRUE(x.IsObject()); | Value x(kArrayType); | |||
EXPECT_TRUE(x.ObjectEmpty()); | Value::Array a = x.GetArray(); | |||
EXPECT_EQ(0u, x.MemberCount()); | a.PushBack(1, allocator); | |||
EXPECT_EQ(kObjectType, y.GetType()); | ||||
EXPECT_TRUE(y.IsObject()); | Value::Array a2(a); // copy constructor | |||
EXPECT_TRUE(y.ObjectEmpty()); | EXPECT_EQ(1, a2.Size()); | |||
EXPECT_EQ(0u, y.MemberCount()); | ||||
Value::Array a3 = a; | ||||
EXPECT_EQ(1, a3.Size()); | ||||
Value::ConstArray y = static_cast<const Value&>(x).GetArray(); | ||||
(void)y; | ||||
// y.PushBack(1, allocator); // should not compile | ||||
// Templated functions | ||||
x.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()); | ||||
Value x2; | ||||
x2.Set<Value::Array>(a); | ||||
EXPECT_TRUE(x.IsArray()); // IsArray() is invariant after moving. | ||||
EXPECT_EQ(1, x2.Get<Value::Array>()[0].GetInt()); | ||||
} | ||||
{ | ||||
Value y(kArrayType); | ||||
y.PushBack(123, allocator); | ||||
Value x(y.GetArray()); // Construct value form array. | ||||
EXPECT_TRUE(x.IsArray()); | ||||
EXPECT_EQ(123, x[0].GetInt()); | ||||
EXPECT_TRUE(y.IsArray()); // Invariant | ||||
EXPECT_TRUE(y.Empty()); | ||||
} | ||||
{ | ||||
Value x(kArrayType); | ||||
Value y(kArrayType); | ||||
y.PushBack(123, allocator); | ||||
x.PushBack(y.GetArray(), allocator); // Implicit constructor to conve | ||||
rt Array to GenericValue | ||||
EXPECT_EQ(1, x.Size()); | ||||
EXPECT_EQ(123, x[0][0].GetInt()); | ||||
EXPECT_TRUE(y.IsArray()); | ||||
EXPECT_TRUE(y.Empty()); | ||||
} | ||||
} | ||||
#if RAPIDJSON_HAS_CXX11_RANGE_FOR | ||||
TEST(Value, ArrayHelperRangeFor) { | ||||
Value::AllocatorType allocator; | ||||
Value x(kArrayType); | ||||
for (int i = 0; i < 10; i++) | ||||
x.PushBack(i, allocator); | ||||
{ | ||||
int i = 0; | ||||
for (auto& v : x.GetArray()) { | ||||
EXPECT_EQ(i, v.GetInt()); | ||||
i++; | ||||
} | ||||
EXPECT_EQ(i, 10); | ||||
} | ||||
{ | ||||
int i = 0; | ||||
for (const auto& v : const_cast<const Value&>(x).GetArray()) { | ||||
EXPECT_EQ(i, v.GetInt()); | ||||
i++; | ||||
} | ||||
EXPECT_EQ(i, 10); | ||||
} | ||||
// Array a = x.GetArray(); | ||||
// Array ca = const_cast<const Value&>(x).GetArray(); | ||||
} | ||||
#endif | ||||
template <typename T, typename Allocator> | ||||
static void TestObject(T& x, Allocator& allocator) { | ||||
const T& y = x; // const version | ||||
// AddMember() | // AddMember() | |||
x.AddMember("A", "Apple", allocator); | x.AddMember("A", "Apple", allocator); | |||
EXPECT_FALSE(x.ObjectEmpty()); | EXPECT_FALSE(x.ObjectEmpty()); | |||
EXPECT_EQ(1u, x.MemberCount()); | EXPECT_EQ(1u, x.MemberCount()); | |||
Value value("Banana", 6); | Value value("Banana", 6); | |||
x.AddMember("B", "Banana", allocator); | x.AddMember("B", "Banana", allocator); | |||
EXPECT_EQ(2u, x.MemberCount()); | EXPECT_EQ(2u, x.MemberCount()); | |||
// AddMember<T>(StringRefType, T, Allocator) | // AddMember<T>(StringRefType, T, Allocator) | |||
{ | { | |||
Value o(kObjectType); | Value o(kObjectType); | |||
o.AddMember("true", true, allocator); | o.AddMember("true", true, allocator); | |||
o.AddMember("false", false, allocator); | o.AddMember("false", false, allocator); | |||
o.AddMember("int", -1, allocator); | o.AddMember("int", -1, allocator); | |||
o.AddMember("uint", 1u, allocator); | o.AddMember("uint", 1u, allocator); | |||
o.AddMember("int64", INT64_C(-4294967296), allocator); | o.AddMember("int64", int64_t(-4294967296), allocator); | |||
o.AddMember("uint64", UINT64_C(4294967296), allocator); | o.AddMember("uint64", uint64_t(4294967296), allocator); | |||
o.AddMember("double", 3.14, allocator); | o.AddMember("double", 3.14, allocator); | |||
o.AddMember("string", "Jelly", allocator); | o.AddMember("string", "Jelly", allocator); | |||
EXPECT_TRUE(o["true"].GetBool()); | EXPECT_TRUE(o["true"].GetBool()); | |||
EXPECT_FALSE(o["false"].GetBool()); | EXPECT_FALSE(o["false"].GetBool()); | |||
EXPECT_EQ(-1, o["int"].GetInt()); | EXPECT_EQ(-1, o["int"].GetInt()); | |||
EXPECT_EQ(1u, o["uint"].GetUint()); | EXPECT_EQ(1u, o["uint"].GetUint()); | |||
EXPECT_EQ(INT64_C(-4294967296), o["int64"].GetInt64()); | EXPECT_EQ(int64_t(-4294967296), o["int64"].GetInt64()); | |||
EXPECT_EQ(UINT64_C(4294967296), o["uint64"].GetUint64()); | EXPECT_EQ(uint64_t(4294967296), o["uint64"].GetUint64()); | |||
EXPECT_STREQ("Jelly",o["string"].GetString()); | EXPECT_STREQ("Jelly",o["string"].GetString()); | |||
EXPECT_EQ(8u, o.MemberCount()); | EXPECT_EQ(8u, o.MemberCount()); | |||
} | } | |||
// AddMember<T>(Value&, T, Allocator) | // AddMember<T>(Value&, T, Allocator) | |||
{ | { | |||
Value o(kObjectType); | Value o(kObjectType); | |||
Value n("s"); | Value n("s"); | |||
o.AddMember(n, "string", allocator); | o.AddMember(n, "string", allocator); | |||
skipping to change at line 1121 | skipping to change at line 1365 | |||
// MemberCount, iterator difference | // MemberCount, iterator difference | |||
EXPECT_EQ(x.MemberCount(), SizeType(x.MemberEnd() - x.MemberBegin())); | 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(9u, x.MemberCount()); | EXPECT_EQ(9u, x.MemberCount()); | |||
for (; itr != x.MemberEnd(); ++itr) { | for (; itr != x.MemberEnd(); ++itr) { | |||
int i = (itr - x.MemberBegin()) + 1; | size_t i = static_cast<size_t>((itr - x.MemberBegin())) + 1; | |||
EXPECT_STREQ(itr->name.GetString(), keys[i]); | EXPECT_STREQ(itr->name.GetString(), keys[i]); | |||
EXPECT_EQ(i, itr->value[0].GetInt()); | EXPECT_EQ(i, itr->value[0].GetInt()); | |||
} | } | |||
// Erase the last | // Erase the last | |||
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(8u, x.MemberCount()); | EXPECT_EQ(8u, x.MemberCount()); | |||
for (; itr != x.MemberEnd(); ++itr) { | for (; itr != x.MemberEnd(); ++itr) { | |||
int i = (itr - x.MemberBegin()) + 1; | size_t i = static_cast<size_t>(itr - x.MemberBegin()) + 1; | |||
EXPECT_STREQ(itr->name.GetString(), keys[i]); | EXPECT_STREQ(itr->name.GetString(), keys[i]); | |||
EXPECT_EQ(i, itr->value[0].GetInt()); | EXPECT_EQ(i, itr->value[0].GetInt()); | |||
} | } | |||
// Erase the middle | // Erase the middle | |||
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(7u, x.MemberCount()); | EXPECT_EQ(7u, x.MemberCount()); | |||
for (; itr != x.MemberEnd(); ++itr) { | for (; itr != x.MemberEnd(); ++itr) { | |||
int i = (itr - x.MemberBegin()); | size_t i = static_cast<size_t>(itr - x.MemberBegin()); | |||
i += (i<4) ? 1 : 2; | i += (i < 4) ? 1 : 2; | |||
EXPECT_STREQ(itr->name.GetString(), keys[i]); | EXPECT_STREQ(itr->name.GetString(), keys[i]); | |||
EXPECT_EQ(i, itr->value[0].GetInt()); | EXPECT_EQ(i, itr->value[0].GetInt()); | |||
} | } | |||
// EraseMember(ConstMemberIterator, ConstMemberIterator) | // EraseMember(ConstMemberIterator, ConstMemberIterator) | |||
// Exhaustive test with all 0 <= first < n, first <= last <= n cases | // Exhaustive test with all 0 <= first < n, first <= last <= n cases | |||
const unsigned n = 10; | const unsigned n = 10; | |||
for (unsigned first = 0; first < n; first++) { | for (unsigned first = 0; first < n; first++) { | |||
for (unsigned last = first; last <= n; last++) { | for (unsigned last = first; last <= n; last++) { | |||
Value(kObjectType).Swap(x); | x.RemoveAllMembers(); | |||
for (unsigned i = 0; i < n; i++) | for (unsigned i = 0; i < n; i++) | |||
x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), a llocator); | x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), a llocator); | |||
itr = x.EraseMember(x.MemberBegin() + first, x.MemberBegin() + last) ; | itr = x.EraseMember(x.MemberBegin() + static_cast<int>(first), x.Mem berBegin() + static_cast<int>(last)); | |||
if (last == n) | if (last == n) | |||
EXPECT_EQ(x.MemberEnd(), itr); | EXPECT_EQ(x.MemberEnd(), itr); | |||
else | else | |||
EXPECT_EQ(x.MemberBegin() + first, itr); | EXPECT_EQ(x.MemberBegin() + static_cast<int>(first), itr); | |||
size_t removeCount = last - first; | size_t removeCount = last - first; | |||
EXPECT_EQ(n - removeCount, x.MemberCount()); | 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]][0].GetUint()); | EXPECT_EQ(i, x[keys[i]][0].GetUint()); | |||
for (unsigned i = first; i < n - removeCount; i++) | for (unsigned i = first; i < n - removeCount; i++) | |||
EXPECT_EQ(i + removeCount, x[keys[i+removeCount]][0].GetUint()); | EXPECT_EQ(i + removeCount, x[keys[i+removeCount]][0].GetUint()); | |||
} | } | |||
} | } | |||
// RemoveAllMembers() | // RemoveAllMembers() | |||
x.RemoveAllMembers(); | x.RemoveAllMembers(); | |||
EXPECT_TRUE(x.ObjectEmpty()); | EXPECT_TRUE(x.ObjectEmpty()); | |||
EXPECT_EQ(0u, x.MemberCount()); | EXPECT_EQ(0u, x.MemberCount()); | |||
} | ||||
TEST(Value, Object) { | ||||
Value x(kObjectType); | ||||
const Value& y = x; // const version | ||||
Value::AllocatorType allocator; | ||||
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() | // SetObject() | |||
Value z; | Value z; | |||
z.SetObject(); | z.SetObject(); | |||
EXPECT_TRUE(z.IsObject()); | EXPECT_TRUE(z.IsObject()); | |||
} | } | |||
TEST(Value, ObjectHelper) { | ||||
Value::AllocatorType allocator; | ||||
{ | ||||
Value x(kObjectType); | ||||
Value::Object o = x.GetObject(); | ||||
TestObject(o, allocator); | ||||
} | ||||
{ | ||||
Value x(kObjectType); | ||||
Value::Object o = x.GetObject(); | ||||
o.AddMember("1", 1, allocator); | ||||
Value::Object o2(o); // copy constructor | ||||
EXPECT_EQ(1, o2.MemberCount()); | ||||
Value::Object o3 = o; | ||||
EXPECT_EQ(1, o3.MemberCount()); | ||||
Value::ConstObject y = static_cast<const Value&>(x).GetObject(); | ||||
(void)y; | ||||
// y.AddMember("1", 1, allocator); // should not compile | ||||
// Templated functions | ||||
x.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()); | ||||
Value x2; | ||||
x2.Set<Value::Object>(o); | ||||
EXPECT_TRUE(x.IsObject()); // IsObject() is invariant after moving | ||||
EXPECT_EQ(1, x2.Get<Value::Object>()["1"].GetInt()); | ||||
} | ||||
{ | ||||
Value x(kObjectType); | ||||
x.AddMember("a", "apple", allocator); | ||||
Value y(x.GetObject()); | ||||
EXPECT_STREQ("apple", y["a"].GetString()); | ||||
EXPECT_TRUE(x.IsObject()); // Invariant | ||||
} | ||||
{ | ||||
Value x(kObjectType); | ||||
x.AddMember("a", "apple", allocator); | ||||
Value y(kObjectType); | ||||
y.AddMember("fruits", x.GetObject(), allocator); | ||||
EXPECT_STREQ("apple", y["fruits"]["a"].GetString()); | ||||
EXPECT_TRUE(x.IsObject()); // Invariant | ||||
} | ||||
} | ||||
#if RAPIDJSON_HAS_CXX11_RANGE_FOR | ||||
TEST(Value, ObjectHelperRangeFor) { | ||||
Value::AllocatorType allocator; | ||||
Value x(kObjectType); | ||||
for (int i = 0; i < 10; i++) { | ||||
char name[10]; | ||||
Value n(name, static_cast<SizeType>(sprintf(name, "%d", i)), allocator); | ||||
x.AddMember(n, i, allocator); | ||||
} | ||||
{ | ||||
int i = 0; | ||||
for (auto& m : x.GetObject()) { | ||||
char name[10]; | ||||
sprintf(name, "%d", i); | ||||
EXPECT_STREQ(name, m.name.GetString()); | ||||
EXPECT_EQ(i, m.value.GetInt()); | ||||
i++; | ||||
} | ||||
EXPECT_EQ(i, 10); | ||||
} | ||||
{ | ||||
int i = 0; | ||||
for (const auto& m : const_cast<const Value&>(x).GetObject()) { | ||||
char name[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(); | ||||
} | ||||
#endif | ||||
TEST(Value, EraseMember_String) { | ||||
Value::AllocatorType allocator; | ||||
Value x(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) { | TEST(Value, BigNestedArray) { | |||
MemoryPoolAllocator<> allocator; | MemoryPoolAllocator<> allocator; | |||
Value x(kArrayType); | Value x(kArrayType); | |||
static const SizeType n = 200; | static const SizeType n = 200; | |||
for (SizeType i = 0; i < n; i++) { | for (SizeType i = 0; i < n; i++) { | |||
Value y(kArrayType); | Value y(kArrayType); | |||
for (SizeType j = 0; j < n; j++) { | for (SizeType j = 0; j < n; j++) { | |||
Value number((int)(i * n + j)); | Value number(static_cast<int>(i * n + j)); | |||
y.PushBack(number, allocator); | y.PushBack(number, allocator); | |||
} | } | |||
x.PushBack(y, allocator); | x.PushBack(y, allocator); | |||
} | } | |||
for (SizeType i = 0; i < n; i++) | for (SizeType i = 0; i < n; i++) | |||
for (SizeType j = 0; j < n; j++) { | for (SizeType j = 0; j < n; j++) { | |||
EXPECT_TRUE(x[i][j].IsInt()); | EXPECT_TRUE(x[i][j].IsInt()); | |||
EXPECT_EQ((int)(i * n + j), x[i][j].GetInt()); | EXPECT_EQ(static_cast<int>(i * n + j), x[i][j].GetInt()); | |||
} | } | |||
} | } | |||
TEST(Value, BigNestedObject) { | TEST(Value, BigNestedObject) { | |||
MemoryPoolAllocator<> allocator; | MemoryPoolAllocator<> allocator; | |||
Value x(kObjectType); | Value x(kObjectType); | |||
static const SizeType n = 200; | static const SizeType n = 200; | |||
for (SizeType i = 0; i < n; i++) { | for (SizeType i = 0; i < n; i++) { | |||
char name1[10]; | char name1[10]; | |||
sprintf(name1, "%d", i); | sprintf(name1, "%d", i); | |||
// Value name(name1); // should not compile | // Value name(name1); // should not compile | |||
Value name(name1, (SizeType)strlen(name1), allocator); | Value name(name1, static_cast<SizeType>(strlen(name1)), allocator); | |||
Value object(kObjectType); | Value object(kObjectType); | |||
for (SizeType j = 0; j < n; j++) { | for (SizeType j = 0; j < n; j++) { | |||
char name2[10]; | char name2[10]; | |||
sprintf(name2, "%d", j); | sprintf(name2, "%d", j); | |||
Value name(name2, (SizeType)strlen(name2), allocator); | Value name3(name2, static_cast<SizeType>(strlen(name2)), allocator); | |||
Value number((int)(i * n + j)); | Value number(static_cast<int>(i * n + j)); | |||
object.AddMember(name, number, allocator); | object.AddMember(name3, number, allocator); | |||
} | } | |||
// x.AddMember(name1, object, allocator); // should not compile | // x.AddMember(name1, object, allocator); // should not compile | |||
x.AddMember(name, object, allocator); | x.AddMember(name, object, allocator); | |||
} | } | |||
for (SizeType i = 0; i < n; i++) { | for (SizeType i = 0; i < n; i++) { | |||
char name1[10]; | char name1[10]; | |||
sprintf(name1, "%d", i); | sprintf(name1, "%d", i); | |||
for (SizeType j = 0; j < n; j++) { | for (SizeType j = 0; j < n; j++) { | |||
char name2[10]; | char name2[10]; | |||
sprintf(name2, "%d", j); | sprintf(name2, "%d", j); | |||
x[name1]; | x[name1]; | |||
EXPECT_EQ((int)(i * n + j), x[name1][name2].GetInt()); | EXPECT_EQ(static_cast<int>(i * n + j), x[name1][name2].GetInt()); | |||
} | } | |||
} | } | |||
} | } | |||
// Issue 18: Error removing last element of object | // Issue 18: Error removing last element of object | |||
// http://code.google.com/p/rapidjson/issues/detail?id=18 | // http://code.google.com/p/rapidjson/issues/detail?id=18 | |||
TEST(Value, RemoveLastElement) { | TEST(Value, RemoveLastElement) { | |||
rapidjson::Document doc; | rapidjson::Document doc; | |||
rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); | rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); | |||
rapidjson::Value objVal(rapidjson::kObjectType); | rapidjson::Value objVal(rapidjson::kObjectType); | |||
skipping to change at line 1271 | skipping to change at line 1644 | |||
V::AllocatorType allocator; | V::AllocatorType allocator; | |||
V o(kObjectType); | V o(kObjectType); | |||
o.AddMember("x", 1, allocator); // Should not call destructor on uninitializ ed name/value of newly allocated members. | o.AddMember("x", 1, allocator); // Should not call destructor on uninitializ ed name/value of newly allocated members. | |||
V a(kArrayType); | V a(kArrayType); | |||
a.PushBack(1, allocator); // Should not call destructor on uninitialized V alue of newly allocated elements. | a.PushBack(1, allocator); // Should not call destructor on uninitialized V alue of newly allocated elements. | |||
} | } | |||
static void TestShortStringOptimization(const char* str) { | static void TestShortStringOptimization(const char* str) { | |||
const rapidjson::SizeType len = (rapidjson::SizeType)strlen(str); | const rapidjson::SizeType len = static_cast<rapidjson::SizeType>(strlen(str) ); | |||
rapidjson::Document doc; | rapidjson::Document doc; | |||
rapidjson::Value val; | rapidjson::Value val; | |||
val.SetString(str, len, doc.GetAllocator()); | val.SetString(str, len, doc.GetAllocator()); | |||
EXPECT_EQ(val.GetStringLength(), len); | EXPECT_EQ(val.GetStringLength(), len); | |||
EXPECT_STREQ(val.GetString(), str); | EXPECT_STREQ(val.GetString(), str); | |||
} | } | |||
TEST(Value, AllocateShortString) { | TEST(Value, AllocateShortString) { | |||
skipping to change at line 1299 | skipping to change at line 1672 | |||
template <int e> | template <int e> | |||
struct TerminateHandler { | struct TerminateHandler { | |||
bool Null() { return e != 0; } | bool Null() { return e != 0; } | |||
bool Bool(bool) { return e != 1; } | bool Bool(bool) { return e != 1; } | |||
bool Int(int) { return e != 2; } | bool Int(int) { return e != 2; } | |||
bool Uint(unsigned) { return e != 3; } | bool Uint(unsigned) { return e != 3; } | |||
bool Int64(int64_t) { return e != 4; } | bool Int64(int64_t) { return e != 4; } | |||
bool Uint64(uint64_t) { return e != 5; } | bool Uint64(uint64_t) { return e != 5; } | |||
bool Double(double) { return e != 6; } | bool Double(double) { return e != 6; } | |||
bool String(const char*, SizeType, bool) { return e != 7; } | bool RawNumber(const char*, SizeType, bool) { return e != 7; } | |||
bool StartObject() { return e != 8; } | bool String(const char*, SizeType, bool) { return e != 8; } | |||
bool Key(const char*, SizeType, bool) { return e != 9; } | bool StartObject() { return e != 9; } | |||
bool EndObject(SizeType) { return e != 10; } | bool Key(const char*, SizeType, bool) { return e != 10; } | |||
bool StartArray() { return e != 11; } | bool EndObject(SizeType) { return e != 11; } | |||
bool EndArray(SizeType) { return e != 12; } | bool StartArray() { return e != 12; } | |||
bool EndArray(SizeType) { return e != 13; } | ||||
}; | }; | |||
#define TEST_TERMINATION(e, json)\ | #define TEST_TERMINATION(e, json)\ | |||
{\ | {\ | |||
Document d; \ | Document d; \ | |||
EXPECT_FALSE(d.Parse(json).HasParseError()); \ | EXPECT_FALSE(d.Parse(json).HasParseError()); \ | |||
Reader reader; \ | Reader reader; \ | |||
TerminateHandler<e> h;\ | TerminateHandler<e> h;\ | |||
EXPECT_FALSE(d.Accept(h));\ | EXPECT_FALSE(d.Accept(h));\ | |||
} | } | |||
TEST(Value, AcceptTerminationByHandler) { | TEST(Value, AcceptTerminationByHandler) { | |||
TEST_TERMINATION(0, "[null]"); | TEST_TERMINATION(0, "[null]"); | |||
TEST_TERMINATION(1, "[true]"); | TEST_TERMINATION(1, "[true]"); | |||
TEST_TERMINATION(1, "[false]"); | TEST_TERMINATION(1, "[false]"); | |||
TEST_TERMINATION(2, "[-1]"); | TEST_TERMINATION(2, "[-1]"); | |||
TEST_TERMINATION(3, "[2147483648]"); | TEST_TERMINATION(3, "[2147483648]"); | |||
TEST_TERMINATION(4, "[-1234567890123456789]"); | TEST_TERMINATION(4, "[-1234567890123456789]"); | |||
TEST_TERMINATION(5, "[9223372036854775808]"); | TEST_TERMINATION(5, "[9223372036854775808]"); | |||
TEST_TERMINATION(6, "[0.5]"); | TEST_TERMINATION(6, "[0.5]"); | |||
TEST_TERMINATION(7, "[\"a\"]"); | // RawNumber() is never called | |||
TEST_TERMINATION(8, "[{}]"); | TEST_TERMINATION(8, "[\"a\"]"); | |||
TEST_TERMINATION(9, "[{\"a\":1}]"); | TEST_TERMINATION(9, "[{}]"); | |||
TEST_TERMINATION(10, "[{}]"); | TEST_TERMINATION(10, "[{\"a\":1}]"); | |||
TEST_TERMINATION(11, "{\"a\":[]}"); | TEST_TERMINATION(11, "[{}]"); | |||
TEST_TERMINATION(12, "{\"a\":[]}"); | TEST_TERMINATION(12, "{\"a\":[]}"); | |||
TEST_TERMINATION(13, "{\"a\":[]}"); | ||||
} | } | |||
struct ValueIntComparer { | ||||
bool operator()(const Value& lhs, const Value& rhs) const { | ||||
return lhs.GetInt() < rhs.GetInt(); | ||||
} | ||||
}; | ||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS | ||||
TEST(Value, Sorting) { | ||||
Value::AllocatorType allocator; | ||||
Value a(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/ | ||||
static void MergeDuplicateKey(Value& v, Value::AllocatorType& a) { | ||||
if (v.IsObject()) { | ||||
// Convert all key:value into key:[value] | ||||
for (Value::MemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); | ||||
++itr) | ||||
itr->value = Value(kArrayType).Move().PushBack(itr->value, a); | ||||
// Merge arrays if key is duplicated | ||||
for (Value::MemberIterator itr = v.MemberBegin(); itr != v.MemberEnd();) | ||||
{ | ||||
Value::MemberIterator itr2 = 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 value | ||||
for (Value::MemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); | ||||
++itr) { | ||||
if (itr->value.Size() == 1) | ||||
itr->value = itr->value[0]; | ||||
MergeDuplicateKey(itr->value, a); // Recursion on the value | ||||
} | ||||
} | ||||
else if (v.IsArray()) | ||||
for (Value::ValueIterator itr = v.Begin(); itr != v.End(); ++itr) | ||||
MergeDuplicateKey(*itr, a); | ||||
} | ||||
TEST(Value, MergeDuplicateKey) { | ||||
Document d; | ||||
d.Parse( | ||||
"{" | ||||
" \"key1\": {" | ||||
" \"a\": \"asdf\"," | ||||
" \"b\": \"foo\"," | ||||
" \"b\": \"bar\"," | ||||
" \"c\": \"fdas\"" | ||||
" }" | ||||
"}"); | ||||
Document d2; | ||||
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 | ||||
End of changes. 67 change blocks. | ||||
95 lines changed or deleted | 477 lines changed or added |