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