From 8bde3be116e587f384b03720198ad287d70e8ecb Mon Sep 17 00:00:00 2001 From: "Philipp A. Hartmann" Date: Fri, 28 Feb 2014 13:01:57 +0100 Subject: [PATCH] GenericValue: add copy constructor and CopyFrom To allow deep copying from an existing GenericValue, an explicit "copy constructor" (with required Allocator param) and an "CopyFrom" assignment function are added. Document d; Document::AllocatorType& a = d.GetAllocator(); Value v1("foo"); // Value v2(v1); // not allowed Value v2(v1,a); // make a copy RAPIDJSON_ASSERT(v1.IsString()); // v1 untouched d.SetArray().PushBack(v1,a).PushBack(v2,a); RAPIDJSON_ASSERT(v1.Empty() && v2.Empty()); v2.CopyFrom(d,a); // copy whole document RAPIDJSON_ASSERT(d.IsArray() && d.Size()); // d untouched v1.SetObject().AddMember( "array", v2, a ); d.PushBack(v1,a); Additionally, the Handler implementation in GenericDocument is made private again, restricting access to GenericReader and GenericValue. --- include/rapidjson/document.h | 42 ++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index 9102915..40a0442 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -69,6 +69,16 @@ public: flags_ = defaultFlags[type]; } + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + \see CopyFrom() + */ + template< typename SourceAllocator > + GenericValue(const GenericValue& rhs, Allocator & allocator); + //! Constructor for boolean value. explicit GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {} @@ -183,6 +193,21 @@ public: new (this) GenericValue(value); return *this; } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + */ + template + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { + RAPIDJSON_ASSERT((void*)this != (void*)&rhs); + this->~GenericValue(); + new (this) GenericValue(rhs,allocator); + return *this; + } + //@} //!@name Type @@ -840,8 +865,10 @@ public: //! Get the capacity of stack in bytes. size_t GetStackCapacity() const { return stack_.GetCapacity(); } -//private: - //friend class GenericReader; // for Reader to call the following private handler functions +private: + // callers of the following private Handler functions + template friend class GenericReader; // for parsing + friend class GenericValue; // for deep copying // Implementation of Handler void Null() { new (stack_.template Push()) ValueType(); } @@ -893,6 +920,17 @@ private: typedef GenericDocument > Document; +// defined here due to the dependency on GenericDocument +template +template +inline +GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) +{ + GenericDocument d(&allocator); + rhs.Accept(d); + RawAssign(*d.stack_.template Pop(1)); +} + } // namespace rapidjson #ifdef _MSC_VER