Home | History | Annotate | Download | only in unicode
      1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 *******************************************************************************
      5 *
      6 *   Copyright (C) 2009-2016, International Business Machines
      7 *   Corporation and others.  All Rights Reserved.
      8 *
      9 *******************************************************************************
     10 *   file name:  localpointer.h
     11 *   encoding:   US-ASCII
     12 *   tab size:   8 (not used)
     13 *   indentation:4
     14 *
     15 *   created on: 2009nov13
     16 *   created by: Markus W. Scherer
     17 */
     18 
     19 #ifndef __LOCALPOINTER_H__
     20 #define __LOCALPOINTER_H__
     21 
     22 /**
     23  * \file
     24  * \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code.
     25  *
     26  * These classes are inspired by
     27  * - std::auto_ptr
     28  * - boost::scoped_ptr & boost::scoped_array
     29  * - Taligent Safe Pointers (TOnlyPointerTo)
     30  *
     31  * but none of those provide for all of the goals for ICU smart pointers:
     32  * - Smart pointer owns the object and releases it when it goes out of scope.
     33  * - No transfer of ownership via copy/assignment to reduce misuse. Simpler & more robust.
     34  * - ICU-compatible: No exceptions.
     35  * - Need to be able to orphan/release the pointer and its ownership.
     36  * - Need variants for normal C++ object pointers, C++ arrays, and ICU C service objects.
     37  *
     38  * For details see http://site.icu-project.org/design/cpp/scoped_ptr
     39  */
     40 
     41 #include "unicode/utypes.h"
     42 
     43 #if U_SHOW_CPLUSPLUS_API
     44 
     45 U_NAMESPACE_BEGIN
     46 
     47 /**
     48  * "Smart pointer" base class; do not use directly: use LocalPointer etc.
     49  *
     50  * Base class for smart pointer classes that do not throw exceptions.
     51  *
     52  * Do not use this base class directly, since it does not delete its pointer.
     53  * A subclass must implement methods that delete the pointer:
     54  * Destructor and adoptInstead().
     55  *
     56  * There is no operator T *() provided because the programmer must decide
     57  * whether to use getAlias() (without transfer of ownership) or orphan()
     58  * (with transfer of ownership and NULLing of the pointer).
     59  *
     60  * @see LocalPointer
     61  * @see LocalArray
     62  * @see U_DEFINE_LOCAL_OPEN_POINTER
     63  * @stable ICU 4.4
     64  */
     65 template<typename T>
     66 class LocalPointerBase {
     67 public:
     68     /**
     69      * Constructor takes ownership.
     70      * @param p simple pointer to an object that is adopted
     71      * @stable ICU 4.4
     72      */
     73     explicit LocalPointerBase(T *p=NULL) : ptr(p) {}
     74     /**
     75      * Destructor deletes the object it owns.
     76      * Subclass must override: Base class does nothing.
     77      * @stable ICU 4.4
     78      */
     79     ~LocalPointerBase() { /* delete ptr; */ }
     80     /**
     81      * NULL check.
     82      * @return TRUE if ==NULL
     83      * @stable ICU 4.4
     84      */
     85     UBool isNull() const { return ptr==NULL; }
     86     /**
     87      * NULL check.
     88      * @return TRUE if !=NULL
     89      * @stable ICU 4.4
     90      */
     91     UBool isValid() const { return ptr!=NULL; }
     92     /**
     93      * Comparison with a simple pointer, so that existing code
     94      * with ==NULL need not be changed.
     95      * @param other simple pointer for comparison
     96      * @return true if this pointer value equals other
     97      * @stable ICU 4.4
     98      */
     99     bool operator==(const T *other) const { return ptr==other; }
    100     /**
    101      * Comparison with a simple pointer, so that existing code
    102      * with !=NULL need not be changed.
    103      * @param other simple pointer for comparison
    104      * @return true if this pointer value differs from other
    105      * @stable ICU 4.4
    106      */
    107     bool operator!=(const T *other) const { return ptr!=other; }
    108     /**
    109      * Access without ownership change.
    110      * @return the pointer value
    111      * @stable ICU 4.4
    112      */
    113     T *getAlias() const { return ptr; }
    114     /**
    115      * Access without ownership change.
    116      * @return the pointer value as a reference
    117      * @stable ICU 4.4
    118      */
    119     T &operator*() const { return *ptr; }
    120     /**
    121      * Access without ownership change.
    122      * @return the pointer value
    123      * @stable ICU 4.4
    124      */
    125     T *operator->() const { return ptr; }
    126     /**
    127      * Gives up ownership; the internal pointer becomes NULL.
    128      * @return the pointer value;
    129      *         caller becomes responsible for deleting the object
    130      * @stable ICU 4.4
    131      */
    132     T *orphan() {
    133         T *p=ptr;
    134         ptr=NULL;
    135         return p;
    136     }
    137     /**
    138      * Deletes the object it owns,
    139      * and adopts (takes ownership of) the one passed in.
    140      * Subclass must override: Base class does not delete the object.
    141      * @param p simple pointer to an object that is adopted
    142      * @stable ICU 4.4
    143      */
    144     void adoptInstead(T *p) {
    145         // delete ptr;
    146         ptr=p;
    147     }
    148 protected:
    149     /**
    150      * Actual pointer.
    151      * @internal
    152      */
    153     T *ptr;
    154 private:
    155     // No comparison operators with other LocalPointerBases.
    156     bool operator==(const LocalPointerBase<T> &other);
    157     bool operator!=(const LocalPointerBase<T> &other);
    158     // No ownership sharing: No copy constructor, no assignment operator.
    159     LocalPointerBase(const LocalPointerBase<T> &other);
    160     void operator=(const LocalPointerBase<T> &other);
    161     // No heap allocation. Use only on the stack.
    162     static void * U_EXPORT2 operator new(size_t size);
    163     static void * U_EXPORT2 operator new[](size_t size);
    164 #if U_HAVE_PLACEMENT_NEW
    165     static void * U_EXPORT2 operator new(size_t, void *ptr);
    166 #endif
    167 };
    168 
    169 /**
    170  * "Smart pointer" class, deletes objects via the standard C++ delete operator.
    171  * For most methods see the LocalPointerBase base class.
    172  *
    173  * Usage example:
    174  * \code
    175  * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
    176  * int32_t length=s->length();  // 2
    177  * UChar lead=s->charAt(0);  // 0xd900
    178  * if(some condition) { return; }  // no need to explicitly delete the pointer
    179  * s.adoptInstead(new UnicodeString((UChar)0xfffc));
    180  * length=s->length();  // 1
    181  * // no need to explicitly delete the pointer
    182  * \endcode
    183  *
    184  * @see LocalPointerBase
    185  * @stable ICU 4.4
    186  */
    187 template<typename T>
    188 class LocalPointer : public LocalPointerBase<T> {
    189 public:
    190     using LocalPointerBase<T>::operator*;
    191     using LocalPointerBase<T>::operator->;
    192     /**
    193      * Constructor takes ownership.
    194      * @param p simple pointer to an object that is adopted
    195      * @stable ICU 4.4
    196      */
    197     explicit LocalPointer(T *p=NULL) : LocalPointerBase<T>(p) {}
    198     /**
    199      * Constructor takes ownership and reports an error if NULL.
    200      *
    201      * This constructor is intended to be used with other-class constructors
    202      * that may report a failure UErrorCode,
    203      * so that callers need to check only for U_FAILURE(errorCode)
    204      * and not also separately for isNull().
    205      *
    206      * @param p simple pointer to an object that is adopted
    207      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
    208      *     if p==NULL and no other failure code had been set
    209      * @stable ICU 55
    210      */
    211     LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
    212         if(p==NULL && U_SUCCESS(errorCode)) {
    213             errorCode=U_MEMORY_ALLOCATION_ERROR;
    214         }
    215     }
    216 #if U_HAVE_RVALUE_REFERENCES
    217     /**
    218      * Move constructor, leaves src with isNull().
    219      * @param src source smart pointer
    220      * @stable ICU 56
    221      */
    222     LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
    223         src.ptr=NULL;
    224     }
    225 #endif
    226     /**
    227      * Destructor deletes the object it owns.
    228      * @stable ICU 4.4
    229      */
    230     ~LocalPointer() {
    231         delete LocalPointerBase<T>::ptr;
    232     }
    233 #if U_HAVE_RVALUE_REFERENCES
    234     /**
    235      * Move assignment operator, leaves src with isNull().
    236      * The behavior is undefined if *this and src are the same object.
    237      * @param src source smart pointer
    238      * @return *this
    239      * @stable ICU 56
    240      */
    241     LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT {
    242         return moveFrom(src);
    243     }
    244 #endif
    245     // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API
    246     /**
    247      * Move assignment, leaves src with isNull().
    248      * The behavior is undefined if *this and src are the same object.
    249      *
    250      * Can be called explicitly, does not need C++11 support.
    251      * @param src source smart pointer
    252      * @return *this
    253      * @draft ICU 56
    254      */
    255     LocalPointer<T> &moveFrom(LocalPointer<T> &src) U_NOEXCEPT {
    256         delete LocalPointerBase<T>::ptr;
    257         LocalPointerBase<T>::ptr=src.ptr;
    258         src.ptr=NULL;
    259         return *this;
    260     }
    261     /**
    262      * Swap pointers.
    263      * @param other other smart pointer
    264      * @stable ICU 56
    265      */
    266     void swap(LocalPointer<T> &other) U_NOEXCEPT {
    267         T *temp=LocalPointerBase<T>::ptr;
    268         LocalPointerBase<T>::ptr=other.ptr;
    269         other.ptr=temp;
    270     }
    271     /**
    272      * Non-member LocalPointer swap function.
    273      * @param p1 will get p2's pointer
    274      * @param p2 will get p1's pointer
    275      * @stable ICU 56
    276      */
    277     friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT {
    278         p1.swap(p2);
    279     }
    280     /**
    281      * Deletes the object it owns,
    282      * and adopts (takes ownership of) the one passed in.
    283      * @param p simple pointer to an object that is adopted
    284      * @stable ICU 4.4
    285      */
    286     void adoptInstead(T *p) {
    287         delete LocalPointerBase<T>::ptr;
    288         LocalPointerBase<T>::ptr=p;
    289     }
    290     /**
    291      * Deletes the object it owns,
    292      * and adopts (takes ownership of) the one passed in.
    293      *
    294      * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
    295      *
    296      * If U_SUCCESS(errorCode) but the input pointer is NULL,
    297      * then U_MEMORY_ALLOCATION_ERROR is set,
    298      * the current object is deleted, and NULL is set.
    299      *
    300      * @param p simple pointer to an object that is adopted
    301      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
    302      *     if p==NULL and no other failure code had been set
    303      * @stable ICU 55
    304      */
    305     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
    306         if(U_SUCCESS(errorCode)) {
    307             delete LocalPointerBase<T>::ptr;
    308             LocalPointerBase<T>::ptr=p;
    309             if(p==NULL) {
    310                 errorCode=U_MEMORY_ALLOCATION_ERROR;
    311             }
    312         } else {
    313             delete p;
    314         }
    315     }
    316 };
    317 
    318 /**
    319  * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
    320  * For most methods see the LocalPointerBase base class.
    321  * Adds operator[] for array item access.
    322  *
    323  * Usage example:
    324  * \code
    325  * LocalArray<UnicodeString> a(new UnicodeString[2]);
    326  * a[0].append((UChar)0x61);
    327  * if(some condition) { return; }  // no need to explicitly delete the array
    328  * a.adoptInstead(new UnicodeString[4]);
    329  * a[3].append((UChar)0x62).append((UChar)0x63).reverse();
    330  * // no need to explicitly delete the array
    331  * \endcode
    332  *
    333  * @see LocalPointerBase
    334  * @stable ICU 4.4
    335  */
    336 template<typename T>
    337 class LocalArray : public LocalPointerBase<T> {
    338 public:
    339     using LocalPointerBase<T>::operator*;
    340     using LocalPointerBase<T>::operator->;
    341     /**
    342      * Constructor takes ownership.
    343      * @param p simple pointer to an array of T objects that is adopted
    344      * @stable ICU 4.4
    345      */
    346     explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {}
    347     /**
    348      * Constructor takes ownership and reports an error if NULL.
    349      *
    350      * This constructor is intended to be used with other-class constructors
    351      * that may report a failure UErrorCode,
    352      * so that callers need to check only for U_FAILURE(errorCode)
    353      * and not also separately for isNull().
    354      *
    355      * @param p simple pointer to an array of T objects that is adopted
    356      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
    357      *     if p==NULL and no other failure code had been set
    358      * @stable ICU 56
    359      */
    360     LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
    361         if(p==NULL && U_SUCCESS(errorCode)) {
    362             errorCode=U_MEMORY_ALLOCATION_ERROR;
    363         }
    364     }
    365 #if U_HAVE_RVALUE_REFERENCES
    366     /**
    367      * Move constructor, leaves src with isNull().
    368      * @param src source smart pointer
    369      * @stable ICU 56
    370      */
    371     LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
    372         src.ptr=NULL;
    373     }
    374 #endif
    375     /**
    376      * Destructor deletes the array it owns.
    377      * @stable ICU 4.4
    378      */
    379     ~LocalArray() {
    380         delete[] LocalPointerBase<T>::ptr;
    381     }
    382 #if U_HAVE_RVALUE_REFERENCES
    383     /**
    384      * Move assignment operator, leaves src with isNull().
    385      * The behavior is undefined if *this and src are the same object.
    386      * @param src source smart pointer
    387      * @return *this
    388      * @stable ICU 56
    389      */
    390     LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT {
    391         return moveFrom(src);
    392     }
    393 #endif
    394     // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API
    395     /**
    396      * Move assignment, leaves src with isNull().
    397      * The behavior is undefined if *this and src are the same object.
    398      *
    399      * Can be called explicitly, does not need C++11 support.
    400      * @param src source smart pointer
    401      * @return *this
    402      * @draft ICU 56
    403      */
    404     LocalArray<T> &moveFrom(LocalArray<T> &src) U_NOEXCEPT {
    405         delete[] LocalPointerBase<T>::ptr;
    406         LocalPointerBase<T>::ptr=src.ptr;
    407         src.ptr=NULL;
    408         return *this;
    409     }
    410     /**
    411      * Swap pointers.
    412      * @param other other smart pointer
    413      * @stable ICU 56
    414      */
    415     void swap(LocalArray<T> &other) U_NOEXCEPT {
    416         T *temp=LocalPointerBase<T>::ptr;
    417         LocalPointerBase<T>::ptr=other.ptr;
    418         other.ptr=temp;
    419     }
    420     /**
    421      * Non-member LocalArray swap function.
    422      * @param p1 will get p2's pointer
    423      * @param p2 will get p1's pointer
    424      * @stable ICU 56
    425      */
    426     friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT {
    427         p1.swap(p2);
    428     }
    429     /**
    430      * Deletes the array it owns,
    431      * and adopts (takes ownership of) the one passed in.
    432      * @param p simple pointer to an array of T objects that is adopted
    433      * @stable ICU 4.4
    434      */
    435     void adoptInstead(T *p) {
    436         delete[] LocalPointerBase<T>::ptr;
    437         LocalPointerBase<T>::ptr=p;
    438     }
    439     /**
    440      * Deletes the array it owns,
    441      * and adopts (takes ownership of) the one passed in.
    442      *
    443      * If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
    444      *
    445      * If U_SUCCESS(errorCode) but the input pointer is NULL,
    446      * then U_MEMORY_ALLOCATION_ERROR is set,
    447      * the current array is deleted, and NULL is set.
    448      *
    449      * @param p simple pointer to an array of T objects that is adopted
    450      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
    451      *     if p==NULL and no other failure code had been set
    452      * @stable ICU 56
    453      */
    454     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
    455         if(U_SUCCESS(errorCode)) {
    456             delete[] LocalPointerBase<T>::ptr;
    457             LocalPointerBase<T>::ptr=p;
    458             if(p==NULL) {
    459                 errorCode=U_MEMORY_ALLOCATION_ERROR;
    460             }
    461         } else {
    462             delete[] p;
    463         }
    464     }
    465     /**
    466      * Array item access (writable).
    467      * No index bounds check.
    468      * @param i array index
    469      * @return reference to the array item
    470      * @stable ICU 4.4
    471      */
    472     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
    473 };
    474 
    475 /**
    476  * \def U_DEFINE_LOCAL_OPEN_POINTER
    477  * "Smart pointer" definition macro, deletes objects via the closeFunction.
    478  * Defines a subclass of LocalPointerBase which works just
    479  * like LocalPointer<Type> except that this subclass will use the closeFunction
    480  * rather than the C++ delete operator.
    481  *
    482  * Usage example:
    483  * \code
    484  * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
    485  * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
    486  *     utf8Out, (int32_t)sizeof(utf8Out),
    487  *     utf8In, utf8InLength, &errorCode);
    488  * if(U_FAILURE(errorCode)) { return; }  // no need to explicitly delete the UCaseMap
    489  * \endcode
    490  *
    491  * @see LocalPointerBase
    492  * @see LocalPointer
    493  * @stable ICU 4.4
    494  */
    495 #if U_HAVE_RVALUE_REFERENCES
    496 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
    497     class LocalPointerClassName : public LocalPointerBase<Type> { \
    498     public: \
    499         using LocalPointerBase<Type>::operator*; \
    500         using LocalPointerBase<Type>::operator->; \
    501         explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
    502         LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \
    503                 : LocalPointerBase<Type>(src.ptr) { \
    504             src.ptr=NULL; \
    505         } \
    506         ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \
    507         LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
    508             return moveFrom(src); \
    509         } \
    510         LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \
    511             if (ptr != NULL) { closeFunction(ptr); } \
    512             LocalPointerBase<Type>::ptr=src.ptr; \
    513             src.ptr=NULL; \
    514             return *this; \
    515         } \
    516         void swap(LocalPointerClassName &other) U_NOEXCEPT { \
    517             Type *temp=LocalPointerBase<Type>::ptr; \
    518             LocalPointerBase<Type>::ptr=other.ptr; \
    519             other.ptr=temp; \
    520         } \
    521         friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
    522             p1.swap(p2); \
    523         } \
    524         void adoptInstead(Type *p) { \
    525             if (ptr != NULL) { closeFunction(ptr); } \
    526             ptr=p; \
    527         } \
    528     }
    529 #else
    530 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
    531     class LocalPointerClassName : public LocalPointerBase<Type> { \
    532     public: \
    533         using LocalPointerBase<Type>::operator*; \
    534         using LocalPointerBase<Type>::operator->; \
    535         explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
    536         ~LocalPointerClassName() { closeFunction(ptr); } \
    537         LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \
    538             if (ptr != NULL) { closeFunction(ptr); } \
    539             LocalPointerBase<Type>::ptr=src.ptr; \
    540             src.ptr=NULL; \
    541             return *this; \
    542         } \
    543         void swap(LocalPointerClassName &other) U_NOEXCEPT { \
    544             Type *temp=LocalPointerBase<Type>::ptr; \
    545             LocalPointerBase<Type>::ptr=other.ptr; \
    546             other.ptr=temp; \
    547         } \
    548         friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
    549             p1.swap(p2); \
    550         } \
    551         void adoptInstead(Type *p) { \
    552             if (ptr != NULL) { closeFunction(ptr); } \
    553             ptr=p; \
    554         } \
    555     }
    556 #endif
    557 
    558 U_NAMESPACE_END
    559 
    560 #endif  /* U_SHOW_CPLUSPLUS_API */
    561 #endif  /* __LOCALPOINTER_H__ */
    562