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