1 // Copyright (C) 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: US-ASCII 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 U_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 */ 65 template<typename T> 66 class LocalPointerBase { 67 public: 68 /** 69 * Constructor takes ownership. 70 * @param p simple pointer to an object that is adopted 71 * @stable ICU 4.4 72 */ ptr(p)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 */ ~LocalPointerBase()79 ~LocalPointerBase() { /* delete ptr; */ } 80 /** 81 * NULL check. 82 * @return TRUE if ==NULL 83 * @stable ICU 4.4 84 */ isNull()85 UBool isNull() const { return ptr==NULL; } 86 /** 87 * NULL check. 88 * @return TRUE if !=NULL 89 * @stable ICU 4.4 90 */ isValid()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 */ getAlias()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 */ orphan()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 */ adoptInstead(T * p)144 void adoptInstead(T *p) { 145 // delete ptr; 146 ptr=p; 147 } 148 protected: 149 /** 150 * Actual pointer. 151 * @internal 152 */ 153 T *ptr; 154 private: 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 * UChar lead=s->charAt(0); // 0xd900 178 * if(some condition) { return; } // no need to explicitly delete the pointer 179 * s.adoptInstead(new UnicodeString((UChar)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 */ 187 template<typename T> 188 class LocalPointer : public LocalPointerBase<T> { 189 public: 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 */ LocalPointer(T * p,UErrorCode & errorCode)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 #if U_HAVE_RVALUE_REFERENCES 217 /** 218 * Move constructor, leaves src with isNull(). 219 * @param src source smart pointer 220 * @stable ICU 56 221 */ LocalPointer(LocalPointer<T> && src)222 LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) { 223 src.ptr=NULL; 224 } 225 #endif 226 /** 227 * Destructor deletes the object it owns. 228 * @stable ICU 4.4 229 */ ~LocalPointer()230 ~LocalPointer() { 231 delete LocalPointerBase<T>::ptr; 232 } 233 #if U_HAVE_RVALUE_REFERENCES 234 /** 235 * Move assignment operator, leaves src with isNull(). 236 * The behavior is undefined if *this and src are the same object. 237 * @param src source smart pointer 238 * @return *this 239 * @stable ICU 56 240 */ 241 LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT { 242 return moveFrom(src); 243 } 244 #endif 245 // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API 246 /** 247 * Move assignment, leaves src with isNull(). 248 * The behavior is undefined if *this and src are the same object. 249 * 250 * Can be called explicitly, does not need C++11 support. 251 * @param src source smart pointer 252 * @return *this 253 * @draft ICU 56 254 */ moveFrom(LocalPointer<T> & src)255 LocalPointer<T> &moveFrom(LocalPointer<T> &src) U_NOEXCEPT { 256 delete LocalPointerBase<T>::ptr; 257 LocalPointerBase<T>::ptr=src.ptr; 258 src.ptr=NULL; 259 return *this; 260 } 261 /** 262 * Swap pointers. 263 * @param other other smart pointer 264 * @stable ICU 56 265 */ swap(LocalPointer<T> & other)266 void swap(LocalPointer<T> &other) U_NOEXCEPT { 267 T *temp=LocalPointerBase<T>::ptr; 268 LocalPointerBase<T>::ptr=other.ptr; 269 other.ptr=temp; 270 } 271 /** 272 * Non-member LocalPointer swap function. 273 * @param p1 will get p2's pointer 274 * @param p2 will get p1's pointer 275 * @stable ICU 56 276 */ swap(LocalPointer<T> & p1,LocalPointer<T> & p2)277 friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT { 278 p1.swap(p2); 279 } 280 /** 281 * Deletes the object it owns, 282 * and adopts (takes ownership of) the one passed in. 283 * @param p simple pointer to an object that is adopted 284 * @stable ICU 4.4 285 */ adoptInstead(T * p)286 void adoptInstead(T *p) { 287 delete LocalPointerBase<T>::ptr; 288 LocalPointerBase<T>::ptr=p; 289 } 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 * @stable 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 }; 317 318 /** 319 * "Smart pointer" class, deletes objects via the C++ array delete[] operator. 320 * For most methods see the LocalPointerBase base class. 321 * Adds operator[] for array item access. 322 * 323 * Usage example: 324 * \code 325 * LocalArray<UnicodeString> a(new UnicodeString[2]); 326 * a[0].append((UChar)0x61); 327 * if(some condition) { return; } // no need to explicitly delete the array 328 * a.adoptInstead(new UnicodeString[4]); 329 * a[3].append((UChar)0x62).append((UChar)0x63).reverse(); 330 * // no need to explicitly delete the array 331 * \endcode 332 * 333 * @see LocalPointerBase 334 * @stable ICU 4.4 335 */ 336 template<typename T> 337 class LocalArray : public LocalPointerBase<T> { 338 public: 339 using LocalPointerBase<T>::operator*; 340 using LocalPointerBase<T>::operator->; 341 /** 342 * Constructor takes ownership. 343 * @param p simple pointer to an array of T objects that is adopted 344 * @stable ICU 4.4 345 */ 346 explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {} 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 * @stable 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 * @stable 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 /** 376 * Destructor deletes the array it owns. 377 * @stable ICU 4.4 378 */ ~LocalArray()379 ~LocalArray() { 380 delete[] LocalPointerBase<T>::ptr; 381 } 382 #if U_HAVE_RVALUE_REFERENCES 383 /** 384 * Move assignment operator, leaves src with isNull(). 385 * The behavior is undefined if *this and src are the same object. 386 * @param src source smart pointer 387 * @return *this 388 * @stable ICU 56 389 */ 390 LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT { 391 return moveFrom(src); 392 } 393 #endif 394 // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API 395 /** 396 * Move assignment, leaves src with isNull(). 397 * The behavior is undefined if *this and src are the same object. 398 * 399 * Can be called explicitly, does not need C++11 support. 400 * @param src source smart pointer 401 * @return *this 402 * @draft ICU 56 403 */ moveFrom(LocalArray<T> & src)404 LocalArray<T> &moveFrom(LocalArray<T> &src) U_NOEXCEPT { 405 delete[] LocalPointerBase<T>::ptr; 406 LocalPointerBase<T>::ptr=src.ptr; 407 src.ptr=NULL; 408 return *this; 409 } 410 /** 411 * Swap pointers. 412 * @param other other smart pointer 413 * @stable ICU 56 414 */ swap(LocalArray<T> & other)415 void swap(LocalArray<T> &other) U_NOEXCEPT { 416 T *temp=LocalPointerBase<T>::ptr; 417 LocalPointerBase<T>::ptr=other.ptr; 418 other.ptr=temp; 419 } 420 /** 421 * Non-member LocalArray swap function. 422 * @param p1 will get p2's pointer 423 * @param p2 will get p1's pointer 424 * @stable ICU 56 425 */ swap(LocalArray<T> & p1,LocalArray<T> & p2)426 friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT { 427 p1.swap(p2); 428 } 429 /** 430 * Deletes the array it owns, 431 * and adopts (takes ownership of) the one passed in. 432 * @param p simple pointer to an array of T objects that is adopted 433 * @stable ICU 4.4 434 */ adoptInstead(T * p)435 void adoptInstead(T *p) { 436 delete[] LocalPointerBase<T>::ptr; 437 LocalPointerBase<T>::ptr=p; 438 } 439 /** 440 * Deletes the array it owns, 441 * and adopts (takes ownership of) the one passed in. 442 * 443 * If U_FAILURE(errorCode), then the current array is retained and the new one deleted. 444 * 445 * If U_SUCCESS(errorCode) but the input pointer is NULL, 446 * then U_MEMORY_ALLOCATION_ERROR is set, 447 * the current array is deleted, and NULL is set. 448 * 449 * @param p simple pointer to an array of T objects that is adopted 450 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 451 * if p==NULL and no other failure code had been set 452 * @stable ICU 56 453 */ adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)454 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { 455 if(U_SUCCESS(errorCode)) { 456 delete[] LocalPointerBase<T>::ptr; 457 LocalPointerBase<T>::ptr=p; 458 if(p==NULL) { 459 errorCode=U_MEMORY_ALLOCATION_ERROR; 460 } 461 } else { 462 delete[] p; 463 } 464 } 465 /** 466 * Array item access (writable). 467 * No index bounds check. 468 * @param i array index 469 * @return reference to the array item 470 * @stable ICU 4.4 471 */ 472 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; } 473 }; 474 475 /** 476 * \def U_DEFINE_LOCAL_OPEN_POINTER 477 * "Smart pointer" definition macro, deletes objects via the closeFunction. 478 * Defines a subclass of LocalPointerBase which works just 479 * like LocalPointer<Type> except that this subclass will use the closeFunction 480 * rather than the C++ delete operator. 481 * 482 * Usage example: 483 * \code 484 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode)); 485 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(), 486 * utf8Out, (int32_t)sizeof(utf8Out), 487 * utf8In, utf8InLength, &errorCode); 488 * if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap 489 * \endcode 490 * 491 * @see LocalPointerBase 492 * @see LocalPointer 493 * @stable ICU 4.4 494 */ 495 #if U_HAVE_RVALUE_REFERENCES 496 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ 497 class LocalPointerClassName : public LocalPointerBase<Type> { \ 498 public: \ 499 using LocalPointerBase<Type>::operator*; \ 500 using LocalPointerBase<Type>::operator->; \ 501 explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \ 502 LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \ 503 : LocalPointerBase<Type>(src.ptr) { \ 504 src.ptr=NULL; \ 505 } \ 506 ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \ 507 LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \ 508 return moveFrom(src); \ 509 } \ 510 LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \ 511 if (ptr != NULL) { closeFunction(ptr); } \ 512 LocalPointerBase<Type>::ptr=src.ptr; \ 513 src.ptr=NULL; \ 514 return *this; \ 515 } \ 516 void swap(LocalPointerClassName &other) U_NOEXCEPT { \ 517 Type *temp=LocalPointerBase<Type>::ptr; \ 518 LocalPointerBase<Type>::ptr=other.ptr; \ 519 other.ptr=temp; \ 520 } \ 521 friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \ 522 p1.swap(p2); \ 523 } \ 524 void adoptInstead(Type *p) { \ 525 if (ptr != NULL) { closeFunction(ptr); } \ 526 ptr=p; \ 527 } \ 528 } 529 #else 530 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ 531 class LocalPointerClassName : public LocalPointerBase<Type> { \ 532 public: \ 533 using LocalPointerBase<Type>::operator*; \ 534 using LocalPointerBase<Type>::operator->; \ 535 explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \ 536 ~LocalPointerClassName() { closeFunction(ptr); } \ 537 LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \ 538 if (ptr != NULL) { closeFunction(ptr); } \ 539 LocalPointerBase<Type>::ptr=src.ptr; \ 540 src.ptr=NULL; \ 541 return *this; \ 542 } \ 543 void swap(LocalPointerClassName &other) U_NOEXCEPT { \ 544 Type *temp=LocalPointerBase<Type>::ptr; \ 545 LocalPointerBase<Type>::ptr=other.ptr; \ 546 other.ptr=temp; \ 547 } \ 548 friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \ 549 p1.swap(p2); \ 550 } \ 551 void adoptInstead(Type *p) { \ 552 if (ptr != NULL) { closeFunction(ptr); } \ 553 ptr=p; \ 554 } \ 555 } 556 #endif 557 558 U_NAMESPACE_END 559 560 #endif /* U_SHOW_CPLUSPLUS_API */ 561 #endif /* __LOCALPOINTER_H__ */ 562