diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 027d68b..cd52b43 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -209,6 +209,11 @@ public: return *v; } + template + ValueType& Create(GenericDocument& root, bool* alreadyExist = 0) const { + return Create(root, root.GetAllocator(), alreadyExist); + } + ValueType* Get(ValueType& root) const { RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; @@ -270,6 +275,27 @@ public: return GetWithDefault(root, v, allocator); } + template + ValueType& GetWithDefault(GenericDocument& root, const ValueType& defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + + template + ValueType& GetWithDefault(GenericDocument& root, GenericStringRef defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + + template + ValueType& GetWithDefault(GenericDocument& root, const Ch* defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(GenericDocument& root, T defaultValue) const { + return GetWithDefault(root, defaultValue, root.GetAllocator()); + } + // Move semantics, create parents if non-exist ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = value; @@ -297,6 +323,35 @@ public: return Create(root, allocator) = v; } + template + ValueType& Set(GenericDocument& root, ValueType& value) const { + return Create(root) = value; + } + + template + ValueType& Set(GenericDocument& root, const ValueType& value) const { + return Create(root).CopyFrom(value, root.GetAllocator()); + } + + template + ValueType& Set(GenericDocument& root, GenericStringRef value) const { + ValueType v(value); + return Create(root) = v; + } + + template + ValueType& Set(GenericDocument& root, const Ch* value) const { + ValueType v(value, root.GetAllocator()); + return Create(root) = v; + } + + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(GenericDocument& root, T value) const { + ValueType v(value); + return Create(root) = v; + } + // Create parents if non-exist ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator).Swap(value); @@ -407,6 +462,8 @@ private: PointerParseErrorCode parseErrorCode_; }; +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { return pointer.Create(root, a); @@ -418,6 +475,21 @@ typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], return CreateValueByPointer(root, pointer, a); } +// No allocator parameter + +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Create(root); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N]) { + const GenericPointer pointer(source, N - 1); + return CreateValueByPointer(root, pointer); +} + +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer) { return pointer.Get(root); @@ -440,6 +512,8 @@ const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&so return GetValueByPointer(root, pointer); } +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { return pointer.GetWithDefault(root, defaultValue, a); @@ -486,6 +560,56 @@ GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValu return GetValueByPointerWithDefault(root, pointer, defaultValue, a); } +// No allocator parameter + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, GenericStringRef defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(root, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], GenericStringRef defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue) { + const GenericPointer pointer(source, N - 1); + return GetValueByPointerWithDefault(root, pointer, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { return pointer.Set(root, value, a); @@ -532,6 +656,56 @@ SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::All return SetValueByPointer(root, pointer, value, a); } +// No allocator parameter + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value) { + return pointer.Set(root, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, GenericStringRef value) { + return pointer.Set(root, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value) { + return pointer.Set(root, value); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value) { + return pointer.Set(root, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], GenericStringRef value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value) { + const GenericPointer pointer(source, N - 1); + return SetValueByPointer(root, pointer, value); +} + +////////////////////////////////////////////////////////////////////////////// + template typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { return pointer.Swap(root, value, a); diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index a18646a..13015ba 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -288,6 +288,18 @@ TEST(Pointer, Create) { Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator()); EXPECT_EQ(&d["foo"][2][0], v); } + + { + // Document with no allocator + Value* v = &Pointer("/foo/-").Create(d); + EXPECT_EQ(&d["foo"][3], v); + } + + { + // Value (not document) must give allocator + Value* v = &Pointer("/-").Create(d["foo"], d.GetAllocator()); + EXPECT_EQ(&d["foo"][4], v); + } } TEST(Pointer, Get) { @@ -358,6 +370,54 @@ TEST(Pointer, GetWithDefault) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, GetWithDefault_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + const Value v("qux"); + EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v)); + EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v)); + EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v)); + EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move()).IsNull()); + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1).GetInt()); + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2).GetInt()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64).GetInt64()); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64).GetUint64()); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1).GetUint64()); + + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true).IsTrue()); + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false).IsTrue()); + + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false).IsFalse()); + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, Set) { Document d; d.Parse(kJson); @@ -408,6 +468,55 @@ TEST(Pointer, Set) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, Set_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + Pointer("/foo/0").Set(d, Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + Pointer("/foo/-").Set(d, Value(456).Move()); + EXPECT_EQ(456, d["foo"][2].GetInt()); + + Pointer("/foo/null").Set(d, Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + Pointer("/foo/int").Set(d, -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + Pointer("/foo/uint").Set(d, 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + Pointer("/foo/int64").Set(d, i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + Pointer("/foo/uint64").Set(d, u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + Pointer("/foo/true").Set(d, true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + Pointer("/foo/false").Set(d, false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + Pointer("/foo/hello").Set(d, "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + Pointer("/foo/world").Set(d, buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, Swap) { Document d; d.Parse(kJson); @@ -431,6 +540,19 @@ TEST(Pointer, CreateValueByPointer) { } } +TEST(Pointer, CreateValueByPointer_NoAllocator) { + Document d; + + { + Value& v = CreateValueByPointer(d, Pointer("/foo/0")); + EXPECT_EQ(&d["foo"][0], &v); + } + { + Value& v = CreateValueByPointer(d, "/foo/1"); + EXPECT_EQ(&d["foo"][1], &v); + } +} + TEST(Pointer, GetValueByPointer) { Document d; d.Parse(kJson); @@ -542,6 +664,102 @@ TEST(Pointer, GetValueByPointerWithDefault_String) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) { + Document d; + d.Parse(kJson); + + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move()).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString()); +} + +TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) { + Document d; + d.Parse(kJson); + + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move()).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, SetValueByPointer_Pointer) { Document d; d.Parse(kJson); @@ -636,6 +854,98 @@ TEST(Pointer, SetValueByPointer_String) { EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } +TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, Pointer("/foo/null"), Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + SetValueByPointer(d, Pointer("/foo/int"), -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, Pointer("/foo/int64"), i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, Pointer("/foo/uint64"), u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, Pointer("/foo/true"), true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, Pointer("/foo/false"), false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, Pointer("/foo/hello"), "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, Pointer("/foo/world"), buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + +TEST(Pointer, SetValueByPointer_String_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + SetValueByPointer(d, "/foo/0", Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, "/foo/null", Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Generic version + SetValueByPointer(d, "/foo/int", -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, "/foo/uint", 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, "/foo/int64", i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, "/foo/uint64", u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, "/foo/true", true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, "/foo/false", false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, "/foo/hello", "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, "/foo/world", buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); +} + TEST(Pointer, SwapValueByPointer) { Document d; d.Parse(kJson);