Home | History | Annotate | Download | only in unicode
      1 //  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:   UTF-8
     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  * char16_t lead=s->charAt(0);  // 0xd900
    178  * if(some condition) { return; }  // no need to explicitly delete the pointer
    179  * s.adoptInstead(new UnicodeString((char16_t)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     /**
    217      * Move constructor, leaves src with isNull().
    218      * @param src source smart pointer
    219      * @stable ICU 56
    220      */
    221     LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
    222         src.ptr=NULL;
    223     }
    224     /**
    225      * Destructor deletes the object it owns.
    226      * @stable ICU 4.4
    227      */
    228     ~LocalPointer() {
    229         delete LocalPointerBase<T>::ptr;
    230     }
    231     /**
    232      * Move assignment operator, leaves src with isNull().
    233      * The behavior is undefined if *this and src are the same object.
    234      * @param src source smart pointer
    235      * @return *this
    236      * @stable ICU 56
    237      */
    238     LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT {
    239         return moveFrom(src);
    240     }
    241     // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API
    242     /**
    243      * Move assignment, leaves src with isNull().
    244      * The behavior is undefined if *this and src are the same object.
    245      *
    246      * Can be called explicitly, does not need C++11 support.
    247      * @param src source smart pointer
    248      * @return *this
    249      * @draft ICU 56
    250      */
    251     LocalPointer<T> &moveFrom(LocalPointer<T> &src) U_NOEXCEPT {
    252         delete LocalPointerBase<T>::ptr;
    253         LocalPointerBase<T>::ptr=src.ptr;
    254         src.ptr=NULL;
    255         return *this;
    256     }
    257     /**
    258      * Swap pointers.
    259      * @param other other smart pointer
    260      * @stable ICU 56
    261      */
    262     void swap(LocalPointer<T> &other) U_NOEXCEPT {
    263         T *temp=LocalPointerBase<T>::ptr;
    264         LocalPointerBase<T>::ptr=other.ptr;
    265         other.ptr=temp;
    266     }
    267     /**
    268      * Non-member LocalPointer swap function.
    269      * @param p1 will get p2's pointer
    270      * @param p2 will get p1's pointer
    271      * @stable ICU 56
    272      */
    273     friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT {
    274         p1.swap(p2);
    275     }
    276     /**
    277      * Deletes the object it owns,
    278      * and adopts (takes ownership of) the one passed in.
    279      * @param p simple pointer to an object that is adopted
    280      * @stable ICU 4.4
    281      */
    282     void adoptInstead(T *p) {
    283         delete LocalPointerBase<T>::ptr;
    284         LocalPointerBase<T>::ptr=p;
    285     }
    286     /**
    287      * Deletes the object it owns,
    288      * and adopts (takes ownership of) the one passed in.
    289      *
    290      * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
    291      *
    292      * If U_SUCCESS(errorCode) but the input pointer is NULL,
    293      * then U_MEMORY_ALLOCATION_ERROR is set,
    294      * the current object is deleted, and NULL is set.
    295      *
    296      * @param p simple pointer to an object that is adopted
    297      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
    298      *     if p==NULL and no other failure code had been set
    299      * @stable ICU 55
    300      */
    301     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
    302         if(U_SUCCESS(errorCode)) {
    303             delete LocalPointerBase<T>::ptr;
    304             LocalPointerBase<T>::ptr=p;
    305             if(p==NULL) {
    306                 errorCode=U_MEMORY_ALLOCATION_ERROR;
    307             }
    308         } else {
    309             delete p;
    310         }
    311     }
    312 };
    313 
    314 /**
    315  * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
    316  * For most methods see the LocalPointerBase base class.
    317  * Adds operator[] for array item access.
    318  *
    319  * Usage example:
    320  * \code
    321  * LocalArray<UnicodeString> a(new UnicodeString[2]);
    322  * a[0].append((char16_t)0x61);
    323  * if(some condition) { return; }  // no need to explicitly delete the array
    324  * a.adoptInstead(new UnicodeString[4]);
    325  * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse();
    326  * // no need to explicitly delete the array
    327  * \endcode
    328  *
    329  * @see LocalPointerBase
    330  * @stable ICU 4.4
    331  */
    332 template<typename T>
    333 class LocalArray : public LocalPointerBase<T> {
    334 public:
    335     using LocalPointerBase<T>::operator*;
    336     using LocalPointerBase<T>::operator->;
    337     /**
    338      * Constructor takes ownership.
    339      * @param p simple pointer to an array of T objects that is adopted
    340      * @stable ICU 4.4
    341      */
    342     explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {}
    343     /**
    344      * Constructor takes ownership and reports an error if NULL.
    345      *
    346      * This constructor is intended to be used with other-class constructors
    347      * that may report a failure UErrorCode,
    348      * so that callers need to check only for U_FAILURE(errorCode)
    349      * and not also separately for isNull().
    350      *
    351      * @param p simple pointer to an array of T objects that is adopted
    352      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
    353      *     if p==NULL and no other failure code had been set
    354      * @stable ICU 56
    355      */
    356     LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
    357         if(p==NULL && U_SUCCESS(errorCode)) {
    358             errorCode=U_MEMORY_ALLOCATION_ERROR;
    359         }
    360     }
    361     /**
    362      * Move constructor, leaves src with isNull().
    363      * @param src source smart pointer
    364      * @stable ICU 56
    365      */
    366     LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
    367         src.ptr=NULL;
    368     }
    369     /**
    370      * Destructor deletes the array it owns.
    371      * @stable ICU 4.4
    372      */
    373     ~LocalArray() {
    374         delete[] LocalPointerBase<T>::ptr;
    375     }
    376     /**
    377      * Move assignment operator, leaves src with isNull().
    378      * The behavior is undefined if *this and src are the same object.
    379      * @param src source smart pointer
    380      * @return *this
    381      * @stable ICU 56
    382      */
    383     LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT {
    384         return moveFrom(src);
    385     }
    386     // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API
    387     /**
    388      * Move assignment, leaves src with isNull().
    389      * The behavior is undefined if *this and src are the same object.
    390      *
    391      * Can be called explicitly, does not need C++11 support.
    392      * @param src source smart pointer
    393      * @return *this
    394      * @draft ICU 56
    395      */
    396     LocalArray<T> &moveFrom(LocalArray<T> &src) U_NOEXCEPT {
    397         delete[] LocalPointerBase<T>::ptr;
    398         LocalPointerBase<T>::ptr=src.ptr;
    399         src.ptr=NULL;
    400         return *this;
    401     }
    402     /**
    403      * Swap pointers.
    404      * @param other other smart pointer
    405      * @stable ICU 56
    406      */
    407     void swap(LocalArray<T> &other) U_NOEXCEPT {
    408         T *temp=LocalPointerBase<T>::ptr;
    409         LocalPointerBase<T>::ptr=other.ptr;
    410         other.ptr=temp;
    411     }
    412     /**
    413      * Non-member LocalArray swap function.
    414      * @param p1 will get p2's pointer
    415      * @param p2 will get p1's pointer
    416      * @stable ICU 56
    417      */
    418     friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT {
    419         p1.swap(p2);
    420     }
    421     /**
    422      * Deletes the array it owns,
    423      * and adopts (takes ownership of) the one passed in.
    424      * @param p simple pointer to an array of T objects that is adopted
    425      * @stable ICU 4.4
    426      */
    427     void adoptInstead(T *p) {
    428         delete[] LocalPointerBase<T>::ptr;
    429         LocalPointerBase<T>::ptr=p;
    430     }
    431     /**
    432      * Deletes the array it owns,
    433      * and adopts (takes ownership of) the one passed in.
    434      *
    435      * If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
    436      *
    437      * If U_SUCCESS(errorCode) but the input pointer is NULL,
    438      * then U_MEMORY_ALLOCATION_ERROR is set,
    439      * the current array is deleted, and NULL is set.
    440      *
    441      * @param p simple pointer to an array of T objects that is adopted
    442      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
    443      *     if p==NULL and no other failure code had been set
    444      * @stable ICU 56
    445      */
    446     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
    447         if(U_SUCCESS(errorCode)) {
    448             delete[] LocalPointerBase<T>::ptr;
    449             LocalPointerBase<T>::ptr=p;
    450             if(p==NULL) {
    451                 errorCode=U_MEMORY_ALLOCATION_ERROR;
    452             }
    453         } else {
    454             delete[] p;
    455         }
    456     }
    457     /**
    458      * Array item access (writable).
    459      * No index bounds check.
    460      * @param i array index
    461      * @return reference to the array item
    462      * @stable ICU 4.4
    463      */
    464     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
    465 };
    466 
    467 /**
    468  * \def U_DEFINE_LOCAL_OPEN_POINTER
    469  * "Smart pointer" definition macro, deletes objects via the closeFunction.
    470  * Defines a subclass of LocalPointerBase which works just
    471  * like LocalPointer<Type> except that this subclass will use the closeFunction
    472  * rather than the C++ delete operator.
    473  *
    474  * Usage example:
    475  * \code
    476  * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
    477  * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
    478  *     utf8Out, (int32_t)sizeof(utf8Out),
    479  *     utf8In, utf8InLength, &errorCode);
    480  * if(U_FAILURE(errorCode)) { return; }  // no need to explicitly delete the UCaseMap
    481  * \endcode
    482  *
    483  * @see LocalPointerBase
    484  * @see LocalPointer
    485  * @stable ICU 4.4
    486  */
    487 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
    488     class LocalPointerClassName : public LocalPointerBase<Type> { \
    489     public: \
    490         using LocalPointerBase<Type>::operator*; \
    491         using LocalPointerBase<Type>::operator->; \
    492         explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
    493         LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \
    494                 : LocalPointerBase<Type>(src.ptr) { \
    495             src.ptr=NULL; \
    496         } \
    497         ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \
    498         LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
    499             return moveFrom(src); \
    500         } \
    501         LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \
    502             if (ptr != NULL) { closeFunction(ptr); } \
    503             LocalPointerBase<Type>::ptr=src.ptr; \
    504             src.ptr=NULL; \
    505             return *this; \
    506         } \
    507         void swap(LocalPointerClassName &other) U_NOEXCEPT { \
    508             Type *temp=LocalPointerBase<Type>::ptr; \
    509             LocalPointerBase<Type>::ptr=other.ptr; \
    510             other.ptr=temp; \
    511         } \
    512         friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
    513             p1.swap(p2); \
    514         } \
    515         void adoptInstead(Type *p) { \
    516             if (ptr != NULL) { closeFunction(ptr); } \
    517             ptr=p; \
    518         } \
    519     }
    520 
    521 U_NAMESPACE_END
    522 
    523 #endif  /* U_SHOW_CPLUSPLUS_API */
    524 #endif  /* __LOCALPOINTER_H__ */
    525