• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <memory>
46 
47 U_NAMESPACE_BEGIN
48 
49 /**
50  * "Smart pointer" base class; do not use directly: use LocalPointer etc.
51  *
52  * Base class for smart pointer classes that do not throw exceptions.
53  *
54  * Do not use this base class directly, since it does not delete its pointer.
55  * A subclass must implement methods that delete the pointer:
56  * Destructor and adoptInstead().
57  *
58  * There is no operator T *() provided because the programmer must decide
59  * whether to use getAlias() (without transfer of ownership) or orphan()
60  * (with transfer of ownership and NULLing of the pointer).
61  *
62  * @see LocalPointer
63  * @see LocalArray
64  * @see U_DEFINE_LOCAL_OPEN_POINTER
65  * @stable ICU 4.4
66  */
67 template<typename T>
68 class LocalPointerBase {
69 public:
70     // No heap allocation. Use only on the stack.
71     static void* U_EXPORT2 operator new(size_t) = delete;
72     static void* U_EXPORT2 operator new[](size_t) = delete;
73 #if U_HAVE_PLACEMENT_NEW
74     static void* U_EXPORT2 operator new(size_t, void*) = delete;
75 #endif
76 
77     /**
78      * Constructor takes ownership.
79      * @param p simple pointer to an object that is adopted
80      * @stable ICU 4.4
81      */
ptr(p)82     explicit LocalPointerBase(T *p=NULL) : ptr(p) {}
83     /**
84      * Destructor deletes the object it owns.
85      * Subclass must override: Base class does nothing.
86      * @stable ICU 4.4
87      */
~LocalPointerBase()88     ~LocalPointerBase() { /* delete ptr; */ }
89     /**
90      * NULL check.
91      * @return true if ==NULL
92      * @stable ICU 4.4
93      */
isNull()94     UBool isNull() const { return ptr==NULL; }
95     /**
96      * NULL check.
97      * @return true if !=NULL
98      * @stable ICU 4.4
99      */
isValid()100     UBool isValid() const { return ptr!=NULL; }
101     /**
102      * Comparison with a simple pointer, so that existing code
103      * with ==NULL need not be changed.
104      * @param other simple pointer for comparison
105      * @return true if this pointer value equals other
106      * @stable ICU 4.4
107      */
108     bool operator==(const T *other) const { return ptr==other; }
109     /**
110      * Comparison with a simple pointer, so that existing code
111      * with !=NULL need not be changed.
112      * @param other simple pointer for comparison
113      * @return true if this pointer value differs from other
114      * @stable ICU 4.4
115      */
116     bool operator!=(const T *other) const { return ptr!=other; }
117     /**
118      * Access without ownership change.
119      * @return the pointer value
120      * @stable ICU 4.4
121      */
getAlias()122     T *getAlias() const { return ptr; }
123     /**
124      * Access without ownership change.
125      * @return the pointer value as a reference
126      * @stable ICU 4.4
127      */
128     T &operator*() const { return *ptr; }
129     /**
130      * Access without ownership change.
131      * @return the pointer value
132      * @stable ICU 4.4
133      */
134     T *operator->() const { return ptr; }
135     /**
136      * Gives up ownership; the internal pointer becomes NULL.
137      * @return the pointer value;
138      *         caller becomes responsible for deleting the object
139      * @stable ICU 4.4
140      */
orphan()141     T *orphan() {
142         T *p=ptr;
143         ptr=NULL;
144         return p;
145     }
146     /**
147      * Deletes the object it owns,
148      * and adopts (takes ownership of) the one passed in.
149      * Subclass must override: Base class does not delete the object.
150      * @param p simple pointer to an object that is adopted
151      * @stable ICU 4.4
152      */
adoptInstead(T * p)153     void adoptInstead(T *p) {
154         // delete ptr;
155         ptr=p;
156     }
157 protected:
158     /**
159      * Actual pointer.
160      * @internal
161      */
162     T *ptr;
163 private:
164     // No comparison operators with other LocalPointerBases.
165     bool operator==(const LocalPointerBase<T> &other);
166     bool operator!=(const LocalPointerBase<T> &other);
167     // No ownership sharing: No copy constructor, no assignment operator.
168     LocalPointerBase(const LocalPointerBase<T> &other);
169     void operator=(const LocalPointerBase<T> &other);
170 };
171 
172 /**
173  * "Smart pointer" class, deletes objects via the standard C++ delete operator.
174  * For most methods see the LocalPointerBase base class.
175  *
176  * Usage example:
177  * \code
178  * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005));
179  * int32_t length=s->length();  // 2
180  * char16_t lead=s->charAt(0);  // 0xd900
181  * if(some condition) { return; }  // no need to explicitly delete the pointer
182  * s.adoptInstead(new UnicodeString((char16_t)0xfffc));
183  * length=s->length();  // 1
184  * // no need to explicitly delete the pointer
185  * \endcode
186  *
187  * @see LocalPointerBase
188  * @stable ICU 4.4
189  */
190 template<typename T>
191 class LocalPointer : public LocalPointerBase<T> {
192 public:
193     using LocalPointerBase<T>::operator*;
194     using LocalPointerBase<T>::operator->;
195     /**
196      * Constructor takes ownership.
197      * @param p simple pointer to an object that is adopted
198      * @stable ICU 4.4
199      */
200     explicit LocalPointer(T *p=NULL) : LocalPointerBase<T>(p) {}
201     /**
202      * Constructor takes ownership and reports an error if NULL.
203      *
204      * This constructor is intended to be used with other-class constructors
205      * that may report a failure UErrorCode,
206      * so that callers need to check only for U_FAILURE(errorCode)
207      * and not also separately for isNull().
208      *
209      * @param p simple pointer to an object that is adopted
210      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
211      *     if p==NULL and no other failure code had been set
212      * @stable ICU 55
213      */
LocalPointer(T * p,UErrorCode & errorCode)214     LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
215         if(p==NULL && U_SUCCESS(errorCode)) {
216             errorCode=U_MEMORY_ALLOCATION_ERROR;
217         }
218     }
219     /**
220      * Move constructor, leaves src with isNull().
221      * @param src source smart pointer
222      * @stable ICU 56
223      */
LocalPointer(LocalPointer<T> && src)224     LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
225         src.ptr=NULL;
226     }
227 
228     /**
229      * Constructs a LocalPointer from a C++11 std::unique_ptr.
230      * The LocalPointer steals the object owned by the std::unique_ptr.
231      *
232      * This constructor works via move semantics. If your std::unique_ptr is
233      * in a local variable, you must use std::move.
234      *
235      * @param p The std::unique_ptr from which the pointer will be stolen.
236      * @stable ICU 64
237      */
LocalPointer(std::unique_ptr<T> && p)238     explicit LocalPointer(std::unique_ptr<T> &&p)
239         : LocalPointerBase<T>(p.release()) {}
240 
241     /**
242      * Destructor deletes the object it owns.
243      * @stable ICU 4.4
244      */
~LocalPointer()245     ~LocalPointer() {
246         delete LocalPointerBase<T>::ptr;
247     }
248     /**
249      * Move assignment operator, leaves src with isNull().
250      * The behavior is undefined if *this and src are the same object.
251      * @param src source smart pointer
252      * @return *this
253      * @stable ICU 56
254      */
255     LocalPointer<T> &operator=(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     /**
263      * Move-assign from an std::unique_ptr to this LocalPointer.
264      * Steals the pointer from the std::unique_ptr.
265      *
266      * @param p The std::unique_ptr from which the pointer will be stolen.
267      * @return *this
268      * @stable ICU 64
269      */
270     LocalPointer<T> &operator=(std::unique_ptr<T> &&p) U_NOEXCEPT {
271         adoptInstead(p.release());
272         return *this;
273     }
274 
275     /**
276      * Swap pointers.
277      * @param other other smart pointer
278      * @stable ICU 56
279      */
swap(LocalPointer<T> & other)280     void swap(LocalPointer<T> &other) U_NOEXCEPT {
281         T *temp=LocalPointerBase<T>::ptr;
282         LocalPointerBase<T>::ptr=other.ptr;
283         other.ptr=temp;
284     }
285     /**
286      * Non-member LocalPointer swap function.
287      * @param p1 will get p2's pointer
288      * @param p2 will get p1's pointer
289      * @stable ICU 56
290      */
swap(LocalPointer<T> & p1,LocalPointer<T> & p2)291     friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT {
292         p1.swap(p2);
293     }
294     /**
295      * Deletes the object it owns,
296      * and adopts (takes ownership of) the one passed in.
297      * @param p simple pointer to an object that is adopted
298      * @stable ICU 4.4
299      */
adoptInstead(T * p)300     void adoptInstead(T *p) {
301         delete LocalPointerBase<T>::ptr;
302         LocalPointerBase<T>::ptr=p;
303     }
304     /**
305      * Deletes the object it owns,
306      * and adopts (takes ownership of) the one passed in.
307      *
308      * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
309      *
310      * If U_SUCCESS(errorCode) but the input pointer is NULL,
311      * then U_MEMORY_ALLOCATION_ERROR is set,
312      * the current object is deleted, and NULL is set.
313      *
314      * @param p simple pointer to an object that is adopted
315      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
316      *     if p==NULL and no other failure code had been set
317      * @stable ICU 55
318      */
adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)319     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
320         if(U_SUCCESS(errorCode)) {
321             delete LocalPointerBase<T>::ptr;
322             LocalPointerBase<T>::ptr=p;
323             if(p==NULL) {
324                 errorCode=U_MEMORY_ALLOCATION_ERROR;
325             }
326         } else {
327             delete p;
328         }
329     }
330 
331     /**
332      * Conversion operator to a C++11 std::unique_ptr.
333      * Disowns the object and gives it to the returned std::unique_ptr.
334      *
335      * This operator works via move semantics. If your LocalPointer is
336      * in a local variable, you must use std::move.
337      *
338      * @return An std::unique_ptr owning the pointer previously owned by this
339      *         icu::LocalPointer.
340      * @stable ICU 64
341      */
342     operator std::unique_ptr<T> () && {
343         return std::unique_ptr<T>(LocalPointerBase<T>::orphan());
344     }
345 };
346 
347 /**
348  * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
349  * For most methods see the LocalPointerBase base class.
350  * Adds operator[] for array item access.
351  *
352  * Usage example:
353  * \code
354  * LocalArray<UnicodeString> a(new UnicodeString[2]);
355  * a[0].append((char16_t)0x61);
356  * if(some condition) { return; }  // no need to explicitly delete the array
357  * a.adoptInstead(new UnicodeString[4]);
358  * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse();
359  * // no need to explicitly delete the array
360  * \endcode
361  *
362  * @see LocalPointerBase
363  * @stable ICU 4.4
364  */
365 template<typename T>
366 class LocalArray : public LocalPointerBase<T> {
367 public:
368     using LocalPointerBase<T>::operator*;
369     using LocalPointerBase<T>::operator->;
370     /**
371      * Constructor takes ownership.
372      * @param p simple pointer to an array of T objects that is adopted
373      * @stable ICU 4.4
374      */
375     explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {}
376     /**
377      * Constructor takes ownership and reports an error if NULL.
378      *
379      * This constructor is intended to be used with other-class constructors
380      * that may report a failure UErrorCode,
381      * so that callers need to check only for U_FAILURE(errorCode)
382      * and not also separately for isNull().
383      *
384      * @param p simple pointer to an array of T objects that is adopted
385      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
386      *     if p==NULL and no other failure code had been set
387      * @stable ICU 56
388      */
LocalArray(T * p,UErrorCode & errorCode)389     LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
390         if(p==NULL && U_SUCCESS(errorCode)) {
391             errorCode=U_MEMORY_ALLOCATION_ERROR;
392         }
393     }
394     /**
395      * Move constructor, leaves src with isNull().
396      * @param src source smart pointer
397      * @stable ICU 56
398      */
LocalArray(LocalArray<T> && src)399     LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
400         src.ptr=NULL;
401     }
402 
403     /**
404      * Constructs a LocalArray from a C++11 std::unique_ptr of an array type.
405      * The LocalPointer steals the array owned by the std::unique_ptr.
406      *
407      * This constructor works via move semantics. If your std::unique_ptr is
408      * in a local variable, you must use std::move.
409      *
410      * @param p The std::unique_ptr from which the array will be stolen.
411      * @stable ICU 64
412      */
LocalArray(std::unique_ptr<T[]> && p)413     explicit LocalArray(std::unique_ptr<T[]> &&p)
414         : LocalPointerBase<T>(p.release()) {}
415 
416     /**
417      * Destructor deletes the array it owns.
418      * @stable ICU 4.4
419      */
~LocalArray()420     ~LocalArray() {
421         delete[] LocalPointerBase<T>::ptr;
422     }
423     /**
424      * Move assignment operator, leaves src with isNull().
425      * The behavior is undefined if *this and src are the same object.
426      * @param src source smart pointer
427      * @return *this
428      * @stable ICU 56
429      */
430     LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT {
431         delete[] LocalPointerBase<T>::ptr;
432         LocalPointerBase<T>::ptr=src.ptr;
433         src.ptr=NULL;
434         return *this;
435     }
436 
437     /**
438      * Move-assign from an std::unique_ptr to this LocalPointer.
439      * Steals the array from the std::unique_ptr.
440      *
441      * @param p The std::unique_ptr from which the array will be stolen.
442      * @return *this
443      * @stable ICU 64
444      */
445     LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) U_NOEXCEPT {
446         adoptInstead(p.release());
447         return *this;
448     }
449 
450     /**
451      * Swap pointers.
452      * @param other other smart pointer
453      * @stable ICU 56
454      */
swap(LocalArray<T> & other)455     void swap(LocalArray<T> &other) U_NOEXCEPT {
456         T *temp=LocalPointerBase<T>::ptr;
457         LocalPointerBase<T>::ptr=other.ptr;
458         other.ptr=temp;
459     }
460     /**
461      * Non-member LocalArray swap function.
462      * @param p1 will get p2's pointer
463      * @param p2 will get p1's pointer
464      * @stable ICU 56
465      */
swap(LocalArray<T> & p1,LocalArray<T> & p2)466     friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT {
467         p1.swap(p2);
468     }
469     /**
470      * Deletes the array it owns,
471      * and adopts (takes ownership of) the one passed in.
472      * @param p simple pointer to an array of T objects that is adopted
473      * @stable ICU 4.4
474      */
adoptInstead(T * p)475     void adoptInstead(T *p) {
476         delete[] LocalPointerBase<T>::ptr;
477         LocalPointerBase<T>::ptr=p;
478     }
479     /**
480      * Deletes the array it owns,
481      * and adopts (takes ownership of) the one passed in.
482      *
483      * If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
484      *
485      * If U_SUCCESS(errorCode) but the input pointer is NULL,
486      * then U_MEMORY_ALLOCATION_ERROR is set,
487      * the current array is deleted, and NULL is set.
488      *
489      * @param p simple pointer to an array of T objects that is adopted
490      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
491      *     if p==NULL and no other failure code had been set
492      * @stable ICU 56
493      */
adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)494     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
495         if(U_SUCCESS(errorCode)) {
496             delete[] LocalPointerBase<T>::ptr;
497             LocalPointerBase<T>::ptr=p;
498             if(p==NULL) {
499                 errorCode=U_MEMORY_ALLOCATION_ERROR;
500             }
501         } else {
502             delete[] p;
503         }
504     }
505     /**
506      * Array item access (writable).
507      * No index bounds check.
508      * @param i array index
509      * @return reference to the array item
510      * @stable ICU 4.4
511      */
512     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
513 
514     /**
515      * Conversion operator to a C++11 std::unique_ptr.
516      * Disowns the object and gives it to the returned std::unique_ptr.
517      *
518      * This operator works via move semantics. If your LocalPointer is
519      * in a local variable, you must use std::move.
520      *
521      * @return An std::unique_ptr owning the pointer previously owned by this
522      *         icu::LocalPointer.
523      * @stable ICU 64
524      */
525     operator std::unique_ptr<T[]> () && {
526         return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan());
527     }
528 };
529 
530 /**
531  * \def U_DEFINE_LOCAL_OPEN_POINTER
532  * "Smart pointer" definition macro, deletes objects via the closeFunction.
533  * Defines a subclass of LocalPointerBase which works just
534  * like LocalPointer<Type> except that this subclass will use the closeFunction
535  * rather than the C++ delete operator.
536  *
537  * Usage example:
538  * \code
539  * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
540  * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
541  *     utf8Out, (int32_t)sizeof(utf8Out),
542  *     utf8In, utf8InLength, &errorCode);
543  * if(U_FAILURE(errorCode)) { return; }  // no need to explicitly delete the UCaseMap
544  * \endcode
545  *
546  * @see LocalPointerBase
547  * @see LocalPointer
548  * @stable ICU 4.4
549  */
550 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
551     class LocalPointerClassName : public LocalPointerBase<Type> { \
552     public: \
553         using LocalPointerBase<Type>::operator*; \
554         using LocalPointerBase<Type>::operator->; \
555         explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
556         LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \
557                 : LocalPointerBase<Type>(src.ptr) { \
558             src.ptr=NULL; \
559         } \
560         /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
561         explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \
562                 : LocalPointerBase<Type>(p.release()) {} \
563         ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \
564         LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
565             if (ptr != NULL) { closeFunction(ptr); } \
566             LocalPointerBase<Type>::ptr=src.ptr; \
567             src.ptr=NULL; \
568             return *this; \
569         } \
570         /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
571         LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
572             adoptInstead(p.release()); \
573             return *this; \
574         } \
575         void swap(LocalPointerClassName &other) U_NOEXCEPT { \
576             Type *temp=LocalPointerBase<Type>::ptr; \
577             LocalPointerBase<Type>::ptr=other.ptr; \
578             other.ptr=temp; \
579         } \
580         friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
581             p1.swap(p2); \
582         } \
583         void adoptInstead(Type *p) { \
584             if (ptr != NULL) { closeFunction(ptr); } \
585             ptr=p; \
586         } \
587         operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
588             return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
589         } \
590     }
591 
592 U_NAMESPACE_END
593 
594 #endif  /* U_SHOW_CPLUSPLUS_API */
595 #endif  /* __LOCALPOINTER_H__ */
596