From 0b86520c4d0b9e96f35cc18bda2e2a498a8e03a4 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Mon, 6 Sep 2021 15:37:30 +0100 Subject: [PATCH] BString: add support for move semantics with C++11 and up. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements the "rule of 5" for this type. While the copy operation for BString was already using shallow copies of the underlying data, this change further optimizes moving the data from one object to another. While it is not the intention to implement move semantics to all types in the legacy Haiku/Be kits, data types like BString are good candidates, because move operations are often useful when working with data within an application. In this implementation, the internal data of the string object will be set to NULL, thus leaving an empty string. Change-Id: I16bf9424f9b17f622b0b57659b80628e18760288 Reviewed-on: https://review.haiku-os.org/c/haiku/+/4428 Reviewed-by: Jérôme Duval --- docs/user/Doxyfile | 2 +- docs/user/support/String.dox | 33 ++++++++++++++++++- headers/os/support/String.h | 6 ++++ src/kits/support/String.cpp | 26 ++++++++++++++- .../kits/support/bstring/StringAssignTest.cpp | 11 +++++++ .../bstring/StringConstructionTest.cpp | 14 +++++++- 6 files changed, 88 insertions(+), 4 deletions(-) diff --git a/docs/user/Doxyfile b/docs/user/Doxyfile index 8975a0b8d1..0ea20bb11f 100644 --- a/docs/user/Doxyfile +++ b/docs/user/Doxyfile @@ -2163,7 +2163,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = __cplusplus \ +PREDEFINED = __cplusplus=201703L \ _SYS_TYPES_H \ __attribute__(x)= diff --git a/docs/user/support/String.dox b/docs/user/support/String.dox index 8594d749b4..d39ec84a48 100644 --- a/docs/user/support/String.dox +++ b/docs/user/support/String.dox @@ -40,7 +40,7 @@ strings. For all operations that perform on bytes, there is an equivalent that operates on UTF-8 strings. See for example the BString::CopyInto() and BString::CopyCharsInto() methods. The main difference is that if there are - any position argumens, the regular method counts the bytes and the + any position argumens, the regular method counts the bytes and the Chars methods counts characters. \since BeOS R5 @@ -94,6 +94,21 @@ */ +#if __cplusplus >= 201103L +/*! + \fn BString::BString(BString&& string) + \brief Move the data from the \a string to this object. + + Create a new string object with the data of another \a string. The + \a string will no longer point to the same contents. + + \note This constructor is only available for modern C++ (C++11 or later). + + \since Haiku R1 +*/ +#endif + + /*! \fn BString::~BString() \brief Free all resources associated with the object. @@ -270,6 +285,22 @@ */ +#if __cplusplus >= 201103L +/*! + \fn BString& BString::operator=(BString&& string) + \brief Move the contents of \a string to this BString object. + + The \a string will no longer point to the same contents. + + \note This method is only available for modern C++ (C++11 or later). + + \return This method always returns \c *this. + + \since Haiku R1 +*/ +#endif + + /*! \fn BString& BString::SetTo(const char* str) \brief Re-initialize the BString to a copy of the data of a string. diff --git a/headers/os/support/String.h b/headers/os/support/String.h index 73a5372f58..2b63510448 100644 --- a/headers/os/support/String.h +++ b/headers/os/support/String.h @@ -22,6 +22,9 @@ public: BString(const char* string); BString(const BString& string); BString(const char* string, int32 maxLength); +#if __cplusplus >= 201103L + BString(BString&& string); +#endif ~BString(); // Access @@ -39,6 +42,9 @@ public: BString& operator=(const BString& string); BString& operator=(const char* string); BString& operator=(char c); +#if __cplusplus >= 201103L + BString& operator=(BString&& string); +#endif BString& SetTo(const char* string); BString& SetTo(const char* string, int32 maxLength); diff --git a/src/kits/support/String.cpp b/src/kits/support/String.cpp index 9bdfcbb280..843f0994ea 100644 --- a/src/kits/support/String.cpp +++ b/src/kits/support/String.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2014 Haiku, Inc. All rights reserved. + * Copyright 2001-2021 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -193,6 +193,15 @@ BString::BString(const char* string, int32 maxLength) } +#if __cplusplus >= 201103L +BString::BString(BString&& string) +{ + fPrivateData = string.fPrivateData; + string.fPrivateData = NULL; +} +#endif + + BString::~BString() { if (!_IsShareable() || atomic_add(&_ReferenceCount(), -1) == 1) @@ -263,6 +272,21 @@ BString::operator=(char c) } +#if __cplusplus >= 201103L +BString& +BString::operator=(BString&& string) +{ + if (this != &string) { + this->~BString(); + // free up any resources allocated by the current contents + fPrivateData = string.fPrivateData; + string.fPrivateData = NULL; + } + return *this; +} +#endif + + BString& BString::SetTo(const char* string, int32 maxLength) { diff --git a/src/tests/kits/support/bstring/StringAssignTest.cpp b/src/tests/kits/support/bstring/StringAssignTest.cpp index 414c76492c..7d6aaf8117 100644 --- a/src/tests/kits/support/bstring/StringAssignTest.cpp +++ b/src/tests/kits/support/bstring/StringAssignTest.cpp @@ -32,6 +32,17 @@ StringAssignTest::PerformTest(void) CPPUNIT_ASSERT(strcmp(str->String(), "Something Else") == 0); delete str; + // =(BString&&) +#if __cplusplus >= 201103L + NextSubTest(); + BString movableString("Something movable"); + str = new BString(); + *str = std::move(movableString); + CPPUNIT_ASSERT(strcmp(str->String(), "Something movable") == 0); + CPPUNIT_ASSERT(strcmp(movableString.String(), "") == 0); + delete str; +#endif + // char ptr is NULL NextSubTest(); char *s = NULL; diff --git a/src/tests/kits/support/bstring/StringConstructionTest.cpp b/src/tests/kits/support/bstring/StringConstructionTest.cpp index 60dd112842..e0648c9670 100644 --- a/src/tests/kits/support/bstring/StringConstructionTest.cpp +++ b/src/tests/kits/support/bstring/StringConstructionTest.cpp @@ -56,7 +56,19 @@ StringConstructionTest::PerformTest(void) CPPUNIT_ASSERT(strncmp(string->String(), str, 5) == 0); CPPUNIT_ASSERT(string->Length() == 5); delete string; - + + // BString(BString&&) +#if __cplusplus >= 201103L + NextSubTest(); + BString movableString(str); + string = new BString(std::move(movableString)); + CPPUNIT_ASSERT(strcmp(string->String(), str) == 0); + CPPUNIT_ASSERT(string->Length() == strlen(str)); + CPPUNIT_ASSERT(strcmp(movableString.String(), "") == 0); + CPPUNIT_ASSERT(movableString.Length() == 0); + delete string; +#endif + NextSubTest(); string = new BString(str, 255); CPPUNIT_ASSERT(strcmp(string->String(), str) == 0);