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 */
|