• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
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<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      */
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 #if U_HAVE_RVALUE_REFERENCES
214     /**
215      * Move constructor, leaves src with isNull().
216      * @param src source smart pointer
217      * @draft ICU 56
218      */
LocalPointer(LocalPointer<T> && src)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      */
~LocalPointer()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      */
moveFrom(LocalPointer<T> & src)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      */
swap(LocalPointer<T> & other)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      */
swap(LocalPointer<T> & p1,LocalPointer<T> & p2)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      */
adoptInstead(T * p)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      */
adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)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      */
LocalArray(T * p,UErrorCode & errorCode)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      */
LocalArray(LocalArray<T> && src)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      */
~LocalArray()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      */
moveFrom(LocalArray<T> & src)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      */
swap(LocalArray<T> & other)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      */
swap(LocalArray<T> & p1,LocalArray<T> & p2)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      */
adoptInstead(T * p)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      */
adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)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