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