blob: e011688b1a54df61696c868dc85754c65ccb9f8b [file] [log] [blame]
Victor Changb3d5c8b2020-08-12 16:47:36 +01001// © 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
47U_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 */
67template<typename T>
68class LocalPointerBase {
69public:
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 */
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 */
88 ~LocalPointerBase() { /* delete ptr; */ }
89 /**
90 * NULL check.
91 * @return TRUE if ==NULL
92 * @stable ICU 4.4
93 */
94 UBool isNull() const { return ptr==NULL; }
95 /**
96 * NULL check.
97 * @return TRUE if !=NULL
98 * @stable ICU 4.4
99 */
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 */
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 */
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 */
153 void adoptInstead(T *p) {
154 // delete ptr;
155 ptr=p;
156 }
157protected:
158 /**
159 * Actual pointer.
160 * @internal
161 */
162 T *ptr;
163private:
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 */
190template<typename T>
191class LocalPointer : public LocalPointerBase<T> {
192public:
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 */
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 */
224 LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
225 src.ptr=NULL;
226 }
227
228#ifndef U_HIDE_DRAFT_API
229 /**
230 * Constructs a LocalPointer from a C++11 std::unique_ptr.
231 * The LocalPointer steals the object owned by the std::unique_ptr.
232 *
233 * This constructor works via move semantics. If your std::unique_ptr is
234 * in a local variable, you must use std::move.
235 *
236 * @param p The std::unique_ptr from which the pointer will be stolen.
237 * @draft ICU 64
238 */
239 explicit LocalPointer(std::unique_ptr<T> &&p)
240 : LocalPointerBase<T>(p.release()) {}
241#endif /* U_HIDE_DRAFT_API */
242
243 /**
244 * Destructor deletes the object it owns.
245 * @stable ICU 4.4
246 */
247 ~LocalPointer() {
248 delete LocalPointerBase<T>::ptr;
249 }
250 /**
251 * Move assignment operator, leaves src with isNull().
252 * The behavior is undefined if *this and src are the same object.
253 * @param src source smart pointer
254 * @return *this
255 * @stable ICU 56
256 */
257 LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT {
258 delete LocalPointerBase<T>::ptr;
259 LocalPointerBase<T>::ptr=src.ptr;
260 src.ptr=NULL;
261 return *this;
262 }
263
264#ifndef U_HIDE_DRAFT_API
265 /**
266 * Move-assign from an std::unique_ptr to this LocalPointer.
267 * Steals the pointer from the std::unique_ptr.
268 *
269 * @param p The std::unique_ptr from which the pointer will be stolen.
270 * @return *this
271 * @draft ICU 64
272 */
273 LocalPointer<T> &operator=(std::unique_ptr<T> &&p) U_NOEXCEPT {
274 adoptInstead(p.release());
275 return *this;
276 }
277#endif /* U_HIDE_DRAFT_API */
278
279 /**
280 * Swap pointers.
281 * @param other other smart pointer
282 * @stable ICU 56
283 */
284 void swap(LocalPointer<T> &other) U_NOEXCEPT {
285 T *temp=LocalPointerBase<T>::ptr;
286 LocalPointerBase<T>::ptr=other.ptr;
287 other.ptr=temp;
288 }
289 /**
290 * Non-member LocalPointer swap function.
291 * @param p1 will get p2's pointer
292 * @param p2 will get p1's pointer
293 * @stable ICU 56
294 */
295 friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT {
296 p1.swap(p2);
297 }
298 /**
299 * Deletes the object it owns,
300 * and adopts (takes ownership of) the one passed in.
301 * @param p simple pointer to an object that is adopted
302 * @stable ICU 4.4
303 */
304 void adoptInstead(T *p) {
305 delete LocalPointerBase<T>::ptr;
306 LocalPointerBase<T>::ptr=p;
307 }
308 /**
309 * Deletes the object it owns,
310 * and adopts (takes ownership of) the one passed in.
311 *
312 * If U_FAILURE(errorCode), then the current object is retained and the new one deleted.
313 *
314 * If U_SUCCESS(errorCode) but the input pointer is NULL,
315 * then U_MEMORY_ALLOCATION_ERROR is set,
316 * the current object is deleted, and NULL is set.
317 *
318 * @param p simple pointer to an object that is adopted
319 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
320 * if p==NULL and no other failure code had been set
321 * @stable ICU 55
322 */
323 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
324 if(U_SUCCESS(errorCode)) {
325 delete LocalPointerBase<T>::ptr;
326 LocalPointerBase<T>::ptr=p;
327 if(p==NULL) {
328 errorCode=U_MEMORY_ALLOCATION_ERROR;
329 }
330 } else {
331 delete p;
332 }
333 }
334
335#ifndef U_HIDE_DRAFT_API
336 /**
337 * Conversion operator to a C++11 std::unique_ptr.
338 * Disowns the object and gives it to the returned std::unique_ptr.
339 *
340 * This operator works via move semantics. If your LocalPointer is
341 * in a local variable, you must use std::move.
342 *
343 * @return An std::unique_ptr owning the pointer previously owned by this
344 * icu::LocalPointer.
345 * @draft ICU 64
346 */
347 operator std::unique_ptr<T> () && {
348 return std::unique_ptr<T>(LocalPointerBase<T>::orphan());
349 }
350#endif /* U_HIDE_DRAFT_API */
351};
352
353/**
354 * "Smart pointer" class, deletes objects via the C++ array delete[] operator.
355 * For most methods see the LocalPointerBase base class.
356 * Adds operator[] for array item access.
357 *
358 * Usage example:
359 * \code
360 * LocalArray<UnicodeString> a(new UnicodeString[2]);
361 * a[0].append((char16_t)0x61);
362 * if(some condition) { return; } // no need to explicitly delete the array
363 * a.adoptInstead(new UnicodeString[4]);
364 * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse();
365 * // no need to explicitly delete the array
366 * \endcode
367 *
368 * @see LocalPointerBase
369 * @stable ICU 4.4
370 */
371template<typename T>
372class LocalArray : public LocalPointerBase<T> {
373public:
374 using LocalPointerBase<T>::operator*;
375 using LocalPointerBase<T>::operator->;
376 /**
377 * Constructor takes ownership.
378 * @param p simple pointer to an array of T objects that is adopted
379 * @stable ICU 4.4
380 */
381 explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {}
382 /**
383 * Constructor takes ownership and reports an error if NULL.
384 *
385 * This constructor is intended to be used with other-class constructors
386 * that may report a failure UErrorCode,
387 * so that callers need to check only for U_FAILURE(errorCode)
388 * and not also separately for isNull().
389 *
390 * @param p simple pointer to an array of T objects that is adopted
391 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
392 * if p==NULL and no other failure code had been set
393 * @stable ICU 56
394 */
395 LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
396 if(p==NULL && U_SUCCESS(errorCode)) {
397 errorCode=U_MEMORY_ALLOCATION_ERROR;
398 }
399 }
400 /**
401 * Move constructor, leaves src with isNull().
402 * @param src source smart pointer
403 * @stable ICU 56
404 */
405 LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
406 src.ptr=NULL;
407 }
408
409#ifndef U_HIDE_DRAFT_API
410 /**
411 * Constructs a LocalArray from a C++11 std::unique_ptr of an array type.
412 * The LocalPointer steals the array owned by the std::unique_ptr.
413 *
414 * This constructor works via move semantics. If your std::unique_ptr is
415 * in a local variable, you must use std::move.
416 *
417 * @param p The std::unique_ptr from which the array will be stolen.
418 * @draft ICU 64
419 */
420 explicit LocalArray(std::unique_ptr<T[]> &&p)
421 : LocalPointerBase<T>(p.release()) {}
422#endif /* U_HIDE_DRAFT_API */
423
424 /**
425 * Destructor deletes the array it owns.
426 * @stable ICU 4.4
427 */
428 ~LocalArray() {
429 delete[] LocalPointerBase<T>::ptr;
430 }
431 /**
432 * Move assignment operator, leaves src with isNull().
433 * The behavior is undefined if *this and src are the same object.
434 * @param src source smart pointer
435 * @return *this
436 * @stable ICU 56
437 */
438 LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT {
439 delete[] LocalPointerBase<T>::ptr;
440 LocalPointerBase<T>::ptr=src.ptr;
441 src.ptr=NULL;
442 return *this;
443 }
444
445#ifndef U_HIDE_DRAFT_API
446 /**
447 * Move-assign from an std::unique_ptr to this LocalPointer.
448 * Steals the array from the std::unique_ptr.
449 *
450 * @param p The std::unique_ptr from which the array will be stolen.
451 * @return *this
452 * @draft ICU 64
453 */
454 LocalArray<T> &operator=(std::unique_ptr<T[]> &&p) U_NOEXCEPT {
455 adoptInstead(p.release());
456 return *this;
457 }
458#endif /* U_HIDE_DRAFT_API */
459
460 /**
461 * Swap pointers.
462 * @param other other smart pointer
463 * @stable ICU 56
464 */
465 void swap(LocalArray<T> &other) U_NOEXCEPT {
466 T *temp=LocalPointerBase<T>::ptr;
467 LocalPointerBase<T>::ptr=other.ptr;
468 other.ptr=temp;
469 }
470 /**
471 * Non-member LocalArray swap function.
472 * @param p1 will get p2's pointer
473 * @param p2 will get p1's pointer
474 * @stable ICU 56
475 */
476 friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT {
477 p1.swap(p2);
478 }
479 /**
480 * Deletes the array it owns,
481 * and adopts (takes ownership of) the one passed in.
482 * @param p simple pointer to an array of T objects that is adopted
483 * @stable ICU 4.4
484 */
485 void adoptInstead(T *p) {
486 delete[] LocalPointerBase<T>::ptr;
487 LocalPointerBase<T>::ptr=p;
488 }
489 /**
490 * Deletes the array it owns,
491 * and adopts (takes ownership of) the one passed in.
492 *
493 * If U_FAILURE(errorCode), then the current array is retained and the new one deleted.
494 *
495 * If U_SUCCESS(errorCode) but the input pointer is NULL,
496 * then U_MEMORY_ALLOCATION_ERROR is set,
497 * the current array is deleted, and NULL is set.
498 *
499 * @param p simple pointer to an array of T objects that is adopted
500 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR
501 * if p==NULL and no other failure code had been set
502 * @stable ICU 56
503 */
504 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) {
505 if(U_SUCCESS(errorCode)) {
506 delete[] LocalPointerBase<T>::ptr;
507 LocalPointerBase<T>::ptr=p;
508 if(p==NULL) {
509 errorCode=U_MEMORY_ALLOCATION_ERROR;
510 }
511 } else {
512 delete[] p;
513 }
514 }
515 /**
516 * Array item access (writable).
517 * No index bounds check.
518 * @param i array index
519 * @return reference to the array item
520 * @stable ICU 4.4
521 */
522 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
523
524#ifndef U_HIDE_DRAFT_API
525 /**
526 * Conversion operator to a C++11 std::unique_ptr.
527 * Disowns the object and gives it to the returned std::unique_ptr.
528 *
529 * This operator works via move semantics. If your LocalPointer is
530 * in a local variable, you must use std::move.
531 *
532 * @return An std::unique_ptr owning the pointer previously owned by this
533 * icu::LocalPointer.
534 * @draft ICU 64
535 */
536 operator std::unique_ptr<T[]> () && {
537 return std::unique_ptr<T[]>(LocalPointerBase<T>::orphan());
538 }
539#endif /* U_HIDE_DRAFT_API */
540};
541
542/**
543 * \def U_DEFINE_LOCAL_OPEN_POINTER
544 * "Smart pointer" definition macro, deletes objects via the closeFunction.
545 * Defines a subclass of LocalPointerBase which works just
546 * like LocalPointer<Type> except that this subclass will use the closeFunction
547 * rather than the C++ delete operator.
548 *
549 * Usage example:
550 * \code
551 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode));
552 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(),
553 * utf8Out, (int32_t)sizeof(utf8Out),
554 * utf8In, utf8InLength, &errorCode);
555 * if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap
556 * \endcode
557 *
558 * @see LocalPointerBase
559 * @see LocalPointer
560 * @stable ICU 4.4
561 */
562#define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \
563 class LocalPointerClassName : public LocalPointerBase<Type> { \
564 public: \
565 using LocalPointerBase<Type>::operator*; \
566 using LocalPointerBase<Type>::operator->; \
567 explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \
568 LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \
569 : LocalPointerBase<Type>(src.ptr) { \
570 src.ptr=NULL; \
571 } \
572 /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
573 explicit LocalPointerClassName(std::unique_ptr<Type, decltype(&closeFunction)> &&p) \
574 : LocalPointerBase<Type>(p.release()) {} \
575 ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \
576 LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \
577 if (ptr != NULL) { closeFunction(ptr); } \
578 LocalPointerBase<Type>::ptr=src.ptr; \
579 src.ptr=NULL; \
580 return *this; \
581 } \
582 /* TODO: Be agnostic of the deleter function signature from the user-provided std::unique_ptr? */ \
583 LocalPointerClassName &operator=(std::unique_ptr<Type, decltype(&closeFunction)> &&p) { \
584 adoptInstead(p.release()); \
585 return *this; \
586 } \
587 void swap(LocalPointerClassName &other) U_NOEXCEPT { \
588 Type *temp=LocalPointerBase<Type>::ptr; \
589 LocalPointerBase<Type>::ptr=other.ptr; \
590 other.ptr=temp; \
591 } \
592 friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \
593 p1.swap(p2); \
594 } \
595 void adoptInstead(Type *p) { \
596 if (ptr != NULL) { closeFunction(ptr); } \
597 ptr=p; \
598 } \
599 operator std::unique_ptr<Type, decltype(&closeFunction)> () && { \
600 return std::unique_ptr<Type, decltype(&closeFunction)>(LocalPointerBase<Type>::orphan(), closeFunction); \
601 } \
602 }
603
604U_NAMESPACE_END
605
606#endif /* U_SHOW_CPLUSPLUS_API */
607#endif /* __LOCALPOINTER_H__ */