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
45U_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 */
65template<typename T>
66class LocalPointerBase {
67public:
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 }
148protected:
149 /**
150 * Actual pointer.
151 * @internal
152 */
153 T *ptr;
154private:
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 */
187template<typename T>
188class LocalPointer : public LocalPointerBase<T> {
189public:
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 */
332template<typename T>
333class LocalArray : public LocalPointerBase<T> {
334public:
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
521U_NAMESPACE_END
522
523#endif /* U_SHOW_CPLUSPLUS_API */
524#endif /* __LOCALPOINTER_H__ */
525