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     explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
165     /**
166      * Move constructor, leaves src with isNull().
167      * @param src source smart pointer
168      */
LocalMemory(LocalMemory<T> && src)169     LocalMemory(LocalMemory<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
170         src.ptr=NULL;
171     }
172     /**
173      * Destructor deletes the memory it owns.
174      */
~LocalMemory()175     ~LocalMemory() {
176         uprv_free(LocalPointerBase<T>::ptr);
177     }
178     /**
179      * Move assignment operator, leaves src with isNull().
180      * The behavior is undefined if *this and src are the same object.
181      * @param src source smart pointer
182      * @return *this
183      */
184     LocalMemory<T> &operator=(LocalMemory<T> &&src) U_NOEXCEPT {
185         return moveFrom(src);
186     }
187     /**
188      * Move assignment, leaves src with isNull().
189      * The behavior is undefined if *this and src are the same object.
190      *
191      * Can be called explicitly, does not need C++11 support.
192      * @param src source smart pointer
193      * @return *this
194      */
moveFrom(LocalMemory<T> & src)195     LocalMemory<T> &moveFrom(LocalMemory<T> &src) U_NOEXCEPT {
196         delete[] LocalPointerBase<T>::ptr;
197         LocalPointerBase<T>::ptr=src.ptr;
198         src.ptr=NULL;
199         return *this;
200     }
201     /**
202      * Swap pointers.
203      * @param other other smart pointer
204      */
swap(LocalMemory<T> & other)205     void swap(LocalMemory<T> &other) U_NOEXCEPT {
206         T *temp=LocalPointerBase<T>::ptr;
207         LocalPointerBase<T>::ptr=other.ptr;
208         other.ptr=temp;
209     }
210     /**
211      * Non-member LocalMemory swap function.
212      * @param p1 will get p2's pointer
213      * @param p2 will get p1's pointer
214      */
swap(LocalMemory<T> & p1,LocalMemory<T> & p2)215     friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) U_NOEXCEPT {
216         p1.swap(p2);
217     }
218     /**
219      * Deletes the array it owns,
220      * and adopts (takes ownership of) the one passed in.
221      * @param p simple pointer to an array of T items that is adopted
222      */
adoptInstead(T * p)223     void adoptInstead(T *p) {
224         uprv_free(LocalPointerBase<T>::ptr);
225         LocalPointerBase<T>::ptr=p;
226     }
227     /**
228      * Deletes the array it owns, allocates a new one and reset its bytes to 0.
229      * Returns the new array pointer.
230      * If the allocation fails, then the current array is unchanged and
231      * this method returns NULL.
232      * @param newCapacity must be >0
233      * @return the allocated array pointer, or NULL if the allocation failed
234      */
235     inline T *allocateInsteadAndReset(int32_t newCapacity=1);
236     /**
237      * Deletes the array it owns and allocates a new one, copying length T items.
238      * Returns the new array pointer.
239      * If the allocation fails, then the current array is unchanged and
240      * this method returns NULL.
241      * @param newCapacity must be >0
242      * @param length number of T items to be copied from the old array to the new one;
243      *               must be no more than the capacity of the old array,
244      *               which the caller must track because the LocalMemory does not track it
245      * @return the allocated array pointer, or NULL if the allocation failed
246      */
247     inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
248     /**
249      * Array item access (writable).
250      * No index bounds check.
251      * @param i array index
252      * @return reference to the array item
253      */
254     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
255 };
256 
257 template<typename T>
allocateInsteadAndReset(int32_t newCapacity)258 inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
259     if(newCapacity>0) {
260         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
261         if(p!=NULL) {
262             uprv_memset(p, 0, newCapacity*sizeof(T));
263             uprv_free(LocalPointerBase<T>::ptr);
264             LocalPointerBase<T>::ptr=p;
265         }
266         return p;
267     } else {
268         return NULL;
269     }
270 }
271 
272 
273 template<typename T>
allocateInsteadAndCopy(int32_t newCapacity,int32_t length)274 inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
275     if(newCapacity>0) {
276         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
277         if(p!=NULL) {
278             if(length>0) {
279                 if(length>newCapacity) {
280                     length=newCapacity;
281                 }
282                 uprv_memcpy(p, LocalPointerBase<T>::ptr, (size_t)length*sizeof(T));
283             }
284             uprv_free(LocalPointerBase<T>::ptr);
285             LocalPointerBase<T>::ptr=p;
286         }
287         return p;
288     } else {
289         return NULL;
290     }
291 }
292 
293 /**
294  * Simple array/buffer management class using uprv_malloc() and uprv_free().
295  * Provides an internal array with fixed capacity. Can alias another array
296  * or allocate one.
297  *
298  * The array address is properly aligned for type T. It might not be properly
299  * aligned for types larger than T (or larger than the largest subtype of T).
300  *
301  * Unlike LocalMemory and LocalArray, this class never adopts
302  * (takes ownership of) another array.
303  */
304 template<typename T, int32_t stackCapacity>
305 class MaybeStackArray {
306 public:
307     /**
308      * Default constructor initializes with internal T[stackCapacity] buffer.
309      */
MaybeStackArray()310     MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
311     /**
312      * Automatically allocates the heap array if the argument is larger than the stack capacity.
313      * Intended for use when an approximate capacity is known at compile time but the true
314      * capacity is not known until runtime.
315      */
MaybeStackArray(int32_t newCapacity)316     MaybeStackArray(int32_t newCapacity) : MaybeStackArray() {
317         if (capacity < newCapacity) { resize(newCapacity); }
318     };
319     /**
320      * Destructor deletes the array (if owned).
321      */
~MaybeStackArray()322     ~MaybeStackArray() { releaseArray(); }
323     /**
324      * Returns the array capacity (number of T items).
325      * @return array capacity
326      */
getCapacity()327     int32_t getCapacity() const { return capacity; }
328     /**
329      * Access without ownership change.
330      * @return the array pointer
331      */
getAlias()332     T *getAlias() const { return ptr; }
333     /**
334      * Returns the array limit. Simple convenience method.
335      * @return getAlias()+getCapacity()
336      */
getArrayLimit()337     T *getArrayLimit() const { return getAlias()+capacity; }
338     // No "operator T *() const" because that can make
339     // expressions like mbs[index] ambiguous for some compilers.
340     /**
341      * Array item access (const).
342      * No index bounds check.
343      * @param i array index
344      * @return reference to the array item
345      */
346     const T &operator[](ptrdiff_t i) const { return ptr[i]; }
347     /**
348      * Array item access (writable).
349      * No index bounds check.
350      * @param i array index
351      * @return reference to the array item
352      */
353     T &operator[](ptrdiff_t i) { return ptr[i]; }
354     /**
355      * Deletes the array (if owned) and aliases another one, no transfer of ownership.
356      * If the arguments are illegal, then the current array is unchanged.
357      * @param otherArray must not be NULL
358      * @param otherCapacity must be >0
359      */
aliasInstead(T * otherArray,int32_t otherCapacity)360     void aliasInstead(T *otherArray, int32_t otherCapacity) {
361         if(otherArray!=NULL && otherCapacity>0) {
362             releaseArray();
363             ptr=otherArray;
364             capacity=otherCapacity;
365             needToRelease=FALSE;
366         }
367     }
368     /**
369      * Deletes the array (if owned) and allocates a new one, copying length T items.
370      * Returns the new array pointer.
371      * If the allocation fails, then the current array is unchanged and
372      * this method returns NULL.
373      * @param newCapacity can be less than or greater than the current capacity;
374      *                    must be >0
375      * @param length number of T items to be copied from the old array to the new one
376      * @return the allocated array pointer, or NULL if the allocation failed
377      */
378     inline T *resize(int32_t newCapacity, int32_t length=0);
379     /**
380      * Gives up ownership of the array if owned, or else clones it,
381      * copying length T items; resets itself to the internal stack array.
382      * Returns NULL if the allocation failed.
383      * @param length number of T items to copy when cloning,
384      *        and capacity of the clone when cloning
385      * @param resultCapacity will be set to the returned array's capacity (output-only)
386      * @return the array pointer;
387      *         caller becomes responsible for deleting the array
388      */
389     inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
390 private:
391     T *ptr;
392     int32_t capacity;
393     UBool needToRelease;
394     T stackArray[stackCapacity];
releaseArray()395     void releaseArray() {
396         if(needToRelease) {
397             uprv_free(ptr);
398         }
399     }
400     /* No comparison operators with other MaybeStackArray's. */
401     bool operator==(const MaybeStackArray & /*other*/) {return FALSE;}
402     bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;}
403     /* No ownership transfer: No copy constructor, no assignment operator. */
MaybeStackArray(const MaybeStackArray &)404     MaybeStackArray(const MaybeStackArray & /*other*/) {}
405     void operator=(const MaybeStackArray & /*other*/) {}
406 
407     // No heap allocation. Use only on the stack.
408     //   (Declaring these functions private triggers a cascade of problems:
409     //      MSVC insists on exporting an instantiation of MaybeStackArray, which
410     //      requires that all functions be defined.
411     //      An empty implementation of new() is rejected, it must return a value.
412     //      Returning NULL is rejected by gcc for operator new.
413     //      The expedient thing is just not to override operator new.
414     //      While relatively pointless, heap allocated instances will function.
415     // static void * U_EXPORT2 operator new(size_t size);
416     // static void * U_EXPORT2 operator new[](size_t size);
417 #if U_HAVE_PLACEMENT_NEW
418     // static void * U_EXPORT2 operator new(size_t, void *ptr);
419 #endif
420 };
421 
422 template<typename T, int32_t stackCapacity>
resize(int32_t newCapacity,int32_t length)423 inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
424     if(newCapacity>0) {
425 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
426       ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T));
427 #endif
428         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
429         if(p!=NULL) {
430             if(length>0) {
431                 if(length>capacity) {
432                     length=capacity;
433                 }
434                 if(length>newCapacity) {
435                     length=newCapacity;
436                 }
437                 uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
438             }
439             releaseArray();
440             ptr=p;
441             capacity=newCapacity;
442             needToRelease=TRUE;
443         }
444         return p;
445     } else {
446         return NULL;
447     }
448 }
449 
450 template<typename T, int32_t stackCapacity>
orphanOrClone(int32_t length,int32_t & resultCapacity)451 inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
452     T *p;
453     if(needToRelease) {
454         p=ptr;
455     } else if(length<=0) {
456         return NULL;
457     } else {
458         if(length>capacity) {
459             length=capacity;
460         }
461         p=(T *)uprv_malloc(length*sizeof(T));
462 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
463       ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
464 #endif
465         if(p==NULL) {
466             return NULL;
467         }
468         uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
469     }
470     resultCapacity=length;
471     ptr=stackArray;
472     capacity=stackCapacity;
473     needToRelease=FALSE;
474     return p;
475 }
476 
477 /**
478  * Variant of MaybeStackArray that allocates a header struct and an array
479  * in one contiguous memory block, using uprv_malloc() and uprv_free().
480  * Provides internal memory with fixed array capacity. Can alias another memory
481  * block or allocate one.
482  * The stackCapacity is the number of T items in the internal memory,
483  * not counting the H header.
484  * Unlike LocalMemory and LocalArray, this class never adopts
485  * (takes ownership of) another memory block.
486  */
487 template<typename H, typename T, int32_t stackCapacity>
488 class MaybeStackHeaderAndArray {
489 public:
490     /**
491      * Default constructor initializes with internal H+T[stackCapacity] buffer.
492      */
MaybeStackHeaderAndArray()493     MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
494     /**
495      * Destructor deletes the memory (if owned).
496      */
~MaybeStackHeaderAndArray()497     ~MaybeStackHeaderAndArray() { releaseMemory(); }
498     /**
499      * Returns the array capacity (number of T items).
500      * @return array capacity
501      */
getCapacity()502     int32_t getCapacity() const { return capacity; }
503     /**
504      * Access without ownership change.
505      * @return the header pointer
506      */
getAlias()507     H *getAlias() const { return ptr; }
508     /**
509      * Returns the array start.
510      * @return array start, same address as getAlias()+1
511      */
getArrayStart()512     T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
513     /**
514      * Returns the array limit.
515      * @return array limit
516      */
getArrayLimit()517     T *getArrayLimit() const { return getArrayStart()+capacity; }
518     /**
519      * Access without ownership change. Same as getAlias().
520      * A class instance can be used directly in expressions that take a T *.
521      * @return the header pointer
522      */
523     operator H *() const { return ptr; }
524     /**
525      * Array item access (writable).
526      * No index bounds check.
527      * @param i array index
528      * @return reference to the array item
529      */
530     T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
531     /**
532      * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
533      * If the arguments are illegal, then the current memory is unchanged.
534      * @param otherArray must not be NULL
535      * @param otherCapacity must be >0
536      */
aliasInstead(H * otherMemory,int32_t otherCapacity)537     void aliasInstead(H *otherMemory, int32_t otherCapacity) {
538         if(otherMemory!=NULL && otherCapacity>0) {
539             releaseMemory();
540             ptr=otherMemory;
541             capacity=otherCapacity;
542             needToRelease=FALSE;
543         }
544     }
545     /**
546      * Deletes the memory block (if owned) and allocates a new one,
547      * copying the header and length T array items.
548      * Returns the new header pointer.
549      * If the allocation fails, then the current memory is unchanged and
550      * this method returns NULL.
551      * @param newCapacity can be less than or greater than the current capacity;
552      *                    must be >0
553      * @param length number of T items to be copied from the old array to the new one
554      * @return the allocated pointer, or NULL if the allocation failed
555      */
556     inline H *resize(int32_t newCapacity, int32_t length=0);
557     /**
558      * Gives up ownership of the memory if owned, or else clones it,
559      * copying the header and length T array items; resets itself to the internal memory.
560      * Returns NULL if the allocation failed.
561      * @param length number of T items to copy when cloning,
562      *        and array capacity of the clone when cloning
563      * @param resultCapacity will be set to the returned array's capacity (output-only)
564      * @return the header pointer;
565      *         caller becomes responsible for deleting the array
566      */
567     inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
568 private:
569     H *ptr;
570     int32_t capacity;
571     UBool needToRelease;
572     // stackHeader must precede stackArray immediately.
573     H stackHeader;
574     T stackArray[stackCapacity];
releaseMemory()575     void releaseMemory() {
576         if(needToRelease) {
577             uprv_free(ptr);
578         }
579     }
580     /* No comparison operators with other MaybeStackHeaderAndArray's. */
581     bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;}
582     bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;}
583     /* No ownership transfer: No copy constructor, no assignment operator. */
MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray &)584     MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
585     void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
586 
587     // No heap allocation. Use only on the stack.
588     //   (Declaring these functions private triggers a cascade of problems;
589     //    see the MaybeStackArray class for details.)
590     // static void * U_EXPORT2 operator new(size_t size);
591     // static void * U_EXPORT2 operator new[](size_t size);
592 #if U_HAVE_PLACEMENT_NEW
593     // static void * U_EXPORT2 operator new(size_t, void *ptr);
594 #endif
595 };
596 
597 template<typename H, typename T, int32_t stackCapacity>
resize(int32_t newCapacity,int32_t length)598 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
599                                                                 int32_t length) {
600     if(newCapacity>=0) {
601 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
602       ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
603 #endif
604         H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
605         if(p!=NULL) {
606             if(length<0) {
607                 length=0;
608             } else if(length>0) {
609                 if(length>capacity) {
610                     length=capacity;
611                 }
612                 if(length>newCapacity) {
613                     length=newCapacity;
614                 }
615             }
616             uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
617             releaseMemory();
618             ptr=p;
619             capacity=newCapacity;
620             needToRelease=TRUE;
621         }
622         return p;
623     } else {
624         return NULL;
625     }
626 }
627 
628 template<typename H, typename T, int32_t stackCapacity>
orphanOrClone(int32_t length,int32_t & resultCapacity)629 inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
630                                                                        int32_t &resultCapacity) {
631     H *p;
632     if(needToRelease) {
633         p=ptr;
634     } else {
635         if(length<0) {
636             length=0;
637         } else if(length>capacity) {
638             length=capacity;
639         }
640 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
641       ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
642 #endif
643         p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
644         if(p==NULL) {
645             return NULL;
646         }
647         uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
648     }
649     resultCapacity=length;
650     ptr=&stackHeader;
651     capacity=stackCapacity;
652     needToRelease=FALSE;
653     return p;
654 }
655 
656 U_NAMESPACE_END
657 
658 #endif  /* __cplusplus */
659 #endif  /* CMEMORY_H */
660