]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/cmemory.h
2 ******************************************************************************
4 * Copyright (C) 1997-2011, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 ******************************************************************************
11 * Contains stdlib.h/string.h memory functions
13 * @author Bertrand A. Damiba
15 * Modification History:
17 * Date Name Description
18 * 6/20/98 Bertrand Created.
19 * 05/03/99 stephen Changed from functions to macros.
21 ******************************************************************************
29 #include "unicode/utypes.h"
30 #include "unicode/localpointer.h"
32 #define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
33 #define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
34 #define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
35 #define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
37 U_CAPI
void * U_EXPORT2
38 uprv_malloc(size_t s
);
40 U_CAPI
void * U_EXPORT2
41 uprv_realloc(void *mem
, size_t size
);
46 U_CAPI
void * U_EXPORT2
47 uprv_calloc(size_t num
, size_t size
);
50 * This should align the memory properly on any machine.
51 * This is very useful for the safeClone functions.
60 * Get the least significant bits of a pointer (a memory address).
61 * For example, with a mask of 3, the macro gets the 2 least significant bits,
62 * which will be 0 if the pointer is 32-bit (4-byte) aligned.
64 * ptrdiff_t is the most appropriate integer type to cast to.
65 * size_t should work too, since on most (or all?) platforms it has the same
68 #define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
71 * Get the amount of bytes that a pointer is off by from
72 * the previous UAlignedMemory-aligned pointer.
74 #define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
77 * Get the amount of bytes to add to a pointer
78 * in order to get the next UAlignedMemory-aligned address.
80 #define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
83 * Indicate whether the ICU allocation functions have been used.
84 * This is used to determine whether ICU is in an initial, unused state.
90 * Heap clean up function, called from u_cleanup()
91 * Clears any user heap functions from u_setMemoryFunctions()
92 * Does NOT deallocate any remaining allocated memory.
95 cmemory_cleanup(void);
98 * A function called by <TT>uhash_remove</TT>,
99 * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
100 * an existing key or value.
101 * @param obj A key or value stored in a hashtable
102 * @see uprv_deleteUObject
104 typedef void U_CALLCONV
UObjectDeleter(void* obj
);
107 * Deleter for UObject instances.
108 * Works for all subclasses of UObject because it has a virtual destructor.
110 U_CAPI
void U_EXPORT2
111 uprv_deleteUObject(void *obj
);
118 * "Smart pointer" class, deletes memory via uprv_free().
119 * For most methods see the LocalPointerBase base class.
120 * Adds operator[] for array item access.
122 * @see LocalPointerBase
125 class LocalMemory
: public LocalPointerBase
<T
> {
128 * Constructor takes ownership.
129 * @param p simple pointer to an array of T items that is adopted
131 explicit LocalMemory(T
*p
=NULL
) : LocalPointerBase
<T
>(p
) {}
133 * Destructor deletes the memory it owns.
136 uprv_free(LocalPointerBase
<T
>::ptr
);
139 * Deletes the array it owns,
140 * and adopts (takes ownership of) the one passed in.
141 * @param p simple pointer to an array of T items that is adopted
143 void adoptInstead(T
*p
) {
144 uprv_free(LocalPointerBase
<T
>::ptr
);
145 LocalPointerBase
<T
>::ptr
=p
;
148 * Deletes the array it owns, allocates a new one and reset its bytes to 0.
149 * Returns the new array pointer.
150 * If the allocation fails, then the current array is unchanged and
151 * this method returns NULL.
152 * @param newCapacity must be >0
153 * @return the allocated array pointer, or NULL if the allocation failed
155 inline T
*allocateInsteadAndReset(int32_t newCapacity
=1);
157 * Deletes the array it owns and allocates a new one, copying length T items.
158 * Returns the new array pointer.
159 * If the allocation fails, then the current array is unchanged and
160 * this method returns NULL.
161 * @param newCapacity must be >0
162 * @param length number of T items to be copied from the old array to the new one;
163 * must be no more than the capacity of the old array,
164 * which the caller must track because the LocalMemory does not track it
165 * @return the allocated array pointer, or NULL if the allocation failed
167 inline T
*allocateInsteadAndCopy(int32_t newCapacity
=1, int32_t length
=0);
169 * Array item access (writable).
170 * No index bounds check.
171 * @param i array index
172 * @return reference to the array item
174 T
&operator[](ptrdiff_t i
) const { return LocalPointerBase
<T
>::ptr
[i
]; }
178 inline T
*LocalMemory
<T
>::allocateInsteadAndReset(int32_t newCapacity
) {
180 T
*p
=(T
*)uprv_malloc(newCapacity
*sizeof(T
));
182 uprv_memset(p
, 0, newCapacity
*sizeof(T
));
183 uprv_free(LocalPointerBase
<T
>::ptr
);
184 LocalPointerBase
<T
>::ptr
=p
;
194 inline T
*LocalMemory
<T
>::allocateInsteadAndCopy(int32_t newCapacity
, int32_t length
) {
196 T
*p
=(T
*)uprv_malloc(newCapacity
*sizeof(T
));
199 if(length
>newCapacity
) {
202 uprv_memcpy(p
, LocalPointerBase
<T
>::ptr
, length
*sizeof(T
));
204 uprv_free(LocalPointerBase
<T
>::ptr
);
205 LocalPointerBase
<T
>::ptr
=p
;
214 * Simple array/buffer management class using uprv_malloc() and uprv_free().
215 * Provides an internal array with fixed capacity. Can alias another array
218 * The array address is properly aligned for type T. It might not be properly
219 * aligned for types larger than T (or larger than the largest subtype of T).
221 * Unlike LocalMemory and LocalArray, this class never adopts
222 * (takes ownership of) another array.
224 template<typename T
, int32_t stackCapacity
>
225 class MaybeStackArray
{
228 * Default constructor initializes with internal T[stackCapacity] buffer.
230 MaybeStackArray() : ptr(stackArray
), capacity(stackCapacity
), needToRelease(FALSE
) {}
232 * Destructor deletes the array (if owned).
234 ~MaybeStackArray() { releaseArray(); }
236 * Returns the array capacity (number of T items).
237 * @return array capacity
239 int32_t getCapacity() const { return capacity
; }
241 * Access without ownership change.
242 * @return the array pointer
244 T
*getAlias() const { return ptr
; }
246 * Returns the array limit. Simple convenience method.
247 * @return getAlias()+getCapacity()
249 T
*getArrayLimit() const { return getAlias()+capacity
; }
251 * Access without ownership change. Same as getAlias().
252 * A class instance can be used directly in expressions that take a T *.
253 * @return the array pointer
255 operator T
*() const { return ptr
; }
257 * Array item access (writable).
258 * No index bounds check.
259 * @param i array index
260 * @return reference to the array item
262 T
&operator[](ptrdiff_t i
) { return ptr
[i
]; }
264 * Deletes the array (if owned) and aliases another one, no transfer of ownership.
265 * If the arguments are illegal, then the current array is unchanged.
266 * @param otherArray must not be NULL
267 * @param otherCapacity must be >0
269 void aliasInstead(T
*otherArray
, int32_t otherCapacity
) {
270 if(otherArray
!=NULL
&& otherCapacity
>0) {
273 capacity
=otherCapacity
;
278 * Deletes the array (if owned) and allocates a new one, copying length T items.
279 * Returns the new array pointer.
280 * If the allocation fails, then the current array is unchanged and
281 * this method returns NULL.
282 * @param newCapacity can be less than or greater than the current capacity;
284 * @param length number of T items to be copied from the old array to the new one
285 * @return the allocated array pointer, or NULL if the allocation failed
287 inline T
*resize(int32_t newCapacity
, int32_t length
=0);
289 * Gives up ownership of the array if owned, or else clones it,
290 * copying length T items; resets itself to the internal stack array.
291 * Returns NULL if the allocation failed.
292 * @param length number of T items to copy when cloning,
293 * and capacity of the clone when cloning
294 * @param resultCapacity will be set to the returned array's capacity (output-only)
295 * @return the array pointer;
296 * caller becomes responsible for deleting the array
298 inline T
*orphanOrClone(int32_t length
, int32_t &resultCapacity
);
303 T stackArray
[stackCapacity
];
304 void releaseArray() {
309 /* No comparison operators with other MaybeStackArray's. */
310 bool operator==(const MaybeStackArray
& /*other*/) {return FALSE
;}
311 bool operator!=(const MaybeStackArray
& /*other*/) {return TRUE
;}
312 /* No ownership transfer: No copy constructor, no assignment operator. */
313 MaybeStackArray(const MaybeStackArray
& /*other*/) {}
314 void operator=(const MaybeStackArray
& /*other*/) {}
316 // No heap allocation. Use only on the stack.
317 // (Declaring these functions private triggers a cascade of problems:
318 // MSVC insists on exporting an instantiation of MaybeStackArray, which
319 // requires that all functions be defined.
320 // An empty implementation of new() is rejected, it must return a value.
321 // Returning NULL is rejected by gcc for operator new.
322 // The expedient thing is just not to override operator new.
323 // While relatively pointless, heap allocated instances will function.
324 // static void * U_EXPORT2 operator new(size_t size);
325 // static void * U_EXPORT2 operator new[](size_t size);
326 #if U_HAVE_PLACEMENT_NEW
327 // static void * U_EXPORT2 operator new(size_t, void *ptr);
331 template<typename T
, int32_t stackCapacity
>
332 inline T
*MaybeStackArray
<T
, stackCapacity
>::resize(int32_t newCapacity
, int32_t length
) {
334 T
*p
=(T
*)uprv_malloc(newCapacity
*sizeof(T
));
337 if(length
>capacity
) {
340 if(length
>newCapacity
) {
343 uprv_memcpy(p
, ptr
, length
*sizeof(T
));
347 capacity
=newCapacity
;
356 template<typename T
, int32_t stackCapacity
>
357 inline T
*MaybeStackArray
<T
, stackCapacity
>::orphanOrClone(int32_t length
, int32_t &resultCapacity
) {
361 } else if(length
<=0) {
364 if(length
>capacity
) {
367 p
=(T
*)uprv_malloc(length
*sizeof(T
));
371 uprv_memcpy(p
, ptr
, length
*sizeof(T
));
373 resultCapacity
=length
;
375 capacity
=stackCapacity
;
381 * Variant of MaybeStackArray that allocates a header struct and an array
382 * in one contiguous memory block, using uprv_malloc() and uprv_free().
383 * Provides internal memory with fixed array capacity. Can alias another memory
384 * block or allocate one.
385 * The stackCapacity is the number of T items in the internal memory,
386 * not counting the H header.
387 * Unlike LocalMemory and LocalArray, this class never adopts
388 * (takes ownership of) another memory block.
390 template<typename H
, typename T
, int32_t stackCapacity
>
391 class MaybeStackHeaderAndArray
{
394 * Default constructor initializes with internal H+T[stackCapacity] buffer.
396 MaybeStackHeaderAndArray() : ptr(&stackHeader
), capacity(stackCapacity
), needToRelease(FALSE
) {}
398 * Destructor deletes the memory (if owned).
400 ~MaybeStackHeaderAndArray() { releaseMemory(); }
402 * Returns the array capacity (number of T items).
403 * @return array capacity
405 int32_t getCapacity() const { return capacity
; }
407 * Access without ownership change.
408 * @return the header pointer
410 H
*getAlias() const { return ptr
; }
412 * Returns the array start.
413 * @return array start, same address as getAlias()+1
415 T
*getArrayStart() const { return reinterpret_cast<T
*>(getAlias()+1); }
417 * Returns the array limit.
418 * @return array limit
420 T
*getArrayLimit() const { return getArrayStart()+capacity
; }
422 * Access without ownership change. Same as getAlias().
423 * A class instance can be used directly in expressions that take a T *.
424 * @return the header pointer
426 operator H
*() const { return ptr
; }
428 * Array item access (writable).
429 * No index bounds check.
430 * @param i array index
431 * @return reference to the array item
433 T
&operator[](ptrdiff_t i
) { return getArrayStart()[i
]; }
435 * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
436 * If the arguments are illegal, then the current memory is unchanged.
437 * @param otherArray must not be NULL
438 * @param otherCapacity must be >0
440 void aliasInstead(H
*otherMemory
, int32_t otherCapacity
) {
441 if(otherMemory
!=NULL
&& otherCapacity
>0) {
444 capacity
=otherCapacity
;
449 * Deletes the memory block (if owned) and allocates a new one,
450 * copying the header and length T array items.
451 * Returns the new header pointer.
452 * If the allocation fails, then the current memory is unchanged and
453 * this method returns NULL.
454 * @param newCapacity can be less than or greater than the current capacity;
456 * @param length number of T items to be copied from the old array to the new one
457 * @return the allocated pointer, or NULL if the allocation failed
459 inline H
*resize(int32_t newCapacity
, int32_t length
=0);
461 * Gives up ownership of the memory if owned, or else clones it,
462 * copying the header and length T array items; resets itself to the internal memory.
463 * Returns NULL if the allocation failed.
464 * @param length number of T items to copy when cloning,
465 * and array capacity of the clone when cloning
466 * @param resultCapacity will be set to the returned array's capacity (output-only)
467 * @return the header pointer;
468 * caller becomes responsible for deleting the array
470 inline H
*orphanOrClone(int32_t length
, int32_t &resultCapacity
);
475 // stackHeader must precede stackArray immediately.
477 T stackArray
[stackCapacity
];
478 void releaseMemory() {
483 /* No comparison operators with other MaybeStackHeaderAndArray's. */
484 bool operator==(const MaybeStackHeaderAndArray
& /*other*/) {return FALSE
;}
485 bool operator!=(const MaybeStackHeaderAndArray
& /*other*/) {return TRUE
;}
486 /* No ownership transfer: No copy constructor, no assignment operator. */
487 MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray
& /*other*/) {}
488 void operator=(const MaybeStackHeaderAndArray
& /*other*/) {}
490 // No heap allocation. Use only on the stack.
491 // (Declaring these functions private triggers a cascade of problems;
492 // see the MaybeStackArray class for details.)
493 // static void * U_EXPORT2 operator new(size_t size);
494 // static void * U_EXPORT2 operator new[](size_t size);
495 #if U_HAVE_PLACEMENT_NEW
496 // static void * U_EXPORT2 operator new(size_t, void *ptr);
500 template<typename H
, typename T
, int32_t stackCapacity
>
501 inline H
*MaybeStackHeaderAndArray
<H
, T
, stackCapacity
>::resize(int32_t newCapacity
,
504 H
*p
=(H
*)uprv_malloc(sizeof(H
)+newCapacity
*sizeof(T
));
508 } else if(length
>0) {
509 if(length
>capacity
) {
512 if(length
>newCapacity
) {
516 uprv_memcpy(p
, ptr
, sizeof(H
)+length
*sizeof(T
));
519 capacity
=newCapacity
;
528 template<typename H
, typename T
, int32_t stackCapacity
>
529 inline H
*MaybeStackHeaderAndArray
<H
, T
, stackCapacity
>::orphanOrClone(int32_t length
,
530 int32_t &resultCapacity
) {
537 } else if(length
>capacity
) {
540 p
=(H
*)uprv_malloc(sizeof(H
)+length
*sizeof(T
));
544 uprv_memcpy(p
, ptr
, sizeof(H
)+length
*sizeof(T
));
546 resultCapacity
=length
;
548 capacity
=stackCapacity
;
555 #endif /* __cplusplus */
556 #endif /* CMEMORY_H */