diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index bc2795f..16d2e60 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -248,6 +248,28 @@ public: return v; } + ValueType& GetWithDefault(ValueType& root, GenericStringRef defaultValue, typename ValueType::AllocatorType& allocator) const { + ValueType v(defaultValue); + return GetWithDefault(root, v, allocator); + } + + ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + Value& v = Create(root, allocator, &alreadyExist); + if (!alreadyExist) { + Value clone(defaultValue, allocator); // This has overhead, so do it inside if. + v = clone; + } + return v; + } + + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + ValueType v(defaultValue); + return GetWithDefault(root, v, allocator); + } + // Move semantics, create parents if non-exist ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { return Create(root, allocator) = value; diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 887a7f8..8368d51 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -313,6 +313,7 @@ TEST(Pointer, GetWithDefault) { Document d; d.Parse(kJson); + // Value version Document::AllocatorType& a = d.GetAllocator(); const Value v("qux"); EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a)); @@ -320,6 +321,41 @@ TEST(Pointer, GetWithDefault) { EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a)); EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a)); EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move(), a).IsNull()); + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x", a).IsNull()); + + // Generic version + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1, a).GetInt()); + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2, a).GetInt()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321, a).GetUint()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678, a).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64, a).GetInt64()); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1, a).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64, a).GetUint64()); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1, a).GetUint64()); + + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true, a).IsTrue()); + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false, a).IsTrue()); + + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false, a).IsFalse()); + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true, a).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello", a).GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer, a).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); } TEST(Pointer, Set) {