From b2d72ef751afc618ba38a22c29d1b607c23df0a9 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Fri, 10 Apr 2015 19:28:12 +0800 Subject: [PATCH] Add XXXByPointer() helper functions --- include/rapidjson/document.h | 2 +- include/rapidjson/pointer.h | 66 +++++++++++++++++++++++++++++ test/unittest/pointertest.cpp | 78 +++++++++++++++++++++++++++++++++-- 3 files changed, 142 insertions(+), 4 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index d41a87e..3b7ef2b 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -427,6 +427,7 @@ public: typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. //!@name Constructors and destructor. //@{ @@ -1661,7 +1662,6 @@ template , typenam class GenericDocument : public GenericValue { public: typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef GenericValue ValueType; //!< Value type of the document. typedef Allocator AllocatorType; //!< Allocator type from template parameter. //! Constructor diff --git a/include/rapidjson/pointer.h b/include/rapidjson/pointer.h index 1ec157e..99a4c1a 100644 --- a/include/rapidjson/pointer.h +++ b/include/rapidjson/pointer.h @@ -325,6 +325,72 @@ private: bool valid_; }; +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.Create(root, a); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Get(root); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer) { + return pointer.Get(root); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { + const Pointer pointer(source, N - 1); + return pointer.Get(root); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { + const Pointer pointer(source, N - 1); + return pointer.Get(root); +} + +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); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.Set(root, value , a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + const Pointer pointer(source, N - 1); + return pointer.Swap(root, value, a); +} + typedef GenericPointer Pointer; RAPIDJSON_NAMESPACE_END diff --git a/test/unittest/pointertest.cpp b/test/unittest/pointertest.cpp index 4d4aece..245fa44 100644 --- a/test/unittest/pointertest.cpp +++ b/test/unittest/pointertest.cpp @@ -244,9 +244,18 @@ TEST(Pointer, Assignment) { TEST(Pointer, Create) { Document d; - EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator())); - EXPECT_EQ(&d["foo"], &Pointer("/foo").Create(d, d.GetAllocator())); - EXPECT_EQ(&d["foo"][0], &Pointer("/foo/0").Create(d, d.GetAllocator())); + { + Value* v = &Pointer("").Create(d, d.GetAllocator()); + EXPECT_EQ(&d, v); + } + { + Value* v = &Pointer("/foo").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"], v); + } + { + Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"][0], v); + } } TEST(Pointer, Get) { @@ -265,6 +274,7 @@ TEST(Pointer, Get) { EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d)); EXPECT_EQ(&d[" "], Pointer("/ ").Get(d)); EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d)); + EXPECT_TRUE(Pointer("/abc").Get(d) == 0); } TEST(Pointer, GetWithDefault) { @@ -298,3 +308,65 @@ TEST(Pointer, Swap) { EXPECT_STREQ("baz", d["foo"][0].GetString()); EXPECT_STREQ("bar", d["foo"][1].GetString()); } + +TEST(Pointer, CreateValueByPointer) { + Document d; + Document::AllocatorType& a = d.GetAllocator(); + + { + Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a); + EXPECT_EQ(&d["foo"][0], &v); + } + { + Value& v = CreateValueByPointer(d, "/foo/1", a); + EXPECT_EQ(&d["foo"][1], &v); + } +} + +TEST(Pointer, GetValueByPointer) { + Document d; + d.Parse(kJson); + + EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0"))); + EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0")); + + // const version + const Value& v = d; + EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0"))); + EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0")); +} + +TEST(Pointer, GetValueByPointerWithDefault) { + Document d; + d.Parse(kJson); + + Document::AllocatorType& a = d.GetAllocator(); + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a)); +} + +TEST(Pointer, SetValueByPointer) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + + SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, "/foo/2", Value(456).Move(), a); + EXPECT_EQ(456, d["foo"][2].GetInt()); +} + +TEST(Pointer, SwapValueByPointer) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); + + SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a); + EXPECT_STREQ("bar", d["foo"][0].GetString()); + EXPECT_STREQ("baz", d["foo"][1].GetString()); +}