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