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 /** 162 * Destructor deletes the memory it owns. 163 */ 164 ~LocalMemory() { 165 uprv_free(LocalPointerBase<T>::ptr); 166 } 167 /** 168 * Deletes the array it owns, 169 * and adopts (takes ownership of) the one passed in. 170 * @param p simple pointer to an array of T items that is adopted 171 */ 172 void adoptInstead(T *p) { 173 uprv_free(LocalPointerBase<T>::ptr); 174 LocalPointerBase<T>::ptr=p; 175 } 176 /** 177 * Deletes the array it owns, allocates a new one and reset its bytes to 0. 178 * Returns the new array pointer. 179 * If the allocation fails, then the current array is unchanged and 180 * this method returns NULL. 181 * @param newCapacity must be >0 182 * @return the allocated array pointer, or NULL if the allocation failed 183 */ 184 inline T *allocateInsteadAndReset(int32_t newCapacity=1); 185 /** 186 * Deletes the array it owns and allocates a new one, copying length T items. 187 * Returns the new array pointer. 188 * If the allocation fails, then the current array is unchanged and 189 * this method returns NULL. 190 * @param newCapacity must be >0 191 * @param length number of T items to be copied from the old array to the new one; 192 * must be no more than the capacity of the old array, 193 * which the caller must track because the LocalMemory does not track it 194 * @return the allocated array pointer, or NULL if the allocation failed 195 */ 196 inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0); 197 /** 198 * Array item access (writable). 199 * No index bounds check. 200 * @param i array index 201 * @return reference to the array item 202 */ 203 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; } 204 }; 205 206 template<typename T> 207 inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) { 208 if(newCapacity>0) { 209 T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 210 if(p!=NULL) { 211 uprv_memset(p, 0, newCapacity*sizeof(T)); 212 uprv_free(LocalPointerBase<T>::ptr); 213 LocalPointerBase<T>::ptr=p; 214 } 215 return p; 216 } else { 217 return NULL; 218 } 219 } 220 221 222 template<typename T> 223 inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) { 224 if(newCapacity>0) { 225 T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 226 if(p!=NULL) { 227 if(length>0) { 228 if(length>newCapacity) { 229 length=newCapacity; 230 } 231 uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T)); 232 } 233 uprv_free(LocalPointerBase<T>::ptr); 234 LocalPointerBase<T>::ptr=p; 235 } 236 return p; 237 } else { 238 return NULL; 239 } 240 } 241 242 /** 243 * Simple array/buffer management class using uprv_malloc() and uprv_free(). 244 * Provides an internal array with fixed capacity. Can alias another array 245 * or allocate one. 246 * 247 * The array address is properly aligned for type T. It might not be properly 248 * aligned for types larger than T (or larger than the largest subtype of T). 249 * 250 * Unlike LocalMemory and LocalArray, this class never adopts 251 * (takes ownership of) another array. 252 */ 253 template<typename T, int32_t stackCapacity> 254 class MaybeStackArray { 255 public: 256 /** 257 * Default constructor initializes with internal T[stackCapacity] buffer. 258 */ 259 MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {} 260 /** 261 * Destructor deletes the array (if owned). 262 */ 263 ~MaybeStackArray() { releaseArray(); } 264 /** 265 * Returns the array capacity (number of T items). 266 * @return array capacity 267 */ 268 int32_t getCapacity() const { return capacity; } 269 /** 270 * Access without ownership change. 271 * @return the array pointer 272 */ 273 T *getAlias() const { return ptr; } 274 /** 275 * Returns the array limit. Simple convenience method. 276 * @return getAlias()+getCapacity() 277 */ 278 T *getArrayLimit() const { return getAlias()+capacity; } 279 // No "operator T *() const" because that can make 280 // expressions like mbs[index] ambiguous for some compilers. 281 /** 282 * Array item access (const). 283 * No index bounds check. 284 * @param i array index 285 * @return reference to the array item 286 */ 287 const T &operator[](ptrdiff_t i) const { return ptr[i]; } 288 /** 289 * Array item access (writable). 290 * No index bounds check. 291 * @param i array index 292 * @return reference to the array item 293 */ 294 T &operator[](ptrdiff_t i) { return ptr[i]; } 295 /** 296 * Deletes the array (if owned) and aliases another one, no transfer of ownership. 297 * If the arguments are illegal, then the current array is unchanged. 298 * @param otherArray must not be NULL 299 * @param otherCapacity must be >0 300 */ 301 void aliasInstead(T *otherArray, int32_t otherCapacity) { 302 if(otherArray!=NULL && otherCapacity>0) { 303 releaseArray(); 304 ptr=otherArray; 305 capacity=otherCapacity; 306 needToRelease=FALSE; 307 } 308 } 309 /** 310 * Deletes the array (if owned) and allocates a new one, copying length T items. 311 * Returns the new array pointer. 312 * If the allocation fails, then the current array is unchanged and 313 * this method returns NULL. 314 * @param newCapacity can be less than or greater than the current capacity; 315 * must be >0 316 * @param length number of T items to be copied from the old array to the new one 317 * @return the allocated array pointer, or NULL if the allocation failed 318 */ 319 inline T *resize(int32_t newCapacity, int32_t length=0); 320 /** 321 * Gives up ownership of the array if owned, or else clones it, 322 * copying length T items; resets itself to the internal stack array. 323 * Returns NULL if the allocation failed. 324 * @param length number of T items to copy when cloning, 325 * and capacity of the clone when cloning 326 * @param resultCapacity will be set to the returned array's capacity (output-only) 327 * @return the array pointer; 328 * caller becomes responsible for deleting the array 329 */ 330 inline T *orphanOrClone(int32_t length, int32_t &resultCapacity); 331 private: 332 T *ptr; 333 int32_t capacity; 334 UBool needToRelease; 335 T stackArray[stackCapacity]; 336 void releaseArray() { 337 if(needToRelease) { 338 uprv_free(ptr); 339 } 340 } 341 /* No comparison operators with other MaybeStackArray's. */ 342 bool operator==(const MaybeStackArray & /*other*/) {return FALSE;} 343 bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;} 344 /* No ownership transfer: No copy constructor, no assignment operator. */ 345 MaybeStackArray(const MaybeStackArray & /*other*/) {} 346 void operator=(const MaybeStackArray & /*other*/) {} 347 348 // No heap allocation. Use only on the stack. 349 // (Declaring these functions private triggers a cascade of problems: 350 // MSVC insists on exporting an instantiation of MaybeStackArray, which 351 // requires that all functions be defined. 352 // An empty implementation of new() is rejected, it must return a value. 353 // Returning NULL is rejected by gcc for operator new. 354 // The expedient thing is just not to override operator new. 355 // While relatively pointless, heap allocated instances will function. 356 // static void * U_EXPORT2 operator new(size_t size); 357 // static void * U_EXPORT2 operator new[](size_t size); 358 #if U_HAVE_PLACEMENT_NEW 359 // static void * U_EXPORT2 operator new(size_t, void *ptr); 360 #endif 361 }; 362 363 template<typename T, int32_t stackCapacity> 364 inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) { 365 if(newCapacity>0) { 366 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 367 ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T)); 368 #endif 369 T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 370 if(p!=NULL) { 371 if(length>0) { 372 if(length>capacity) { 373 length=capacity; 374 } 375 if(length>newCapacity) { 376 length=newCapacity; 377 } 378 uprv_memcpy(p, ptr, length*sizeof(T)); 379 } 380 releaseArray(); 381 ptr=p; 382 capacity=newCapacity; 383 needToRelease=TRUE; 384 } 385 return p; 386 } else { 387 return NULL; 388 } 389 } 390 391 template<typename T, int32_t stackCapacity> 392 inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) { 393 T *p; 394 if(needToRelease) { 395 p=ptr; 396 } else if(length<=0) { 397 return NULL; 398 } else { 399 if(length>capacity) { 400 length=capacity; 401 } 402 p=(T *)uprv_malloc(length*sizeof(T)); 403 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 404 ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T)); 405 #endif 406 if(p==NULL) { 407 return NULL; 408 } 409 uprv_memcpy(p, ptr, length*sizeof(T)); 410 } 411 resultCapacity=length; 412 ptr=stackArray; 413 capacity=stackCapacity; 414 needToRelease=FALSE; 415 return p; 416 } 417 418 /** 419 * Variant of MaybeStackArray that allocates a header struct and an array 420 * in one contiguous memory block, using uprv_malloc() and uprv_free(). 421 * Provides internal memory with fixed array capacity. Can alias another memory 422 * block or allocate one. 423 * The stackCapacity is the number of T items in the internal memory, 424 * not counting the H header. 425 * Unlike LocalMemory and LocalArray, this class never adopts 426 * (takes ownership of) another memory block. 427 */ 428 template<typename H, typename T, int32_t stackCapacity> 429 class MaybeStackHeaderAndArray { 430 public: 431 /** 432 * Default constructor initializes with internal H+T[stackCapacity] buffer. 433 */ 434 MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {} 435 /** 436 * Destructor deletes the memory (if owned). 437 */ 438 ~MaybeStackHeaderAndArray() { releaseMemory(); } 439 /** 440 * Returns the array capacity (number of T items). 441 * @return array capacity 442 */ 443 int32_t getCapacity() const { return capacity; } 444 /** 445 * Access without ownership change. 446 * @return the header pointer 447 */ 448 H *getAlias() const { return ptr; } 449 /** 450 * Returns the array start. 451 * @return array start, same address as getAlias()+1 452 */ 453 T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); } 454 /** 455 * Returns the array limit. 456 * @return array limit 457 */ 458 T *getArrayLimit() const { return getArrayStart()+capacity; } 459 /** 460 * Access without ownership change. Same as getAlias(). 461 * A class instance can be used directly in expressions that take a T *. 462 * @return the header pointer 463 */ 464 operator H *() const { return ptr; } 465 /** 466 * Array item access (writable). 467 * No index bounds check. 468 * @param i array index 469 * @return reference to the array item 470 */ 471 T &operator[](ptrdiff_t i) { return getArrayStart()[i]; } 472 /** 473 * Deletes the memory block (if owned) and aliases another one, no transfer of ownership. 474 * If the arguments are illegal, then the current memory is unchanged. 475 * @param otherArray must not be NULL 476 * @param otherCapacity must be >0 477 */ 478 void aliasInstead(H *otherMemory, int32_t otherCapacity) { 479 if(otherMemory!=NULL && otherCapacity>0) { 480 releaseMemory(); 481 ptr=otherMemory; 482 capacity=otherCapacity; 483 needToRelease=FALSE; 484 } 485 } 486 /** 487 * Deletes the memory block (if owned) and allocates a new one, 488 * copying the header and length T array items. 489 * Returns the new header pointer. 490 * If the allocation fails, then the current memory is unchanged and 491 * this method returns NULL. 492 * @param newCapacity can be less than or greater than the current capacity; 493 * must be >0 494 * @param length number of T items to be copied from the old array to the new one 495 * @return the allocated pointer, or NULL if the allocation failed 496 */ 497 inline H *resize(int32_t newCapacity, int32_t length=0); 498 /** 499 * Gives up ownership of the memory if owned, or else clones it, 500 * copying the header and length T array items; resets itself to the internal memory. 501 * Returns NULL if the allocation failed. 502 * @param length number of T items to copy when cloning, 503 * and array capacity of the clone when cloning 504 * @param resultCapacity will be set to the returned array's capacity (output-only) 505 * @return the header pointer; 506 * caller becomes responsible for deleting the array 507 */ 508 inline H *orphanOrClone(int32_t length, int32_t &resultCapacity); 509 private: 510 H *ptr; 511 int32_t capacity; 512 UBool needToRelease; 513 // stackHeader must precede stackArray immediately. 514 H stackHeader; 515 T stackArray[stackCapacity]; 516 void releaseMemory() { 517 if(needToRelease) { 518 uprv_free(ptr); 519 } 520 } 521 /* No comparison operators with other MaybeStackHeaderAndArray's. */ 522 bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;} 523 bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;} 524 /* No ownership transfer: No copy constructor, no assignment operator. */ 525 MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {} 526 void operator=(const MaybeStackHeaderAndArray & /*other*/) {} 527 528 // No heap allocation. Use only on the stack. 529 // (Declaring these functions private triggers a cascade of problems; 530 // see the MaybeStackArray class for details.) 531 // static void * U_EXPORT2 operator new(size_t size); 532 // static void * U_EXPORT2 operator new[](size_t size); 533 #if U_HAVE_PLACEMENT_NEW 534 // static void * U_EXPORT2 operator new(size_t, void *ptr); 535 #endif 536 }; 537 538 template<typename H, typename T, int32_t stackCapacity> 539 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity, 540 int32_t length) { 541 if(newCapacity>=0) { 542 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 543 ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T)); 544 #endif 545 H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T)); 546 if(p!=NULL) { 547 if(length<0) { 548 length=0; 549 } else if(length>0) { 550 if(length>capacity) { 551 length=capacity; 552 } 553 if(length>newCapacity) { 554 length=newCapacity; 555 } 556 } 557 uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T)); 558 releaseMemory(); 559 ptr=p; 560 capacity=newCapacity; 561 needToRelease=TRUE; 562 } 563 return p; 564 } else { 565 return NULL; 566 } 567 } 568 569 template<typename H, typename T, int32_t stackCapacity> 570 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length, 571 int32_t &resultCapacity) { 572 H *p; 573 if(needToRelease) { 574 p=ptr; 575 } else { 576 if(length<0) { 577 length=0; 578 } else if(length>capacity) { 579 length=capacity; 580 } 581 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 582 ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T)); 583 #endif 584 p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T)); 585 if(p==NULL) { 586 return NULL; 587 } 588 uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T)); 589 } 590 resultCapacity=length; 591 ptr=&stackHeader; 592 capacity=stackCapacity; 593 needToRelease=FALSE; 594 return p; 595 } 596 597 U_NAMESPACE_END 598 599 #endif /* __cplusplus */ 600 #endif /* CMEMORY_H */ 601