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
46U_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
65U_CAPI void * U_EXPORT2
66uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
67
68U_CAPI void * U_EXPORT2
69uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
70
71U_CAPI void U_EXPORT2
72uprv_free(void *mem);
73
74U_CAPI void * U_EXPORT2
75uprv_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 */
81typedef 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  */
114U_CFUNC UBool
115cmemory_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  */
122U_CFUNC UBool
123cmemory_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 */
132typedef 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 */
138U_CAPI void U_EXPORT2
139uprv_deleteUObject(void *obj);
140
141#ifdef __cplusplus
142
143U_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 */
152template<typename T>
153class LocalMemory : public LocalPointerBase<T> {
154public:
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     */
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     */
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
205template<typename T>
206inline 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
221template<typename T>
222inline 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 */
252template<typename T, int32_t stackCapacity>
253class MaybeStackArray {
254public:
255    /**
256     * Default constructor initializes with internal T[stackCapacity] buffer.
257     */
258    MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
259    /**
260     * Destructor deletes the array (if owned).
261     */
262    ~MaybeStackArray() { releaseArray(); }
263    /**
264     * Returns the array capacity (number of T items).
265     * @return array capacity
266     */
267    int32_t getCapacity() const { return capacity; }
268    /**
269     * Access without ownership change.
270     * @return the array pointer
271     */
272    T *getAlias() const { return ptr; }
273    /**
274     * Returns the array limit. Simple convenience method.
275     * @return getAlias()+getCapacity()
276     */
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     */
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);
330private:
331    T *ptr;
332    int32_t capacity;
333    UBool needToRelease;
334    T stackArray[stackCapacity];
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. */
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
362template<typename T, int32_t stackCapacity>
363inline 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
390template<typename T, int32_t stackCapacity>
391inline 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 */
427template<typename H, typename T, int32_t stackCapacity>
428class MaybeStackHeaderAndArray {
429public:
430    /**
431     * Default constructor initializes with internal H+T[stackCapacity] buffer.
432     */
433    MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
434    /**
435     * Destructor deletes the memory (if owned).
436     */
437    ~MaybeStackHeaderAndArray() { releaseMemory(); }
438    /**
439     * Returns the array capacity (number of T items).
440     * @return array capacity
441     */
442    int32_t getCapacity() const { return capacity; }
443    /**
444     * Access without ownership change.
445     * @return the header pointer
446     */
447    H *getAlias() const { return ptr; }
448    /**
449     * Returns the array start.
450     * @return array start, same address as getAlias()+1
451     */
452    T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
453    /**
454     * Returns the array limit.
455     * @return array limit
456     */
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     */
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);
508private:
509    H *ptr;
510    int32_t capacity;
511    UBool needToRelease;
512    // stackHeader must precede stackArray immediately.
513    H stackHeader;
514    T stackArray[stackCapacity];
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. */
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
537template<typename H, typename T, int32_t stackCapacity>
538inline 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
568template<typename H, typename T, int32_t stackCapacity>
569inline 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
596U_NAMESPACE_END
597
598#endif  /* __cplusplus */
599#endif  /* CMEMORY_H */
600