]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/cmemory.h
ICU-491.11.2.tar.gz
[apple/icu.git] / icuSources / common / cmemory.h
1 /*
2 ******************************************************************************
3 *
4 * Copyright (C) 1997-2011, 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 <stddef.h>
28 #include <string.h>
29 #include "unicode/utypes.h"
30 #include "unicode/localpointer.h"
31
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)
36
37 U_CAPI void * U_EXPORT2
38 uprv_malloc(size_t s);
39
40 U_CAPI void * U_EXPORT2
41 uprv_realloc(void *mem, size_t size);
42
43 U_CAPI void U_EXPORT2
44 uprv_free(void *mem);
45
46 U_CAPI void * U_EXPORT2
47 uprv_calloc(size_t num, size_t size);
48
49 /**
50 * This should align the memory properly on any machine.
51 * This is very useful for the safeClone functions.
52 */
53 typedef union {
54 long t1;
55 double t2;
56 void *t3;
57 } UAlignedMemory;
58
59 /**
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.
63 *
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
66 * width as ptrdiff_t.
67 */
68 #define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
69
70 /**
71 * Get the amount of bytes that a pointer is off by from
72 * the previous UAlignedMemory-aligned pointer.
73 */
74 #define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
75
76 /**
77 * Get the amount of bytes to add to a pointer
78 * in order to get the next UAlignedMemory-aligned address.
79 */
80 #define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
81
82 /**
83 * Indicate whether the ICU allocation functions have been used.
84 * This is used to determine whether ICU is in an initial, unused state.
85 */
86 U_CFUNC UBool
87 cmemory_inUse(void);
88
89 /**
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.
93 */
94 U_CFUNC UBool
95 cmemory_cleanup(void);
96
97 /**
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
103 */
104 typedef void U_CALLCONV UObjectDeleter(void* obj);
105
106 /**
107 * Deleter for UObject instances.
108 * Works for all subclasses of UObject because it has a virtual destructor.
109 */
110 U_CAPI void U_EXPORT2
111 uprv_deleteUObject(void *obj);
112
113 #ifdef __cplusplus
114
115 U_NAMESPACE_BEGIN
116
117 /**
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.
121 *
122 * @see LocalPointerBase
123 */
124 template<typename T>
125 class LocalMemory : public LocalPointerBase<T> {
126 public:
127 /**
128 * Constructor takes ownership.
129 * @param p simple pointer to an array of T items that is adopted
130 */
131 explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
132 /**
133 * Destructor deletes the memory it owns.
134 */
135 ~LocalMemory() {
136 uprv_free(LocalPointerBase<T>::ptr);
137 }
138 /**
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
142 */
143 void adoptInstead(T *p) {
144 uprv_free(LocalPointerBase<T>::ptr);
145 LocalPointerBase<T>::ptr=p;
146 }
147 /**
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
154 */
155 inline T *allocateInsteadAndReset(int32_t newCapacity=1);
156 /**
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
166 */
167 inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
168 /**
169 * Array item access (writable).
170 * No index bounds check.
171 * @param i array index
172 * @return reference to the array item
173 */
174 T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
175 };
176
177 template<typename T>
178 inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
179 if(newCapacity>0) {
180 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
181 if(p!=NULL) {
182 uprv_memset(p, 0, newCapacity*sizeof(T));
183 uprv_free(LocalPointerBase<T>::ptr);
184 LocalPointerBase<T>::ptr=p;
185 }
186 return p;
187 } else {
188 return NULL;
189 }
190 }
191
192
193 template<typename T>
194 inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
195 if(newCapacity>0) {
196 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
197 if(p!=NULL) {
198 if(length>0) {
199 if(length>newCapacity) {
200 length=newCapacity;
201 }
202 uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T));
203 }
204 uprv_free(LocalPointerBase<T>::ptr);
205 LocalPointerBase<T>::ptr=p;
206 }
207 return p;
208 } else {
209 return NULL;
210 }
211 }
212
213 /**
214 * Simple array/buffer management class using uprv_malloc() and uprv_free().
215 * Provides an internal array with fixed capacity. Can alias another array
216 * or allocate one.
217 *
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).
220 *
221 * Unlike LocalMemory and LocalArray, this class never adopts
222 * (takes ownership of) another array.
223 */
224 template<typename T, int32_t stackCapacity>
225 class MaybeStackArray {
226 public:
227 /**
228 * Default constructor initializes with internal T[stackCapacity] buffer.
229 */
230 MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
231 /**
232 * Destructor deletes the array (if owned).
233 */
234 ~MaybeStackArray() { releaseArray(); }
235 /**
236 * Returns the array capacity (number of T items).
237 * @return array capacity
238 */
239 int32_t getCapacity() const { return capacity; }
240 /**
241 * Access without ownership change.
242 * @return the array pointer
243 */
244 T *getAlias() const { return ptr; }
245 /**
246 * Returns the array limit. Simple convenience method.
247 * @return getAlias()+getCapacity()
248 */
249 T *getArrayLimit() const { return getAlias()+capacity; }
250 /**
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
254 */
255 operator T *() const { return ptr; }
256 /**
257 * Array item access (writable).
258 * No index bounds check.
259 * @param i array index
260 * @return reference to the array item
261 */
262 T &operator[](ptrdiff_t i) { return ptr[i]; }
263 /**
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
268 */
269 void aliasInstead(T *otherArray, int32_t otherCapacity) {
270 if(otherArray!=NULL && otherCapacity>0) {
271 releaseArray();
272 ptr=otherArray;
273 capacity=otherCapacity;
274 needToRelease=FALSE;
275 }
276 }
277 /**
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;
283 * must be >0
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
286 */
287 inline T *resize(int32_t newCapacity, int32_t length=0);
288 /**
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
297 */
298 inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
299 private:
300 T *ptr;
301 int32_t capacity;
302 UBool needToRelease;
303 T stackArray[stackCapacity];
304 void releaseArray() {
305 if(needToRelease) {
306 uprv_free(ptr);
307 }
308 }
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*/) {}
315
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);
328 #endif
329 };
330
331 template<typename T, int32_t stackCapacity>
332 inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
333 if(newCapacity>0) {
334 T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
335 if(p!=NULL) {
336 if(length>0) {
337 if(length>capacity) {
338 length=capacity;
339 }
340 if(length>newCapacity) {
341 length=newCapacity;
342 }
343 uprv_memcpy(p, ptr, length*sizeof(T));
344 }
345 releaseArray();
346 ptr=p;
347 capacity=newCapacity;
348 needToRelease=TRUE;
349 }
350 return p;
351 } else {
352 return NULL;
353 }
354 }
355
356 template<typename T, int32_t stackCapacity>
357 inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
358 T *p;
359 if(needToRelease) {
360 p=ptr;
361 } else if(length<=0) {
362 return NULL;
363 } else {
364 if(length>capacity) {
365 length=capacity;
366 }
367 p=(T *)uprv_malloc(length*sizeof(T));
368 if(p==NULL) {
369 return NULL;
370 }
371 uprv_memcpy(p, ptr, length*sizeof(T));
372 }
373 resultCapacity=length;
374 ptr=stackArray;
375 capacity=stackCapacity;
376 needToRelease=FALSE;
377 return p;
378 }
379
380 /**
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.
389 */
390 template<typename H, typename T, int32_t stackCapacity>
391 class MaybeStackHeaderAndArray {
392 public:
393 /**
394 * Default constructor initializes with internal H+T[stackCapacity] buffer.
395 */
396 MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
397 /**
398 * Destructor deletes the memory (if owned).
399 */
400 ~MaybeStackHeaderAndArray() { releaseMemory(); }
401 /**
402 * Returns the array capacity (number of T items).
403 * @return array capacity
404 */
405 int32_t getCapacity() const { return capacity; }
406 /**
407 * Access without ownership change.
408 * @return the header pointer
409 */
410 H *getAlias() const { return ptr; }
411 /**
412 * Returns the array start.
413 * @return array start, same address as getAlias()+1
414 */
415 T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
416 /**
417 * Returns the array limit.
418 * @return array limit
419 */
420 T *getArrayLimit() const { return getArrayStart()+capacity; }
421 /**
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
425 */
426 operator H *() const { return ptr; }
427 /**
428 * Array item access (writable).
429 * No index bounds check.
430 * @param i array index
431 * @return reference to the array item
432 */
433 T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
434 /**
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
439 */
440 void aliasInstead(H *otherMemory, int32_t otherCapacity) {
441 if(otherMemory!=NULL && otherCapacity>0) {
442 releaseMemory();
443 ptr=otherMemory;
444 capacity=otherCapacity;
445 needToRelease=FALSE;
446 }
447 }
448 /**
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;
455 * must be >0
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
458 */
459 inline H *resize(int32_t newCapacity, int32_t length=0);
460 /**
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
469 */
470 inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
471 private:
472 H *ptr;
473 int32_t capacity;
474 UBool needToRelease;
475 // stackHeader must precede stackArray immediately.
476 H stackHeader;
477 T stackArray[stackCapacity];
478 void releaseMemory() {
479 if(needToRelease) {
480 uprv_free(ptr);
481 }
482 }
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*/) {}
489
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);
497 #endif
498 };
499
500 template<typename H, typename T, int32_t stackCapacity>
501 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
502 int32_t length) {
503 if(newCapacity>=0) {
504 H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
505 if(p!=NULL) {
506 if(length<0) {
507 length=0;
508 } else if(length>0) {
509 if(length>capacity) {
510 length=capacity;
511 }
512 if(length>newCapacity) {
513 length=newCapacity;
514 }
515 }
516 uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
517 releaseMemory();
518 ptr=p;
519 capacity=newCapacity;
520 needToRelease=TRUE;
521 }
522 return p;
523 } else {
524 return NULL;
525 }
526 }
527
528 template<typename H, typename T, int32_t stackCapacity>
529 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
530 int32_t &resultCapacity) {
531 H *p;
532 if(needToRelease) {
533 p=ptr;
534 } else {
535 if(length<0) {
536 length=0;
537 } else if(length>capacity) {
538 length=capacity;
539 }
540 p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
541 if(p==NULL) {
542 return NULL;
543 }
544 uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
545 }
546 resultCapacity=length;
547 ptr=&stackHeader;
548 capacity=stackCapacity;
549 needToRelease=FALSE;
550 return p;
551 }
552
553 U_NAMESPACE_END
554
555 #endif /* __cplusplus */
556 #endif /* CMEMORY_H */