mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
ICU-10086 move & swap for UnicodeString, LocalPointer, LocalArray
X-SVN-Rev: 37469
This commit is contained in:
parent
475ba73f13
commit
f7e715daee
10 changed files with 733 additions and 53 deletions
|
@ -158,12 +158,55 @@ public:
|
|||
* @param p simple pointer to an array of T items that is adopted
|
||||
*/
|
||||
explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* Move constructor, leaves src with isNull().
|
||||
* @param src source smart pointer
|
||||
*/
|
||||
LocalMemory(LocalMemory<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
|
||||
src.ptr=NULL;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Destructor deletes the memory it owns.
|
||||
*/
|
||||
~LocalMemory() {
|
||||
uprv_free(LocalPointerBase<T>::ptr);
|
||||
}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* Move assignment operator, leaves src with isNull().
|
||||
* The behavior is undefined if *this and src are the same object.
|
||||
* @param src source smart pointer
|
||||
* @return *this
|
||||
*/
|
||||
LocalMemory<T> &operator=(LocalMemory<T> &&src) U_NOEXCEPT {
|
||||
return moveFrom(src);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Move assignment, leaves src with isNull().
|
||||
* The behavior is undefined if *this and src are the same object.
|
||||
*
|
||||
* Can be called explicitly, does not need C++11 support.
|
||||
* @param src source smart pointer
|
||||
* @return *this
|
||||
*/
|
||||
LocalMemory<T> &moveFrom(LocalMemory<T> &src) U_NOEXCEPT {
|
||||
delete[] LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=src.ptr;
|
||||
src.ptr=NULL;
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Swap pointers.
|
||||
* @param other other smart pointer
|
||||
*/
|
||||
void swap(LocalMemory<T> &other) U_NOEXCEPT {
|
||||
T *temp=LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=other.ptr;
|
||||
other.ptr=temp;
|
||||
}
|
||||
/**
|
||||
* Deletes the array it owns,
|
||||
* and adopts (takes ownership of) the one passed in.
|
||||
|
@ -203,6 +246,16 @@ public:
|
|||
T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Non-member LocalMemory swap function.
|
||||
* @param p1 will get p2's pointer
|
||||
* @param p2 will get p1's pointer
|
||||
*/
|
||||
template<typename T>
|
||||
inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) U_NOEXCEPT {
|
||||
p1.swap(p2);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
|
||||
if(newCapacity>0) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2009-2014, International Business Machines
|
||||
* Copyright (C) 2009-2015, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
*******************************************************************************
|
||||
|
@ -151,11 +151,11 @@ protected:
|
|||
T *ptr;
|
||||
private:
|
||||
// No comparison operators with other LocalPointerBases.
|
||||
bool operator==(const LocalPointerBase &other);
|
||||
bool operator!=(const LocalPointerBase &other);
|
||||
// No ownership transfer: No copy constructor, no assignment operator.
|
||||
LocalPointerBase(const LocalPointerBase &other);
|
||||
void operator=(const LocalPointerBase &other);
|
||||
bool operator==(const LocalPointerBase<T> &other);
|
||||
bool operator!=(const LocalPointerBase<T> &other);
|
||||
// No ownership sharing: No copy constructor, no assignment operator.
|
||||
LocalPointerBase(const LocalPointerBase<T> &other);
|
||||
void operator=(const LocalPointerBase<T> &other);
|
||||
// No heap allocation. Use only on the stack.
|
||||
static void * U_EXPORT2 operator new(size_t size);
|
||||
static void * U_EXPORT2 operator new[](size_t size);
|
||||
|
@ -210,6 +210,16 @@ public:
|
|||
errorCode=U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* Move constructor, leaves src with isNull().
|
||||
* @param src source smart pointer
|
||||
* @draft ICU 56
|
||||
*/
|
||||
LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
|
||||
src.ptr=NULL;
|
||||
}
|
||||
#endif
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
/**
|
||||
* Destructor deletes the object it owns.
|
||||
|
@ -218,6 +228,45 @@ public:
|
|||
~LocalPointer() {
|
||||
delete LocalPointerBase<T>::ptr;
|
||||
}
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* Move assignment operator, leaves src with isNull().
|
||||
* The behavior is undefined if *this and src are the same object.
|
||||
* @param src source smart pointer
|
||||
* @return *this
|
||||
* @draft ICU 56
|
||||
*/
|
||||
LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT {
|
||||
return moveFrom(src);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Move assignment, leaves src with isNull().
|
||||
* The behavior is undefined if *this and src are the same object.
|
||||
*
|
||||
* Can be called explicitly, does not need C++11 support.
|
||||
* @param src source smart pointer
|
||||
* @return *this
|
||||
* @draft ICU 56
|
||||
*/
|
||||
LocalPointer<T> &moveFrom(LocalPointer<T> &src) U_NOEXCEPT {
|
||||
delete LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=src.ptr;
|
||||
src.ptr=NULL;
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Swap pointers.
|
||||
* @param other other smart pointer
|
||||
* @draft ICU 56
|
||||
*/
|
||||
void swap(LocalPointer<T> &other) U_NOEXCEPT {
|
||||
T *temp=LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=other.ptr;
|
||||
other.ptr=temp;
|
||||
}
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
/**
|
||||
* Deletes the object it owns,
|
||||
* and adopts (takes ownership of) the one passed in.
|
||||
|
@ -258,6 +307,19 @@ public:
|
|||
#endif /* U_HIDE_DRAFT_API */
|
||||
};
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Non-member LocalPointer swap function.
|
||||
* @param p1 will get p2's pointer
|
||||
* @param p2 will get p1's pointer
|
||||
* @draft ICU 56
|
||||
*/
|
||||
template<typename T>
|
||||
inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT {
|
||||
p1.swap(p2);
|
||||
}
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
/**
|
||||
* "Smart pointer" class, deletes objects via the C++ array delete[] operator.
|
||||
* For most methods see the LocalPointerBase base class.
|
||||
|
@ -285,6 +347,36 @@ public:
|
|||
* @stable ICU 4.4
|
||||
*/
|
||||
explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {}
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Constructor takes ownership and reports an error if NULL.
|
||||
*
|
||||
* This constructor is intended to be used with other-class constructors
|
||||
* that may report a failure UErrorCode,
|
||||
* so that callers need to check only for U_FAILURE(errorCode)
|
||||
* and not also separately for isNull().
|
||||
*
|
||||
* @param p simple pointer to an array of T objects that is adopted
|
||||
* @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
|
||||
* if p==NULL and no other failure code had been set
|
||||
* @draft ICU 56
|
||||
*/
|
||||
LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
|
||||
if(p==NULL && U_SUCCESS(errorCode)) {
|
||||
errorCode=U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* Move constructor, leaves src with isNull().
|
||||
* @param src source smart pointer
|
||||
* @draft ICU 56
|
||||
*/
|
||||
LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
|
||||
src.ptr=NULL;
|
||||
}
|
||||
#endif
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
/**
|
||||
* Destructor deletes the array it owns.
|
||||
* @stable ICU 4.4
|
||||
|
@ -292,6 +384,45 @@ public:
|
|||
~LocalArray() {
|
||||
delete[] LocalPointerBase<T>::ptr;
|
||||
}
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* Move assignment operator, leaves src with isNull().
|
||||
* The behavior is undefined if *this and src are the same object.
|
||||
* @param src source smart pointer
|
||||
* @return *this
|
||||
* @draft ICU 56
|
||||
*/
|
||||
LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT {
|
||||
return moveFrom(src);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Move assignment, leaves src with isNull().
|
||||
* The behavior is undefined if *this and src are the same object.
|
||||
*
|
||||
* Can be called explicitly, does not need C++11 support.
|
||||
* @param src source smart pointer
|
||||
* @return *this
|
||||
* @draft ICU 56
|
||||
*/
|
||||
LocalArray<T> &moveFrom(LocalArray<T> &src) U_NOEXCEPT {
|
||||
delete[] LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=src.ptr;
|
||||
src.ptr=NULL;
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Swap pointers.
|
||||
* @param other other smart pointer
|
||||
* @draft ICU 56
|
||||
*/
|
||||
void swap(LocalArray<T> &other) U_NOEXCEPT {
|
||||
T *temp=LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=other.ptr;
|
||||
other.ptr=temp;
|
||||
}
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
/**
|
||||
* Deletes the array it owns,
|
||||
* and adopts (takes ownership of) the one passed in.
|
||||
|
@ -302,6 +433,34 @@ public:
|
|||
delete[] LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=p;
|
||||
}
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Deletes the array it owns,
|
||||
* and adopts (takes ownership of) the one passed in.
|
||||
*
|
||||
* If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
|
||||
*
|
||||
* If U_SUCCESS(errorCode) but the input pointer is NULL,
|
||||
* then U_MEMORY_ALLOCATION_ERROR is set,
|
||||
* the current array is deleted, and NULL is set.
|
||||
*
|
||||
* @param p simple pointer to an array of T objects that is adopted
|
||||
* @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
|
||||
* if p==NULL and no other failure code had been set
|
||||
* @draft ICU 56
|
||||
*/
|
||||
void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
|
||||
if(U_SUCCESS(errorCode)) {
|
||||
delete[] LocalPointerBase<T>::ptr;
|
||||
LocalPointerBase<T>::ptr=p;
|
||||
if(p==NULL) {
|
||||
errorCode=U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
} else {
|
||||
delete[] p;
|
||||
}
|
||||
}
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
/**
|
||||
* Array item access (writable).
|
||||
* No index bounds check.
|
||||
|
@ -312,6 +471,19 @@ public:
|
|||
T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
|
||||
};
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Non-member LocalArray swap function.
|
||||
* @param p1 will get p2's pointer
|
||||
* @param p2 will get p1's pointer
|
||||
* @draft ICU 56
|
||||
*/
|
||||
template<typename T>
|
||||
inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT {
|
||||
p1.swap(p2);
|
||||
}
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
/**
|
||||
* \def U_DEFINE_LOCAL_OPEN_POINTER
|
||||
* "Smart pointer" definition macro, deletes objects via the closeFunction.
|
||||
|
@ -335,16 +507,64 @@ public:
|
|||
* @see LocalPointer
|
||||
* @stable ICU 4.4
|
||||
*/
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
#define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
|
||||
class LocalPointerClassName : public LocalPointerBase<Type> { \
|
||||
public: \
|
||||
explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
|
||||
LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \
|
||||
: LocalPointerBase<Type>(src.ptr) { \
|
||||
src.ptr=NULL; \
|
||||
} \
|
||||
~LocalPointerClassName() { closeFunction(ptr); } \
|
||||
LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
|
||||
return moveFrom(src); \
|
||||
} \
|
||||
LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \
|
||||
closeFunction(ptr); \
|
||||
LocalPointerBase<Type>::ptr=src.ptr; \
|
||||
src.ptr=NULL; \
|
||||
return *this; \
|
||||
} \
|
||||
void swap(LocalPointerClassName &other) U_NOEXCEPT { \
|
||||
Type *temp=LocalPointerBase<Type>::ptr; \
|
||||
LocalPointerBase<Type>::ptr=other.ptr; \
|
||||
other.ptr=temp; \
|
||||
} \
|
||||
void adoptInstead(Type *p) { \
|
||||
closeFunction(ptr); \
|
||||
ptr=p; \
|
||||
} \
|
||||
}; \
|
||||
inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
|
||||
p1.swap(p2); \
|
||||
}
|
||||
#else
|
||||
#define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
|
||||
class LocalPointerClassName : public LocalPointerBase<Type> { \
|
||||
public: \
|
||||
explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
|
||||
~LocalPointerClassName() { closeFunction(ptr); } \
|
||||
LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \
|
||||
closeFunction(ptr); \
|
||||
LocalPointerBase<Type>::ptr=src.ptr; \
|
||||
src.ptr=NULL; \
|
||||
return *this; \
|
||||
} \
|
||||
void swap(LocalPointerClassName &other) U_NOEXCEPT { \
|
||||
Type *temp=LocalPointerBase<Type>::ptr; \
|
||||
LocalPointerBase<Type>::ptr=other.ptr; \
|
||||
other.ptr=temp; \
|
||||
} \
|
||||
void adoptInstead(Type *p) { \
|
||||
closeFunction(ptr); \
|
||||
ptr=p; \
|
||||
} \
|
||||
}; \
|
||||
inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
|
||||
p1.swap(p2); \
|
||||
}
|
||||
#endif
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -429,6 +429,12 @@
|
|||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0
|
||||
#endif
|
||||
#ifndef __has_feature
|
||||
# define __has_feature(x) 0
|
||||
#endif
|
||||
#ifndef __has_extension
|
||||
# define __has_extension(x) 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def U_MALLOC_ATTR
|
||||
|
@ -454,6 +460,62 @@
|
|||
# define U_ALLOC_SIZE_ATTR2(X,Y)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def U_CPLUSPLUS_VERSION
|
||||
* 0 if no C++; 1, 11, 14, ... if C++.
|
||||
* Support for specific features cannot always be determined by the C++ version alone.
|
||||
* @internal
|
||||
*/
|
||||
#ifdef U_CPLUSPLUS_VERSION
|
||||
# if U_CPLUSPLUS_VERSION != 0 && !defined(__cplusplus)
|
||||
# undef U_CPLUSPLUS_VERSION
|
||||
# define U_CPLUSPLUS_VERSION 0
|
||||
# endif
|
||||
/* Otherwise use the predefined value. */
|
||||
#elif !defined(__cplusplus)
|
||||
# define U_CPLUSPLUS_VERSION 0
|
||||
#elif __cplusplus >= 201402L
|
||||
# define U_CPLUSPLUS_VERSION 14
|
||||
#elif __cplusplus >= 201103L
|
||||
# define U_CPLUSPLUS_VERSION 11
|
||||
#else
|
||||
// C++98 or C++03
|
||||
# define U_CPLUSPLUS_VERSION 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def U_HAVE_RVALUE_REFERENCES
|
||||
* Set to 1 if the compiler supports rvalue references.
|
||||
* C++11 feature, necessary for move constructor & move assignment.
|
||||
* @internal
|
||||
*/
|
||||
#ifdef U_HAVE_RVALUE_REFERENCES
|
||||
/* Use the predefined value. */
|
||||
#elif U_CPLUSPLUS_VERSION >= 11 || __has_feature(cxx_rvalue_references) || __has_extension(cxx_rvalue_references) \
|
||||
|| defined(__GXX_EXPERIMENTAL_CXX0X__) \
|
||||
|| (defined(_MSC_VER) && _MSC_VER >= 1600) /* Visual Studio 2010 */
|
||||
# define U_HAVE_RVALUE_REFERENCES 1
|
||||
#else
|
||||
# define U_HAVE_RVALUE_REFERENCES 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \def U_NOEXCEPT
|
||||
* "noexcept" if supported, otherwise empty.
|
||||
* Some code, especially STL containers, uses move semantics of objects only
|
||||
* if the move constructor and the move operator are declared as not throwing exceptions.
|
||||
* @internal
|
||||
*/
|
||||
#ifdef U_NOEXCEPT
|
||||
/* Use the predefined value. */
|
||||
#elif U_CPLUSPLUS_VERSION >= 11 || __has_feature(cxx_noexcept) || __has_extension(cxx_noexcept) \
|
||||
|| U_GCC_MAJOR_MINOR >= 406 \
|
||||
|| (defined(_MSC_VER) && _MSC_VER >= 1900) /* Visual Studio 2015 */
|
||||
# define U_NOEXCEPT noexcept
|
||||
#else
|
||||
# define U_NOEXCEPT
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
|
@ -670,7 +732,7 @@
|
|||
* does not support u"abc" string literals.
|
||||
* C++11 and C11 require support for UTF-16 literals
|
||||
*/
|
||||
# if (defined(__cplusplus) && __cplusplus >= 201103L) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
|
||||
# if U_CPLUSPLUS_VERSION >= 11 || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
|
||||
# define U_HAVE_CHAR16_T 1
|
||||
# else
|
||||
# define U_HAVE_CHAR16_T 0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
******************************************************************************
|
||||
*
|
||||
* Copyright (C) 1999-2014, International Business Machines
|
||||
* Copyright (C) 1999-2015, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*
|
||||
******************************************************************************
|
||||
|
@ -132,7 +132,7 @@
|
|||
* @internal
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus>=201103L
|
||||
#if U_CPLUSPLUS_VERSION >= 11
|
||||
/* C++11 */
|
||||
#ifndef U_OVERRIDE
|
||||
#define U_OVERRIDE override
|
||||
|
|
|
@ -1877,6 +1877,40 @@ public:
|
|||
*/
|
||||
UnicodeString &fastCopyFrom(const UnicodeString &src);
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* 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
|
||||
* @return *this
|
||||
* @draft ICU 56
|
||||
*/
|
||||
UnicodeString &operator=(UnicodeString &&src) U_NOEXCEPT {
|
||||
return moveFrom(src);
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* Can be called explicitly, does not need C++11 support.
|
||||
* @param src source string
|
||||
* @return *this
|
||||
* @draft ICU 56
|
||||
*/
|
||||
UnicodeString &moveFrom(UnicodeString &src) U_NOEXCEPT;
|
||||
|
||||
/**
|
||||
* Swap strings.
|
||||
* @param other other string
|
||||
* @draft ICU 56
|
||||
*/
|
||||
void swap(UnicodeString &other) U_NOEXCEPT;
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
/**
|
||||
* Assignment operator. Replace the characters in this UnicodeString
|
||||
* with the code unit <TT>ch</TT>.
|
||||
|
@ -3131,6 +3165,18 @@ public:
|
|||
*/
|
||||
UnicodeString(const UnicodeString& that);
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
/**
|
||||
* 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
|
||||
* @draft ICU 56
|
||||
*/
|
||||
UnicodeString(UnicodeString &&src) U_NOEXCEPT;
|
||||
#endif
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
/**
|
||||
* 'Substring' constructor from tail of source string.
|
||||
* @param src The UnicodeString object to copy.
|
||||
|
@ -3440,6 +3486,9 @@ private:
|
|||
// implements assigment operator, copy constructor, and fastCopyFrom()
|
||||
UnicodeString ©From(const UnicodeString &src, UBool fastCopy=FALSE);
|
||||
|
||||
// Copies just the fields without memory management.
|
||||
void copyFieldsFrom(UnicodeString &src, UBool setSrcToBogus) U_NOEXCEPT;
|
||||
|
||||
// Pin start and limit to acceptable values.
|
||||
inline void pinIndex(int32_t& start) const;
|
||||
inline void pinIndices(int32_t& start,
|
||||
|
@ -3619,6 +3668,19 @@ private:
|
|||
U_COMMON_API UnicodeString U_EXPORT2
|
||||
operator+ (const UnicodeString &s1, const UnicodeString &s2);
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Non-member UnicodeString swap function.
|
||||
* @param s1 will get s2's contents and state
|
||||
* @param s2 will get s1's contents and state
|
||||
* @draft ICU 56
|
||||
*/
|
||||
U_COMMON_API inline void U_EXPORT2
|
||||
swap(UnicodeString &s1, UnicodeString &s2) U_NOEXCEPT {
|
||||
s1.swap(s2);
|
||||
}
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
//========================================
|
||||
// Inline members
|
||||
//========================================
|
||||
|
|
|
@ -306,6 +306,13 @@ UnicodeString::UnicodeString(const UnicodeString& that) {
|
|||
copyFrom(that);
|
||||
}
|
||||
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
UnicodeString::UnicodeString(UnicodeString &&src) U_NOEXCEPT {
|
||||
fUnion.fFields.fLengthAndFlags = kShortString;
|
||||
moveFrom(src);
|
||||
}
|
||||
#endif
|
||||
|
||||
UnicodeString::UnicodeString(const UnicodeString& that,
|
||||
int32_t srcStart) {
|
||||
fUnion.fFields.fLengthAndFlags = kShortString;
|
||||
|
@ -536,6 +543,47 @@ UnicodeString::copyFrom(const UnicodeString &src, UBool fastCopy) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
UnicodeString &UnicodeString::moveFrom(UnicodeString &src) U_NOEXCEPT {
|
||||
// No explicit check for self move assignment, consistent with standard library.
|
||||
// Self move assignment causes no crash nor leak but might make the object bogus.
|
||||
releaseArray();
|
||||
copyFieldsFrom(src, TRUE);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Same as moveFrom() except without memory management.
|
||||
void UnicodeString::copyFieldsFrom(UnicodeString &src, UBool setSrcToBogus) U_NOEXCEPT {
|
||||
int16_t lengthAndFlags = fUnion.fFields.fLengthAndFlags = src.fUnion.fFields.fLengthAndFlags;
|
||||
if(lengthAndFlags & kUsingStackBuffer) {
|
||||
// Short string using the stack buffer, copy the contents.
|
||||
uprv_memcpy(fUnion.fStackFields.fBuffer, src.fUnion.fStackFields.fBuffer,
|
||||
getShortLength() * U_SIZEOF_UCHAR);
|
||||
} else {
|
||||
// In all other cases, copy all fields.
|
||||
fUnion.fFields.fArray = src.fUnion.fFields.fArray;
|
||||
fUnion.fFields.fCapacity = src.fUnion.fFields.fCapacity;
|
||||
if(!hasShortLength()) {
|
||||
fUnion.fFields.fLength = src.fUnion.fFields.fLength;
|
||||
}
|
||||
if(setSrcToBogus) {
|
||||
// Set src to bogus without releasing any memory.
|
||||
src.fUnion.fFields.fLengthAndFlags = kIsBogus;
|
||||
src.fUnion.fFields.fArray = NULL;
|
||||
src.fUnion.fFields.fCapacity = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnicodeString::swap(UnicodeString &other) U_NOEXCEPT {
|
||||
UnicodeString temp; // Empty short string: Known not to need releaseArray().
|
||||
// Copy fields without resetting source values in between.
|
||||
temp.copyFieldsFrom(*this, FALSE);
|
||||
this->copyFieldsFrom(other, FALSE);
|
||||
other.copyFieldsFrom(temp, FALSE);
|
||||
// Set temp to an empty string so that other's memory is not released twice.
|
||||
temp.fUnion.fFields.fLengthAndFlags = kShortString;
|
||||
}
|
||||
|
||||
//========================================
|
||||
// Miscellaneous operations
|
||||
//========================================
|
||||
|
|
|
@ -77,8 +77,8 @@ void BreakTransliterator::handleTransliterate(Replaceable& text, UTransPosition&
|
|||
{
|
||||
Mutex m;
|
||||
BreakTransliterator *nonConstThis = const_cast<BreakTransliterator *>(this);
|
||||
boundaries.adoptInstead(nonConstThis->cachedBoundaries.orphan());
|
||||
bi.adoptInstead(nonConstThis->cachedBI.orphan());
|
||||
boundaries.moveFrom(nonConstThis->cachedBoundaries);
|
||||
bi.moveFrom(nonConstThis->cachedBI);
|
||||
}
|
||||
if (bi.isNull()) {
|
||||
bi.adoptInstead(BreakIterator::createWordInstance(Locale::getEnglish(), status));
|
||||
|
@ -143,10 +143,10 @@ void BreakTransliterator::handleTransliterate(Replaceable& text, UTransPosition&
|
|||
Mutex m;
|
||||
BreakTransliterator *nonConstThis = const_cast<BreakTransliterator *>(this);
|
||||
if (nonConstThis->cachedBI.isNull()) {
|
||||
nonConstThis->cachedBI.adoptInstead(bi.orphan());
|
||||
nonConstThis->cachedBI.moveFrom(bi);
|
||||
}
|
||||
if (nonConstThis->cachedBoundaries.isNull()) {
|
||||
nonConstThis->cachedBoundaries.adoptInstead(boundaries.orphan());
|
||||
nonConstThis->cachedBoundaries.moveFrom(boundaries);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2014, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2015, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
|
@ -250,8 +250,11 @@ public:
|
|||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=NULL);
|
||||
|
||||
void TestLocalPointer();
|
||||
void TestLocalPointerMoveSwap();
|
||||
void TestLocalArray();
|
||||
void TestLocalArrayMoveSwap();
|
||||
void TestLocalXyzPointer();
|
||||
void TestLocalXyzPointerMoveSwap();
|
||||
void TestLocalXyzPointerNull();
|
||||
};
|
||||
|
||||
|
@ -265,13 +268,16 @@ void LocalPointerTest::runIndexedTest(int32_t index, UBool exec, const char *&na
|
|||
}
|
||||
TESTCASE_AUTO_BEGIN;
|
||||
TESTCASE_AUTO(TestLocalPointer);
|
||||
TESTCASE_AUTO(TestLocalPointerMoveSwap);
|
||||
TESTCASE_AUTO(TestLocalArray);
|
||||
TESTCASE_AUTO(TestLocalArrayMoveSwap);
|
||||
TESTCASE_AUTO(TestLocalXyzPointer);
|
||||
TESTCASE_AUTO(TestLocalXyzPointerMoveSwap);
|
||||
TESTCASE_AUTO(TestLocalXyzPointerNull);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
// Exercise every LocalPointer and LocalPointerBase method.
|
||||
// Exercise almost every LocalPointer and LocalPointerBase method.
|
||||
void LocalPointerTest::TestLocalPointer() {
|
||||
// constructor
|
||||
LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
|
||||
|
@ -294,7 +300,6 @@ void LocalPointerTest::TestLocalPointer() {
|
|||
errln("LocalPointer orphan() failure");
|
||||
}
|
||||
delete orphan;
|
||||
// destructor
|
||||
s.adoptInstead(new UnicodeString());
|
||||
if(s->length()!=0) {
|
||||
errln("LocalPointer adoptInstead(empty) failure");
|
||||
|
@ -336,9 +341,50 @@ void LocalPointerTest::TestLocalPointer() {
|
|||
errln("LocalPointer(NULL, errorCode) did not set U_MEMORY_ALLOCATION_ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
// destructor
|
||||
}
|
||||
|
||||
// Exercise every LocalArray method (but not LocalPointerBase).
|
||||
void LocalPointerTest::TestLocalPointerMoveSwap() {
|
||||
UnicodeString *p1 = new UnicodeString((UChar)0x61);
|
||||
UnicodeString *p2 = new UnicodeString((UChar)0x62);
|
||||
LocalPointer<UnicodeString> s1(p1);
|
||||
LocalPointer<UnicodeString> s2(p2);
|
||||
s1.swap(s2);
|
||||
if(s1.getAlias() != p2 || s2.getAlias() != p1) {
|
||||
errln("LocalPointer.swap() did not swap");
|
||||
}
|
||||
swap(s1, s2);
|
||||
if(s1.getAlias() != p1 || s2.getAlias() != p2) {
|
||||
errln("swap(LocalPointer) did not swap back");
|
||||
}
|
||||
LocalPointer<UnicodeString> s3;
|
||||
s3.moveFrom(s1);
|
||||
if(s3.getAlias() != p1 || s1.isValid()) {
|
||||
errln("LocalPointer.moveFrom() did not move");
|
||||
}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
infoln("TestLocalPointerMoveSwap() with rvalue references");
|
||||
s1 = static_cast<LocalPointer<UnicodeString> &&>(s3);
|
||||
if(s1.getAlias() != p1 || s3.isValid()) {
|
||||
errln("LocalPointer move assignment operator did not move");
|
||||
}
|
||||
LocalPointer<UnicodeString> s4(static_cast<LocalPointer<UnicodeString> &&>(s2));
|
||||
if(s4.getAlias() != p2 || s2.isValid()) {
|
||||
errln("LocalPointer move constructor did not move");
|
||||
}
|
||||
#else
|
||||
infoln("TestLocalPointerMoveSwap() without rvalue references");
|
||||
#endif
|
||||
|
||||
// Move self assignment leaves the object valid but in an undefined state.
|
||||
// Do it to make sure there is no crash,
|
||||
// but do not check for any particular resulting value.
|
||||
s1.moveFrom(s1);
|
||||
s3.moveFrom(s3);
|
||||
}
|
||||
|
||||
// Exercise almost every LocalArray method (but not LocalPointerBase).
|
||||
void LocalPointerTest::TestLocalArray() {
|
||||
// constructor
|
||||
LocalArray<UnicodeString> a(new UnicodeString[2]);
|
||||
|
@ -354,9 +400,87 @@ void LocalPointerTest::TestLocalArray() {
|
|||
if(a[3].length()!=2 || a[3][1]!=0x62) {
|
||||
errln("LocalArray adoptInstead() failure");
|
||||
}
|
||||
|
||||
// LocalArray(p, errorCode) sets U_MEMORY_ALLOCATION_ERROR if p==NULL.
|
||||
UErrorCode errorCode = U_ZERO_ERROR;
|
||||
LocalArray<UnicodeString> ua(new UnicodeString[3], errorCode);
|
||||
if(ua.isNull() && U_SUCCESS(errorCode)) {
|
||||
errln("LocalArray(p, errorCode) failure");
|
||||
return;
|
||||
}
|
||||
errorCode = U_ZERO_ERROR;
|
||||
UnicodeString *u4 = new UnicodeString[4];
|
||||
ua.adoptInsteadAndCheckErrorCode(u4, errorCode);
|
||||
if(ua.isNull() && U_SUCCESS(errorCode)) {
|
||||
errln("adoptInsteadAndCheckErrorCode(p, errorCode) failure");
|
||||
return;
|
||||
}
|
||||
// Incoming failure: Keep the current object and delete the input object.
|
||||
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
ua.adoptInsteadAndCheckErrorCode(new UnicodeString[5], errorCode);
|
||||
if(ua.isValid() && ua.getAlias() != u4) {
|
||||
errln("adoptInsteadAndCheckErrorCode(p, U_FAILURE) did not retain the old array");
|
||||
return;
|
||||
}
|
||||
errorCode = U_ZERO_ERROR;
|
||||
ua.adoptInsteadAndCheckErrorCode(NULL, errorCode);
|
||||
if(errorCode != U_MEMORY_ALLOCATION_ERROR) {
|
||||
errln("adoptInsteadAndCheckErrorCode(NULL, errorCode) did not set U_MEMORY_ALLOCATION_ERROR");
|
||||
return;
|
||||
}
|
||||
if(ua.isValid()) {
|
||||
errln("adoptInsteadAndCheckErrorCode(NULL, errorCode) kept the array");
|
||||
return;
|
||||
}
|
||||
errorCode = U_ZERO_ERROR;
|
||||
LocalArray<UnicodeString> null(NULL, errorCode);
|
||||
if(errorCode != U_MEMORY_ALLOCATION_ERROR) {
|
||||
errln("LocalArray(NULL, errorCode) did not set U_MEMORY_ALLOCATION_ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
// destructor
|
||||
}
|
||||
|
||||
void LocalPointerTest::TestLocalArrayMoveSwap() {
|
||||
UnicodeString *p1 = new UnicodeString[2];
|
||||
UnicodeString *p2 = new UnicodeString[3];
|
||||
LocalArray<UnicodeString> a1(p1);
|
||||
LocalArray<UnicodeString> a2(p2);
|
||||
a1.swap(a2);
|
||||
if(a1.getAlias() != p2 || a2.getAlias() != p1) {
|
||||
errln("LocalArray.swap() did not swap");
|
||||
}
|
||||
swap(a1, a2);
|
||||
if(a1.getAlias() != p1 || a2.getAlias() != p2) {
|
||||
errln("swap(LocalArray) did not swap back");
|
||||
}
|
||||
LocalArray<UnicodeString> a3;
|
||||
a3.moveFrom(a1);
|
||||
if(a3.getAlias() != p1 || a1.isValid()) {
|
||||
errln("LocalArray.moveFrom() did not move");
|
||||
}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
infoln("TestLocalArrayMoveSwap() with rvalue references");
|
||||
a1 = static_cast<LocalArray<UnicodeString> &&>(a3);
|
||||
if(a1.getAlias() != p1 || a3.isValid()) {
|
||||
errln("LocalArray move assignment operator did not move");
|
||||
}
|
||||
LocalArray<UnicodeString> a4(static_cast<LocalArray<UnicodeString> &&>(a2));
|
||||
if(a4.getAlias() != p2 || a2.isValid()) {
|
||||
errln("LocalArray move constructor did not move");
|
||||
}
|
||||
#else
|
||||
infoln("TestLocalArrayMoveSwap() without rvalue references");
|
||||
#endif
|
||||
|
||||
// Move self assignment leaves the object valid but in an undefined state.
|
||||
// Do it to make sure there is no crash,
|
||||
// but do not check for any particular resulting value.
|
||||
a1.moveFrom(a1);
|
||||
a3.moveFrom(a3);
|
||||
}
|
||||
|
||||
#include "unicode/ucnvsel.h"
|
||||
#include "unicode/ucal.h"
|
||||
#include "unicode/udatpg.h"
|
||||
|
@ -475,6 +599,61 @@ void LocalPointerTest::TestLocalXyzPointer() {
|
|||
// destructors
|
||||
}
|
||||
|
||||
void LocalPointerTest::TestLocalXyzPointerMoveSwap() {
|
||||
#if !UCONFIG_NO_NORMALIZATION
|
||||
IcuTestErrorCode errorCode(*this, "TestLocalXyzPointerMoveSwap");
|
||||
const UNormalizer2 *nfc=unorm2_getNFCInstance(errorCode);
|
||||
const UNormalizer2 *nfd=unorm2_getNFDInstance(errorCode);
|
||||
if(errorCode.logIfFailureAndReset("unorm2_getNF[CD]Instance()")) {
|
||||
return;
|
||||
}
|
||||
UnicodeSet emptySet;
|
||||
UNormalizer2 *p1 = unorm2_openFiltered(nfc, emptySet.toUSet(), errorCode);
|
||||
UNormalizer2 *p2 = unorm2_openFiltered(nfd, emptySet.toUSet(), errorCode);
|
||||
LocalUNormalizer2Pointer f1(p1);
|
||||
LocalUNormalizer2Pointer f2(p2);
|
||||
if(errorCode.logIfFailureAndReset("unorm2_openFiltered()")) {
|
||||
return;
|
||||
}
|
||||
if(f1.isNull() || f2.isNull()) {
|
||||
errln("LocalUNormalizer2Pointer failure");
|
||||
return;
|
||||
}
|
||||
f1.swap(f2);
|
||||
if(f1.getAlias() != p2 || f2.getAlias() != p1) {
|
||||
errln("LocalUNormalizer2Pointer.swap() did not swap");
|
||||
}
|
||||
swap(f1, f2);
|
||||
if(f1.getAlias() != p1 || f2.getAlias() != p2) {
|
||||
errln("swap(LocalUNormalizer2Pointer) did not swap back");
|
||||
}
|
||||
LocalUNormalizer2Pointer f3;
|
||||
f3.moveFrom(f1);
|
||||
if(f3.getAlias() != p1 || f1.isValid()) {
|
||||
errln("LocalUNormalizer2Pointer.moveFrom() did not move");
|
||||
}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
infoln("TestLocalXyzPointerMoveSwap() with rvalue references");
|
||||
f1 = static_cast<LocalUNormalizer2Pointer &&>(f3);
|
||||
if(f1.getAlias() != p1 || f3.isValid()) {
|
||||
errln("LocalUNormalizer2Pointer move assignment operator did not move");
|
||||
}
|
||||
LocalUNormalizer2Pointer f4(static_cast<LocalUNormalizer2Pointer &&>(f2));
|
||||
if(f4.getAlias() != p2 || f2.isValid()) {
|
||||
errln("LocalUNormalizer2Pointer move constructor did not move");
|
||||
}
|
||||
#else
|
||||
infoln("TestLocalXyzPointerMoveSwap() without rvalue references");
|
||||
#endif
|
||||
#endif /* !UCONFIG_NO_NORMALIZATION */
|
||||
|
||||
// Move self assignment leaves the object valid but in an undefined state.
|
||||
// Do it to make sure there is no crash,
|
||||
// but do not check for any particular resulting value.
|
||||
f1.moveFrom(f1);
|
||||
f3.moveFrom(f3);
|
||||
}
|
||||
|
||||
// Try LocalXyzPointer types with NULL pointers.
|
||||
void LocalPointerTest::TestLocalXyzPointerNull() {
|
||||
{
|
||||
|
|
|
@ -30,41 +30,33 @@ UnicodeStringTest::~UnicodeStringTest() {}
|
|||
void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char *par)
|
||||
{
|
||||
if (exec) logln("TestSuite UnicodeStringTest: ");
|
||||
switch (index) {
|
||||
case 0:
|
||||
name = "StringCaseTest";
|
||||
if (exec) {
|
||||
logln("StringCaseTest---"); logln("");
|
||||
StringCaseTest test;
|
||||
callTest(test, par);
|
||||
}
|
||||
break;
|
||||
case 1: name = "TestBasicManipulation"; if (exec) TestBasicManipulation(); break;
|
||||
case 2: name = "TestCompare"; if (exec) TestCompare(); break;
|
||||
case 3: name = "TestExtract"; if (exec) TestExtract(); break;
|
||||
case 4: name = "TestRemoveReplace"; if (exec) TestRemoveReplace(); break;
|
||||
case 5: name = "TestSearching"; if (exec) TestSearching(); break;
|
||||
case 6: name = "TestSpacePadding"; if (exec) TestSpacePadding(); break;
|
||||
case 7: name = "TestPrefixAndSuffix"; if (exec) TestPrefixAndSuffix(); break;
|
||||
case 8: name = "TestFindAndReplace"; if (exec) TestFindAndReplace(); break;
|
||||
case 9: name = "TestBogus"; if (exec) TestBogus(); break;
|
||||
case 10: name = "TestReverse"; if (exec) TestReverse(); break;
|
||||
case 11: name = "TestMiscellaneous"; if (exec) TestMiscellaneous(); break;
|
||||
case 12: name = "TestStackAllocation"; if (exec) TestStackAllocation(); break;
|
||||
case 13: name = "TestUnescape"; if (exec) TestUnescape(); break;
|
||||
case 14: name = "TestCountChar32"; if (exec) TestCountChar32(); break;
|
||||
case 15: name = "TestStringEnumeration"; if (exec) TestStringEnumeration(); break;
|
||||
case 16: name = "TestNameSpace"; if (exec) TestNameSpace(); break;
|
||||
case 17: name = "TestUTF32"; if (exec) TestUTF32(); break;
|
||||
case 18: name = "TestUTF8"; if (exec) TestUTF8(); break;
|
||||
case 19: name = "TestReadOnlyAlias"; if (exec) TestReadOnlyAlias(); break;
|
||||
case 20: name = "TestAppendable"; if (exec) TestAppendable(); break;
|
||||
case 21: name = "TestUnicodeStringImplementsAppendable"; if (exec) TestUnicodeStringImplementsAppendable(); break;
|
||||
case 22: name = "TestSizeofUnicodeString"; if (exec) TestSizeofUnicodeString(); break;
|
||||
case 23: name = "TestStartsWithAndEndsWithNulTerminated"; if (exec) TestStartsWithAndEndsWithNulTerminated(); break;
|
||||
|
||||
default: name = ""; break; //needed to end loop
|
||||
}
|
||||
TESTCASE_AUTO_BEGIN;
|
||||
TESTCASE_AUTO_CLASS(StringCaseTest);
|
||||
TESTCASE_AUTO(TestBasicManipulation);
|
||||
TESTCASE_AUTO(TestCompare);
|
||||
TESTCASE_AUTO(TestExtract);
|
||||
TESTCASE_AUTO(TestRemoveReplace);
|
||||
TESTCASE_AUTO(TestSearching);
|
||||
TESTCASE_AUTO(TestSpacePadding);
|
||||
TESTCASE_AUTO(TestPrefixAndSuffix);
|
||||
TESTCASE_AUTO(TestFindAndReplace);
|
||||
TESTCASE_AUTO(TestBogus);
|
||||
TESTCASE_AUTO(TestReverse);
|
||||
TESTCASE_AUTO(TestMiscellaneous);
|
||||
TESTCASE_AUTO(TestStackAllocation);
|
||||
TESTCASE_AUTO(TestUnescape);
|
||||
TESTCASE_AUTO(TestCountChar32);
|
||||
TESTCASE_AUTO(TestStringEnumeration);
|
||||
TESTCASE_AUTO(TestNameSpace);
|
||||
TESTCASE_AUTO(TestUTF32);
|
||||
TESTCASE_AUTO(TestUTF8);
|
||||
TESTCASE_AUTO(TestReadOnlyAlias);
|
||||
TESTCASE_AUTO(TestAppendable);
|
||||
TESTCASE_AUTO(TestUnicodeStringImplementsAppendable);
|
||||
TESTCASE_AUTO(TestSizeofUnicodeString);
|
||||
TESTCASE_AUTO(TestStartsWithAndEndsWithNulTerminated);
|
||||
TESTCASE_AUTO(TestMoveSwap);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2130,3 +2122,66 @@ UnicodeStringTest::TestSizeofUnicodeString() {
|
|||
expectedStackBufferLength);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UnicodeStringTest::TestMoveSwap() {
|
||||
static const UChar abc[3] = { 0x61, 0x62, 0x63 }; // "abc"
|
||||
UnicodeString s1(FALSE, abc, UPRV_LENGTHOF(abc)); // read-only alias
|
||||
UnicodeString s2(100, 0x7a, 100); // 100 * 'z' should be on the heap
|
||||
UnicodeString s3("defg", 4, US_INV); // in stack buffer
|
||||
const UChar *p = s2.getBuffer();
|
||||
s1.swap(s2);
|
||||
if(s1.getBuffer() != p || s1.length() != 100 || s2.getBuffer() != abc || s2.length() != 3) {
|
||||
errln("UnicodeString.swap() did not swap");
|
||||
}
|
||||
swap(s2, s3);
|
||||
if(s2 != UNICODE_STRING_SIMPLE("defg") || s3.getBuffer() != abc || s3.length() != 3) {
|
||||
errln("swap(UnicodeString) did not swap back");
|
||||
}
|
||||
UnicodeString s4;
|
||||
s4.moveFrom(s1);
|
||||
if(s4.getBuffer() != p || s4.length() != 100 || !s1.isBogus()) {
|
||||
errln("UnicodeString.moveFrom(heap) did not move");
|
||||
}
|
||||
UnicodeString s5;
|
||||
s5.moveFrom(s2);
|
||||
if(s5 != UNICODE_STRING_SIMPLE("defg")) {
|
||||
errln("UnicodeString.moveFrom(stack) did not move");
|
||||
}
|
||||
UnicodeString s6;
|
||||
s6.moveFrom(s3);
|
||||
if(s6.getBuffer() != abc || s6.length() != 3) {
|
||||
errln("UnicodeString.moveFrom(alias) did not move");
|
||||
}
|
||||
#if U_HAVE_RVALUE_REFERENCES
|
||||
infoln("TestMoveSwap() with rvalue references");
|
||||
s1 = static_cast<UnicodeString &&>(s6);
|
||||
if(s1.getBuffer() != abc || s1.length() != 3) {
|
||||
errln("UnicodeString move assignment operator did not move");
|
||||
}
|
||||
UnicodeString s7(static_cast<UnicodeString &&>(s4));
|
||||
if(s7.getBuffer() != p || s7.length() != 100 || !s4.isBogus()) {
|
||||
errln("UnicodeString move constructor did not move");
|
||||
}
|
||||
#else
|
||||
infoln("TestMoveSwap() without rvalue references");
|
||||
UnicodeString s7;
|
||||
#endif
|
||||
|
||||
// Move self assignment leaves the object valid but in an undefined state.
|
||||
// Do it to make sure there is no crash,
|
||||
// but do not check for any particular resulting value.
|
||||
s1.moveFrom(s1);
|
||||
s2.moveFrom(s2);
|
||||
s3.moveFrom(s3);
|
||||
s4.moveFrom(s4);
|
||||
s5.moveFrom(s5);
|
||||
s6.moveFrom(s6);
|
||||
s7.moveFrom(s7);
|
||||
// Simple copy assignment must work.
|
||||
UnicodeString simple = UNICODE_STRING_SIMPLE("simple");
|
||||
s1 = s6 = s4 = s7 = simple;
|
||||
if(s1 != simple || s4 != simple || s6 != simple || s7 != simple) {
|
||||
errln("UnicodeString copy after self-move did not work");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/********************************************************************
|
||||
* COPYRIGHT:
|
||||
* Copyright (c) 1997-2012, International Business Machines Corporation and
|
||||
* Copyright (c) 1997-2015, International Business Machines Corporation and
|
||||
* others. All Rights Reserved.
|
||||
********************************************************************/
|
||||
|
||||
|
@ -88,6 +88,7 @@ public:
|
|||
void TestAppendable();
|
||||
void TestUnicodeStringImplementsAppendable();
|
||||
void TestSizeofUnicodeString();
|
||||
void TestMoveSwap();
|
||||
};
|
||||
|
||||
class StringCaseTest: public IntlTest {
|
||||
|
|
Loading…
Add table
Reference in a new issue