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