123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 |
- // © 2016 and later: Unicode, Inc. and others.
- // License & terms of use: http://www.unicode.org/copyright.html
- /*
- *******************************************************************************
- *
- * Copyright (C) 2009-2016, International Business Machines
- * Corporation and others. All Rights Reserved.
- *
- *******************************************************************************
- * file name: localpointer.h
- * encoding: UTF-8
- * tab size: 8 (not used)
- * indentation:4
- *
- * created on: 2009nov13
- * created by: Markus W. Scherer
- */
- #ifndef __LOCALPOINTER_H__
- #define __LOCALPOINTER_H__
- /**
- * \file
- * \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code.
- *
- * These classes are inspired by
- * - std::auto_ptr
- * - boost::scoped_ptr & boost::scoped_array
- * - Taligent Safe Pointers (TOnlyPointerTo)
- *
- * but none of those provide for all of the goals for ICU smart pointers:
- * - Smart pointer owns the object and releases it when it goes out of scope.
- * - No transfer of ownership via copy/assignment to reduce misuse. Simpler & more robust.
- * - ICU-compatible: No exceptions.
- * - Need to be able to orphan/release the pointer and its ownership.
- * - Need variants for normal C++ object pointers, C++ arrays, and ICU C service objects.
- *
- * For details see https://icu.unicode.org/design/cpp/scoped_ptr
- */
- #include "unicode/utypes.h"
- #if U_SHOW_CPLUSPLUS_API
- #include <memory>
- U_NAMESPACE_BEGIN
- /**
- * "Smart pointer" base class; do not use directly: use LocalPointer etc.
- *
- * Base class for smart pointer classes that do not throw exceptions.
- *
- * Do not use this base class directly, since it does not delete its pointer.
- * A subclass must implement methods that delete the pointer:
- * Destructor and adoptInstead().
- *
- * There is no operator T *() provided because the programmer must decide
- * whether to use getAlias() (without transfer of ownership) or orphan()
- * (with transfer of ownership and NULLing of the pointer).
- *
- * @see LocalPointer
- * @see LocalArray
- * @see U_DEFINE_LOCAL_OPEN_POINTER
- * @stable ICU 4.4
- */
- template<typename T>
- 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
- * @stable ICU 4.4
- */
- explicit LocalPointerBase(T *p=nullptr) : ptr(p) {}
- /**
- * Destructor deletes the object it owns.
- * Subclass must override: Base class does nothing.
- * @stable ICU 4.4
- */
- ~LocalPointerBase() { /* delete ptr; */ }
- /**
- * nullptr check.
- * @return true if ==nullptr
- * @stable ICU 4.4
- */
- UBool isNull() const { return ptr==nullptr; }
- /**
- * nullptr check.
- * @return true if !=nullptr
- * @stable ICU 4.4
- */
- UBool isValid() const { return ptr!=nullptr; }
- /**
- * Comparison with a simple pointer, so that existing code
- * with ==nullptr need not be changed.
- * @param other simple pointer for comparison
- * @return true if this pointer value equals other
- * @stable ICU 4.4
- */
- bool operator==(const T *other) const { return ptr==other; }
- /**
- * Comparison with a simple pointer, so that existing code
- * with !=nullptr need not be changed.
- * @param other simple pointer for comparison
- * @return true if this pointer value differs from other
- * @stable ICU 4.4
- */
- bool operator!=(const T *other) const { return ptr!=other; }
- /**
- * Access without ownership change.
- * @return the pointer value
- * @stable ICU 4.4
- */
- T *getAlias() const { return ptr; }
- /**
- * Access without ownership change.
- * @return the pointer value as a reference
- * @stable ICU 4.4
- */
- T &operator*() const { return *ptr; }
- /**
- * Access without ownership change.
- * @return the pointer value
- * @stable ICU 4.4
- */
- T *operator->() const { return ptr; }
- /**
- * Gives up ownership; the internal pointer becomes nullptr.
- * @return the pointer value;
- * caller becomes responsible for deleting the object
- * @stable ICU 4.4
- */
- T *orphan() {
- T *p=ptr;
- ptr=nullptr;
- return p;
- }
- /**
- * Deletes the object it owns,
- * and adopts (takes ownership of) the one passed in.
- * Subclass must override: Base class does not delete the object.
- * @param p simple pointer to an object that is adopted
- * @stable ICU 4.4
- */
- void adoptInstead(T *p) {
- // delete ptr;
- ptr=p;
- }
- protected:
- /**
- * Actual pointer.
- * @internal
- */
- T *ptr;
- private:
- // No comparison operators with other LocalPointerBases.
- 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);
- };
- /**
- * "Smart pointer" class, deletes objects via the standard C++ delete operator.
- * For most methods see the LocalPointerBase base class.
- *
- * Usage example:
- * \code
- * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
- * int32_t length=s->length(); // 2
- * char16_t lead=s->charAt(0); // 0xd900
- * if(some condition) { return; } // no need to explicitly delete the pointer
- * s.adoptInstead(new UnicodeString((char16_t)0xfffc));
- * length=s->length(); // 1
- * // no need to explicitly delete the pointer
- * \endcode
- *
- * @see LocalPointerBase
- * @stable ICU 4.4
- */
- template<typename T>
- class LocalPointer : public LocalPointerBase<T> {
- public:
- using LocalPointerBase<T>::operator*;
- using LocalPointerBase<T>::operator->;
- /**
- * Constructor takes ownership.
- * @param p simple pointer to an object that is adopted
- * @stable ICU 4.4
- */
- explicit LocalPointer(T *p=nullptr) : LocalPointerBase<T>(p) {}
- /**
- * Constructor takes ownership and reports an error if nullptr.
- *
- * 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 object that is adopted
- * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
- * if p==nullptr and no other failure code had been set
- * @stable ICU 55
- */
- LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
- if(p==nullptr && U_SUCCESS(errorCode)) {
- errorCode=U_MEMORY_ALLOCATION_ERROR;
- }
- }
- /**
- * Move constructor, leaves src with isNull().
- * @param src source smart pointer
- * @stable ICU 56
- */
- LocalPointer(LocalPointer<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
- src.ptr=nullptr;
- }
- /**
- * 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.
- * @stable ICU 64
- */
- explicit LocalPointer(std::unique_ptr<T> &&p)
- : LocalPointerBase<T>(p.release()) {}
- /**
- * Destructor deletes the object it owns.
- * @stable ICU 4.4
- */
- ~LocalPointer() {
- delete LocalPointerBase<T>::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<T> &operator=(LocalPointer<T> &&src) noexcept {
- delete LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::ptr=src.ptr;
- src.ptr=nullptr;
- return *this;
- }
- /**
- * 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
- * @stable ICU 64
- */
- LocalPointer<T> &operator=(std::unique_ptr<T> &&p) noexcept {
- adoptInstead(p.release());
- return *this;
- }
- /**
- * Swap pointers.
- * @param other other smart pointer
- * @stable ICU 56
- */
- void swap(LocalPointer<T> &other) noexcept {
- T *temp=LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::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<T> &p1, LocalPointer<T> &p2) noexcept {
- p1.swap(p2);
- }
- /**
- * Deletes the object it owns,
- * and adopts (takes ownership of) the one passed in.
- * @param p simple pointer to an object that is adopted
- * @stable ICU 4.4
- */
- void adoptInstead(T *p) {
- delete LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::ptr=p;
- }
- /**
- * Deletes the object it owns,
- * and adopts (takes ownership of) the one passed in.
- *
- * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
- *
- * If U_SUCCESS(errorCode) but the input pointer is nullptr,
- * then U_MEMORY_ALLOCATION_ERROR is set,
- * the current object is deleted, and nullptr is set.
- *
- * @param p simple pointer to an object that is adopted
- * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
- * if p==nullptr and no other failure code had been set
- * @stable ICU 55
- */
- void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
- if(U_SUCCESS(errorCode)) {
- delete LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::ptr=p;
- if(p==nullptr) {
- errorCode=U_MEMORY_ALLOCATION_ERROR;
- }
- } else {
- delete p;
- }
- }
- /**
- * 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.
- * @stable ICU 64
- */
- operator std::unique_ptr<T> () && {
- return std::unique_ptr<T>(LocalPointerBase<T>::orphan());
- }
- };
- /**
- * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
- * For most methods see the LocalPointerBase base class.
- * Adds operator[] for array item access.
- *
- * Usage example:
- * \code
- * LocalArray<UnicodeString> a(new UnicodeString[2]);
- * 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((char16_t)0x62).append((char16_t)0x63).reverse();
- * // no need to explicitly delete the array
- * \endcode
- *
- * @see LocalPointerBase
- * @stable ICU 4.4
- */
- template<typename T>
- class LocalArray : public LocalPointerBase<T> {
- public:
- using LocalPointerBase<T>::operator*;
- using LocalPointerBase<T>::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=nullptr) : LocalPointerBase<T>(p) {}
- /**
- * Constructor takes ownership and reports an error if nullptr.
- *
- * 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==nullptr and no other failure code had been set
- * @stable ICU 56
- */
- LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
- if(p==nullptr && U_SUCCESS(errorCode)) {
- errorCode=U_MEMORY_ALLOCATION_ERROR;
- }
- }
- /**
- * Move constructor, leaves src with isNull().
- * @param src source smart pointer
- * @stable ICU 56
- */
- LocalArray(LocalArray<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
- src.ptr=nullptr;
- }
- /**
- * 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.
- * @stable ICU 64
- */
- explicit LocalArray(std::unique_ptr<T[]> &&p)
- : LocalPointerBase<T>(p.release()) {}
- /**
- * Destructor deletes the array it owns.
- * @stable ICU 4.4
- */
- ~LocalArray() {
- delete[] LocalPointerBase<T>::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<T> &operator=(LocalArray<T> &&src) noexcept {
- delete[] LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::ptr=src.ptr;
- src.ptr=nullptr;
- return *this;
- }
- /**
- * 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
- * @stable ICU 64
- */
- LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) noexcept {
- adoptInstead(p.release());
- return *this;
- }
- /**
- * Swap pointers.
- * @param other other smart pointer
- * @stable ICU 56
- */
- void swap(LocalArray<T> &other) noexcept {
- T *temp=LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::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<T> &p1, LocalArray<T> &p2) noexcept {
- p1.swap(p2);
- }
- /**
- * Deletes the array it owns,
- * and adopts (takes ownership of) the one passed in.
- * @param p simple pointer to an array of T objects that is adopted
- * @stable ICU 4.4
- */
- void adoptInstead(T *p) {
- delete[] LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::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 nullptr,
- * then U_MEMORY_ALLOCATION_ERROR is set,
- * the current array is deleted, and nullptr 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==nullptr and no other failure code had been set
- * @stable ICU 56
- */
- void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
- if(U_SUCCESS(errorCode)) {
- delete[] LocalPointerBase<T>::ptr;
- LocalPointerBase<T>::ptr=p;
- if(p==nullptr) {
- errorCode=U_MEMORY_ALLOCATION_ERROR;
- }
- } else {
- delete[] p;
- }
- }
- /**
- * Array item access (writable).
- * No index bounds check.
- * @param i array index
- * @return reference to the array item
- * @stable ICU 4.4
- */
- T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
- /**
- * 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.
- * @stable ICU 64
- */
- operator std::unique_ptr<T[]> () && {
- return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan());
- }
- };
- /**
- * \def U_DEFINE_LOCAL_OPEN_POINTER
- * "Smart pointer" definition macro, deletes objects via the closeFunction.
- * Defines a subclass of LocalPointerBase which works just
- * like LocalPointer<Type> except that this subclass will use the closeFunction
- * rather than the C++ delete operator.
- *
- * Usage example:
- * \code
- * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
- * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
- * utf8Out, (int32_t)sizeof(utf8Out),
- * utf8In, utf8InLength, &errorCode);
- * if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap
- * \endcode
- *
- * @see LocalPointerBase
- * @see LocalPointer
- * @stable ICU 4.4
- */
- #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
- class LocalPointerClassName : public LocalPointerBase<Type> { \
- public: \
- using LocalPointerBase<Type>::operator*; \
- using LocalPointerBase<Type>::operator->; \
- explicit LocalPointerClassName(Type *p=nullptr) : LocalPointerBase<Type>(p) {} \
- LocalPointerClassName(LocalPointerClassName &&src) noexcept \
- : LocalPointerBase<Type>(src.ptr) { \
- src.ptr=nullptr; \
- } \
- /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
- explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \
- : LocalPointerBase<Type>(p.release()) {} \
- ~LocalPointerClassName() { if (ptr != nullptr) { closeFunction(ptr); } } \
- LocalPointerClassName &operator=(LocalPointerClassName &&src) noexcept { \
- if (ptr != nullptr) { closeFunction(ptr); } \
- LocalPointerBase<Type>::ptr=src.ptr; \
- src.ptr=nullptr; \
- return *this; \
- } \
- /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
- LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
- adoptInstead(p.release()); \
- return *this; \
- } \
- void swap(LocalPointerClassName &other) noexcept { \
- Type *temp=LocalPointerBase<Type>::ptr; \
- LocalPointerBase<Type>::ptr=other.ptr; \
- other.ptr=temp; \
- } \
- friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) noexcept { \
- p1.swap(p2); \
- } \
- void adoptInstead(Type *p) { \
- if (ptr != nullptr) { closeFunction(ptr); } \
- ptr=p; \
- } \
- operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
- return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
- } \
- }
- U_NAMESPACE_END
- #endif /* U_SHOW_CPLUSPLUS_API */
- #endif /* __LOCALPOINTER_H__ */
|