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) 1997-2016, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 * 9 ****************************************************************************** 10 * 11 * File CMEMORY.H 12 * 13 * Contains stdlib.h/string.h memory functions 14 * 15 * @author Bertrand A. Damiba 16 * 17 * Modification History: 18 * 19 * Date Name Description 20 * 6/20/98 Bertrand Created. 21 * 05/03/99 stephen Changed from functions to macros. 22 * 23 ****************************************************************************** 24 */ 25 26 #ifndef CMEMORY_H 27 #define CMEMORY_H 28 29 #include "unicode/utypes.h" 30 31 #include <stddef.h> 32 #include <string.h> 33 #include "unicode/localpointer.h" 34 35 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 36 #include <stdio.h> 37 #endif 38 39 40 #define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size) 41 #define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size) 42 43 /** 44 * \def UPRV_LENGTHOF 45 * Convenience macro to determine the length of a fixed array at compile-time. 46 * @param array A fixed length array 47 * @return The length of the array, in elements 48 * @internal 49 */ 50 #define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 51 #define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size) 52 #define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size) 53 54 U_CAPI void * U_EXPORT2 55 uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1); 56 57 U_CAPI void * U_EXPORT2 58 uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2); 59 60 U_CAPI void U_EXPORT2 61 uprv_free(void *mem); 62 63 U_CAPI void * U_EXPORT2 64 uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2); 65 66 /** 67 * This should align the memory properly on any machine. 68 * This is very useful for the safeClone functions. 69 */ 70 typedef union { 71 long t1; 72 double t2; 73 void *t3; 74 } UAlignedMemory; 75 76 /** 77 * Get the least significant bits of a pointer (a memory address). 78 * For example, with a mask of 3, the macro gets the 2 least significant bits, 79 * which will be 0 if the pointer is 32-bit (4-byte) aligned. 80 * 81 * ptrdiff_t is the most appropriate integer type to cast to. 82 * size_t should work too, since on most (or all?) platforms it has the same 83 * width as ptrdiff_t. 84 */ 85 #define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask)) 86 87 /** 88 * Get the amount of bytes that a pointer is off by from 89 * the previous UAlignedMemory-aligned pointer. 90 */ 91 #define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1) 92 93 /** 94 * Get the amount of bytes to add to a pointer 95 * in order to get the next UAlignedMemory-aligned address. 96 */ 97 #define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr)) 98 99 /** 100 * Heap clean up function, called from u_cleanup() 101 * Clears any user heap functions from u_setMemoryFunctions() 102 * Does NOT deallocate any remaining allocated memory. 103 */ 104 U_CFUNC UBool 105 cmemory_cleanup(void); 106 107 /** 108 * A function called by <TT>uhash_remove</TT>, 109 * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete 110 * an existing key or value. 111 * @param obj A key or value stored in a hashtable 112 * @see uprv_deleteUObject 113 */ 114 typedef void U_CALLCONV UObjectDeleter(void* obj); 115 116 /** 117 * Deleter for UObject instances. 118 * Works for all subclasses of UObject because it has a virtual destructor. 119 */ 120 U_CAPI void U_EXPORT2 121 uprv_deleteUObject(void *obj); 122 123 #ifdef __cplusplus 124 125 U_NAMESPACE_BEGIN 126 127 /** 128 * "Smart pointer" class, deletes memory via uprv_free(). 129 * For most methods see the LocalPointerBase base class. 130 * Adds operator[] for array item access. 131 * 132 * @see LocalPointerBase 133 */ 134 template<typename T> 135 class LocalMemory : public LocalPointerBase<T> { 136 public: 137 using LocalPointerBase<T>::operator*; 138 using LocalPointerBase<T>::operator->; 139 /** 140 * Constructor takes ownership. 141 * @param p simple pointer to an array of T items that is adopted 142 */ 143 explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {} 144 /** 145 * Move constructor, leaves src with isNull(). 146 * @param src source smart pointer 147 */ 148 LocalMemory(LocalMemory<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) { 149 src.ptr=NULL; 150 } 151 /** 152 * Destructor deletes the memory it owns. 153 */ 154 ~LocalMemory() { 155 uprv_free(LocalPointerBase<T>::ptr); 156 } 157 /** 158 * Move assignment operator, leaves src with isNull(). 159 * The behavior is undefined if *this and src are the same object. 160 * @param src source smart pointer 161 * @return *this 162 */ 163 LocalMemory<T> &operator=(LocalMemory<T> &&src) U_NOEXCEPT { 164 return moveFrom(src); 165 } 166 /** 167 * Move assignment, leaves src with isNull(). 168 * The behavior is undefined if *this and src are the same object. 169 * 170 * Can be called explicitly, does not need C++11 support. 171 * @param src source smart pointer 172 * @return *this 173 */ 174 LocalMemory<T> &moveFrom(LocalMemory<T> &src) U_NOEXCEPT { 175 uprv_free(LocalPointerBase<T>::ptr); 176 LocalPointerBase<T>::ptr=src.ptr; 177 src.ptr=NULL; 178 return *this; 179 } 180 /** 181 * Swap pointers. 182 * @param other other smart pointer 183 */ 184 void swap(LocalMemory<T> &other) U_NOEXCEPT { 185 T *temp=LocalPointerBase<T>::ptr; 186 LocalPointerBase<T>::ptr=other.ptr; 187 other.ptr=temp; 188 } 189 /** 190 * Non-member LocalMemory swap function. 191 * @param p1 will get p2's pointer 192 * @param p2 will get p1's pointer 193 */ 194 friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) U_NOEXCEPT { 195 p1.swap(p2); 196 } 197 /** 198 * Deletes the array it owns, 199 * and adopts (takes ownership of) the one passed in. 200 * @param p simple pointer to an array of T items that is adopted 201 */ 202 void adoptInstead(T *p) { 203 uprv_free(LocalPointerBase<T>::ptr); 204 LocalPointerBase<T>::ptr=p; 205 } 206 /** 207 * Deletes the array it owns, allocates a new one and reset its bytes to 0. 208 * Returns the new array pointer. 209 * If the allocation fails, then the current array is unchanged and 210 * this method returns NULL. 211 * @param newCapacity must be >0 212 * @return the allocated array pointer, or NULL if the allocation failed 213 */ 214 inline T *allocateInsteadAndReset(int32_t newCapacity=1); 215 /** 216 * Deletes the array it owns and allocates a new one, copying length T items. 217 * Returns the new array pointer. 218 * If the allocation fails, then the current array is unchanged and 219 * this method returns NULL. 220 * @param newCapacity must be >0 221 * @param length number of T items to be copied from the old array to the new one; 222 * must be no more than the capacity of the old array, 223 * which the caller must track because the LocalMemory does not track it 224 * @return the allocated array pointer, or NULL if the allocation failed 225 */ 226 inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0); 227 /** 228 * Array item access (writable). 229 * No index bounds check. 230 * @param i array index 231 * @return reference to the array item 232 */ 233 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; } 234 }; 235 236 template<typename T> 237 inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) { 238 if(newCapacity>0) { 239 T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 240 if(p!=NULL) { 241 uprv_memset(p, 0, newCapacity*sizeof(T)); 242 uprv_free(LocalPointerBase<T>::ptr); 243 LocalPointerBase<T>::ptr=p; 244 } 245 return p; 246 } else { 247 return NULL; 248 } 249 } 250 251 252 template<typename T> 253 inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) { 254 if(newCapacity>0) { 255 T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 256 if(p!=NULL) { 257 if(length>0) { 258 if(length>newCapacity) { 259 length=newCapacity; 260 } 261 uprv_memcpy(p, LocalPointerBase<T>::ptr, (size_t)length*sizeof(T)); 262 } 263 uprv_free(LocalPointerBase<T>::ptr); 264 LocalPointerBase<T>::ptr=p; 265 } 266 return p; 267 } else { 268 return NULL; 269 } 270 } 271 272 /** 273 * Simple array/buffer management class using uprv_malloc() and uprv_free(). 274 * Provides an internal array with fixed capacity. Can alias another array 275 * or allocate one. 276 * 277 * The array address is properly aligned for type T. It might not be properly 278 * aligned for types larger than T (or larger than the largest subtype of T). 279 * 280 * Unlike LocalMemory and LocalArray, this class never adopts 281 * (takes ownership of) another array. 282 * 283 * WARNING: MaybeStackArray only works with primitive (plain-old data) types. 284 * It does NOT know how to call a destructor! If you work with classes with 285 * destructors, consider LocalArray in localpointer.h. 286 */ 287 template<typename T, int32_t stackCapacity> 288 class MaybeStackArray { 289 public: 290 /** 291 * Default constructor initializes with internal T[stackCapacity] buffer. 292 */ 293 MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {} 294 /** 295 * Automatically allocates the heap array if the argument is larger than the stack capacity. 296 * Intended for use when an approximate capacity is known at compile time but the true 297 * capacity is not known until runtime. 298 */ 299 MaybeStackArray(int32_t newCapacity) : MaybeStackArray() { 300 if (capacity < newCapacity) { resize(newCapacity); } 301 }; 302 /** 303 * Destructor deletes the array (if owned). 304 */ 305 ~MaybeStackArray() { releaseArray(); } 306 /** 307 * Move constructor: transfers ownership or copies the stack array. 308 */ 309 MaybeStackArray(MaybeStackArray<T, stackCapacity> &&src) U_NOEXCEPT; 310 /** 311 * Move assignment: transfers ownership or copies the stack array. 312 */ 313 MaybeStackArray<T, stackCapacity> &operator=(MaybeStackArray<T, stackCapacity> &&src) U_NOEXCEPT; 314 /** 315 * Returns the array capacity (number of T items). 316 * @return array capacity 317 */ 318 int32_t getCapacity() const { return capacity; } 319 /** 320 * Access without ownership change. 321 * @return the array pointer 322 */ 323 T *getAlias() const { return ptr; } 324 /** 325 * Returns the array limit. Simple convenience method. 326 * @return getAlias()+getCapacity() 327 */ 328 T *getArrayLimit() const { return getAlias()+capacity; } 329 // No "operator T *() const" because that can make 330 // expressions like mbs[index] ambiguous for some compilers. 331 /** 332 * Array item access (const). 333 * No index bounds check. 334 * @param i array index 335 * @return reference to the array item 336 */ 337 const T &operator[](ptrdiff_t i) const { return ptr[i]; } 338 /** 339 * Array item access (writable). 340 * No index bounds check. 341 * @param i array index 342 * @return reference to the array item 343 */ 344 T &operator[](ptrdiff_t i) { return ptr[i]; } 345 /** 346 * Deletes the array (if owned) and aliases another one, no transfer of ownership. 347 * If the arguments are illegal, then the current array is unchanged. 348 * @param otherArray must not be NULL 349 * @param otherCapacity must be >0 350 */ 351 void aliasInstead(T *otherArray, int32_t otherCapacity) { 352 if(otherArray!=NULL && otherCapacity>0) { 353 releaseArray(); 354 ptr=otherArray; 355 capacity=otherCapacity; 356 needToRelease=FALSE; 357 } 358 } 359 /** 360 * Deletes the array (if owned) and allocates a new one, copying length T items. 361 * Returns the new array pointer. 362 * If the allocation fails, then the current array is unchanged and 363 * this method returns NULL. 364 * @param newCapacity can be less than or greater than the current capacity; 365 * must be >0 366 * @param length number of T items to be copied from the old array to the new one 367 * @return the allocated array pointer, or NULL if the allocation failed 368 */ 369 inline T *resize(int32_t newCapacity, int32_t length=0); 370 /** 371 * Gives up ownership of the array if owned, or else clones it, 372 * copying length T items; resets itself to the internal stack array. 373 * Returns NULL if the allocation failed. 374 * @param length number of T items to copy when cloning, 375 * and capacity of the clone when cloning 376 * @param resultCapacity will be set to the returned array's capacity (output-only) 377 * @return the array pointer; 378 * caller becomes responsible for deleting the array 379 */ 380 inline T *orphanOrClone(int32_t length, int32_t &resultCapacity); 381 private: 382 T *ptr; 383 int32_t capacity; 384 UBool needToRelease; 385 T stackArray[stackCapacity]; 386 void releaseArray() { 387 if(needToRelease) { 388 uprv_free(ptr); 389 } 390 } 391 void resetToStackArray() { 392 ptr=stackArray; 393 capacity=stackCapacity; 394 needToRelease=FALSE; 395 } 396 /* No comparison operators with other MaybeStackArray's. */ 397 bool operator==(const MaybeStackArray & /*other*/) {return FALSE;} 398 bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;} 399 /* No ownership transfer: No copy constructor, no assignment operator. */ 400 MaybeStackArray(const MaybeStackArray & /*other*/) {} 401 void operator=(const MaybeStackArray & /*other*/) {} 402 403 // No heap allocation. Use only on the stack. 404 // (Declaring these functions private triggers a cascade of problems: 405 // MSVC insists on exporting an instantiation of MaybeStackArray, which 406 // requires that all functions be defined. 407 // An empty implementation of new() is rejected, it must return a value. 408 // Returning NULL is rejected by gcc for operator new. 409 // The expedient thing is just not to override operator new. 410 // While relatively pointless, heap allocated instances will function. 411 // static void * U_EXPORT2 operator new(size_t size); 412 // static void * U_EXPORT2 operator new[](size_t size); 413 #if U_HAVE_PLACEMENT_NEW 414 // static void * U_EXPORT2 operator new(size_t, void *ptr); 415 #endif 416 }; 417 418 template<typename T, int32_t stackCapacity> 419 icu::MaybeStackArray<T, stackCapacity>::MaybeStackArray( 420 MaybeStackArray <T, stackCapacity>&& src) U_NOEXCEPT 421 : ptr(src.ptr), capacity(src.capacity), needToRelease(src.needToRelease) { 422 if (src.ptr == src.stackArray) { 423 ptr = stackArray; 424 uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity); 425 } else { 426 src.resetToStackArray(); // take ownership away from src 427 } 428 } 429 430 template<typename T, int32_t stackCapacity> 431 inline MaybeStackArray <T, stackCapacity>& 432 MaybeStackArray<T, stackCapacity>::operator=(MaybeStackArray <T, stackCapacity>&& src) U_NOEXCEPT { 433 releaseArray(); // in case this instance had its own memory allocated 434 capacity = src.capacity; 435 needToRelease = src.needToRelease; 436 if (src.ptr == src.stackArray) { 437 ptr = stackArray; 438 uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity); 439 } else { 440 ptr = src.ptr; 441 src.resetToStackArray(); // take ownership away from src 442 } 443 return *this; 444 } 445 446 template<typename T, int32_t stackCapacity> 447 inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) { 448 if(newCapacity>0) { 449 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 450 ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T)); 451 #endif 452 T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 453 if(p!=NULL) { 454 if(length>0) { 455 if(length>capacity) { 456 length=capacity; 457 } 458 if(length>newCapacity) { 459 length=newCapacity; 460 } 461 uprv_memcpy(p, ptr, (size_t)length*sizeof(T)); 462 } 463 releaseArray(); 464 ptr=p; 465 capacity=newCapacity; 466 needToRelease=TRUE; 467 } 468 return p; 469 } else { 470 return NULL; 471 } 472 } 473 474 template<typename T, int32_t stackCapacity> 475 inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) { 476 T *p; 477 if(needToRelease) { 478 p=ptr; 479 } else if(length<=0) { 480 return NULL; 481 } else { 482 if(length>capacity) { 483 length=capacity; 484 } 485 p=(T *)uprv_malloc(length*sizeof(T)); 486 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 487 ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T)); 488 #endif 489 if(p==NULL) { 490 return NULL; 491 } 492 uprv_memcpy(p, ptr, (size_t)length*sizeof(T)); 493 } 494 resultCapacity=length; 495 resetToStackArray(); 496 return p; 497 } 498 499 /** 500 * Variant of MaybeStackArray that allocates a header struct and an array 501 * in one contiguous memory block, using uprv_malloc() and uprv_free(). 502 * Provides internal memory with fixed array capacity. Can alias another memory 503 * block or allocate one. 504 * The stackCapacity is the number of T items in the internal memory, 505 * not counting the H header. 506 * Unlike LocalMemory and LocalArray, this class never adopts 507 * (takes ownership of) another memory block. 508 */ 509 template<typename H, typename T, int32_t stackCapacity> 510 class MaybeStackHeaderAndArray { 511 public: 512 /** 513 * Default constructor initializes with internal H+T[stackCapacity] buffer. 514 */ 515 MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {} 516 /** 517 * Destructor deletes the memory (if owned). 518 */ 519 ~MaybeStackHeaderAndArray() { releaseMemory(); } 520 /** 521 * Returns the array capacity (number of T items). 522 * @return array capacity 523 */ 524 int32_t getCapacity() const { return capacity; } 525 /** 526 * Access without ownership change. 527 * @return the header pointer 528 */ 529 H *getAlias() const { return ptr; } 530 /** 531 * Returns the array start. 532 * @return array start, same address as getAlias()+1 533 */ 534 T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); } 535 /** 536 * Returns the array limit. 537 * @return array limit 538 */ 539 T *getArrayLimit() const { return getArrayStart()+capacity; } 540 /** 541 * Access without ownership change. Same as getAlias(). 542 * A class instance can be used directly in expressions that take a T *. 543 * @return the header pointer 544 */ 545 operator H *() const { return ptr; } 546 /** 547 * Array item access (writable). 548 * No index bounds check. 549 * @param i array index 550 * @return reference to the array item 551 */ 552 T &operator[](ptrdiff_t i) { return getArrayStart()[i]; } 553 /** 554 * Deletes the memory block (if owned) and aliases another one, no transfer of ownership. 555 * If the arguments are illegal, then the current memory is unchanged. 556 * @param otherArray must not be NULL 557 * @param otherCapacity must be >0 558 */ 559 void aliasInstead(H *otherMemory, int32_t otherCapacity) { 560 if(otherMemory!=NULL && otherCapacity>0) { 561 releaseMemory(); 562 ptr=otherMemory; 563 capacity=otherCapacity; 564 needToRelease=FALSE; 565 } 566 } 567 /** 568 * Deletes the memory block (if owned) and allocates a new one, 569 * copying the header and length T array items. 570 * Returns the new header pointer. 571 * If the allocation fails, then the current memory is unchanged and 572 * this method returns NULL. 573 * @param newCapacity can be less than or greater than the current capacity; 574 * must be >0 575 * @param length number of T items to be copied from the old array to the new one 576 * @return the allocated pointer, or NULL if the allocation failed 577 */ 578 inline H *resize(int32_t newCapacity, int32_t length=0); 579 /** 580 * Gives up ownership of the memory if owned, or else clones it, 581 * copying the header and length T array items; resets itself to the internal memory. 582 * Returns NULL if the allocation failed. 583 * @param length number of T items to copy when cloning, 584 * and array capacity of the clone when cloning 585 * @param resultCapacity will be set to the returned array's capacity (output-only) 586 * @return the header pointer; 587 * caller becomes responsible for deleting the array 588 */ 589 inline H *orphanOrClone(int32_t length, int32_t &resultCapacity); 590 private: 591 H *ptr; 592 int32_t capacity; 593 UBool needToRelease; 594 // stackHeader must precede stackArray immediately. 595 H stackHeader; 596 T stackArray[stackCapacity]; 597 void releaseMemory() { 598 if(needToRelease) { 599 uprv_free(ptr); 600 } 601 } 602 /* No comparison operators with other MaybeStackHeaderAndArray's. */ 603 bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;} 604 bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;} 605 /* No ownership transfer: No copy constructor, no assignment operator. */ 606 MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {} 607 void operator=(const MaybeStackHeaderAndArray & /*other*/) {} 608 609 // No heap allocation. Use only on the stack. 610 // (Declaring these functions private triggers a cascade of problems; 611 // see the MaybeStackArray class for details.) 612 // static void * U_EXPORT2 operator new(size_t size); 613 // static void * U_EXPORT2 operator new[](size_t size); 614 #if U_HAVE_PLACEMENT_NEW 615 // static void * U_EXPORT2 operator new(size_t, void *ptr); 616 #endif 617 }; 618 619 template<typename H, typename T, int32_t stackCapacity> 620 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity, 621 int32_t length) { 622 if(newCapacity>=0) { 623 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 624 ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T)); 625 #endif 626 H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T)); 627 if(p!=NULL) { 628 if(length<0) { 629 length=0; 630 } else if(length>0) { 631 if(length>capacity) { 632 length=capacity; 633 } 634 if(length>newCapacity) { 635 length=newCapacity; 636 } 637 } 638 uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T)); 639 releaseMemory(); 640 ptr=p; 641 capacity=newCapacity; 642 needToRelease=TRUE; 643 } 644 return p; 645 } else { 646 return NULL; 647 } 648 } 649 650 template<typename H, typename T, int32_t stackCapacity> 651 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length, 652 int32_t &resultCapacity) { 653 H *p; 654 if(needToRelease) { 655 p=ptr; 656 } else { 657 if(length<0) { 658 length=0; 659 } else if(length>capacity) { 660 length=capacity; 661 } 662 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 663 ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T)); 664 #endif 665 p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T)); 666 if(p==NULL) { 667 return NULL; 668 } 669 uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T)); 670 } 671 resultCapacity=length; 672 ptr=&stackHeader; 673 capacity=stackCapacity; 674 needToRelease=FALSE; 675 return p; 676 } 677 678 U_NAMESPACE_END 679 680 #endif /* __cplusplus */ 681 #endif /* CMEMORY_H */ 682