Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add GenericDocument<>::Swap #376

Merged
merged 4 commits into from
Jul 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions include/rapidjson/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,20 @@ class GenericValue {
return *this;
}

//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.value, b.value);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }

//! Prepare Value for move semantics
/*! \return *this */
GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
Expand Down Expand Up @@ -1803,6 +1817,35 @@ class GenericDocument : public GenericValue<Encoding, Allocator> {
}
#endif

//! Exchange the contents of this document with those of another.
/*!
\param other Another document.
\note Constant complexity.
\see GenericValue::Swap
*/
GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT {
ValueType::Swap(rhs);
stack_.Swap(rhs.stack_);
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(parseResult_, rhs.parseResult_);
return *this;
}

//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.doc, b.doc);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }

//!@name Parse from stream
//!@{

Expand Down
10 changes: 10 additions & 0 deletions include/rapidjson/internal/stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define RAPIDJSON_INTERNAL_STACK_H_

#include "../rapidjson.h"
#include "swap.h"

RAPIDJSON_NAMESPACE_BEGIN
namespace internal {
Expand Down Expand Up @@ -81,6 +82,15 @@ class Stack {
}
#endif

void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
internal::Swap(allocator_, rhs.allocator_);
internal::Swap(ownAllocator_, rhs.ownAllocator_);
internal::Swap(stack_, rhs.stack_);
internal::Swap(stackTop_, rhs.stackTop_);
internal::Swap(stackEnd_, rhs.stackEnd_);
internal::Swap(initialCapacity_, rhs.initialCapacity_);
}

void Clear() { stackTop_ = stack_; }

void ShrinkToFit() {
Expand Down
37 changes: 37 additions & 0 deletions include/rapidjson/internal/swap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

#ifndef RAPIDJSON_INTERNAL_SWAP_H_
#define RAPIDJSON_INTERNAL_SWAP_H_

#include "../rapidjson.h"

RAPIDJSON_NAMESPACE_BEGIN
namespace internal {

//! Custom swap() to avoid dependency on C++ <algorith> header
/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only.
\note This has the same semantics as std::swap().
*/
template <typename T>
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
T tmp = a;
a = b;
b = tmp;
}

} // namespace internal
RAPIDJSON_NAMESPACE_END

#endif // RAPIDJSON_INTERNAL_SWAP_H_
26 changes: 25 additions & 1 deletion test/unittest/documenttest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "rapidjson/encodedstream.h"
#include "rapidjson/stringbuffer.h"
#include <sstream>
#include <algorithm>

using namespace rapidjson;

Expand Down Expand Up @@ -202,7 +203,8 @@ TEST(Document, Swap) {
o.SetObject().AddMember("a", 1, a);

// Swap between Document and Value
d1.Swap(o);
// d1.Swap(o); // doesn't compile
o.Swap(d1);
EXPECT_TRUE(d1.IsObject());
EXPECT_TRUE(o.IsArray());

Expand All @@ -212,8 +214,30 @@ TEST(Document, Swap) {
d1.Swap(d2);
EXPECT_TRUE(d1.IsArray());
EXPECT_TRUE(d2.IsObject());
EXPECT_EQ(&d2.GetAllocator(), &a);

// reset value
Value().Swap(d1);
EXPECT_TRUE(d1.IsNull());

// reset document, including allocator
Document().Swap(d2);
EXPECT_TRUE(d2.IsNull());
EXPECT_NE(&d2.GetAllocator(), &a);

// testing std::swap compatibility
d1.SetBool(true);
using std::swap;
swap(d1, d2);
EXPECT_TRUE(d1.IsNull());
EXPECT_TRUE(d2.IsTrue());

swap(o, d2);
EXPECT_TRUE(o.IsTrue());
EXPECT_TRUE(d2.IsArray());
}


// This should be slow due to assignment in inner-loop.
struct OutputStringStream : public std::ostringstream {
typedef char Ch;
Expand Down
6 changes: 6 additions & 0 deletions test/unittest/valuetest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ TEST(Value, Swap) {
EXPECT_TRUE(v1.IsObject());
EXPECT_TRUE(v2.IsInt());
EXPECT_EQ(1234, v2.GetInt());

// testing std::swap compatibility
using std::swap;
swap(v1, v2);
EXPECT_TRUE(v1.IsInt());
EXPECT_TRUE(v2.IsObject());
}

TEST(Value, Null) {
Expand Down