1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/common/cmemory.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,599 @@ 1.4 +/* 1.5 +****************************************************************************** 1.6 +* 1.7 +* Copyright (C) 1997-2012, International Business Machines 1.8 +* Corporation and others. All Rights Reserved. 1.9 +* 1.10 +****************************************************************************** 1.11 +* 1.12 +* File CMEMORY.H 1.13 +* 1.14 +* Contains stdlib.h/string.h memory functions 1.15 +* 1.16 +* @author Bertrand A. Damiba 1.17 +* 1.18 +* Modification History: 1.19 +* 1.20 +* Date Name Description 1.21 +* 6/20/98 Bertrand Created. 1.22 +* 05/03/99 stephen Changed from functions to macros. 1.23 +* 1.24 +****************************************************************************** 1.25 +*/ 1.26 + 1.27 +#ifndef CMEMORY_H 1.28 +#define CMEMORY_H 1.29 + 1.30 +#include "unicode/utypes.h" 1.31 + 1.32 +#include <stddef.h> 1.33 +#include <string.h> 1.34 +#include "unicode/localpointer.h" 1.35 + 1.36 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.37 +#include <stdio.h> 1.38 +#endif 1.39 + 1.40 +#if U_DEBUG 1.41 + 1.42 +/* 1.43 + * The C++ standard requires that the source pointer for memcpy() & memmove() 1.44 + * is valid, not NULL, and not at the end of an allocated memory block. 1.45 + * In debug mode, we read one byte from the source point to verify that it's 1.46 + * a valid, readable pointer. 1.47 + */ 1.48 + 1.49 +U_CAPI void uprv_checkValidMemory(const void *p, size_t n); 1.50 + 1.51 +#define uprv_memcpy(dst, src, size) ( \ 1.52 + uprv_checkValidMemory(src, 1), \ 1.53 + U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)) 1.54 +#define uprv_memmove(dst, src, size) ( \ 1.55 + uprv_checkValidMemory(src, 1), \ 1.56 + U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)) 1.57 + 1.58 +#else 1.59 + 1.60 +#define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size) 1.61 +#define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size) 1.62 + 1.63 +#endif /* U_DEBUG */ 1.64 + 1.65 +#define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size) 1.66 +#define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size) 1.67 + 1.68 +U_CAPI void * U_EXPORT2 1.69 +uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1); 1.70 + 1.71 +U_CAPI void * U_EXPORT2 1.72 +uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2); 1.73 + 1.74 +U_CAPI void U_EXPORT2 1.75 +uprv_free(void *mem); 1.76 + 1.77 +U_CAPI void * U_EXPORT2 1.78 +uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2); 1.79 + 1.80 +/** 1.81 + * This should align the memory properly on any machine. 1.82 + * This is very useful for the safeClone functions. 1.83 + */ 1.84 +typedef union { 1.85 + long t1; 1.86 + double t2; 1.87 + void *t3; 1.88 +} UAlignedMemory; 1.89 + 1.90 +/** 1.91 + * Get the least significant bits of a pointer (a memory address). 1.92 + * For example, with a mask of 3, the macro gets the 2 least significant bits, 1.93 + * which will be 0 if the pointer is 32-bit (4-byte) aligned. 1.94 + * 1.95 + * ptrdiff_t is the most appropriate integer type to cast to. 1.96 + * size_t should work too, since on most (or all?) platforms it has the same 1.97 + * width as ptrdiff_t. 1.98 + */ 1.99 +#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask)) 1.100 + 1.101 +/** 1.102 + * Get the amount of bytes that a pointer is off by from 1.103 + * the previous UAlignedMemory-aligned pointer. 1.104 + */ 1.105 +#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1) 1.106 + 1.107 +/** 1.108 + * Get the amount of bytes to add to a pointer 1.109 + * in order to get the next UAlignedMemory-aligned address. 1.110 + */ 1.111 +#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr)) 1.112 + 1.113 +/** 1.114 + * Indicate whether the ICU allocation functions have been used. 1.115 + * This is used to determine whether ICU is in an initial, unused state. 1.116 + */ 1.117 +U_CFUNC UBool 1.118 +cmemory_inUse(void); 1.119 + 1.120 +/** 1.121 + * Heap clean up function, called from u_cleanup() 1.122 + * Clears any user heap functions from u_setMemoryFunctions() 1.123 + * Does NOT deallocate any remaining allocated memory. 1.124 + */ 1.125 +U_CFUNC UBool 1.126 +cmemory_cleanup(void); 1.127 + 1.128 +/** 1.129 + * A function called by <TT>uhash_remove</TT>, 1.130 + * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete 1.131 + * an existing key or value. 1.132 + * @param obj A key or value stored in a hashtable 1.133 + * @see uprv_deleteUObject 1.134 + */ 1.135 +typedef void U_CALLCONV UObjectDeleter(void* obj); 1.136 + 1.137 +/** 1.138 + * Deleter for UObject instances. 1.139 + * Works for all subclasses of UObject because it has a virtual destructor. 1.140 + */ 1.141 +U_CAPI void U_EXPORT2 1.142 +uprv_deleteUObject(void *obj); 1.143 + 1.144 +#ifdef __cplusplus 1.145 + 1.146 +U_NAMESPACE_BEGIN 1.147 + 1.148 +/** 1.149 + * "Smart pointer" class, deletes memory via uprv_free(). 1.150 + * For most methods see the LocalPointerBase base class. 1.151 + * Adds operator[] for array item access. 1.152 + * 1.153 + * @see LocalPointerBase 1.154 + */ 1.155 +template<typename T> 1.156 +class LocalMemory : public LocalPointerBase<T> { 1.157 +public: 1.158 + /** 1.159 + * Constructor takes ownership. 1.160 + * @param p simple pointer to an array of T items that is adopted 1.161 + */ 1.162 + explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {} 1.163 + /** 1.164 + * Destructor deletes the memory it owns. 1.165 + */ 1.166 + ~LocalMemory() { 1.167 + uprv_free(LocalPointerBase<T>::ptr); 1.168 + } 1.169 + /** 1.170 + * Deletes the array it owns, 1.171 + * and adopts (takes ownership of) the one passed in. 1.172 + * @param p simple pointer to an array of T items that is adopted 1.173 + */ 1.174 + void adoptInstead(T *p) { 1.175 + uprv_free(LocalPointerBase<T>::ptr); 1.176 + LocalPointerBase<T>::ptr=p; 1.177 + } 1.178 + /** 1.179 + * Deletes the array it owns, allocates a new one and reset its bytes to 0. 1.180 + * Returns the new array pointer. 1.181 + * If the allocation fails, then the current array is unchanged and 1.182 + * this method returns NULL. 1.183 + * @param newCapacity must be >0 1.184 + * @return the allocated array pointer, or NULL if the allocation failed 1.185 + */ 1.186 + inline T *allocateInsteadAndReset(int32_t newCapacity=1); 1.187 + /** 1.188 + * Deletes the array it owns and allocates a new one, copying length T items. 1.189 + * Returns the new array pointer. 1.190 + * If the allocation fails, then the current array is unchanged and 1.191 + * this method returns NULL. 1.192 + * @param newCapacity must be >0 1.193 + * @param length number of T items to be copied from the old array to the new one; 1.194 + * must be no more than the capacity of the old array, 1.195 + * which the caller must track because the LocalMemory does not track it 1.196 + * @return the allocated array pointer, or NULL if the allocation failed 1.197 + */ 1.198 + inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0); 1.199 + /** 1.200 + * Array item access (writable). 1.201 + * No index bounds check. 1.202 + * @param i array index 1.203 + * @return reference to the array item 1.204 + */ 1.205 + T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; } 1.206 +}; 1.207 + 1.208 +template<typename T> 1.209 +inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) { 1.210 + if(newCapacity>0) { 1.211 + T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 1.212 + if(p!=NULL) { 1.213 + uprv_memset(p, 0, newCapacity*sizeof(T)); 1.214 + uprv_free(LocalPointerBase<T>::ptr); 1.215 + LocalPointerBase<T>::ptr=p; 1.216 + } 1.217 + return p; 1.218 + } else { 1.219 + return NULL; 1.220 + } 1.221 +} 1.222 + 1.223 + 1.224 +template<typename T> 1.225 +inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) { 1.226 + if(newCapacity>0) { 1.227 + T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 1.228 + if(p!=NULL) { 1.229 + if(length>0) { 1.230 + if(length>newCapacity) { 1.231 + length=newCapacity; 1.232 + } 1.233 + uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T)); 1.234 + } 1.235 + uprv_free(LocalPointerBase<T>::ptr); 1.236 + LocalPointerBase<T>::ptr=p; 1.237 + } 1.238 + return p; 1.239 + } else { 1.240 + return NULL; 1.241 + } 1.242 +} 1.243 + 1.244 +/** 1.245 + * Simple array/buffer management class using uprv_malloc() and uprv_free(). 1.246 + * Provides an internal array with fixed capacity. Can alias another array 1.247 + * or allocate one. 1.248 + * 1.249 + * The array address is properly aligned for type T. It might not be properly 1.250 + * aligned for types larger than T (or larger than the largest subtype of T). 1.251 + * 1.252 + * Unlike LocalMemory and LocalArray, this class never adopts 1.253 + * (takes ownership of) another array. 1.254 + */ 1.255 +template<typename T, int32_t stackCapacity> 1.256 +class MaybeStackArray { 1.257 +public: 1.258 + /** 1.259 + * Default constructor initializes with internal T[stackCapacity] buffer. 1.260 + */ 1.261 + MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {} 1.262 + /** 1.263 + * Destructor deletes the array (if owned). 1.264 + */ 1.265 + ~MaybeStackArray() { releaseArray(); } 1.266 + /** 1.267 + * Returns the array capacity (number of T items). 1.268 + * @return array capacity 1.269 + */ 1.270 + int32_t getCapacity() const { return capacity; } 1.271 + /** 1.272 + * Access without ownership change. 1.273 + * @return the array pointer 1.274 + */ 1.275 + T *getAlias() const { return ptr; } 1.276 + /** 1.277 + * Returns the array limit. Simple convenience method. 1.278 + * @return getAlias()+getCapacity() 1.279 + */ 1.280 + T *getArrayLimit() const { return getAlias()+capacity; } 1.281 + // No "operator T *() const" because that can make 1.282 + // expressions like mbs[index] ambiguous for some compilers. 1.283 + /** 1.284 + * Array item access (const). 1.285 + * No index bounds check. 1.286 + * @param i array index 1.287 + * @return reference to the array item 1.288 + */ 1.289 + const T &operator[](ptrdiff_t i) const { return ptr[i]; } 1.290 + /** 1.291 + * Array item access (writable). 1.292 + * No index bounds check. 1.293 + * @param i array index 1.294 + * @return reference to the array item 1.295 + */ 1.296 + T &operator[](ptrdiff_t i) { return ptr[i]; } 1.297 + /** 1.298 + * Deletes the array (if owned) and aliases another one, no transfer of ownership. 1.299 + * If the arguments are illegal, then the current array is unchanged. 1.300 + * @param otherArray must not be NULL 1.301 + * @param otherCapacity must be >0 1.302 + */ 1.303 + void aliasInstead(T *otherArray, int32_t otherCapacity) { 1.304 + if(otherArray!=NULL && otherCapacity>0) { 1.305 + releaseArray(); 1.306 + ptr=otherArray; 1.307 + capacity=otherCapacity; 1.308 + needToRelease=FALSE; 1.309 + } 1.310 + } 1.311 + /** 1.312 + * Deletes the array (if owned) and allocates a new one, copying length T items. 1.313 + * Returns the new array pointer. 1.314 + * If the allocation fails, then the current array is unchanged and 1.315 + * this method returns NULL. 1.316 + * @param newCapacity can be less than or greater than the current capacity; 1.317 + * must be >0 1.318 + * @param length number of T items to be copied from the old array to the new one 1.319 + * @return the allocated array pointer, or NULL if the allocation failed 1.320 + */ 1.321 + inline T *resize(int32_t newCapacity, int32_t length=0); 1.322 + /** 1.323 + * Gives up ownership of the array if owned, or else clones it, 1.324 + * copying length T items; resets itself to the internal stack array. 1.325 + * Returns NULL if the allocation failed. 1.326 + * @param length number of T items to copy when cloning, 1.327 + * and capacity of the clone when cloning 1.328 + * @param resultCapacity will be set to the returned array's capacity (output-only) 1.329 + * @return the array pointer; 1.330 + * caller becomes responsible for deleting the array 1.331 + */ 1.332 + inline T *orphanOrClone(int32_t length, int32_t &resultCapacity); 1.333 +private: 1.334 + T *ptr; 1.335 + int32_t capacity; 1.336 + UBool needToRelease; 1.337 + T stackArray[stackCapacity]; 1.338 + void releaseArray() { 1.339 + if(needToRelease) { 1.340 + uprv_free(ptr); 1.341 + } 1.342 + } 1.343 + /* No comparison operators with other MaybeStackArray's. */ 1.344 + bool operator==(const MaybeStackArray & /*other*/) {return FALSE;} 1.345 + bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;} 1.346 + /* No ownership transfer: No copy constructor, no assignment operator. */ 1.347 + MaybeStackArray(const MaybeStackArray & /*other*/) {} 1.348 + void operator=(const MaybeStackArray & /*other*/) {} 1.349 + 1.350 + // No heap allocation. Use only on the stack. 1.351 + // (Declaring these functions private triggers a cascade of problems: 1.352 + // MSVC insists on exporting an instantiation of MaybeStackArray, which 1.353 + // requires that all functions be defined. 1.354 + // An empty implementation of new() is rejected, it must return a value. 1.355 + // Returning NULL is rejected by gcc for operator new. 1.356 + // The expedient thing is just not to override operator new. 1.357 + // While relatively pointless, heap allocated instances will function. 1.358 + // static void * U_EXPORT2 operator new(size_t size); 1.359 + // static void * U_EXPORT2 operator new[](size_t size); 1.360 +#if U_HAVE_PLACEMENT_NEW 1.361 + // static void * U_EXPORT2 operator new(size_t, void *ptr); 1.362 +#endif 1.363 +}; 1.364 + 1.365 +template<typename T, int32_t stackCapacity> 1.366 +inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) { 1.367 + if(newCapacity>0) { 1.368 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.369 + ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T)); 1.370 +#endif 1.371 + T *p=(T *)uprv_malloc(newCapacity*sizeof(T)); 1.372 + if(p!=NULL) { 1.373 + if(length>0) { 1.374 + if(length>capacity) { 1.375 + length=capacity; 1.376 + } 1.377 + if(length>newCapacity) { 1.378 + length=newCapacity; 1.379 + } 1.380 + uprv_memcpy(p, ptr, length*sizeof(T)); 1.381 + } 1.382 + releaseArray(); 1.383 + ptr=p; 1.384 + capacity=newCapacity; 1.385 + needToRelease=TRUE; 1.386 + } 1.387 + return p; 1.388 + } else { 1.389 + return NULL; 1.390 + } 1.391 +} 1.392 + 1.393 +template<typename T, int32_t stackCapacity> 1.394 +inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) { 1.395 + T *p; 1.396 + if(needToRelease) { 1.397 + p=ptr; 1.398 + } else if(length<=0) { 1.399 + return NULL; 1.400 + } else { 1.401 + if(length>capacity) { 1.402 + length=capacity; 1.403 + } 1.404 + p=(T *)uprv_malloc(length*sizeof(T)); 1.405 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.406 + ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T)); 1.407 +#endif 1.408 + if(p==NULL) { 1.409 + return NULL; 1.410 + } 1.411 + uprv_memcpy(p, ptr, length*sizeof(T)); 1.412 + } 1.413 + resultCapacity=length; 1.414 + ptr=stackArray; 1.415 + capacity=stackCapacity; 1.416 + needToRelease=FALSE; 1.417 + return p; 1.418 +} 1.419 + 1.420 +/** 1.421 + * Variant of MaybeStackArray that allocates a header struct and an array 1.422 + * in one contiguous memory block, using uprv_malloc() and uprv_free(). 1.423 + * Provides internal memory with fixed array capacity. Can alias another memory 1.424 + * block or allocate one. 1.425 + * The stackCapacity is the number of T items in the internal memory, 1.426 + * not counting the H header. 1.427 + * Unlike LocalMemory and LocalArray, this class never adopts 1.428 + * (takes ownership of) another memory block. 1.429 + */ 1.430 +template<typename H, typename T, int32_t stackCapacity> 1.431 +class MaybeStackHeaderAndArray { 1.432 +public: 1.433 + /** 1.434 + * Default constructor initializes with internal H+T[stackCapacity] buffer. 1.435 + */ 1.436 + MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {} 1.437 + /** 1.438 + * Destructor deletes the memory (if owned). 1.439 + */ 1.440 + ~MaybeStackHeaderAndArray() { releaseMemory(); } 1.441 + /** 1.442 + * Returns the array capacity (number of T items). 1.443 + * @return array capacity 1.444 + */ 1.445 + int32_t getCapacity() const { return capacity; } 1.446 + /** 1.447 + * Access without ownership change. 1.448 + * @return the header pointer 1.449 + */ 1.450 + H *getAlias() const { return ptr; } 1.451 + /** 1.452 + * Returns the array start. 1.453 + * @return array start, same address as getAlias()+1 1.454 + */ 1.455 + T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); } 1.456 + /** 1.457 + * Returns the array limit. 1.458 + * @return array limit 1.459 + */ 1.460 + T *getArrayLimit() const { return getArrayStart()+capacity; } 1.461 + /** 1.462 + * Access without ownership change. Same as getAlias(). 1.463 + * A class instance can be used directly in expressions that take a T *. 1.464 + * @return the header pointer 1.465 + */ 1.466 + operator H *() const { return ptr; } 1.467 + /** 1.468 + * Array item access (writable). 1.469 + * No index bounds check. 1.470 + * @param i array index 1.471 + * @return reference to the array item 1.472 + */ 1.473 + T &operator[](ptrdiff_t i) { return getArrayStart()[i]; } 1.474 + /** 1.475 + * Deletes the memory block (if owned) and aliases another one, no transfer of ownership. 1.476 + * If the arguments are illegal, then the current memory is unchanged. 1.477 + * @param otherArray must not be NULL 1.478 + * @param otherCapacity must be >0 1.479 + */ 1.480 + void aliasInstead(H *otherMemory, int32_t otherCapacity) { 1.481 + if(otherMemory!=NULL && otherCapacity>0) { 1.482 + releaseMemory(); 1.483 + ptr=otherMemory; 1.484 + capacity=otherCapacity; 1.485 + needToRelease=FALSE; 1.486 + } 1.487 + } 1.488 + /** 1.489 + * Deletes the memory block (if owned) and allocates a new one, 1.490 + * copying the header and length T array items. 1.491 + * Returns the new header pointer. 1.492 + * If the allocation fails, then the current memory is unchanged and 1.493 + * this method returns NULL. 1.494 + * @param newCapacity can be less than or greater than the current capacity; 1.495 + * must be >0 1.496 + * @param length number of T items to be copied from the old array to the new one 1.497 + * @return the allocated pointer, or NULL if the allocation failed 1.498 + */ 1.499 + inline H *resize(int32_t newCapacity, int32_t length=0); 1.500 + /** 1.501 + * Gives up ownership of the memory if owned, or else clones it, 1.502 + * copying the header and length T array items; resets itself to the internal memory. 1.503 + * Returns NULL if the allocation failed. 1.504 + * @param length number of T items to copy when cloning, 1.505 + * and array capacity of the clone when cloning 1.506 + * @param resultCapacity will be set to the returned array's capacity (output-only) 1.507 + * @return the header pointer; 1.508 + * caller becomes responsible for deleting the array 1.509 + */ 1.510 + inline H *orphanOrClone(int32_t length, int32_t &resultCapacity); 1.511 +private: 1.512 + H *ptr; 1.513 + int32_t capacity; 1.514 + UBool needToRelease; 1.515 + // stackHeader must precede stackArray immediately. 1.516 + H stackHeader; 1.517 + T stackArray[stackCapacity]; 1.518 + void releaseMemory() { 1.519 + if(needToRelease) { 1.520 + uprv_free(ptr); 1.521 + } 1.522 + } 1.523 + /* No comparison operators with other MaybeStackHeaderAndArray's. */ 1.524 + bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;} 1.525 + bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;} 1.526 + /* No ownership transfer: No copy constructor, no assignment operator. */ 1.527 + MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {} 1.528 + void operator=(const MaybeStackHeaderAndArray & /*other*/) {} 1.529 + 1.530 + // No heap allocation. Use only on the stack. 1.531 + // (Declaring these functions private triggers a cascade of problems; 1.532 + // see the MaybeStackArray class for details.) 1.533 + // static void * U_EXPORT2 operator new(size_t size); 1.534 + // static void * U_EXPORT2 operator new[](size_t size); 1.535 +#if U_HAVE_PLACEMENT_NEW 1.536 + // static void * U_EXPORT2 operator new(size_t, void *ptr); 1.537 +#endif 1.538 +}; 1.539 + 1.540 +template<typename H, typename T, int32_t stackCapacity> 1.541 +inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity, 1.542 + int32_t length) { 1.543 + if(newCapacity>=0) { 1.544 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.545 + ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T)); 1.546 +#endif 1.547 + H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T)); 1.548 + if(p!=NULL) { 1.549 + if(length<0) { 1.550 + length=0; 1.551 + } else if(length>0) { 1.552 + if(length>capacity) { 1.553 + length=capacity; 1.554 + } 1.555 + if(length>newCapacity) { 1.556 + length=newCapacity; 1.557 + } 1.558 + } 1.559 + uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T)); 1.560 + releaseMemory(); 1.561 + ptr=p; 1.562 + capacity=newCapacity; 1.563 + needToRelease=TRUE; 1.564 + } 1.565 + return p; 1.566 + } else { 1.567 + return NULL; 1.568 + } 1.569 +} 1.570 + 1.571 +template<typename H, typename T, int32_t stackCapacity> 1.572 +inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length, 1.573 + int32_t &resultCapacity) { 1.574 + H *p; 1.575 + if(needToRelease) { 1.576 + p=ptr; 1.577 + } else { 1.578 + if(length<0) { 1.579 + length=0; 1.580 + } else if(length>capacity) { 1.581 + length=capacity; 1.582 + } 1.583 +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) 1.584 + ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T)); 1.585 +#endif 1.586 + p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T)); 1.587 + if(p==NULL) { 1.588 + return NULL; 1.589 + } 1.590 + uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T)); 1.591 + } 1.592 + resultCapacity=length; 1.593 + ptr=&stackHeader; 1.594 + capacity=stackCapacity; 1.595 + needToRelease=FALSE; 1.596 + return p; 1.597 +} 1.598 + 1.599 +U_NAMESPACE_END 1.600 + 1.601 +#endif /* __cplusplus */ 1.602 +#endif /* CMEMORY_H */