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