X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b331163bffd790ced0e88b73f44f86d49ccc48a5..340931cb2e044a2141d11567dd0f782524e32994:/icuSources/common/unicode/localpointer.h diff --git a/icuSources/common/unicode/localpointer.h b/icuSources/common/unicode/localpointer.h index e3aabf65..e011688b 100644 --- a/icuSources/common/unicode/localpointer.h +++ b/icuSources/common/unicode/localpointer.h @@ -1,12 +1,14 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* * -* Copyright (C) 2009-2014, International Business Machines +* Copyright (C) 2009-2016, International Business Machines * Corporation and others. All Rights Reserved. * ******************************************************************************* * file name: localpointer.h -* encoding: US-ASCII +* encoding: UTF-8 * tab size: 8 (not used) * indentation:4 * @@ -18,7 +20,7 @@ #define __LOCALPOINTER_H__ /** - * \file + * \file * \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code. * * These classes are inspired by @@ -40,6 +42,8 @@ #if U_SHOW_CPLUSPLUS_API +#include + U_NAMESPACE_BEGIN /** @@ -52,7 +56,7 @@ U_NAMESPACE_BEGIN * Destructor and adoptInstead(). * * There is no operator T *() provided because the programmer must decide - * whether to use getAlias() (without transfer of ownership) or orpan() + * whether to use getAlias() (without transfer of ownership) or orphan() * (with transfer of ownership and NULLing of the pointer). * * @see LocalPointer @@ -63,6 +67,13 @@ U_NAMESPACE_BEGIN template class LocalPointerBase { public: + // No heap allocation. Use only on the stack. + static void* U_EXPORT2 operator new(size_t) = delete; + static void* U_EXPORT2 operator new[](size_t) = delete; +#if U_HAVE_PLACEMENT_NEW + static void* U_EXPORT2 operator new(size_t, void*) = delete; +#endif + /** * Constructor takes ownership. * @param p simple pointer to an object that is adopted @@ -151,17 +162,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); - // 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); -#if U_HAVE_PLACEMENT_NEW - static void * U_EXPORT2 operator new(size_t, void *ptr); -#endif + bool operator==(const LocalPointerBase &other); + bool operator!=(const LocalPointerBase &other); + // No ownership sharing: No copy constructor, no assignment operator. + LocalPointerBase(const LocalPointerBase &other); + void operator=(const LocalPointerBase &other); }; /** @@ -172,9 +177,9 @@ private: * \code * LocalPointer s(new UnicodeString((UChar32)0x50005)); * int32_t length=s->length(); // 2 - * UChar lead=s->charAt(0); // 0xd900 + * char16_t lead=s->charAt(0); // 0xd900 * if(some condition) { return; } // no need to explicitly delete the pointer - * s.adoptInstead(new UnicodeString((UChar)0xfffc)); + * s.adoptInstead(new UnicodeString((char16_t)0xfffc)); * length=s->length(); // 1 * // no need to explicitly delete the pointer * \endcode @@ -185,13 +190,14 @@ private: template class LocalPointer : public LocalPointerBase { public: + using LocalPointerBase::operator*; + using LocalPointerBase::operator->; /** * Constructor takes ownership. * @param p simple pointer to an object that is adopted * @stable ICU 4.4 */ explicit LocalPointer(T *p=NULL) : LocalPointerBase(p) {} -#ifndef U_HIDE_DRAFT_API /** * Constructor takes ownership and reports an error if NULL. * @@ -203,14 +209,37 @@ public: * @param p simple pointer to an object 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 55 + * @stable ICU 55 */ LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase(p) { if(p==NULL && U_SUCCESS(errorCode)) { errorCode=U_MEMORY_ALLOCATION_ERROR; } } + /** + * Move constructor, leaves src with isNull(). + * @param src source smart pointer + * @stable ICU 56 + */ + LocalPointer(LocalPointer &&src) U_NOEXCEPT : LocalPointerBase(src.ptr) { + src.ptr=NULL; + } + +#ifndef U_HIDE_DRAFT_API + /** + * Constructs a LocalPointer from a C++11 std::unique_ptr. + * The LocalPointer steals the object owned by the std::unique_ptr. + * + * This constructor works via move semantics. If your std::unique_ptr is + * in a local variable, you must use std::move. + * + * @param p The std::unique_ptr from which the pointer will be stolen. + * @draft ICU 64 + */ + explicit LocalPointer(std::unique_ptr &&p) + : LocalPointerBase(p.release()) {} #endif /* U_HIDE_DRAFT_API */ + /** * Destructor deletes the object it owns. * @stable ICU 4.4 @@ -218,6 +247,54 @@ public: ~LocalPointer() { delete LocalPointerBase::ptr; } + /** + * 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 + * @stable ICU 56 + */ + LocalPointer &operator=(LocalPointer &&src) U_NOEXCEPT { + delete LocalPointerBase::ptr; + LocalPointerBase::ptr=src.ptr; + src.ptr=NULL; + return *this; + } + +#ifndef U_HIDE_DRAFT_API + /** + * Move-assign from an std::unique_ptr to this LocalPointer. + * Steals the pointer from the std::unique_ptr. + * + * @param p The std::unique_ptr from which the pointer will be stolen. + * @return *this + * @draft ICU 64 + */ + LocalPointer &operator=(std::unique_ptr &&p) U_NOEXCEPT { + adoptInstead(p.release()); + return *this; + } +#endif /* U_HIDE_DRAFT_API */ + + /** + * Swap pointers. + * @param other other smart pointer + * @stable ICU 56 + */ + void swap(LocalPointer &other) U_NOEXCEPT { + T *temp=LocalPointerBase::ptr; + LocalPointerBase::ptr=other.ptr; + other.ptr=temp; + } + /** + * Non-member LocalPointer swap function. + * @param p1 will get p2's pointer + * @param p2 will get p1's pointer + * @stable ICU 56 + */ + friend inline void swap(LocalPointer &p1, LocalPointer &p2) U_NOEXCEPT { + p1.swap(p2); + } /** * Deletes the object it owns, * and adopts (takes ownership of) the one passed in. @@ -228,7 +305,6 @@ public: delete LocalPointerBase::ptr; LocalPointerBase::ptr=p; } -#ifndef U_HIDE_DRAFT_API /** * Deletes the object it owns, * and adopts (takes ownership of) the one passed in. @@ -242,7 +318,7 @@ public: * @param p simple pointer to an object 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 55 + * @stable ICU 55 */ void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { if(U_SUCCESS(errorCode)) { @@ -255,6 +331,22 @@ public: delete p; } } + +#ifndef U_HIDE_DRAFT_API + /** + * Conversion operator to a C++11 std::unique_ptr. + * Disowns the object and gives it to the returned std::unique_ptr. + * + * This operator works via move semantics. If your LocalPointer is + * in a local variable, you must use std::move. + * + * @return An std::unique_ptr owning the pointer previously owned by this + * icu::LocalPointer. + * @draft ICU 64 + */ + operator std::unique_ptr () && { + return std::unique_ptr(LocalPointerBase::orphan()); + } #endif /* U_HIDE_DRAFT_API */ }; @@ -266,10 +358,10 @@ public: * Usage example: * \code * LocalArray a(new UnicodeString[2]); - * a[0].append((UChar)0x61); + * a[0].append((char16_t)0x61); * if(some condition) { return; } // no need to explicitly delete the array * a.adoptInstead(new UnicodeString[4]); - * a[3].append((UChar)0x62).append((UChar)0x63).reverse(); + * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse(); * // no need to explicitly delete the array * \endcode * @@ -279,12 +371,56 @@ public: template class LocalArray : public LocalPointerBase { public: + using LocalPointerBase::operator*; + using LocalPointerBase::operator->; /** * Constructor takes ownership. * @param p simple pointer to an array of T objects that is adopted * @stable ICU 4.4 */ explicit LocalArray(T *p=NULL) : LocalPointerBase(p) {} + /** + * 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 + * @stable ICU 56 + */ + LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase(p) { + if(p==NULL && U_SUCCESS(errorCode)) { + errorCode=U_MEMORY_ALLOCATION_ERROR; + } + } + /** + * Move constructor, leaves src with isNull(). + * @param src source smart pointer + * @stable ICU 56 + */ + LocalArray(LocalArray &&src) U_NOEXCEPT : LocalPointerBase(src.ptr) { + src.ptr=NULL; + } + +#ifndef U_HIDE_DRAFT_API + /** + * Constructs a LocalArray from a C++11 std::unique_ptr of an array type. + * The LocalPointer steals the array owned by the std::unique_ptr. + * + * This constructor works via move semantics. If your std::unique_ptr is + * in a local variable, you must use std::move. + * + * @param p The std::unique_ptr from which the array will be stolen. + * @draft ICU 64 + */ + explicit LocalArray(std::unique_ptr &&p) + : LocalPointerBase(p.release()) {} +#endif /* U_HIDE_DRAFT_API */ + /** * Destructor deletes the array it owns. * @stable ICU 4.4 @@ -292,6 +428,54 @@ public: ~LocalArray() { delete[] LocalPointerBase::ptr; } + /** + * 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 + * @stable ICU 56 + */ + LocalArray &operator=(LocalArray &&src) U_NOEXCEPT { + delete[] LocalPointerBase::ptr; + LocalPointerBase::ptr=src.ptr; + src.ptr=NULL; + return *this; + } + +#ifndef U_HIDE_DRAFT_API + /** + * Move-assign from an std::unique_ptr to this LocalPointer. + * Steals the array from the std::unique_ptr. + * + * @param p The std::unique_ptr from which the array will be stolen. + * @return *this + * @draft ICU 64 + */ + LocalArray &operator=(std::unique_ptr &&p) U_NOEXCEPT { + adoptInstead(p.release()); + return *this; + } +#endif /* U_HIDE_DRAFT_API */ + + /** + * Swap pointers. + * @param other other smart pointer + * @stable ICU 56 + */ + void swap(LocalArray &other) U_NOEXCEPT { + T *temp=LocalPointerBase::ptr; + LocalPointerBase::ptr=other.ptr; + other.ptr=temp; + } + /** + * Non-member LocalArray swap function. + * @param p1 will get p2's pointer + * @param p2 will get p1's pointer + * @stable ICU 56 + */ + friend inline void swap(LocalArray &p1, LocalArray &p2) U_NOEXCEPT { + p1.swap(p2); + } /** * Deletes the array it owns, * and adopts (takes ownership of) the one passed in. @@ -302,6 +486,32 @@ public: delete[] LocalPointerBase::ptr; LocalPointerBase::ptr=p; } + /** + * 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 + * @stable ICU 56 + */ + void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { + if(U_SUCCESS(errorCode)) { + delete[] LocalPointerBase::ptr; + LocalPointerBase::ptr=p; + if(p==NULL) { + errorCode=U_MEMORY_ALLOCATION_ERROR; + } + } else { + delete[] p; + } + } /** * Array item access (writable). * No index bounds check. @@ -310,6 +520,23 @@ public: * @stable ICU 4.4 */ T &operator[](ptrdiff_t i) const { return LocalPointerBase::ptr[i]; } + +#ifndef U_HIDE_DRAFT_API + /** + * Conversion operator to a C++11 std::unique_ptr. + * Disowns the object and gives it to the returned std::unique_ptr. + * + * This operator works via move semantics. If your LocalPointer is + * in a local variable, you must use std::move. + * + * @return An std::unique_ptr owning the pointer previously owned by this + * icu::LocalPointer. + * @draft ICU 64 + */ + operator std::unique_ptr () && { + return std::unique_ptr(LocalPointerBase::orphan()); + } +#endif /* U_HIDE_DRAFT_API */ }; /** @@ -319,9 +546,6 @@ public: * like LocalPointer except that this subclass will use the closeFunction * rather than the C++ delete operator. * - * Requirement: The closeFunction must tolerate a NULL pointer. - * (We could add a NULL check here but it is normally redundant.) - * * Usage example: * \code * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode)); @@ -338,12 +562,43 @@ public: #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ class LocalPointerClassName : public LocalPointerBase { \ public: \ + using LocalPointerBase::operator*; \ + using LocalPointerBase::operator->; \ explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase(p) {} \ - ~LocalPointerClassName() { closeFunction(ptr); } \ + LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \ + : LocalPointerBase(src.ptr) { \ + src.ptr=NULL; \ + } \ + /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \ + explicit LocalPointerClassName(std::unique_ptr &&p) \ + : LocalPointerBase(p.release()) {} \ + ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \ + LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \ + if (ptr != NULL) { closeFunction(ptr); } \ + LocalPointerBase::ptr=src.ptr; \ + src.ptr=NULL; \ + return *this; \ + } \ + /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \ + LocalPointerClassName &operator=(std::unique_ptr &&p) { \ + adoptInstead(p.release()); \ + return *this; \ + } \ + void swap(LocalPointerClassName &other) U_NOEXCEPT { \ + Type *temp=LocalPointerBase::ptr; \ + LocalPointerBase::ptr=other.ptr; \ + other.ptr=temp; \ + } \ + friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \ + p1.swap(p2); \ + } \ void adoptInstead(Type *p) { \ - closeFunction(ptr); \ + if (ptr != NULL) { closeFunction(ptr); } \ ptr=p; \ } \ + operator std::unique_ptr () && { \ + return std::unique_ptr(LocalPointerBase::orphan(), closeFunction); \ + } \ } U_NAMESPACE_END