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      */
~LocalMemory()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      */
adoptInstead(T * p)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>
allocateInsteadAndReset(int32_t newCapacity)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>
allocateInsteadAndCopy(int32_t newCapacity,int32_t length)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      */
MaybeStackArray()259     MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
260     /**
261      * Destructor deletes the array (if owned).
262      */
~MaybeStackArray()263     ~MaybeStackArray() { releaseArray(); }
264     /**
265      * Returns the array capacity (number of T items).
266      * @return array capacity
267      */
getCapacity()268     int32_t getCapacity() const { return capacity; }
269     /**
270      * Access without ownership change.
271      * @return the array pointer
272      */
getAlias()273     T *getAlias() const { return ptr; }
274     /**
275      * Returns the array limit. Simple convenience method.
276      * @return getAlias()+getCapacity()
277      */
getArrayLimit()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      */
aliasInstead(T * otherArray,int32_t otherCapacity)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];
releaseArray()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. */
MaybeStackArray(const MaybeStackArray &)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>
resize(int32_t newCapacity,int32_t length)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>
orphanOrClone(int32_t length,int32_t & resultCapacity)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      */
MaybeStackHeaderAndArray()434     MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
435     /**
436      * Destructor deletes the memory (if owned).
437      */
~MaybeStackHeaderAndArray()438     ~MaybeStackHeaderAndArray() { releaseMemory(); }
439     /**
440      * Returns the array capacity (number of T items).
441      * @return array capacity
442      */
getCapacity()443     int32_t getCapacity() const { return capacity; }
444     /**
445      * Access without ownership change.
446      * @return the header pointer
447      */
getAlias()448     H *getAlias() const { return ptr; }
449     /**
450      * Returns the array start.
451      * @return array start, same address as getAlias()+1
452      */
getArrayStart()453     T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
454     /**
455      * Returns the array limit.
456      * @return array limit
457      */
getArrayLimit()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      */
aliasInstead(H * otherMemory,int32_t otherCapacity)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];
releaseMemory()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. */
MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray &)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>
resize(int32_t newCapacity,int32_t length)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>
orphanOrClone(int32_t length,int32_t & resultCapacity)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