Skip to content

Commit

Permalink
Merge pull request #376 from pah/feature/document-swap
Browse files Browse the repository at this point in the history
add GenericDocument<>::Swap with std::swap() support
  • Loading branch information
miloyip committed Jul 13, 2015
2 parents 9b3b2d0 + c2b5864 commit 823b731
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 1 deletion.
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 @@ -1818,6 +1832,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

0 comments on commit 823b731

Please sign in to comment.