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 https://icu.unicode.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=nullptr) : 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 * nullptr check.
91 * @return true if ==nullptr
92 * @stable ICU 4.4
93 */
94 UBool isNull() const { return ptr==nullptr; }
95 /**
96 * nullptr check.
97 * @return true if !=nullptr
98 * @stable ICU 4.4
99 */
100 UBool isValid() const { return ptr!=nullptr; }
101 /**
102 * Comparison with a simple pointer, so that existing code
103 * with ==nullptr 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 !=nullptr 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 nullptr.
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=nullptr;
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=nullptr) : LocalPointerBase<T>(p) {}
201 /**
202 * Constructor takes ownership and reports an error if nullptr.
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==nullptr 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==nullptr && 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) noexcept : LocalPointerBase<T>(src.ptr) {
225 src.ptr=nullptr;
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 */
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 */
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) noexcept {
256 delete LocalPointerBase<T>::ptr;
257 LocalPointerBase<T>::ptr=src.ptr;
258 src.ptr=nullptr;
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) 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 */
280 void swap(LocalPointer<T> &other) 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 */
291 friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) 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 */
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 nullptr,
311 * then U_MEMORY_ALLOCATION_ERROR is set,
312 * the current object is deleted, and nullptr 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==nullptr and no other failure code had been set
317 * @stable ICU 55
318 */
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==nullptr) {
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 */
365template<typename T>
366class LocalArray : public LocalPointerBase<T> {
367public:
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=nullptr) : LocalPointerBase<T>(p) {}
376 /**
377 * Constructor takes ownership and reports an error if nullptr.
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==nullptr and no other failure code had been set
387 * @stable ICU 56
388 */
389 LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) {
390 if(p==nullptr && 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 */
399 LocalArray(LocalArray<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
400 src.ptr=nullptr;
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 */
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 */
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) noexcept {
431 delete[] LocalPointerBase<T>::ptr;
432 LocalPointerBase<T>::ptr=src.ptr;
433 src.ptr=nullptr;
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) 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 */
455 void swap(LocalArray<T> &other) 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 */
466 friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) 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 */
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 nullptr,
486 * then U_MEMORY_ALLOCATION_ERROR is set,
487 * the current array is deleted, and nullptr 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==nullptr and no other failure code had been set
492 * @stable ICU 56
493 */
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==nullptr) {
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=nullptr) : LocalPointerBase<Type>(p) {} \
556 LocalPointerClassName(LocalPointerClassName &&src) noexcept \
557 : LocalPointerBase<Type>(src.ptr) { \
558 src.ptr=nullptr; \
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 != nullptr) { closeFunction(ptr); } } \
564 LocalPointerClassName &operator=(LocalPointerClassName &&src) noexcept { \
565 if (ptr != nullptr) { closeFunction(ptr); } \
566 LocalPointerBase<Type>::ptr=src.ptr; \
567 src.ptr=nullptr; \
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) 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) noexcept { \
581 p1.swap(p2); \
582 } \
583 void adoptInstead(Type *p) { \
584 if (ptr != nullptr) { 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
592U_NAMESPACE_END
593
594#endif /* U_SHOW_CPLUSPLUS_API */
595#endif /* __LOCALPOINTER_H__ */
596