1 /*
2 *******************************************************************************
3 *
4 *   Copyright (C) 2009-2014, 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      */
ptr(p)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      */
~LocalPointerBase()77     ~LocalPointerBase() { /* delete ptr; */ }
78     /**
79      * NULL check.
80      * @return TRUE if ==NULL
81      * @stable ICU 4.4
82      */
isNull()83     UBool isNull() const { return ptr==NULL; }
84     /**
85      * NULL check.
86      * @return TRUE if !=NULL
87      * @stable ICU 4.4
88      */
isValid()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      */
getAlias()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      */
orphan()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      */
adoptInstead(T * p)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 &other);
155     bool operator!=(const LocalPointerBase &other);
156     // No ownership transfer: No copy constructor, no assignment operator.
157     LocalPointerBase(const LocalPointerBase &other);
158     void operator=(const LocalPointerBase &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      */
LocalPointer(T * p,UErrorCode & errorCode)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 #endif  /* U_HIDE_DRAFT_API */
214     /**
215      * Destructor deletes the object it owns.
216      * @stable ICU 4.4
217      */
~LocalPointer()218     ~LocalPointer() {
219         delete LocalPointerBase<T>::ptr;
220     }
221     /**
222      * Deletes the object it owns,
223      * and adopts (takes ownership of) the one passed in.
224      * @param p simple pointer to an object that is adopted
225      * @stable ICU 4.4
226      */
adoptInstead(T * p)227     void adoptInstead(T *p) {
228         delete LocalPointerBase<T>::ptr;
229         LocalPointerBase<T>::ptr=p;
230     }
231 #ifndef U_HIDE_DRAFT_API
232     /**
233      * Deletes the object it owns,
234      * and adopts (takes ownership of) the one passed in.
235      *
236      * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
237      *
238      * If U_SUCCESS(errorCode) but the input pointer is NULL,
239      * then U_MEMORY_ALLOCATION_ERROR is set,
240      * the current object is deleted, and NULL is set.
241      *
242      * @param p simple pointer to an object that is adopted
243      * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
244      *     if p==NULL and no other failure code had been set
245      * @draft ICU 55
246      */
adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)247     void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
248         if(U_SUCCESS(errorCode)) {
249             delete LocalPointerBase<T>::ptr;
250             LocalPointerBase<T>::ptr=p;
251             if(p==NULL) {
252                 errorCode=U_MEMORY_ALLOCATION_ERROR;
253             }
254         } else {
255             delete p;
256         }
257     }
258 #endif  /* U_HIDE_DRAFT_API */
259 };
260 
261 /**
262  * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
263  * For most methods see the LocalPointerBase base class.
264  * Adds operator[] for array item access.
265  *
266  * Usage example:
267  * \code
268  * LocalArray<UnicodeString> a(new UnicodeString[2]);
269  * a[0].append((UChar)0x61);
270  * if(some condition) { return; }  // no need to explicitly delete the array
271  * a.adoptInstead(new UnicodeString[4]);
272  * a[3].append((UChar)0x62).append((UChar)0x63).reverse();
273  * // no need to explicitly delete the array
274  * \endcode
275  *
276  * @see LocalPointerBase
277  * @stable ICU 4.4
278  */
279 template<typename T>
280 class LocalArray : public LocalPointerBase<T> {
281 public:
282     /**
283      * Constructor takes ownership.
284      * @param p simple pointer to an array of T objects that is adopted
285      * @stable ICU 4.4
286      */
287     explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {}
288     /**
289      * Destructor deletes the array it owns.
290      * @stable ICU 4.4
291      */
~LocalArray()292     ~LocalArray() {
293         delete[] LocalPointerBase<T>::ptr;
294     }
295     /**
296      * Deletes the array it owns,
297      * and adopts (takes ownership of) the one passed in.
298      * @param p simple pointer to an array of T objects that is adopted
299      * @stable ICU 4.4
300      */
adoptInstead(T * p)301     void adoptInstead(T *p) {
302         delete[] LocalPointerBase<T>::ptr;
303         LocalPointerBase<T>::ptr=p;
304     }
305     /**
306      * Array item access (writable).
307      * No index bounds check.
308      * @param i array index
309      * @return reference to the array item
310      * @stable ICU 4.4
311      */
312     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
313 };
314 
315 /**
316  * \def U_DEFINE_LOCAL_OPEN_POINTER
317  * "Smart pointer" definition macro, deletes objects via the closeFunction.
318  * Defines a subclass of LocalPointerBase which works just
319  * like LocalPointer<Type> except that this subclass will use the closeFunction
320  * rather than the C++ delete operator.
321  *
322  * Requirement: The closeFunction must tolerate a NULL pointer.
323  * (We could add a NULL check here but it is normally redundant.)
324  *
325  * Usage example:
326  * \code
327  * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
328  * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
329  *     utf8Out, (int32_t)sizeof(utf8Out),
330  *     utf8In, utf8InLength, &errorCode);
331  * if(U_FAILURE(errorCode)) { return; }  // no need to explicitly delete the UCaseMap
332  * \endcode
333  *
334  * @see LocalPointerBase
335  * @see LocalPointer
336  * @stable ICU 4.4
337  */
338 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
339     class LocalPointerClassName : public LocalPointerBase<Type> { \
340     public: \
341         explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
342         ~LocalPointerClassName() { closeFunction(ptr); } \
343         void adoptInstead(Type *p) { \
344             closeFunction(ptr); \
345             ptr=p; \
346         } \
347     }
348 
349 U_NAMESPACE_END
350 
351 #endif  /* U_SHOW_CPLUSPLUS_API */
352 #endif  /* __LOCALPOINTER_H__ */
353