LCOV - code coverage report
Current view: top level - intl/icu/source/common - cmemory.h (source / functions) Hit Total Coverage
Test: output.info Lines: 23 137 16.8 %
Date: 2017-07-14 16:53:18 Functions: 8 104 7.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13