From 2b00891a86f7083f15843814c3db3f545f08bd93 Mon Sep 17 00:00:00 2001 From: Motti Date: Mon, 20 Apr 2015 17:44:47 +0300 Subject: [PATCH] move ctors * Add move constructor to Value::CZString * Add unit test for Value move constructor * Allow includer to specify in advance the value for JSON_HAS_RVALUE_REFERENCES --- include/json/config.h | 55 ++++++++++++++++++++++++++++--------- include/json/value.h | 7 +++++ src/lib_json/json_value.cpp | 18 ++++++++++++ src/test_lib_json/main.cpp | 15 ++++++++++ 4 files changed, 82 insertions(+), 13 deletions(-) diff --git a/include/json/config.h b/include/json/config.h index a16f0c2..7201ba7 100644 --- a/include/json/config.h +++ b/include/json/config.h @@ -56,30 +56,59 @@ // Storages, and 64 bits integer support is disabled. // #define JSON_NO_INT64 1 -#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6 +#if defined(_MSC_VER) // MSVC +# if _MSC_VER <= 1200 // MSVC 6 // Microsoft Visual Studio 6 only support conversion from __int64 to double // (no conversion from unsigned __int64). - #define JSON_USE_INT64_DOUBLE_CONVERSION 1 +# define JSON_USE_INT64_DOUBLE_CONVERSION 1 // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' // characters in the debug information) // All projects I've ever seen with VS6 were using this globally (not bothering // with pragma push/pop). # pragma warning(disable : 4786) -#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6 +# endif // MSVC 6 -#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 +# if _MSC_VER >= 1500 // MSVC 2008 /// Indicates that the following function is deprecated. -#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) -#elif defined(__clang__) && defined(__has_feature) -#if __has_feature(attribute_deprecated_with_message) -#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -#endif -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) -#define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -#elif defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +# endif + +#endif // defined(_MSC_VER) + + +#ifndef JSON_HAS_RVALUE_REFERENCES + +#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // MSVC >= 2010 + +#ifdef __clang__ +#if __has_feature(cxx_rvalue_references) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // has_feature + +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) +#define JSON_HAS_RVALUE_REFERENCES 1 +#endif // GXX_EXPERIMENTAL + +#endif // __clang__ || __GNUC__ + +#endif // not defined JSON_HAS_RVALUE_REFERENCES + +#ifndef JSON_HAS_RVALUE_REFERENCES +#define JSON_HAS_RVALUE_REFERENCES 0 #endif +#ifdef __clang__ +#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) +# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) +# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +# endif // GNUC version +#endif // __clang__ || __GNUC__ + #if !defined(JSONCPP_DEPRECATED) #define JSONCPP_DEPRECATED(message) #endif // if !defined(JSONCPP_DEPRECATED) diff --git a/include/json/value.h b/include/json/value.h index 7f3ad9b..1cfda07 100644 --- a/include/json/value.h +++ b/include/json/value.h @@ -212,6 +212,9 @@ private: CZString(ArrayIndex index); CZString(char const* str, unsigned length, DuplicationPolicy allocate); CZString(CZString const& other); +#if JSON_HAS_RVALUE_REFERENCES + CZString(CZString&& other); +#endif ~CZString(); CZString& operator=(CZString other); bool operator<(CZString const& other) const; @@ -294,6 +297,10 @@ Json::Value obj_value(Json::objectValue); // {} Value(bool value); /// Deep copy. Value(const Value& other); +#if JSON_HAS_RVALUE_REFERENCES + /// Move constructor + Value(Value&& other); +#endif ~Value(); /// Deep copy, then swap(other). diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 9a16491..9f56c74 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -237,6 +237,15 @@ Value::CZString::CZString(const CZString& other) storage_.length_ = other.storage_.length_; } +#if JSON_HAS_RVALUE_REFERENCES +Value::CZString::CZString(CZString&& other) + : cstr_(other.cstr_), + index_(other.index_) +{ + other.cstr_ = 0; +} +#endif + Value::CZString::~CZString() { if (cstr_ && storage_.policy_ == duplicate) releaseStringValue(const_cast(cstr_)); @@ -425,6 +434,15 @@ Value::Value(Value const& other) } } +#if JSON_HAS_RVALUE_REFERENCES +// Move constructor +Value::Value(Value&& other) +{ + initBasic(nullValue); + swap(other); +} +#endif + Value::~Value() { switch (type_) { case nullValue: diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index ad0ad5f..30136b0 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -2497,6 +2497,19 @@ JSONTEST_FIXTURE(IteratorTest, const) { JSONTEST_ASSERT_STRING_EQUAL(expected, out.str()); } +struct RValueTest : JsonTest::TestCase {}; + +JSONTEST_FIXTURE(RValueTest, moveConstruction) { +#if JSON_HAS_RVALUE_REFERENCES + Json::Value json; + json["key"] = "value"; + Json::Value moved = std::move(json); + JSONTEST_ASSERT(moved != json); // Possibly not nullValue; definitely not equal. + JSONTEST_ASSERT_EQUAL(Json::objectValue, moved.type()); + JSONTEST_ASSERT_EQUAL(Json::stringValue, moved["key"].type()); +#endif +} + int main(int argc, const char* argv[]) { JsonTest::Runner runner; JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr); @@ -2570,5 +2583,7 @@ int main(int argc, const char* argv[]) { JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, indexes); JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, const); + JSONTEST_REGISTER_FIXTURE(runner, RValueTest, moveConstruction); + return runner.runCommandLine(argc, argv); }