Home | History | Annotate | Download | only in common
      1 /*
      2 ******************************************************************************
      3 *
      4 *   Copyright (C) 1997-2010, 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 #include "unicode/localpointer.h"
     29 #include <stddef.h>
     30 #include <string.h>
     31 
     32 
     33 #define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
     34 #define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
     35 #define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
     36 #define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
     37 
     38 U_CAPI void * U_EXPORT2
     39 uprv_malloc(size_t s);
     40 
     41 U_CAPI void * U_EXPORT2
     42 uprv_realloc(void *mem, size_t size);
     43 
     44 U_CAPI void U_EXPORT2
     45 uprv_free(void *mem);
     46 
     47 /**
     48  * This should align the memory properly on any machine.
     49  * This is very useful for the safeClone functions.
     50  */
     51 typedef union {
     52     long    t1;
     53     double  t2;
     54     void   *t3;
     55 } UAlignedMemory;
     56 
     57 /**
     58  * Get the least significant bits of a pointer (a memory address).
     59  * For example, with a mask of 3, the macro gets the 2 least significant bits,
     60  * which will be 0 if the pointer is 32-bit (4-byte) aligned.
     61  *
     62  * ptrdiff_t is the most appropriate integer type to cast to.
     63  * size_t should work too, since on most (or all?) platforms it has the same
     64  * width as ptrdiff_t.
     65  */
     66 #define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
     67 
     68 /**
     69  * Get the amount of bytes that a pointer is off by from
     70  * the previous UAlignedMemory-aligned pointer.
     71  */
     72 #define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
     73 
     74 /**
     75  * Get the amount of bytes to add to a pointer
     76  * in order to get the next UAlignedMemory-aligned address.
     77  */
     78 #define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
     79 
     80 /**
     81   *  Indicate whether the ICU allocation functions have been used.
     82   *  This is used to determine whether ICU is in an initial, unused state.
     83   */
     84 U_CFUNC UBool
     85 cmemory_inUse(void);
     86 
     87 /**
     88   *  Heap clean up function, called from u_cleanup()
     89   *    Clears any user heap functions from u_setMemoryFunctions()
     90   *    Does NOT deallocate any remaining allocated memory.
     91   */
     92 U_CFUNC UBool
     93 cmemory_cleanup(void);
     94 
     95 #ifdef XP_CPLUSPLUS
     96 
     97 U_NAMESPACE_BEGIN
     98 
     99 /**
    100  * "Smart pointer" class, deletes memory via uprv_free().
    101  * For most methods see the LocalPointerBase base class.
    102  * Adds operator[] for array item access.
    103  *
    104  * @see LocalPointerBase
    105  */
    106 template<typename T>
    107 class LocalMemory : public LocalPointerBase<T> {
    108 public:
    109     /**
    110      * Constructor takes ownership.
    111      * @param p simple pointer to an array of T items that is adopted
    112      */
    113     explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
    114     /**
    115      * Destructor deletes the memory it owns.
    116      */
    117     ~LocalMemory() {
    118         uprv_free(LocalPointerBase<T>::ptr);
    119     }
    120     /**
    121      * Deletes the array it owns,
    122      * and adopts (takes ownership of) the one passed in.
    123      * @param p simple pointer to an array of T items that is adopted
    124      */
    125     void adoptInstead(T *p) {
    126         uprv_free(LocalPointerBase<T>::ptr);
    127         LocalPointerBase<T>::ptr=p;
    128     }
    129     /**
    130      * Deletes the array it owns, allocates a new one and reset its bytes to 0.
    131      * Returns the new array pointer.
    132      * If the allocation fails, then the current array is unchanged and
    133      * this method returns NULL.
    134      * @param newCapacity must be >0
    135      * @return the allocated array pointer, or NULL if the allocation failed
    136      */
    137     inline T *allocateInsteadAndReset(int32_t newCapacity=1);
    138     /**
    139      * Deletes the array it owns and allocates a new one, copying length T items.
    140      * Returns the new array pointer.
    141      * If the allocation fails, then the current array is unchanged and
    142      * this method returns NULL.
    143      * @param newCapacity must be >0
    144      * @param length number of T items to be copied from the old array to the new one;
    145      *               must be no more than the capacity of the old array,
    146      *               which the caller must track because the LocalMemory does not track it
    147      * @return the allocated array pointer, or NULL if the allocation failed
    148      */
    149     inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
    150     /**
    151      * Array item access (writable).
    152      * No index bounds check.
    153      * @param i array index
    154      * @return reference to the array item
    155      */
    156     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
    157 };
    158 
    159 /**
    160  * Simple array/buffer management class using uprv_malloc() and uprv_free().
    161  * Provides an internal array with fixed capacity. Can alias another array
    162  * or allocate one.
    163  * Unlike LocalMemory and LocalArray, this class never adopts
    164  * (takes ownership of) another array.
    165  */
    166 template<typename T, int32_t stackCapacity>
    167 class MaybeStackArray {
    168 public:
    169     /**
    170      * Default constructor initializes with internal T[stackCapacity] buffer.
    171      */
    172     MaybeStackArray() : needToRelease(FALSE), capacity(stackCapacity), ptr(stackArray) {}
    173     /**
    174      * Destructor deletes the array (if owned).
    175      */
    176     ~MaybeStackArray() { releaseArray(); }
    177     /**
    178      * Returns the array capacity (number of T items).
    179      * @return array capacity
    180      */
    181     int32_t getCapacity() const { return capacity; }
    182     /**
    183      * Access without ownership change.
    184      * @return the array pointer
    185      */
    186     T *getAlias() const { return ptr; }
    187     /**
    188      * Returns the array limit. Simple convenience method.
    189      * @return getAlias()+getCapacity()
    190      */
    191     T *getArrayLimit() const { return getAlias()+capacity; }
    192     /**
    193      * Access without ownership change. Same as getAlias().
    194      * A class instance can be used directly in expressions that take a T *.
    195      * @return the array pointer
    196      */
    197     operator T *() const { return ptr; }
    198     /**
    199      * Array item access (writable).
    200      * No index bounds check.
    201      * @param i array index
    202      * @return reference to the array item
    203      */
    204     T &operator[](ptrdiff_t i) { return ptr[i]; }
    205     /**
    206      * Deletes the array (if owned) and aliases another one, no transfer of ownership.
    207      * If the arguments are illegal, then the current array is unchanged.
    208      * @param otherArray must not be NULL
    209      * @param otherCapacity must be >0
    210      */
    211     void aliasInstead(T *otherArray, int32_t otherCapacity) {
    212         if(otherArray!=NULL && otherCapacity>0) {
    213             releaseArray();
    214             ptr=otherArray;
    215             capacity=otherCapacity;
    216             needToRelease=FALSE;
    217         }
    218     };
    219     /**
    220      * Deletes the array (if owned) and allocates a new one, copying length T items.
    221      * Returns the new array pointer.
    222      * If the allocation fails, then the current array is unchanged and
    223      * this method returns NULL.
    224      * @param newCapacity can be less than or greater than the current capacity;
    225      *                    must be >0
    226      * @param length number of T items to be copied from the old array to the new one
    227      * @return the allocated array pointer, or NULL if the allocation failed
    228      */
    229     inline T *resize(int32_t newCapacity, int32_t length=0);
    230     /**
    231      * Gives up ownership of the array if owned, or else clones it,
    232      * copying length T items; resets itself to the internal stack array.
    233      * Returns NULL if the allocation failed.
    234      * @param length number of T items to copy when cloning,
    235      *        and capacity of the clone when cloning
    236      * @param resultCapacity will be set to the returned array's capacity (output-only)
    237      * @return the array pointer;
    238      *         caller becomes responsible for deleting the array
    239      * @draft ICU 4.4
    240      */
    241     inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
    242 private:
    243     UBool needToRelease;
    244     int32_t capacity;
    245     T *ptr;
    246     T stackArray[stackCapacity];
    247     void releaseArray() {
    248         if(needToRelease) {
    249             uprv_free(ptr);
    250         }
    251     }
    252     /* No comparison operators with other MaybeStackArray's. */
    253     bool operator==(const MaybeStackArray & /*other*/) {return FALSE;};
    254     bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;};
    255     /* No ownership transfer: No copy constructor, no assignment operator. */
    256     MaybeStackArray(const MaybeStackArray & /*other*/) {};
    257     void operator=(const MaybeStackArray & /*other*/) {};
    258 
    259     // No heap allocation. Use only on the stack.
    260     //   (Declaring these functions private triggers a cascade of problems:
    261     //      MSVC insists on exporting an instantiation of MaybeStackArray, which
    262     //      requires that all functions be defined.
    263     //      An empty implementation of new() is rejected, it must return a value.
    264     //      Returning NULL is rejected by gcc for operator new.
    265     //      The expedient thing is just not to override operator new.
    266     //      While relatively pointless, heap allocated instances will function.
    267     // static void * U_EXPORT2 operator new(size_t size);
    268     // static void * U_EXPORT2 operator new[](size_t size);
    269 #if U_HAVE_PLACEMENT_NEW
    270     // static void * U_EXPORT2 operator new(size_t, void *ptr);
    271 #endif
    272 };
    273 
    274 template<typename T>
    275 inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
    276     if(newCapacity>0) {
    277         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
    278         if(p!=NULL) {
    279             uprv_memset(p, 0, newCapacity*sizeof(T));
    280             uprv_free(LocalPointerBase<T>::ptr);
    281             LocalPointerBase<T>::ptr=p;
    282         }
    283         return p;
    284     } else {
    285         return NULL;
    286     }
    287 }
    288 
    289 
    290 template<typename T>
    291 inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
    292     if(newCapacity>0) {
    293         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
    294         if(p!=NULL) {
    295             if(length>0) {
    296                 if(length>newCapacity) {
    297                     length=newCapacity;
    298                 }
    299                 uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T));
    300             }
    301             uprv_free(LocalPointerBase<T>::ptr);
    302             LocalPointerBase<T>::ptr=p;
    303         }
    304         return p;
    305     } else {
    306         return NULL;
    307     }
    308 }
    309 
    310 template<typename T, int32_t stackCapacity>
    311 inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
    312     if(newCapacity>0) {
    313         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
    314         if(p!=NULL) {
    315             if(length>0) {
    316                 if(length>capacity) {
    317                     length=capacity;
    318                 }
    319                 if(length>newCapacity) {
    320                     length=newCapacity;
    321                 }
    322                 uprv_memcpy(p, ptr, length*sizeof(T));
    323             }
    324             releaseArray();
    325             ptr=p;
    326             capacity=newCapacity;
    327             needToRelease=TRUE;
    328         }
    329         return p;
    330     } else {
    331         return NULL;
    332     }
    333 }
    334 
    335 template<typename T, int32_t stackCapacity>
    336 inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
    337     T *p;
    338     if(needToRelease) {
    339         p=ptr;
    340     } else if(length<=0) {
    341         return NULL;
    342     } else {
    343         if(length>capacity) {
    344             length=capacity;
    345         }
    346         p=(T *)uprv_malloc(length*sizeof(T));
    347         if(p==NULL) {
    348             return NULL;
    349         }
    350         uprv_memcpy(p, ptr, length*sizeof(T));
    351     }
    352     resultCapacity=length;
    353     ptr=stackArray;
    354     capacity=stackCapacity;
    355     needToRelease=FALSE;
    356     return p;
    357 }
    358 
    359 U_NAMESPACE_END
    360 
    361 #endif  /* XP_CPLUSPLUS */
    362 #endif  /* CMEMORY_H */
    363