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