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 45 #include <memory> 46 47 U_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 */ 67 template<typename T> 68 class LocalPointerBase { 69 public: 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 */ ptr(p)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 */ ~LocalPointerBase()88 ~LocalPointerBase() { /* delete ptr; */ } 89 /** 90 * NULL check. 91 * @return TRUE if ==NULL 92 * @stable ICU 4.4 93 */ isNull()94 UBool isNull() const { return ptr==NULL; } 95 /** 96 * NULL check. 97 * @return TRUE if !=NULL 98 * @stable ICU 4.4 99 */ isValid()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 */ getAlias()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 */ orphan()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 */ adoptInstead(T * p)153 void adoptInstead(T *p) { 154 // delete ptr; 155 ptr=p; 156 } 157 protected: 158 /** 159 * Actual pointer. 160 * @internal 161 */ 162 T *ptr; 163 private: 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 */ 190 template<typename T> 191 class LocalPointer : public LocalPointerBase<T> { 192 public: 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 */ LocalPointer(T * p,UErrorCode & errorCode)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 */ LocalPointer(LocalPointer<T> && src)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 */ LocalPointer(std::unique_ptr<T> && p)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 */ ~LocalPointer()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 */ swap(LocalPointer<T> & other)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 */ swap(LocalPointer<T> & p1,LocalPointer<T> & p2)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 */ adoptInstead(T * p)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 */ adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)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 */ 371 template<typename T> 372 class LocalArray : public LocalPointerBase<T> { 373 public: 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 */ LocalArray(T * p,UErrorCode & errorCode)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 */ LocalArray(LocalArray<T> && src)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 */ LocalArray(std::unique_ptr<T[]> && p)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 */ ~LocalArray()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 */ swap(LocalArray<T> & other)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 */ swap(LocalArray<T> & p1,LocalArray<T> & p2)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 */ adoptInstead(T * p)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 */ adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)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 604 U_NAMESPACE_END 605 606 #endif /* U_SHOW_CPLUSPLUS_API */ 607 #endif /* __LOCALPOINTER_H__ */ 608