1 /* 2 ******************************************************************************* 3 * 4 * Copyright (C) 2009-2015, International Business Machines 5 * Corporation and others. All Rights Reserved. 6 * 7 ******************************************************************************* 8 * file name: localpointer.h 9 * encoding: US-ASCII 10 * tab size: 8 (not used) 11 * indentation:4 12 * 13 * created on: 2009nov13 14 * created by: Markus W. Scherer 15 */ 16 17 #ifndef __LOCALPOINTER_H__ 18 #define __LOCALPOINTER_H__ 19 20 /** 21 * \file 22 * \brief C++ API: "Smart pointers" for use with and in ICU4C C++ code. 23 * 24 * These classes are inspired by 25 * - std::auto_ptr 26 * - boost::scoped_ptr & boost::scoped_array 27 * - Taligent Safe Pointers (TOnlyPointerTo) 28 * 29 * but none of those provide for all of the goals for ICU smart pointers: 30 * - Smart pointer owns the object and releases it when it goes out of scope. 31 * - No transfer of ownership via copy/assignment to reduce misuse. Simpler & more robust. 32 * - ICU-compatible: No exceptions. 33 * - Need to be able to orphan/release the pointer and its ownership. 34 * - Need variants for normal C++ object pointers, C++ arrays, and ICU C service objects. 35 * 36 * For details see http://site.icu-project.org/design/cpp/scoped_ptr 37 */ 38 39 #include "unicode/utypes.h" 40 41 #if U_SHOW_CPLUSPLUS_API 42 43 U_NAMESPACE_BEGIN 44 45 /** 46 * "Smart pointer" base class; do not use directly: use LocalPointer etc. 47 * 48 * Base class for smart pointer classes that do not throw exceptions. 49 * 50 * Do not use this base class directly, since it does not delete its pointer. 51 * A subclass must implement methods that delete the pointer: 52 * Destructor and adoptInstead(). 53 * 54 * There is no operator T *() provided because the programmer must decide 55 * whether to use getAlias() (without transfer of ownership) or orpan() 56 * (with transfer of ownership and NULLing of the pointer). 57 * 58 * @see LocalPointer 59 * @see LocalArray 60 * @see U_DEFINE_LOCAL_OPEN_POINTER 61 * @stable ICU 4.4 62 */ 63 template<typename T> 64 class LocalPointerBase { 65 public: 66 /** 67 * Constructor takes ownership. 68 * @param p simple pointer to an object that is adopted 69 * @stable ICU 4.4 70 */ ptr(p)71 explicit LocalPointerBase(T *p=NULL) : ptr(p) {} 72 /** 73 * Destructor deletes the object it owns. 74 * Subclass must override: Base class does nothing. 75 * @stable ICU 4.4 76 */ ~LocalPointerBase()77 ~LocalPointerBase() { /* delete ptr; */ } 78 /** 79 * NULL check. 80 * @return TRUE if ==NULL 81 * @stable ICU 4.4 82 */ isNull()83 UBool isNull() const { return ptr==NULL; } 84 /** 85 * NULL check. 86 * @return TRUE if !=NULL 87 * @stable ICU 4.4 88 */ isValid()89 UBool isValid() const { return ptr!=NULL; } 90 /** 91 * Comparison with a simple pointer, so that existing code 92 * with ==NULL need not be changed. 93 * @param other simple pointer for comparison 94 * @return true if this pointer value equals other 95 * @stable ICU 4.4 96 */ 97 bool operator==(const T *other) const { return ptr==other; } 98 /** 99 * Comparison with a simple pointer, so that existing code 100 * with !=NULL need not be changed. 101 * @param other simple pointer for comparison 102 * @return true if this pointer value differs from other 103 * @stable ICU 4.4 104 */ 105 bool operator!=(const T *other) const { return ptr!=other; } 106 /** 107 * Access without ownership change. 108 * @return the pointer value 109 * @stable ICU 4.4 110 */ getAlias()111 T *getAlias() const { return ptr; } 112 /** 113 * Access without ownership change. 114 * @return the pointer value as a reference 115 * @stable ICU 4.4 116 */ 117 T &operator*() const { return *ptr; } 118 /** 119 * Access without ownership change. 120 * @return the pointer value 121 * @stable ICU 4.4 122 */ 123 T *operator->() const { return ptr; } 124 /** 125 * Gives up ownership; the internal pointer becomes NULL. 126 * @return the pointer value; 127 * caller becomes responsible for deleting the object 128 * @stable ICU 4.4 129 */ orphan()130 T *orphan() { 131 T *p=ptr; 132 ptr=NULL; 133 return p; 134 } 135 /** 136 * Deletes the object it owns, 137 * and adopts (takes ownership of) the one passed in. 138 * Subclass must override: Base class does not delete the object. 139 * @param p simple pointer to an object that is adopted 140 * @stable ICU 4.4 141 */ adoptInstead(T * p)142 void adoptInstead(T *p) { 143 // delete ptr; 144 ptr=p; 145 } 146 protected: 147 /** 148 * Actual pointer. 149 * @internal 150 */ 151 T *ptr; 152 private: 153 // No comparison operators with other LocalPointerBases. 154 bool operator==(const LocalPointerBase<T> &other); 155 bool operator!=(const LocalPointerBase<T> &other); 156 // No ownership sharing: No copy constructor, no assignment operator. 157 LocalPointerBase(const LocalPointerBase<T> &other); 158 void operator=(const LocalPointerBase<T> &other); 159 // No heap allocation. Use only on the stack. 160 static void * U_EXPORT2 operator new(size_t size); 161 static void * U_EXPORT2 operator new[](size_t size); 162 #if U_HAVE_PLACEMENT_NEW 163 static void * U_EXPORT2 operator new(size_t, void *ptr); 164 #endif 165 }; 166 167 /** 168 * "Smart pointer" class, deletes objects via the standard C++ delete operator. 169 * For most methods see the LocalPointerBase base class. 170 * 171 * Usage example: 172 * \code 173 * LocalPointer<UnicodeString> s(new UnicodeString((UChar32)0x50005)); 174 * int32_t length=s->length(); // 2 175 * UChar lead=s->charAt(0); // 0xd900 176 * if(some condition) { return; } // no need to explicitly delete the pointer 177 * s.adoptInstead(new UnicodeString((UChar)0xfffc)); 178 * length=s->length(); // 1 179 * // no need to explicitly delete the pointer 180 * \endcode 181 * 182 * @see LocalPointerBase 183 * @stable ICU 4.4 184 */ 185 template<typename T> 186 class LocalPointer : public LocalPointerBase<T> { 187 public: 188 /** 189 * Constructor takes ownership. 190 * @param p simple pointer to an object that is adopted 191 * @stable ICU 4.4 192 */ 193 explicit LocalPointer(T *p=NULL) : LocalPointerBase<T>(p) {} 194 #ifndef U_HIDE_DRAFT_API 195 /** 196 * Constructor takes ownership and reports an error if NULL. 197 * 198 * This constructor is intended to be used with other-class constructors 199 * that may report a failure UErrorCode, 200 * so that callers need to check only for U_FAILURE(errorCode) 201 * and not also separately for isNull(). 202 * 203 * @param p simple pointer to an object that is adopted 204 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 205 * if p==NULL and no other failure code had been set 206 * @draft ICU 55 207 */ LocalPointer(T * p,UErrorCode & errorCode)208 LocalPointer(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) { 209 if(p==NULL && U_SUCCESS(errorCode)) { 210 errorCode=U_MEMORY_ALLOCATION_ERROR; 211 } 212 } 213 #if U_HAVE_RVALUE_REFERENCES 214 /** 215 * Move constructor, leaves src with isNull(). 216 * @param src source smart pointer 217 * @draft ICU 56 218 */ LocalPointer(LocalPointer<T> && src)219 LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) { 220 src.ptr=NULL; 221 } 222 #endif 223 #endif /* U_HIDE_DRAFT_API */ 224 /** 225 * Destructor deletes the object it owns. 226 * @stable ICU 4.4 227 */ ~LocalPointer()228 ~LocalPointer() { 229 delete LocalPointerBase<T>::ptr; 230 } 231 #ifndef U_HIDE_DRAFT_API 232 #if U_HAVE_RVALUE_REFERENCES 233 /** 234 * Move assignment operator, leaves src with isNull(). 235 * The behavior is undefined if *this and src are the same object. 236 * @param src source smart pointer 237 * @return *this 238 * @draft ICU 56 239 */ 240 LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT { 241 return moveFrom(src); 242 } 243 #endif 244 /** 245 * Move assignment, leaves src with isNull(). 246 * The behavior is undefined if *this and src are the same object. 247 * 248 * Can be called explicitly, does not need C++11 support. 249 * @param src source smart pointer 250 * @return *this 251 * @draft ICU 56 252 */ moveFrom(LocalPointer<T> & src)253 LocalPointer<T> &moveFrom(LocalPointer<T> &src) U_NOEXCEPT { 254 delete LocalPointerBase<T>::ptr; 255 LocalPointerBase<T>::ptr=src.ptr; 256 src.ptr=NULL; 257 return *this; 258 } 259 /** 260 * Swap pointers. 261 * @param other other smart pointer 262 * @draft ICU 56 263 */ swap(LocalPointer<T> & other)264 void swap(LocalPointer<T> &other) U_NOEXCEPT { 265 T *temp=LocalPointerBase<T>::ptr; 266 LocalPointerBase<T>::ptr=other.ptr; 267 other.ptr=temp; 268 } 269 /** 270 * Non-member LocalPointer swap function. 271 * @param p1 will get p2's pointer 272 * @param p2 will get p1's pointer 273 * @draft ICU 56 274 */ swap(LocalPointer<T> & p1,LocalPointer<T> & p2)275 friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT { 276 p1.swap(p2); 277 } 278 #endif /* U_HIDE_DRAFT_API */ 279 /** 280 * Deletes the object it owns, 281 * and adopts (takes ownership of) the one passed in. 282 * @param p simple pointer to an object that is adopted 283 * @stable ICU 4.4 284 */ adoptInstead(T * p)285 void adoptInstead(T *p) { 286 delete LocalPointerBase<T>::ptr; 287 LocalPointerBase<T>::ptr=p; 288 } 289 #ifndef U_HIDE_DRAFT_API 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 * @draft 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 #endif /* U_HIDE_DRAFT_API */ 317 }; 318 319 /** 320 * "Smart pointer" class, deletes objects via the C++ array delete[] operator. 321 * For most methods see the LocalPointerBase base class. 322 * Adds operator[] for array item access. 323 * 324 * Usage example: 325 * \code 326 * LocalArray<UnicodeString> a(new UnicodeString[2]); 327 * a[0].append((UChar)0x61); 328 * if(some condition) { return; } // no need to explicitly delete the array 329 * a.adoptInstead(new UnicodeString[4]); 330 * a[3].append((UChar)0x62).append((UChar)0x63).reverse(); 331 * // no need to explicitly delete the array 332 * \endcode 333 * 334 * @see LocalPointerBase 335 * @stable ICU 4.4 336 */ 337 template<typename T> 338 class LocalArray : public LocalPointerBase<T> { 339 public: 340 /** 341 * Constructor takes ownership. 342 * @param p simple pointer to an array of T objects that is adopted 343 * @stable ICU 4.4 344 */ 345 explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {} 346 #ifndef U_HIDE_DRAFT_API 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 * @draft 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 * @draft 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 #endif /* U_HIDE_DRAFT_API */ 376 /** 377 * Destructor deletes the array it owns. 378 * @stable ICU 4.4 379 */ ~LocalArray()380 ~LocalArray() { 381 delete[] LocalPointerBase<T>::ptr; 382 } 383 #ifndef U_HIDE_DRAFT_API 384 #if U_HAVE_RVALUE_REFERENCES 385 /** 386 * Move assignment operator, leaves src with isNull(). 387 * The behavior is undefined if *this and src are the same object. 388 * @param src source smart pointer 389 * @return *this 390 * @draft ICU 56 391 */ 392 LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT { 393 return moveFrom(src); 394 } 395 #endif 396 /** 397 * Move assignment, leaves src with isNull(). 398 * The behavior is undefined if *this and src are the same object. 399 * 400 * Can be called explicitly, does not need C++11 support. 401 * @param src source smart pointer 402 * @return *this 403 * @draft ICU 56 404 */ moveFrom(LocalArray<T> & src)405 LocalArray<T> &moveFrom(LocalArray<T> &src) U_NOEXCEPT { 406 delete[] LocalPointerBase<T>::ptr; 407 LocalPointerBase<T>::ptr=src.ptr; 408 src.ptr=NULL; 409 return *this; 410 } 411 /** 412 * Swap pointers. 413 * @param other other smart pointer 414 * @draft ICU 56 415 */ swap(LocalArray<T> & other)416 void swap(LocalArray<T> &other) U_NOEXCEPT { 417 T *temp=LocalPointerBase<T>::ptr; 418 LocalPointerBase<T>::ptr=other.ptr; 419 other.ptr=temp; 420 } 421 /** 422 * Non-member LocalArray swap function. 423 * @param p1 will get p2's pointer 424 * @param p2 will get p1's pointer 425 * @draft ICU 56 426 */ swap(LocalArray<T> & p1,LocalArray<T> & p2)427 friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT { 428 p1.swap(p2); 429 } 430 #endif /* U_HIDE_DRAFT_API */ 431 /** 432 * Deletes the array it owns, 433 * and adopts (takes ownership of) the one passed in. 434 * @param p simple pointer to an array of T objects that is adopted 435 * @stable ICU 4.4 436 */ adoptInstead(T * p)437 void adoptInstead(T *p) { 438 delete[] LocalPointerBase<T>::ptr; 439 LocalPointerBase<T>::ptr=p; 440 } 441 #ifndef U_HIDE_DRAFT_API 442 /** 443 * Deletes the array it owns, 444 * and adopts (takes ownership of) the one passed in. 445 * 446 * If U_FAILURE(errorCode), then the current array is retained and the new one deleted. 447 * 448 * If U_SUCCESS(errorCode) but the input pointer is NULL, 449 * then U_MEMORY_ALLOCATION_ERROR is set, 450 * the current array is deleted, and NULL is set. 451 * 452 * @param p simple pointer to an array of T objects that is adopted 453 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 454 * if p==NULL and no other failure code had been set 455 * @draft ICU 56 456 */ adoptInsteadAndCheckErrorCode(T * p,UErrorCode & errorCode)457 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { 458 if(U_SUCCESS(errorCode)) { 459 delete[] LocalPointerBase<T>::ptr; 460 LocalPointerBase<T>::ptr=p; 461 if(p==NULL) { 462 errorCode=U_MEMORY_ALLOCATION_ERROR; 463 } 464 } else { 465 delete[] p; 466 } 467 } 468 #endif /* U_HIDE_DRAFT_API */ 469 /** 470 * Array item access (writable). 471 * No index bounds check. 472 * @param i array index 473 * @return reference to the array item 474 * @stable ICU 4.4 475 */ 476 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; } 477 }; 478 479 /** 480 * \def U_DEFINE_LOCAL_OPEN_POINTER 481 * "Smart pointer" definition macro, deletes objects via the closeFunction. 482 * Defines a subclass of LocalPointerBase which works just 483 * like LocalPointer<Type> except that this subclass will use the closeFunction 484 * rather than the C++ delete operator. 485 * 486 * Requirement: The closeFunction must tolerate a NULL pointer. 487 * (We could add a NULL check here but it is normally redundant.) 488 * 489 * Usage example: 490 * \code 491 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode)); 492 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(), 493 * utf8Out, (int32_t)sizeof(utf8Out), 494 * utf8In, utf8InLength, &errorCode); 495 * if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap 496 * \endcode 497 * 498 * @see LocalPointerBase 499 * @see LocalPointer 500 * @stable ICU 4.4 501 */ 502 #if U_HAVE_RVALUE_REFERENCES 503 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ 504 class LocalPointerClassName : public LocalPointerBase<Type> { \ 505 public: \ 506 explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \ 507 LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \ 508 : LocalPointerBase<Type>(src.ptr) { \ 509 src.ptr=NULL; \ 510 } \ 511 ~LocalPointerClassName() { closeFunction(ptr); } \ 512 LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \ 513 return moveFrom(src); \ 514 } \ 515 LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \ 516 closeFunction(ptr); \ 517 LocalPointerBase<Type>::ptr=src.ptr; \ 518 src.ptr=NULL; \ 519 return *this; \ 520 } \ 521 void swap(LocalPointerClassName &other) U_NOEXCEPT { \ 522 Type *temp=LocalPointerBase<Type>::ptr; \ 523 LocalPointerBase<Type>::ptr=other.ptr; \ 524 other.ptr=temp; \ 525 } \ 526 friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \ 527 p1.swap(p2); \ 528 } \ 529 void adoptInstead(Type *p) { \ 530 closeFunction(ptr); \ 531 ptr=p; \ 532 } \ 533 } 534 #else 535 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ 536 class LocalPointerClassName : public LocalPointerBase<Type> { \ 537 public: \ 538 explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \ 539 ~LocalPointerClassName() { closeFunction(ptr); } \ 540 LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \ 541 closeFunction(ptr); \ 542 LocalPointerBase<Type>::ptr=src.ptr; \ 543 src.ptr=NULL; \ 544 return *this; \ 545 } \ 546 void swap(LocalPointerClassName &other) U_NOEXCEPT { \ 547 Type *temp=LocalPointerBase<Type>::ptr; \ 548 LocalPointerBase<Type>::ptr=other.ptr; \ 549 other.ptr=temp; \ 550 } \ 551 friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \ 552 p1.swap(p2); \ 553 } \ 554 void adoptInstead(Type *p) { \ 555 closeFunction(ptr); \ 556 ptr=p; \ 557 } \ 558 } 559 #endif 560 561 U_NAMESPACE_END 562 563 #endif /* U_SHOW_CPLUSPLUS_API */ 564 #endif /* __LOCALPOINTER_H__ */ 565