From: Shane Carr Date: Tue, 13 Feb 2018 02:28:00 +0000 (+0000) Subject: ICU-13585 Adding std::move operators to CharString and MaybeStackArray. X-Git-Tag: release-62-rc~200^2~119 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fb26c75df0162289cb278455eca0a328bcc92784;p=icu ICU-13585 Adding std::move operators to CharString and MaybeStackArray. X-SVN-Rev: 40904 --- diff --git a/icu4c/source/common/charstr.cpp b/icu4c/source/common/charstr.cpp index 8bacd20ddc7..353f1d52542 100644 --- a/icu4c/source/common/charstr.cpp +++ b/icu4c/source/common/charstr.cpp @@ -23,6 +23,18 @@ U_NAMESPACE_BEGIN +CharString::CharString(CharString&& src) U_NOEXCEPT + : buffer(std::move(src.buffer)), len(src.len) { + src.len = 0; // not strictly necessary because we make no guarantees on the source string +} + +CharString& CharString::operator=(CharString&& src) U_NOEXCEPT { + buffer = std::move(src.buffer); + len = src.len; + src.len = 0; // not strictly necessary because we make no guarantees on the source string + return *this; +} + CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { len=s.len; diff --git a/icu4c/source/common/charstr.h b/icu4c/source/common/charstr.h index 3cfdf6a897a..86f69c383a0 100644 --- a/icu4c/source/common/charstr.h +++ b/icu4c/source/common/charstr.h @@ -55,6 +55,18 @@ public: } ~CharString() {} + /** + * Move constructor; might leave src in an undefined state. + * This string will have the same contents and state that the source string had. + */ + CharString(CharString &&src) U_NOEXCEPT; + /** + * Move assignment operator; might leave src in an undefined state. + * This string will have the same contents and state that the source string had. + * The behavior is undefined if *this and src are the same object. + */ + CharString &operator=(CharString &&src) U_NOEXCEPT; + /** * Replaces this string's contents with the other string's contents. * CharString does not support the standard copy constructor nor diff --git a/icu4c/source/common/cmemory.h b/icu4c/source/common/cmemory.h index 5cb52993abc..e3532c759e1 100644 --- a/icu4c/source/common/cmemory.h +++ b/icu4c/source/common/cmemory.h @@ -299,6 +299,14 @@ public: * Destructor deletes the array (if owned). */ ~MaybeStackArray() { releaseArray(); } + /** + * Move constructor: transfers ownership or copies the stack array. + */ + MaybeStackArray(MaybeStackArray &&src) U_NOEXCEPT; + /** + * Move assignment: transfers ownership or copies the stack array. + */ + MaybeStackArray &operator=(MaybeStackArray &&src) U_NOEXCEPT; /** * Returns the array capacity (number of T items). * @return array capacity @@ -376,6 +384,11 @@ private: uprv_free(ptr); } } + void resetToStackArray() { + ptr=stackArray; + capacity=stackCapacity; + needToRelease=FALSE; + } /* No comparison operators with other MaybeStackArray's. */ bool operator==(const MaybeStackArray & /*other*/) {return FALSE;} bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;} @@ -398,6 +411,34 @@ private: #endif }; +template +icu::MaybeStackArray::MaybeStackArray( + MaybeStackArray && src) U_NOEXCEPT + : ptr(src.ptr), capacity(src.capacity), needToRelease(src.needToRelease) { + if (src.ptr == src.stackArray) { + ptr = stackArray; + uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity); + } else { + src.resetToStackArray(); // take ownership away from src + } +} + +template +inline MaybeStackArray & +MaybeStackArray::operator=(MaybeStackArray && src) U_NOEXCEPT { + releaseArray(); // in case this instance had its own memory allocated + capacity = src.capacity; + needToRelease = src.needToRelease; + if (src.ptr == src.stackArray) { + ptr = stackArray; + uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity); + } else { + ptr = src.ptr; + src.resetToStackArray(); // take ownership away from src + } + return *this; +} + template inline T *MaybeStackArray::resize(int32_t newCapacity, int32_t length) { if(newCapacity>0) { @@ -447,9 +488,7 @@ inline T *MaybeStackArray::orphanOrClone(int32_t length, int32 uprv_memcpy(p, ptr, (size_t)length*sizeof(T)); } resultCapacity=length; - ptr=stackArray; - capacity=stackCapacity; - needToRelease=FALSE; + resetToStackArray(); return p; } diff --git a/icu4c/source/common/unicode/unistr.h b/icu4c/source/common/unicode/unistr.h index b99a686126c..5920d3fdd12 100644 --- a/icu4c/source/common/unicode/unistr.h +++ b/icu4c/source/common/unicode/unistr.h @@ -1892,7 +1892,7 @@ public: UnicodeString &fastCopyFrom(const UnicodeString &src); /** - * Move assignment operator, might leave src in bogus state. + * Move assignment operator; might leave src in bogus state. * This string will have the same contents and state that the source string had. * The behavior is undefined if *this and src are the same object. * @param src source string @@ -1905,7 +1905,7 @@ public: // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API /** - * Move assignment, might leave src in bogus state. + * Move assignment; might leave src in bogus state. * This string will have the same contents and state that the source string had. * The behavior is undefined if *this and src are the same object. * @@ -3350,7 +3350,7 @@ public: UnicodeString(const UnicodeString& that); /** - * Move constructor, might leave src in bogus state. + * Move constructor; might leave src in bogus state. * This string will have the same contents and state that the source string had. * @param src source string * @stable ICU 56 diff --git a/icu4c/source/test/intltest/strtest.cpp b/icu4c/source/test/intltest/strtest.cpp index d8fd7a0042a..b95b525296e 100644 --- a/icu4c/source/test/intltest/strtest.cpp +++ b/icu4c/source/test/intltest/strtest.cpp @@ -551,6 +551,28 @@ StringTest::TestCharString() { if (chStr.length() != 0) { errln("%s:%d expected length() = 0, got %d", __FILE__, __LINE__, chStr.length()); } + + { + CharString s1("Short string", errorCode); + CharString s2(std::move(s1)); + assertEquals("s2 should have content of s1", "Short string", s2.data()); + CharString s3("Dummy", errorCode); + s3 = std::move(s2); + assertEquals("s3 should have content of s2", "Short string", s3.data()); + } + + { + CharString s1("Long string over 40 characters to trigger heap allocation", errorCode); + CharString s2(std::move(s1)); + assertEquals("s2 should have content of s1", + "Long string over 40 characters to trigger heap allocation", + s2.data()); + CharString s3("Dummy string with over 40 characters to trigger heap allocation", errorCode); + s3 = std::move(s2); + assertEquals("s3 should have content of s2", + "Long string over 40 characters to trigger heap allocation", + s3.data()); + } } void