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