From 2786103abd16997af6c27079a8c11b4c430fcc99 Mon Sep 17 00:00:00 2001 From: miloyip Date: Tue, 12 May 2015 22:48:14 +0800 Subject: [PATCH] Add Value::XXXMember(...) overloads for std::string --- include/rapidjson/document.h | 50 ++++++++++++++++++++++++++++++++++++ test/unittest/valuetest.cpp | 22 ++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index aab489c05..ca809631e 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -844,6 +844,12 @@ class GenericValue { template const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + //! Const member iterator /*! \pre IsObject() == true */ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); } @@ -867,6 +873,18 @@ class GenericValue { */ bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } +#endif + //! Check whether a member exists in the object with GenericValue name. /*! This version is faster because it does not need a StrLen(). It can also handle string with null character. @@ -923,6 +941,18 @@ class GenericValue { } template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string& name) { return FindMember(StringRef(name)); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(StringRef(name)); } +#endif + //! Add a member (name-value pair) to the object. /*! \param name A string value as name of member. \param value Value of any type. @@ -969,6 +999,22 @@ class GenericValue { return AddMember(name, v, allocator); } +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + //! Add any primitive value as member (name-value pair) to the object. /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t \param name A string value as name of member. @@ -1087,6 +1133,10 @@ class GenericValue { return RemoveMember(n); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + template bool RemoveMember(const GenericValue& name) { MemberIterator m = FindMember(name); diff --git a/test/unittest/valuetest.cpp b/test/unittest/valuetest.cpp index 1922222a0..5e142e1e9 100644 --- a/test/unittest/valuetest.cpp +++ b/test/unittest/valuetest.cpp @@ -957,6 +957,19 @@ TEST(Value, Object) { EXPECT_EQ(2u, o.MemberCount()); } +#if RAPIDJSON_HAS_STDSTRING + { + // AddMember(StringRefType, const std::string&, Allocator) + Value o(kObjectType); + o.AddMember("b", std::string("Banana"), allocator); + EXPECT_STREQ("Banana", o["b"].GetString()); + + // RemoveMember(const std::string&) + o.RemoveMember(std::string("b")); + EXPECT_TRUE(o.ObjectEmpty()); + } +#endif + #if RAPIDJSON_HAS_CXX11_RVALUE_REFS // AddMember(GenericValue&&, ...) variants { @@ -986,6 +999,10 @@ TEST(Value, Object) { EXPECT_TRUE(y.HasMember("A")); EXPECT_TRUE(y.HasMember("B")); +#if RAPIDJSON_HAS_STDSTRING + EXPECT_TRUE(x.HasMember(std::string("A"))); +#endif + name.SetString("C\0D"); EXPECT_TRUE(x.HasMember(name)); EXPECT_TRUE(y.HasMember(name)); @@ -1009,6 +1026,11 @@ TEST(Value, Object) { EXPECT_STREQ("Banana", y["B"].GetString()); EXPECT_STREQ("CherryD", y[C0D].GetString()); +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("Apple", x["A"].GetString()); + EXPECT_STREQ("Apple", y[std::string("A")].GetString()); +#endif + // member iterator Value::MemberIterator itr = x.MemberBegin(); EXPECT_TRUE(itr != x.MemberEnd());