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 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 */ 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 */ 79 ~LocalPointerBase() { /* delete ptr; */ } 80 /** 81 * NULL check. 82 * @return TRUE if ==NULL 83 * @stable ICU 4.4 84 */ 85 UBool isNull() const { return ptr==NULL; } 86 /** 87 * NULL check. 88 * @return TRUE if !=NULL 89 * @stable ICU 4.4 90 */ 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 */ 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 */ 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 */ 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 * char16_t lead=s->charAt(0); // 0xd900 178 * if(some condition) { return; } // no need to explicitly delete the pointer 179 * s.adoptInstead(new UnicodeString((char16_t)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 */ 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 /** 217 * Move constructor, leaves src with isNull(). 218 * @param src source smart pointer 219 * @stable ICU 56 220 */ 221 LocalPointer(LocalPointer<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) { 222 src.ptr=NULL; 223 } 224 /** 225 * Destructor deletes the object it owns. 226 * @stable ICU 4.4 227 */ 228 ~LocalPointer() { 229 delete LocalPointerBase<T>::ptr; 230 } 231 /** 232 * Move assignment operator, leaves src with isNull(). 233 * The behavior is undefined if *this and src are the same object. 234 * @param src source smart pointer 235 * @return *this 236 * @stable ICU 56 237 */ 238 LocalPointer<T> &operator=(LocalPointer<T> &&src) U_NOEXCEPT { 239 return moveFrom(src); 240 } 241 // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API 242 /** 243 * Move assignment, leaves src with isNull(). 244 * The behavior is undefined if *this and src are the same object. 245 * 246 * Can be called explicitly, does not need C++11 support. 247 * @param src source smart pointer 248 * @return *this 249 * @draft ICU 56 250 */ 251 LocalPointer<T> &moveFrom(LocalPointer<T> &src) U_NOEXCEPT { 252 delete LocalPointerBase<T>::ptr; 253 LocalPointerBase<T>::ptr=src.ptr; 254 src.ptr=NULL; 255 return *this; 256 } 257 /** 258 * Swap pointers. 259 * @param other other smart pointer 260 * @stable ICU 56 261 */ 262 void swap(LocalPointer<T> &other) U_NOEXCEPT { 263 T *temp=LocalPointerBase<T>::ptr; 264 LocalPointerBase<T>::ptr=other.ptr; 265 other.ptr=temp; 266 } 267 /** 268 * Non-member LocalPointer swap function. 269 * @param p1 will get p2's pointer 270 * @param p2 will get p1's pointer 271 * @stable ICU 56 272 */ 273 friend inline void swap(LocalPointer<T> &p1, LocalPointer<T> &p2) U_NOEXCEPT { 274 p1.swap(p2); 275 } 276 /** 277 * Deletes the object it owns, 278 * and adopts (takes ownership of) the one passed in. 279 * @param p simple pointer to an object that is adopted 280 * @stable ICU 4.4 281 */ 282 void adoptInstead(T *p) { 283 delete LocalPointerBase<T>::ptr; 284 LocalPointerBase<T>::ptr=p; 285 } 286 /** 287 * Deletes the object it owns, 288 * and adopts (takes ownership of) the one passed in. 289 * 290 * If U_FAILURE(errorCode), then the current object is retained and the new one deleted. 291 * 292 * If U_SUCCESS(errorCode) but the input pointer is NULL, 293 * then U_MEMORY_ALLOCATION_ERROR is set, 294 * the current object is deleted, and NULL is set. 295 * 296 * @param p simple pointer to an object that is adopted 297 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 298 * if p==NULL and no other failure code had been set 299 * @stable ICU 55 300 */ 301 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { 302 if(U_SUCCESS(errorCode)) { 303 delete LocalPointerBase<T>::ptr; 304 LocalPointerBase<T>::ptr=p; 305 if(p==NULL) { 306 errorCode=U_MEMORY_ALLOCATION_ERROR; 307 } 308 } else { 309 delete p; 310 } 311 } 312 }; 313 314 /** 315 * "Smart pointer" class, deletes objects via the C++ array delete[] operator. 316 * For most methods see the LocalPointerBase base class. 317 * Adds operator[] for array item access. 318 * 319 * Usage example: 320 * \code 321 * LocalArray<UnicodeString> a(new UnicodeString[2]); 322 * a[0].append((char16_t)0x61); 323 * if(some condition) { return; } // no need to explicitly delete the array 324 * a.adoptInstead(new UnicodeString[4]); 325 * a[3].append((char16_t)0x62).append((char16_t)0x63).reverse(); 326 * // no need to explicitly delete the array 327 * \endcode 328 * 329 * @see LocalPointerBase 330 * @stable ICU 4.4 331 */ 332 template<typename T> 333 class LocalArray : public LocalPointerBase<T> { 334 public: 335 using LocalPointerBase<T>::operator*; 336 using LocalPointerBase<T>::operator->; 337 /** 338 * Constructor takes ownership. 339 * @param p simple pointer to an array of T objects that is adopted 340 * @stable ICU 4.4 341 */ 342 explicit LocalArray(T *p=NULL) : LocalPointerBase<T>(p) {} 343 /** 344 * Constructor takes ownership and reports an error if NULL. 345 * 346 * This constructor is intended to be used with other-class constructors 347 * that may report a failure UErrorCode, 348 * so that callers need to check only for U_FAILURE(errorCode) 349 * and not also separately for isNull(). 350 * 351 * @param p simple pointer to an array of T objects that is adopted 352 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 353 * if p==NULL and no other failure code had been set 354 * @stable ICU 56 355 */ 356 LocalArray(T *p, UErrorCode &errorCode) : LocalPointerBase<T>(p) { 357 if(p==NULL && U_SUCCESS(errorCode)) { 358 errorCode=U_MEMORY_ALLOCATION_ERROR; 359 } 360 } 361 /** 362 * Move constructor, leaves src with isNull(). 363 * @param src source smart pointer 364 * @stable ICU 56 365 */ 366 LocalArray(LocalArray<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) { 367 src.ptr=NULL; 368 } 369 /** 370 * Destructor deletes the array it owns. 371 * @stable ICU 4.4 372 */ 373 ~LocalArray() { 374 delete[] LocalPointerBase<T>::ptr; 375 } 376 /** 377 * Move assignment operator, leaves src with isNull(). 378 * The behavior is undefined if *this and src are the same object. 379 * @param src source smart pointer 380 * @return *this 381 * @stable ICU 56 382 */ 383 LocalArray<T> &operator=(LocalArray<T> &&src) U_NOEXCEPT { 384 return moveFrom(src); 385 } 386 // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API 387 /** 388 * Move assignment, leaves src with isNull(). 389 * The behavior is undefined if *this and src are the same object. 390 * 391 * Can be called explicitly, does not need C++11 support. 392 * @param src source smart pointer 393 * @return *this 394 * @draft ICU 56 395 */ 396 LocalArray<T> &moveFrom(LocalArray<T> &src) U_NOEXCEPT { 397 delete[] LocalPointerBase<T>::ptr; 398 LocalPointerBase<T>::ptr=src.ptr; 399 src.ptr=NULL; 400 return *this; 401 } 402 /** 403 * Swap pointers. 404 * @param other other smart pointer 405 * @stable ICU 56 406 */ 407 void swap(LocalArray<T> &other) U_NOEXCEPT { 408 T *temp=LocalPointerBase<T>::ptr; 409 LocalPointerBase<T>::ptr=other.ptr; 410 other.ptr=temp; 411 } 412 /** 413 * Non-member LocalArray swap function. 414 * @param p1 will get p2's pointer 415 * @param p2 will get p1's pointer 416 * @stable ICU 56 417 */ 418 friend inline void swap(LocalArray<T> &p1, LocalArray<T> &p2) U_NOEXCEPT { 419 p1.swap(p2); 420 } 421 /** 422 * Deletes the array it owns, 423 * and adopts (takes ownership of) the one passed in. 424 * @param p simple pointer to an array of T objects that is adopted 425 * @stable ICU 4.4 426 */ 427 void adoptInstead(T *p) { 428 delete[] LocalPointerBase<T>::ptr; 429 LocalPointerBase<T>::ptr=p; 430 } 431 /** 432 * Deletes the array it owns, 433 * and adopts (takes ownership of) the one passed in. 434 * 435 * If U_FAILURE(errorCode), then the current array is retained and the new one deleted. 436 * 437 * If U_SUCCESS(errorCode) but the input pointer is NULL, 438 * then U_MEMORY_ALLOCATION_ERROR is set, 439 * the current array is deleted, and NULL is set. 440 * 441 * @param p simple pointer to an array of T objects that is adopted 442 * @param errorCode in/out UErrorCode, set to U_MEMORY_ALLOCATION_ERROR 443 * if p==NULL and no other failure code had been set 444 * @stable ICU 56 445 */ 446 void adoptInsteadAndCheckErrorCode(T *p, UErrorCode &errorCode) { 447 if(U_SUCCESS(errorCode)) { 448 delete[] LocalPointerBase<T>::ptr; 449 LocalPointerBase<T>::ptr=p; 450 if(p==NULL) { 451 errorCode=U_MEMORY_ALLOCATION_ERROR; 452 } 453 } else { 454 delete[] p; 455 } 456 } 457 /** 458 * Array item access (writable). 459 * No index bounds check. 460 * @param i array index 461 * @return reference to the array item 462 * @stable ICU 4.4 463 */ 464 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; } 465 }; 466 467 /** 468 * \def U_DEFINE_LOCAL_OPEN_POINTER 469 * "Smart pointer" definition macro, deletes objects via the closeFunction. 470 * Defines a subclass of LocalPointerBase which works just 471 * like LocalPointer<Type> except that this subclass will use the closeFunction 472 * rather than the C++ delete operator. 473 * 474 * Usage example: 475 * \code 476 * LocalUCaseMapPointer csm(ucasemap_open(localeID, options, &errorCode)); 477 * utf8OutLength=ucasemap_utf8ToLower(csm.getAlias(), 478 * utf8Out, (int32_t)sizeof(utf8Out), 479 * utf8In, utf8InLength, &errorCode); 480 * if(U_FAILURE(errorCode)) { return; } // no need to explicitly delete the UCaseMap 481 * \endcode 482 * 483 * @see LocalPointerBase 484 * @see LocalPointer 485 * @stable ICU 4.4 486 */ 487 #define U_DEFINE_LOCAL_OPEN_POINTER(LocalPointerClassName, Type, closeFunction) \ 488 class LocalPointerClassName : public LocalPointerBase<Type> { \ 489 public: \ 490 using LocalPointerBase<Type>::operator*; \ 491 using LocalPointerBase<Type>::operator->; \ 492 explicit LocalPointerClassName(Type *p=NULL) : LocalPointerBase<Type>(p) {} \ 493 LocalPointerClassName(LocalPointerClassName &&src) U_NOEXCEPT \ 494 : LocalPointerBase<Type>(src.ptr) { \ 495 src.ptr=NULL; \ 496 } \ 497 ~LocalPointerClassName() { if (ptr != NULL) { closeFunction(ptr); } } \ 498 LocalPointerClassName &operator=(LocalPointerClassName &&src) U_NOEXCEPT { \ 499 return moveFrom(src); \ 500 } \ 501 LocalPointerClassName &moveFrom(LocalPointerClassName &src) U_NOEXCEPT { \ 502 if (ptr != NULL) { closeFunction(ptr); } \ 503 LocalPointerBase<Type>::ptr=src.ptr; \ 504 src.ptr=NULL; \ 505 return *this; \ 506 } \ 507 void swap(LocalPointerClassName &other) U_NOEXCEPT { \ 508 Type *temp=LocalPointerBase<Type>::ptr; \ 509 LocalPointerBase<Type>::ptr=other.ptr; \ 510 other.ptr=temp; \ 511 } \ 512 friend inline void swap(LocalPointerClassName &p1, LocalPointerClassName &p2) U_NOEXCEPT { \ 513 p1.swap(p2); \ 514 } \ 515 void adoptInstead(Type *p) { \ 516 if (ptr != NULL) { closeFunction(ptr); } \ 517 ptr=p; \ 518 } \ 519 } 520 521 U_NAMESPACE_END 522 523 #endif /* U_SHOW_CPLUSPLUS_API */ 524 #endif /* __LOCALPOINTER_H__ */ 525