xref: /aosp_15_r20/external/icu/libicu/cts_headers/cmemory.h (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker // © 2016 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker /*
4*0e209d39SAndroid Build Coastguard Worker ******************************************************************************
5*0e209d39SAndroid Build Coastguard Worker *
6*0e209d39SAndroid Build Coastguard Worker *   Copyright (C) 1997-2016, International Business Machines
7*0e209d39SAndroid Build Coastguard Worker *   Corporation and others.  All Rights Reserved.
8*0e209d39SAndroid Build Coastguard Worker *
9*0e209d39SAndroid Build Coastguard Worker ******************************************************************************
10*0e209d39SAndroid Build Coastguard Worker *
11*0e209d39SAndroid Build Coastguard Worker * File CMEMORY.H
12*0e209d39SAndroid Build Coastguard Worker *
13*0e209d39SAndroid Build Coastguard Worker *  Contains stdlib.h/string.h memory functions
14*0e209d39SAndroid Build Coastguard Worker *
15*0e209d39SAndroid Build Coastguard Worker * @author       Bertrand A. Damiba
16*0e209d39SAndroid Build Coastguard Worker *
17*0e209d39SAndroid Build Coastguard Worker * Modification History:
18*0e209d39SAndroid Build Coastguard Worker *
19*0e209d39SAndroid Build Coastguard Worker *   Date        Name        Description
20*0e209d39SAndroid Build Coastguard Worker *   6/20/98     Bertrand    Created.
21*0e209d39SAndroid Build Coastguard Worker *  05/03/99     stephen     Changed from functions to macros.
22*0e209d39SAndroid Build Coastguard Worker *
23*0e209d39SAndroid Build Coastguard Worker ******************************************************************************
24*0e209d39SAndroid Build Coastguard Worker */
25*0e209d39SAndroid Build Coastguard Worker 
26*0e209d39SAndroid Build Coastguard Worker #ifndef CMEMORY_H
27*0e209d39SAndroid Build Coastguard Worker #define CMEMORY_H
28*0e209d39SAndroid Build Coastguard Worker 
29*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h"
30*0e209d39SAndroid Build Coastguard Worker 
31*0e209d39SAndroid Build Coastguard Worker #include <stddef.h>
32*0e209d39SAndroid Build Coastguard Worker #include <string.h>
33*0e209d39SAndroid Build Coastguard Worker #include "unicode/localpointer.h"
34*0e209d39SAndroid Build Coastguard Worker #include "uassert.h"
35*0e209d39SAndroid Build Coastguard Worker 
36*0e209d39SAndroid Build Coastguard Worker #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
37*0e209d39SAndroid Build Coastguard Worker #include <stdio.h>
38*0e209d39SAndroid Build Coastguard Worker #endif
39*0e209d39SAndroid Build Coastguard Worker 
40*0e209d39SAndroid Build Coastguard Worker // uprv_memcpy and uprv_memmove
41*0e209d39SAndroid Build Coastguard Worker #if defined(__clang__)
42*0e209d39SAndroid Build Coastguard Worker #define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
43*0e209d39SAndroid Build Coastguard Worker     /* Suppress warnings about addresses that will never be NULL */ \
44*0e209d39SAndroid Build Coastguard Worker     _Pragma("clang diagnostic push") \
45*0e209d39SAndroid Build Coastguard Worker     _Pragma("clang diagnostic ignored \"-Waddress\"") \
46*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(dst != NULL); \
47*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(src != NULL); \
48*0e209d39SAndroid Build Coastguard Worker     _Pragma("clang diagnostic pop") \
49*0e209d39SAndroid Build Coastguard Worker     U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \
50*0e209d39SAndroid Build Coastguard Worker } UPRV_BLOCK_MACRO_END
51*0e209d39SAndroid Build Coastguard Worker #define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
52*0e209d39SAndroid Build Coastguard Worker     /* Suppress warnings about addresses that will never be NULL */ \
53*0e209d39SAndroid Build Coastguard Worker     _Pragma("clang diagnostic push") \
54*0e209d39SAndroid Build Coastguard Worker     _Pragma("clang diagnostic ignored \"-Waddress\"") \
55*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(dst != NULL); \
56*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(src != NULL); \
57*0e209d39SAndroid Build Coastguard Worker     _Pragma("clang diagnostic pop") \
58*0e209d39SAndroid Build Coastguard Worker     U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \
59*0e209d39SAndroid Build Coastguard Worker } UPRV_BLOCK_MACRO_END
60*0e209d39SAndroid Build Coastguard Worker #elif defined(__GNUC__)
61*0e209d39SAndroid Build Coastguard Worker #define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
62*0e209d39SAndroid Build Coastguard Worker     /* Suppress warnings about addresses that will never be NULL */ \
63*0e209d39SAndroid Build Coastguard Worker     _Pragma("GCC diagnostic push") \
64*0e209d39SAndroid Build Coastguard Worker     _Pragma("GCC diagnostic ignored \"-Waddress\"") \
65*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(dst != NULL); \
66*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(src != NULL); \
67*0e209d39SAndroid Build Coastguard Worker     _Pragma("GCC diagnostic pop") \
68*0e209d39SAndroid Build Coastguard Worker     U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \
69*0e209d39SAndroid Build Coastguard Worker } UPRV_BLOCK_MACRO_END
70*0e209d39SAndroid Build Coastguard Worker #define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
71*0e209d39SAndroid Build Coastguard Worker     /* Suppress warnings about addresses that will never be NULL */ \
72*0e209d39SAndroid Build Coastguard Worker     _Pragma("GCC diagnostic push") \
73*0e209d39SAndroid Build Coastguard Worker     _Pragma("GCC diagnostic ignored \"-Waddress\"") \
74*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(dst != NULL); \
75*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(src != NULL); \
76*0e209d39SAndroid Build Coastguard Worker     _Pragma("GCC diagnostic pop") \
77*0e209d39SAndroid Build Coastguard Worker     U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \
78*0e209d39SAndroid Build Coastguard Worker } UPRV_BLOCK_MACRO_END
79*0e209d39SAndroid Build Coastguard Worker #else
80*0e209d39SAndroid Build Coastguard Worker #define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
81*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(dst != NULL); \
82*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(src != NULL); \
83*0e209d39SAndroid Build Coastguard Worker     U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \
84*0e209d39SAndroid Build Coastguard Worker } UPRV_BLOCK_MACRO_END
85*0e209d39SAndroid Build Coastguard Worker #define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
86*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(dst != NULL); \
87*0e209d39SAndroid Build Coastguard Worker     U_ASSERT(src != NULL); \
88*0e209d39SAndroid Build Coastguard Worker     U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \
89*0e209d39SAndroid Build Coastguard Worker } UPRV_BLOCK_MACRO_END
90*0e209d39SAndroid Build Coastguard Worker #endif
91*0e209d39SAndroid Build Coastguard Worker 
92*0e209d39SAndroid Build Coastguard Worker /**
93*0e209d39SAndroid Build Coastguard Worker  * \def UPRV_LENGTHOF
94*0e209d39SAndroid Build Coastguard Worker  * Convenience macro to determine the length of a fixed array at compile-time.
95*0e209d39SAndroid Build Coastguard Worker  * @param array A fixed length array
96*0e209d39SAndroid Build Coastguard Worker  * @return The length of the array, in elements
97*0e209d39SAndroid Build Coastguard Worker  * @internal
98*0e209d39SAndroid Build Coastguard Worker  */
99*0e209d39SAndroid Build Coastguard Worker #define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
100*0e209d39SAndroid Build Coastguard Worker #define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
101*0e209d39SAndroid Build Coastguard Worker #define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
102*0e209d39SAndroid Build Coastguard Worker #define uprv_memchr(ptr, value, num) U_STANDARD_CPP_NAMESPACE memchr(ptr, value, num)
103*0e209d39SAndroid Build Coastguard Worker 
104*0e209d39SAndroid Build Coastguard Worker U_CAPI void * U_EXPORT2
105*0e209d39SAndroid Build Coastguard Worker uprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
106*0e209d39SAndroid Build Coastguard Worker 
107*0e209d39SAndroid Build Coastguard Worker U_CAPI void * U_EXPORT2
108*0e209d39SAndroid Build Coastguard Worker uprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
109*0e209d39SAndroid Build Coastguard Worker 
110*0e209d39SAndroid Build Coastguard Worker U_CAPI void U_EXPORT2
111*0e209d39SAndroid Build Coastguard Worker uprv_free(void *mem);
112*0e209d39SAndroid Build Coastguard Worker 
113*0e209d39SAndroid Build Coastguard Worker U_CAPI void * U_EXPORT2
114*0e209d39SAndroid Build Coastguard Worker uprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
115*0e209d39SAndroid Build Coastguard Worker 
116*0e209d39SAndroid Build Coastguard Worker /**
117*0e209d39SAndroid Build Coastguard Worker  * Get the least significant bits of a pointer (a memory address).
118*0e209d39SAndroid Build Coastguard Worker  * For example, with a mask of 3, the macro gets the 2 least significant bits,
119*0e209d39SAndroid Build Coastguard Worker  * which will be 0 if the pointer is 32-bit (4-byte) aligned.
120*0e209d39SAndroid Build Coastguard Worker  *
121*0e209d39SAndroid Build Coastguard Worker  * uintptr_t is the most appropriate integer type to cast to.
122*0e209d39SAndroid Build Coastguard Worker  */
123*0e209d39SAndroid Build Coastguard Worker #define U_POINTER_MASK_LSB(ptr, mask) ((uintptr_t)(ptr) & (mask))
124*0e209d39SAndroid Build Coastguard Worker 
125*0e209d39SAndroid Build Coastguard Worker /**
126*0e209d39SAndroid Build Coastguard Worker  * Create & return an instance of "type" in statically allocated storage.
127*0e209d39SAndroid Build Coastguard Worker  * e.g.
128*0e209d39SAndroid Build Coastguard Worker  *    static std::mutex *myMutex = STATIC_NEW(std::mutex);
129*0e209d39SAndroid Build Coastguard Worker  * To destroy an object created in this way, invoke the destructor explicitly, e.g.
130*0e209d39SAndroid Build Coastguard Worker  *    myMutex->~mutex();
131*0e209d39SAndroid Build Coastguard Worker  * DO NOT use delete.
132*0e209d39SAndroid Build Coastguard Worker  * DO NOT use with class UMutex, which has specific support for static instances.
133*0e209d39SAndroid Build Coastguard Worker  *
134*0e209d39SAndroid Build Coastguard Worker  * STATIC_NEW is intended for use when
135*0e209d39SAndroid Build Coastguard Worker  *   - We want a static (or global) object.
136*0e209d39SAndroid Build Coastguard Worker  *   - We don't want it to ever be destructed, or to explicitly control destruction,
137*0e209d39SAndroid Build Coastguard Worker  *     to avoid use-after-destruction problems.
138*0e209d39SAndroid Build Coastguard Worker  *   - We want to avoid an ordinary heap allocated object,
139*0e209d39SAndroid Build Coastguard Worker  *     to avoid the possibility of memory allocation failures, and
140*0e209d39SAndroid Build Coastguard Worker  *     to avoid memory leak reports, from valgrind, for example.
141*0e209d39SAndroid Build Coastguard Worker  * This is defined as a macro rather than a template function because each invocation
142*0e209d39SAndroid Build Coastguard Worker  * must define distinct static storage for the object being returned.
143*0e209d39SAndroid Build Coastguard Worker  */
144*0e209d39SAndroid Build Coastguard Worker #define STATIC_NEW(type) [] () { \
145*0e209d39SAndroid Build Coastguard Worker     alignas(type) static char storage[sizeof(type)]; \
146*0e209d39SAndroid Build Coastguard Worker     return new(storage) type();} ()
147*0e209d39SAndroid Build Coastguard Worker 
148*0e209d39SAndroid Build Coastguard Worker /**
149*0e209d39SAndroid Build Coastguard Worker   *  Heap clean up function, called from u_cleanup()
150*0e209d39SAndroid Build Coastguard Worker   *    Clears any user heap functions from u_setMemoryFunctions()
151*0e209d39SAndroid Build Coastguard Worker   *    Does NOT deallocate any remaining allocated memory.
152*0e209d39SAndroid Build Coastguard Worker   */
153*0e209d39SAndroid Build Coastguard Worker U_CFUNC UBool
154*0e209d39SAndroid Build Coastguard Worker cmemory_cleanup(void);
155*0e209d39SAndroid Build Coastguard Worker 
156*0e209d39SAndroid Build Coastguard Worker /**
157*0e209d39SAndroid Build Coastguard Worker  * A function called by <TT>uhash_remove</TT>,
158*0e209d39SAndroid Build Coastguard Worker  * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
159*0e209d39SAndroid Build Coastguard Worker  * an existing key or value.
160*0e209d39SAndroid Build Coastguard Worker  * @param obj A key or value stored in a hashtable
161*0e209d39SAndroid Build Coastguard Worker  * @see uprv_deleteUObject
162*0e209d39SAndroid Build Coastguard Worker  */
163*0e209d39SAndroid Build Coastguard Worker typedef void U_CALLCONV UObjectDeleter(void* obj);
164*0e209d39SAndroid Build Coastguard Worker 
165*0e209d39SAndroid Build Coastguard Worker /**
166*0e209d39SAndroid Build Coastguard Worker  * Deleter for UObject instances.
167*0e209d39SAndroid Build Coastguard Worker  * Works for all subclasses of UObject because it has a virtual destructor.
168*0e209d39SAndroid Build Coastguard Worker  */
169*0e209d39SAndroid Build Coastguard Worker U_CAPI void U_EXPORT2
170*0e209d39SAndroid Build Coastguard Worker uprv_deleteUObject(void *obj);
171*0e209d39SAndroid Build Coastguard Worker 
172*0e209d39SAndroid Build Coastguard Worker #ifdef __cplusplus
173*0e209d39SAndroid Build Coastguard Worker 
174*0e209d39SAndroid Build Coastguard Worker #include <utility>
175*0e209d39SAndroid Build Coastguard Worker #include "unicode/uobject.h"
176*0e209d39SAndroid Build Coastguard Worker 
177*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN
178*0e209d39SAndroid Build Coastguard Worker 
179*0e209d39SAndroid Build Coastguard Worker /**
180*0e209d39SAndroid Build Coastguard Worker  * "Smart pointer" class, deletes memory via uprv_free().
181*0e209d39SAndroid Build Coastguard Worker  * For most methods see the LocalPointerBase base class.
182*0e209d39SAndroid Build Coastguard Worker  * Adds operator[] for array item access.
183*0e209d39SAndroid Build Coastguard Worker  *
184*0e209d39SAndroid Build Coastguard Worker  * @see LocalPointerBase
185*0e209d39SAndroid Build Coastguard Worker  */
186*0e209d39SAndroid Build Coastguard Worker template<typename T>
187*0e209d39SAndroid Build Coastguard Worker class LocalMemory : public LocalPointerBase<T> {
188*0e209d39SAndroid Build Coastguard Worker public:
189*0e209d39SAndroid Build Coastguard Worker     using LocalPointerBase<T>::operator*;
190*0e209d39SAndroid Build Coastguard Worker     using LocalPointerBase<T>::operator->;
191*0e209d39SAndroid Build Coastguard Worker     /**
192*0e209d39SAndroid Build Coastguard Worker      * Constructor takes ownership.
193*0e209d39SAndroid Build Coastguard Worker      * @param p simple pointer to an array of T items that is adopted
194*0e209d39SAndroid Build Coastguard Worker      */
195*0e209d39SAndroid Build Coastguard Worker     explicit LocalMemory(T *p=nullptr) : LocalPointerBase<T>(p) {}
196*0e209d39SAndroid Build Coastguard Worker     /**
197*0e209d39SAndroid Build Coastguard Worker      * Move constructor, leaves src with isNull().
198*0e209d39SAndroid Build Coastguard Worker      * @param src source smart pointer
199*0e209d39SAndroid Build Coastguard Worker      */
LocalMemory(LocalMemory<T> && src)200*0e209d39SAndroid Build Coastguard Worker     LocalMemory(LocalMemory<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
201*0e209d39SAndroid Build Coastguard Worker         src.ptr=nullptr;
202*0e209d39SAndroid Build Coastguard Worker     }
203*0e209d39SAndroid Build Coastguard Worker     /**
204*0e209d39SAndroid Build Coastguard Worker      * Destructor deletes the memory it owns.
205*0e209d39SAndroid Build Coastguard Worker      */
~LocalMemory()206*0e209d39SAndroid Build Coastguard Worker     ~LocalMemory() {
207*0e209d39SAndroid Build Coastguard Worker         uprv_free(LocalPointerBase<T>::ptr);
208*0e209d39SAndroid Build Coastguard Worker     }
209*0e209d39SAndroid Build Coastguard Worker     /**
210*0e209d39SAndroid Build Coastguard Worker      * Move assignment operator, leaves src with isNull().
211*0e209d39SAndroid Build Coastguard Worker      * The behavior is undefined if *this and src are the same object.
212*0e209d39SAndroid Build Coastguard Worker      * @param src source smart pointer
213*0e209d39SAndroid Build Coastguard Worker      * @return *this
214*0e209d39SAndroid Build Coastguard Worker      */
215*0e209d39SAndroid Build Coastguard Worker     LocalMemory<T> &operator=(LocalMemory<T> &&src) noexcept {
216*0e209d39SAndroid Build Coastguard Worker         uprv_free(LocalPointerBase<T>::ptr);
217*0e209d39SAndroid Build Coastguard Worker         LocalPointerBase<T>::ptr=src.ptr;
218*0e209d39SAndroid Build Coastguard Worker         src.ptr=nullptr;
219*0e209d39SAndroid Build Coastguard Worker         return *this;
220*0e209d39SAndroid Build Coastguard Worker     }
221*0e209d39SAndroid Build Coastguard Worker     /**
222*0e209d39SAndroid Build Coastguard Worker      * Swap pointers.
223*0e209d39SAndroid Build Coastguard Worker      * @param other other smart pointer
224*0e209d39SAndroid Build Coastguard Worker      */
swap(LocalMemory<T> & other)225*0e209d39SAndroid Build Coastguard Worker     void swap(LocalMemory<T> &other) noexcept {
226*0e209d39SAndroid Build Coastguard Worker         T *temp=LocalPointerBase<T>::ptr;
227*0e209d39SAndroid Build Coastguard Worker         LocalPointerBase<T>::ptr=other.ptr;
228*0e209d39SAndroid Build Coastguard Worker         other.ptr=temp;
229*0e209d39SAndroid Build Coastguard Worker     }
230*0e209d39SAndroid Build Coastguard Worker     /**
231*0e209d39SAndroid Build Coastguard Worker      * Non-member LocalMemory swap function.
232*0e209d39SAndroid Build Coastguard Worker      * @param p1 will get p2's pointer
233*0e209d39SAndroid Build Coastguard Worker      * @param p2 will get p1's pointer
234*0e209d39SAndroid Build Coastguard Worker      */
swap(LocalMemory<T> & p1,LocalMemory<T> & p2)235*0e209d39SAndroid Build Coastguard Worker     friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) noexcept {
236*0e209d39SAndroid Build Coastguard Worker         p1.swap(p2);
237*0e209d39SAndroid Build Coastguard Worker     }
238*0e209d39SAndroid Build Coastguard Worker     /**
239*0e209d39SAndroid Build Coastguard Worker      * Deletes the array it owns,
240*0e209d39SAndroid Build Coastguard Worker      * and adopts (takes ownership of) the one passed in.
241*0e209d39SAndroid Build Coastguard Worker      * @param p simple pointer to an array of T items that is adopted
242*0e209d39SAndroid Build Coastguard Worker      */
adoptInstead(T * p)243*0e209d39SAndroid Build Coastguard Worker     void adoptInstead(T *p) {
244*0e209d39SAndroid Build Coastguard Worker         uprv_free(LocalPointerBase<T>::ptr);
245*0e209d39SAndroid Build Coastguard Worker         LocalPointerBase<T>::ptr=p;
246*0e209d39SAndroid Build Coastguard Worker     }
247*0e209d39SAndroid Build Coastguard Worker     /**
248*0e209d39SAndroid Build Coastguard Worker      * Deletes the array it owns, allocates a new one and reset its bytes to 0.
249*0e209d39SAndroid Build Coastguard Worker      * Returns the new array pointer.
250*0e209d39SAndroid Build Coastguard Worker      * If the allocation fails, then the current array is unchanged and
251*0e209d39SAndroid Build Coastguard Worker      * this method returns nullptr.
252*0e209d39SAndroid Build Coastguard Worker      * @param newCapacity must be >0
253*0e209d39SAndroid Build Coastguard Worker      * @return the allocated array pointer, or nullptr if the allocation failed
254*0e209d39SAndroid Build Coastguard Worker      */
255*0e209d39SAndroid Build Coastguard Worker     inline T *allocateInsteadAndReset(int32_t newCapacity=1);
256*0e209d39SAndroid Build Coastguard Worker     /**
257*0e209d39SAndroid Build Coastguard Worker      * Deletes the array it owns and allocates a new one, copying length T items.
258*0e209d39SAndroid Build Coastguard Worker      * Returns the new array pointer.
259*0e209d39SAndroid Build Coastguard Worker      * If the allocation fails, then the current array is unchanged and
260*0e209d39SAndroid Build Coastguard Worker      * this method returns nullptr.
261*0e209d39SAndroid Build Coastguard Worker      * @param newCapacity must be >0
262*0e209d39SAndroid Build Coastguard Worker      * @param length number of T items to be copied from the old array to the new one;
263*0e209d39SAndroid Build Coastguard Worker      *               must be no more than the capacity of the old array,
264*0e209d39SAndroid Build Coastguard Worker      *               which the caller must track because the LocalMemory does not track it
265*0e209d39SAndroid Build Coastguard Worker      * @return the allocated array pointer, or nullptr if the allocation failed
266*0e209d39SAndroid Build Coastguard Worker      */
267*0e209d39SAndroid Build Coastguard Worker     inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
268*0e209d39SAndroid Build Coastguard Worker     /**
269*0e209d39SAndroid Build Coastguard Worker      * Array item access (writable).
270*0e209d39SAndroid Build Coastguard Worker      * No index bounds check.
271*0e209d39SAndroid Build Coastguard Worker      * @param i array index
272*0e209d39SAndroid Build Coastguard Worker      * @return reference to the array item
273*0e209d39SAndroid Build Coastguard Worker      */
274*0e209d39SAndroid Build Coastguard Worker     T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
275*0e209d39SAndroid Build Coastguard Worker };
276*0e209d39SAndroid Build Coastguard Worker 
277*0e209d39SAndroid Build Coastguard Worker template<typename T>
allocateInsteadAndReset(int32_t newCapacity)278*0e209d39SAndroid Build Coastguard Worker inline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
279*0e209d39SAndroid Build Coastguard Worker     if(newCapacity>0) {
280*0e209d39SAndroid Build Coastguard Worker         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
281*0e209d39SAndroid Build Coastguard Worker         if(p!=nullptr) {
282*0e209d39SAndroid Build Coastguard Worker             uprv_memset(p, 0, newCapacity*sizeof(T));
283*0e209d39SAndroid Build Coastguard Worker             uprv_free(LocalPointerBase<T>::ptr);
284*0e209d39SAndroid Build Coastguard Worker             LocalPointerBase<T>::ptr=p;
285*0e209d39SAndroid Build Coastguard Worker         }
286*0e209d39SAndroid Build Coastguard Worker         return p;
287*0e209d39SAndroid Build Coastguard Worker     } else {
288*0e209d39SAndroid Build Coastguard Worker         return nullptr;
289*0e209d39SAndroid Build Coastguard Worker     }
290*0e209d39SAndroid Build Coastguard Worker }
291*0e209d39SAndroid Build Coastguard Worker 
292*0e209d39SAndroid Build Coastguard Worker 
293*0e209d39SAndroid Build Coastguard Worker template<typename T>
allocateInsteadAndCopy(int32_t newCapacity,int32_t length)294*0e209d39SAndroid Build Coastguard Worker inline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
295*0e209d39SAndroid Build Coastguard Worker     if(newCapacity>0) {
296*0e209d39SAndroid Build Coastguard Worker         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
297*0e209d39SAndroid Build Coastguard Worker         if(p!=nullptr) {
298*0e209d39SAndroid Build Coastguard Worker             if(length>0) {
299*0e209d39SAndroid Build Coastguard Worker                 if(length>newCapacity) {
300*0e209d39SAndroid Build Coastguard Worker                     length=newCapacity;
301*0e209d39SAndroid Build Coastguard Worker                 }
302*0e209d39SAndroid Build Coastguard Worker                 uprv_memcpy(p, LocalPointerBase<T>::ptr, (size_t)length*sizeof(T));
303*0e209d39SAndroid Build Coastguard Worker             }
304*0e209d39SAndroid Build Coastguard Worker             uprv_free(LocalPointerBase<T>::ptr);
305*0e209d39SAndroid Build Coastguard Worker             LocalPointerBase<T>::ptr=p;
306*0e209d39SAndroid Build Coastguard Worker         }
307*0e209d39SAndroid Build Coastguard Worker         return p;
308*0e209d39SAndroid Build Coastguard Worker     } else {
309*0e209d39SAndroid Build Coastguard Worker         return nullptr;
310*0e209d39SAndroid Build Coastguard Worker     }
311*0e209d39SAndroid Build Coastguard Worker }
312*0e209d39SAndroid Build Coastguard Worker 
313*0e209d39SAndroid Build Coastguard Worker /**
314*0e209d39SAndroid Build Coastguard Worker  * Simple array/buffer management class using uprv_malloc() and uprv_free().
315*0e209d39SAndroid Build Coastguard Worker  * Provides an internal array with fixed capacity. Can alias another array
316*0e209d39SAndroid Build Coastguard Worker  * or allocate one.
317*0e209d39SAndroid Build Coastguard Worker  *
318*0e209d39SAndroid Build Coastguard Worker  * The array address is properly aligned for type T. It might not be properly
319*0e209d39SAndroid Build Coastguard Worker  * aligned for types larger than T (or larger than the largest subtype of T).
320*0e209d39SAndroid Build Coastguard Worker  *
321*0e209d39SAndroid Build Coastguard Worker  * Unlike LocalMemory and LocalArray, this class never adopts
322*0e209d39SAndroid Build Coastguard Worker  * (takes ownership of) another array.
323*0e209d39SAndroid Build Coastguard Worker  *
324*0e209d39SAndroid Build Coastguard Worker  * WARNING: MaybeStackArray only works with primitive (plain-old data) types.
325*0e209d39SAndroid Build Coastguard Worker  * It does NOT know how to call a destructor! If you work with classes with
326*0e209d39SAndroid Build Coastguard Worker  * destructors, consider:
327*0e209d39SAndroid Build Coastguard Worker  *
328*0e209d39SAndroid Build Coastguard Worker  * - LocalArray in localpointer.h if you know the length ahead of time
329*0e209d39SAndroid Build Coastguard Worker  * - MaybeStackVector if you know the length at runtime
330*0e209d39SAndroid Build Coastguard Worker  */
331*0e209d39SAndroid Build Coastguard Worker template<typename T, int32_t stackCapacity>
332*0e209d39SAndroid Build Coastguard Worker class MaybeStackArray {
333*0e209d39SAndroid Build Coastguard Worker public:
334*0e209d39SAndroid Build Coastguard Worker     // No heap allocation. Use only on the stack.
335*0e209d39SAndroid Build Coastguard Worker     static void* U_EXPORT2 operator new(size_t) noexcept = delete;
336*0e209d39SAndroid Build Coastguard Worker     static void* U_EXPORT2 operator new[](size_t) noexcept = delete;
337*0e209d39SAndroid Build Coastguard Worker #if U_HAVE_PLACEMENT_NEW
338*0e209d39SAndroid Build Coastguard Worker     static void* U_EXPORT2 operator new(size_t, void*) noexcept = delete;
339*0e209d39SAndroid Build Coastguard Worker #endif
340*0e209d39SAndroid Build Coastguard Worker 
341*0e209d39SAndroid Build Coastguard Worker     /**
342*0e209d39SAndroid Build Coastguard Worker      * Default constructor initializes with internal T[stackCapacity] buffer.
343*0e209d39SAndroid Build Coastguard Worker      */
MaybeStackArray()344*0e209d39SAndroid Build Coastguard Worker     MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(false) {}
345*0e209d39SAndroid Build Coastguard Worker     /**
346*0e209d39SAndroid Build Coastguard Worker      * Automatically allocates the heap array if the argument is larger than the stack capacity.
347*0e209d39SAndroid Build Coastguard Worker      * Intended for use when an approximate capacity is known at compile time but the true
348*0e209d39SAndroid Build Coastguard Worker      * capacity is not known until runtime.
349*0e209d39SAndroid Build Coastguard Worker      */
MaybeStackArray(int32_t newCapacity,UErrorCode status)350*0e209d39SAndroid Build Coastguard Worker     MaybeStackArray(int32_t newCapacity, UErrorCode status) : MaybeStackArray() {
351*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
352*0e209d39SAndroid Build Coastguard Worker             return;
353*0e209d39SAndroid Build Coastguard Worker         }
354*0e209d39SAndroid Build Coastguard Worker         if (capacity < newCapacity) {
355*0e209d39SAndroid Build Coastguard Worker             if (resize(newCapacity) == nullptr) {
356*0e209d39SAndroid Build Coastguard Worker                 status = U_MEMORY_ALLOCATION_ERROR;
357*0e209d39SAndroid Build Coastguard Worker             }
358*0e209d39SAndroid Build Coastguard Worker         }
359*0e209d39SAndroid Build Coastguard Worker     }
360*0e209d39SAndroid Build Coastguard Worker     /**
361*0e209d39SAndroid Build Coastguard Worker      * Destructor deletes the array (if owned).
362*0e209d39SAndroid Build Coastguard Worker      */
~MaybeStackArray()363*0e209d39SAndroid Build Coastguard Worker     ~MaybeStackArray() { releaseArray(); }
364*0e209d39SAndroid Build Coastguard Worker     /**
365*0e209d39SAndroid Build Coastguard Worker      * Move constructor: transfers ownership or copies the stack array.
366*0e209d39SAndroid Build Coastguard Worker      */
367*0e209d39SAndroid Build Coastguard Worker     MaybeStackArray(MaybeStackArray<T, stackCapacity> &&src) noexcept;
368*0e209d39SAndroid Build Coastguard Worker     /**
369*0e209d39SAndroid Build Coastguard Worker      * Move assignment: transfers ownership or copies the stack array.
370*0e209d39SAndroid Build Coastguard Worker      */
371*0e209d39SAndroid Build Coastguard Worker     MaybeStackArray<T, stackCapacity> &operator=(MaybeStackArray<T, stackCapacity> &&src) noexcept;
372*0e209d39SAndroid Build Coastguard Worker     /**
373*0e209d39SAndroid Build Coastguard Worker      * Returns the array capacity (number of T items).
374*0e209d39SAndroid Build Coastguard Worker      * @return array capacity
375*0e209d39SAndroid Build Coastguard Worker      */
getCapacity()376*0e209d39SAndroid Build Coastguard Worker     int32_t getCapacity() const { return capacity; }
377*0e209d39SAndroid Build Coastguard Worker     /**
378*0e209d39SAndroid Build Coastguard Worker      * Access without ownership change.
379*0e209d39SAndroid Build Coastguard Worker      * @return the array pointer
380*0e209d39SAndroid Build Coastguard Worker      */
getAlias()381*0e209d39SAndroid Build Coastguard Worker     T *getAlias() const { return ptr; }
382*0e209d39SAndroid Build Coastguard Worker     /**
383*0e209d39SAndroid Build Coastguard Worker      * Returns the array limit. Simple convenience method.
384*0e209d39SAndroid Build Coastguard Worker      * @return getAlias()+getCapacity()
385*0e209d39SAndroid Build Coastguard Worker      */
getArrayLimit()386*0e209d39SAndroid Build Coastguard Worker     T *getArrayLimit() const { return getAlias()+capacity; }
387*0e209d39SAndroid Build Coastguard Worker     // No "operator T *() const" because that can make
388*0e209d39SAndroid Build Coastguard Worker     // expressions like mbs[index] ambiguous for some compilers.
389*0e209d39SAndroid Build Coastguard Worker     /**
390*0e209d39SAndroid Build Coastguard Worker      * Array item access (const).
391*0e209d39SAndroid Build Coastguard Worker      * No index bounds check.
392*0e209d39SAndroid Build Coastguard Worker      * @param i array index
393*0e209d39SAndroid Build Coastguard Worker      * @return reference to the array item
394*0e209d39SAndroid Build Coastguard Worker      */
395*0e209d39SAndroid Build Coastguard Worker     const T &operator[](ptrdiff_t i) const { return ptr[i]; }
396*0e209d39SAndroid Build Coastguard Worker     /**
397*0e209d39SAndroid Build Coastguard Worker      * Array item access (writable).
398*0e209d39SAndroid Build Coastguard Worker      * No index bounds check.
399*0e209d39SAndroid Build Coastguard Worker      * @param i array index
400*0e209d39SAndroid Build Coastguard Worker      * @return reference to the array item
401*0e209d39SAndroid Build Coastguard Worker      */
402*0e209d39SAndroid Build Coastguard Worker     T &operator[](ptrdiff_t i) { return ptr[i]; }
403*0e209d39SAndroid Build Coastguard Worker     /**
404*0e209d39SAndroid Build Coastguard Worker      * Deletes the array (if owned) and aliases another one, no transfer of ownership.
405*0e209d39SAndroid Build Coastguard Worker      * If the arguments are illegal, then the current array is unchanged.
406*0e209d39SAndroid Build Coastguard Worker      * @param otherArray must not be nullptr
407*0e209d39SAndroid Build Coastguard Worker      * @param otherCapacity must be >0
408*0e209d39SAndroid Build Coastguard Worker      */
aliasInstead(T * otherArray,int32_t otherCapacity)409*0e209d39SAndroid Build Coastguard Worker     void aliasInstead(T *otherArray, int32_t otherCapacity) {
410*0e209d39SAndroid Build Coastguard Worker         if(otherArray!=nullptr && otherCapacity>0) {
411*0e209d39SAndroid Build Coastguard Worker             releaseArray();
412*0e209d39SAndroid Build Coastguard Worker             ptr=otherArray;
413*0e209d39SAndroid Build Coastguard Worker             capacity=otherCapacity;
414*0e209d39SAndroid Build Coastguard Worker             needToRelease=false;
415*0e209d39SAndroid Build Coastguard Worker         }
416*0e209d39SAndroid Build Coastguard Worker     }
417*0e209d39SAndroid Build Coastguard Worker     /**
418*0e209d39SAndroid Build Coastguard Worker      * Deletes the array (if owned) and allocates a new one, copying length T items.
419*0e209d39SAndroid Build Coastguard Worker      * Returns the new array pointer.
420*0e209d39SAndroid Build Coastguard Worker      * If the allocation fails, then the current array is unchanged and
421*0e209d39SAndroid Build Coastguard Worker      * this method returns nullptr.
422*0e209d39SAndroid Build Coastguard Worker      * @param newCapacity can be less than or greater than the current capacity;
423*0e209d39SAndroid Build Coastguard Worker      *                    must be >0
424*0e209d39SAndroid Build Coastguard Worker      * @param length number of T items to be copied from the old array to the new one
425*0e209d39SAndroid Build Coastguard Worker      * @return the allocated array pointer, or nullptr if the allocation failed
426*0e209d39SAndroid Build Coastguard Worker      */
427*0e209d39SAndroid Build Coastguard Worker     inline T *resize(int32_t newCapacity, int32_t length=0);
428*0e209d39SAndroid Build Coastguard Worker     /**
429*0e209d39SAndroid Build Coastguard Worker      * Gives up ownership of the array if owned, or else clones it,
430*0e209d39SAndroid Build Coastguard Worker      * copying length T items; resets itself to the internal stack array.
431*0e209d39SAndroid Build Coastguard Worker      * Returns nullptr if the allocation failed.
432*0e209d39SAndroid Build Coastguard Worker      * @param length number of T items to copy when cloning,
433*0e209d39SAndroid Build Coastguard Worker      *        and capacity of the clone when cloning
434*0e209d39SAndroid Build Coastguard Worker      * @param resultCapacity will be set to the returned array's capacity (output-only)
435*0e209d39SAndroid Build Coastguard Worker      * @return the array pointer;
436*0e209d39SAndroid Build Coastguard Worker      *         caller becomes responsible for deleting the array
437*0e209d39SAndroid Build Coastguard Worker      */
438*0e209d39SAndroid Build Coastguard Worker     inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
439*0e209d39SAndroid Build Coastguard Worker 
440*0e209d39SAndroid Build Coastguard Worker protected:
441*0e209d39SAndroid Build Coastguard Worker     // Resizes the array to the size of src, then copies the contents of src.
copyFrom(const MaybeStackArray & src,UErrorCode & status)442*0e209d39SAndroid Build Coastguard Worker     void copyFrom(const MaybeStackArray &src, UErrorCode &status) {
443*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
444*0e209d39SAndroid Build Coastguard Worker             return;
445*0e209d39SAndroid Build Coastguard Worker         }
446*0e209d39SAndroid Build Coastguard Worker         if (this->resize(src.capacity, 0) == nullptr) {
447*0e209d39SAndroid Build Coastguard Worker             status = U_MEMORY_ALLOCATION_ERROR;
448*0e209d39SAndroid Build Coastguard Worker             return;
449*0e209d39SAndroid Build Coastguard Worker         }
450*0e209d39SAndroid Build Coastguard Worker         uprv_memcpy(this->ptr, src.ptr, (size_t)capacity * sizeof(T));
451*0e209d39SAndroid Build Coastguard Worker     }
452*0e209d39SAndroid Build Coastguard Worker 
453*0e209d39SAndroid Build Coastguard Worker private:
454*0e209d39SAndroid Build Coastguard Worker     T *ptr;
455*0e209d39SAndroid Build Coastguard Worker     int32_t capacity;
456*0e209d39SAndroid Build Coastguard Worker     UBool needToRelease;
457*0e209d39SAndroid Build Coastguard Worker     T stackArray[stackCapacity];
releaseArray()458*0e209d39SAndroid Build Coastguard Worker     void releaseArray() {
459*0e209d39SAndroid Build Coastguard Worker         if(needToRelease) {
460*0e209d39SAndroid Build Coastguard Worker             uprv_free(ptr);
461*0e209d39SAndroid Build Coastguard Worker         }
462*0e209d39SAndroid Build Coastguard Worker     }
resetToStackArray()463*0e209d39SAndroid Build Coastguard Worker     void resetToStackArray() {
464*0e209d39SAndroid Build Coastguard Worker         ptr=stackArray;
465*0e209d39SAndroid Build Coastguard Worker         capacity=stackCapacity;
466*0e209d39SAndroid Build Coastguard Worker         needToRelease=false;
467*0e209d39SAndroid Build Coastguard Worker     }
468*0e209d39SAndroid Build Coastguard Worker     /* No comparison operators with other MaybeStackArray's. */
469*0e209d39SAndroid Build Coastguard Worker     bool operator==(const MaybeStackArray & /*other*/) = delete;
470*0e209d39SAndroid Build Coastguard Worker     bool operator!=(const MaybeStackArray & /*other*/) = delete;
471*0e209d39SAndroid Build Coastguard Worker     /* No ownership transfer: No copy constructor, no assignment operator. */
472*0e209d39SAndroid Build Coastguard Worker     MaybeStackArray(const MaybeStackArray & /*other*/) = delete;
473*0e209d39SAndroid Build Coastguard Worker     void operator=(const MaybeStackArray & /*other*/) = delete;
474*0e209d39SAndroid Build Coastguard Worker };
475*0e209d39SAndroid Build Coastguard Worker 
476*0e209d39SAndroid Build Coastguard Worker template<typename T, int32_t stackCapacity>
MaybeStackArray(MaybeStackArray<T,stackCapacity> && src)477*0e209d39SAndroid Build Coastguard Worker icu::MaybeStackArray<T, stackCapacity>::MaybeStackArray(
478*0e209d39SAndroid Build Coastguard Worker         MaybeStackArray <T, stackCapacity>&& src) noexcept
479*0e209d39SAndroid Build Coastguard Worker         : ptr(src.ptr), capacity(src.capacity), needToRelease(src.needToRelease) {
480*0e209d39SAndroid Build Coastguard Worker     if (src.ptr == src.stackArray) {
481*0e209d39SAndroid Build Coastguard Worker         ptr = stackArray;
482*0e209d39SAndroid Build Coastguard Worker         uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity);
483*0e209d39SAndroid Build Coastguard Worker     } else {
484*0e209d39SAndroid Build Coastguard Worker         src.resetToStackArray();  // take ownership away from src
485*0e209d39SAndroid Build Coastguard Worker     }
486*0e209d39SAndroid Build Coastguard Worker }
487*0e209d39SAndroid Build Coastguard Worker 
488*0e209d39SAndroid Build Coastguard Worker template<typename T, int32_t stackCapacity>
489*0e209d39SAndroid Build Coastguard Worker inline MaybeStackArray <T, stackCapacity>&
490*0e209d39SAndroid Build Coastguard Worker MaybeStackArray<T, stackCapacity>::operator=(MaybeStackArray <T, stackCapacity>&& src) noexcept {
491*0e209d39SAndroid Build Coastguard Worker     releaseArray();  // in case this instance had its own memory allocated
492*0e209d39SAndroid Build Coastguard Worker     capacity = src.capacity;
493*0e209d39SAndroid Build Coastguard Worker     needToRelease = src.needToRelease;
494*0e209d39SAndroid Build Coastguard Worker     if (src.ptr == src.stackArray) {
495*0e209d39SAndroid Build Coastguard Worker         ptr = stackArray;
496*0e209d39SAndroid Build Coastguard Worker         uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity);
497*0e209d39SAndroid Build Coastguard Worker     } else {
498*0e209d39SAndroid Build Coastguard Worker         ptr = src.ptr;
499*0e209d39SAndroid Build Coastguard Worker         src.resetToStackArray();  // take ownership away from src
500*0e209d39SAndroid Build Coastguard Worker     }
501*0e209d39SAndroid Build Coastguard Worker     return *this;
502*0e209d39SAndroid Build Coastguard Worker }
503*0e209d39SAndroid Build Coastguard Worker 
504*0e209d39SAndroid Build Coastguard Worker template<typename T, int32_t stackCapacity>
resize(int32_t newCapacity,int32_t length)505*0e209d39SAndroid Build Coastguard Worker inline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
506*0e209d39SAndroid Build Coastguard Worker     if(newCapacity>0) {
507*0e209d39SAndroid Build Coastguard Worker #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
508*0e209d39SAndroid Build Coastguard Worker         ::fprintf(::stderr, "MaybeStackArray (resize) alloc %d * %lu\n", newCapacity, sizeof(T));
509*0e209d39SAndroid Build Coastguard Worker #endif
510*0e209d39SAndroid Build Coastguard Worker         T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
511*0e209d39SAndroid Build Coastguard Worker         if(p!=nullptr) {
512*0e209d39SAndroid Build Coastguard Worker             if(length>0) {
513*0e209d39SAndroid Build Coastguard Worker                 if(length>capacity) {
514*0e209d39SAndroid Build Coastguard Worker                     length=capacity;
515*0e209d39SAndroid Build Coastguard Worker                 }
516*0e209d39SAndroid Build Coastguard Worker                 if(length>newCapacity) {
517*0e209d39SAndroid Build Coastguard Worker                     length=newCapacity;
518*0e209d39SAndroid Build Coastguard Worker                 }
519*0e209d39SAndroid Build Coastguard Worker                 uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
520*0e209d39SAndroid Build Coastguard Worker             }
521*0e209d39SAndroid Build Coastguard Worker             releaseArray();
522*0e209d39SAndroid Build Coastguard Worker             ptr=p;
523*0e209d39SAndroid Build Coastguard Worker             capacity=newCapacity;
524*0e209d39SAndroid Build Coastguard Worker             needToRelease=true;
525*0e209d39SAndroid Build Coastguard Worker         }
526*0e209d39SAndroid Build Coastguard Worker         return p;
527*0e209d39SAndroid Build Coastguard Worker     } else {
528*0e209d39SAndroid Build Coastguard Worker         return nullptr;
529*0e209d39SAndroid Build Coastguard Worker     }
530*0e209d39SAndroid Build Coastguard Worker }
531*0e209d39SAndroid Build Coastguard Worker 
532*0e209d39SAndroid Build Coastguard Worker template<typename T, int32_t stackCapacity>
orphanOrClone(int32_t length,int32_t & resultCapacity)533*0e209d39SAndroid Build Coastguard Worker inline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
534*0e209d39SAndroid Build Coastguard Worker     T *p;
535*0e209d39SAndroid Build Coastguard Worker     if(needToRelease) {
536*0e209d39SAndroid Build Coastguard Worker         p=ptr;
537*0e209d39SAndroid Build Coastguard Worker     } else if(length<=0) {
538*0e209d39SAndroid Build Coastguard Worker         return nullptr;
539*0e209d39SAndroid Build Coastguard Worker     } else {
540*0e209d39SAndroid Build Coastguard Worker         if(length>capacity) {
541*0e209d39SAndroid Build Coastguard Worker             length=capacity;
542*0e209d39SAndroid Build Coastguard Worker         }
543*0e209d39SAndroid Build Coastguard Worker         p=(T *)uprv_malloc(length*sizeof(T));
544*0e209d39SAndroid Build Coastguard Worker #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
545*0e209d39SAndroid Build Coastguard Worker       ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
546*0e209d39SAndroid Build Coastguard Worker #endif
547*0e209d39SAndroid Build Coastguard Worker         if(p==nullptr) {
548*0e209d39SAndroid Build Coastguard Worker             return nullptr;
549*0e209d39SAndroid Build Coastguard Worker         }
550*0e209d39SAndroid Build Coastguard Worker         uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
551*0e209d39SAndroid Build Coastguard Worker     }
552*0e209d39SAndroid Build Coastguard Worker     resultCapacity=length;
553*0e209d39SAndroid Build Coastguard Worker     resetToStackArray();
554*0e209d39SAndroid Build Coastguard Worker     return p;
555*0e209d39SAndroid Build Coastguard Worker }
556*0e209d39SAndroid Build Coastguard Worker 
557*0e209d39SAndroid Build Coastguard Worker /**
558*0e209d39SAndroid Build Coastguard Worker  * Variant of MaybeStackArray that allocates a header struct and an array
559*0e209d39SAndroid Build Coastguard Worker  * in one contiguous memory block, using uprv_malloc() and uprv_free().
560*0e209d39SAndroid Build Coastguard Worker  * Provides internal memory with fixed array capacity. Can alias another memory
561*0e209d39SAndroid Build Coastguard Worker  * block or allocate one.
562*0e209d39SAndroid Build Coastguard Worker  * The stackCapacity is the number of T items in the internal memory,
563*0e209d39SAndroid Build Coastguard Worker  * not counting the H header.
564*0e209d39SAndroid Build Coastguard Worker  * Unlike LocalMemory and LocalArray, this class never adopts
565*0e209d39SAndroid Build Coastguard Worker  * (takes ownership of) another memory block.
566*0e209d39SAndroid Build Coastguard Worker  */
567*0e209d39SAndroid Build Coastguard Worker template<typename H, typename T, int32_t stackCapacity>
568*0e209d39SAndroid Build Coastguard Worker class MaybeStackHeaderAndArray {
569*0e209d39SAndroid Build Coastguard Worker public:
570*0e209d39SAndroid Build Coastguard Worker     // No heap allocation. Use only on the stack.
571*0e209d39SAndroid Build Coastguard Worker     static void* U_EXPORT2 operator new(size_t) noexcept = delete;
572*0e209d39SAndroid Build Coastguard Worker     static void* U_EXPORT2 operator new[](size_t) noexcept = delete;
573*0e209d39SAndroid Build Coastguard Worker #if U_HAVE_PLACEMENT_NEW
574*0e209d39SAndroid Build Coastguard Worker     static void* U_EXPORT2 operator new(size_t, void*) noexcept = delete;
575*0e209d39SAndroid Build Coastguard Worker #endif
576*0e209d39SAndroid Build Coastguard Worker 
577*0e209d39SAndroid Build Coastguard Worker     /**
578*0e209d39SAndroid Build Coastguard Worker      * Default constructor initializes with internal H+T[stackCapacity] buffer.
579*0e209d39SAndroid Build Coastguard Worker      */
MaybeStackHeaderAndArray()580*0e209d39SAndroid Build Coastguard Worker     MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(false) {}
581*0e209d39SAndroid Build Coastguard Worker     /**
582*0e209d39SAndroid Build Coastguard Worker      * Destructor deletes the memory (if owned).
583*0e209d39SAndroid Build Coastguard Worker      */
~MaybeStackHeaderAndArray()584*0e209d39SAndroid Build Coastguard Worker     ~MaybeStackHeaderAndArray() { releaseMemory(); }
585*0e209d39SAndroid Build Coastguard Worker     /**
586*0e209d39SAndroid Build Coastguard Worker      * Returns the array capacity (number of T items).
587*0e209d39SAndroid Build Coastguard Worker      * @return array capacity
588*0e209d39SAndroid Build Coastguard Worker      */
getCapacity()589*0e209d39SAndroid Build Coastguard Worker     int32_t getCapacity() const { return capacity; }
590*0e209d39SAndroid Build Coastguard Worker     /**
591*0e209d39SAndroid Build Coastguard Worker      * Access without ownership change.
592*0e209d39SAndroid Build Coastguard Worker      * @return the header pointer
593*0e209d39SAndroid Build Coastguard Worker      */
getAlias()594*0e209d39SAndroid Build Coastguard Worker     H *getAlias() const { return ptr; }
595*0e209d39SAndroid Build Coastguard Worker     /**
596*0e209d39SAndroid Build Coastguard Worker      * Returns the array start.
597*0e209d39SAndroid Build Coastguard Worker      * @return array start, same address as getAlias()+1
598*0e209d39SAndroid Build Coastguard Worker      */
getArrayStart()599*0e209d39SAndroid Build Coastguard Worker     T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
600*0e209d39SAndroid Build Coastguard Worker     /**
601*0e209d39SAndroid Build Coastguard Worker      * Returns the array limit.
602*0e209d39SAndroid Build Coastguard Worker      * @return array limit
603*0e209d39SAndroid Build Coastguard Worker      */
getArrayLimit()604*0e209d39SAndroid Build Coastguard Worker     T *getArrayLimit() const { return getArrayStart()+capacity; }
605*0e209d39SAndroid Build Coastguard Worker     /**
606*0e209d39SAndroid Build Coastguard Worker      * Access without ownership change. Same as getAlias().
607*0e209d39SAndroid Build Coastguard Worker      * A class instance can be used directly in expressions that take a T *.
608*0e209d39SAndroid Build Coastguard Worker      * @return the header pointer
609*0e209d39SAndroid Build Coastguard Worker      */
610*0e209d39SAndroid Build Coastguard Worker     operator H *() const { return ptr; }
611*0e209d39SAndroid Build Coastguard Worker     /**
612*0e209d39SAndroid Build Coastguard Worker      * Array item access (writable).
613*0e209d39SAndroid Build Coastguard Worker      * No index bounds check.
614*0e209d39SAndroid Build Coastguard Worker      * @param i array index
615*0e209d39SAndroid Build Coastguard Worker      * @return reference to the array item
616*0e209d39SAndroid Build Coastguard Worker      */
617*0e209d39SAndroid Build Coastguard Worker     T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
618*0e209d39SAndroid Build Coastguard Worker     /**
619*0e209d39SAndroid Build Coastguard Worker      * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
620*0e209d39SAndroid Build Coastguard Worker      * If the arguments are illegal, then the current memory is unchanged.
621*0e209d39SAndroid Build Coastguard Worker      * @param otherArray must not be nullptr
622*0e209d39SAndroid Build Coastguard Worker      * @param otherCapacity must be >0
623*0e209d39SAndroid Build Coastguard Worker      */
aliasInstead(H * otherMemory,int32_t otherCapacity)624*0e209d39SAndroid Build Coastguard Worker     void aliasInstead(H *otherMemory, int32_t otherCapacity) {
625*0e209d39SAndroid Build Coastguard Worker         if(otherMemory!=nullptr && otherCapacity>0) {
626*0e209d39SAndroid Build Coastguard Worker             releaseMemory();
627*0e209d39SAndroid Build Coastguard Worker             ptr=otherMemory;
628*0e209d39SAndroid Build Coastguard Worker             capacity=otherCapacity;
629*0e209d39SAndroid Build Coastguard Worker             needToRelease=false;
630*0e209d39SAndroid Build Coastguard Worker         }
631*0e209d39SAndroid Build Coastguard Worker     }
632*0e209d39SAndroid Build Coastguard Worker     /**
633*0e209d39SAndroid Build Coastguard Worker      * Deletes the memory block (if owned) and allocates a new one,
634*0e209d39SAndroid Build Coastguard Worker      * copying the header and length T array items.
635*0e209d39SAndroid Build Coastguard Worker      * Returns the new header pointer.
636*0e209d39SAndroid Build Coastguard Worker      * If the allocation fails, then the current memory is unchanged and
637*0e209d39SAndroid Build Coastguard Worker      * this method returns nullptr.
638*0e209d39SAndroid Build Coastguard Worker      * @param newCapacity can be less than or greater than the current capacity;
639*0e209d39SAndroid Build Coastguard Worker      *                    must be >0
640*0e209d39SAndroid Build Coastguard Worker      * @param length number of T items to be copied from the old array to the new one
641*0e209d39SAndroid Build Coastguard Worker      * @return the allocated pointer, or nullptr if the allocation failed
642*0e209d39SAndroid Build Coastguard Worker      */
643*0e209d39SAndroid Build Coastguard Worker     inline H *resize(int32_t newCapacity, int32_t length=0);
644*0e209d39SAndroid Build Coastguard Worker     /**
645*0e209d39SAndroid Build Coastguard Worker      * Gives up ownership of the memory if owned, or else clones it,
646*0e209d39SAndroid Build Coastguard Worker      * copying the header and length T array items; resets itself to the internal memory.
647*0e209d39SAndroid Build Coastguard Worker      * Returns nullptr if the allocation failed.
648*0e209d39SAndroid Build Coastguard Worker      * @param length number of T items to copy when cloning,
649*0e209d39SAndroid Build Coastguard Worker      *        and array capacity of the clone when cloning
650*0e209d39SAndroid Build Coastguard Worker      * @param resultCapacity will be set to the returned array's capacity (output-only)
651*0e209d39SAndroid Build Coastguard Worker      * @return the header pointer;
652*0e209d39SAndroid Build Coastguard Worker      *         caller becomes responsible for deleting the array
653*0e209d39SAndroid Build Coastguard Worker      */
654*0e209d39SAndroid Build Coastguard Worker     inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
655*0e209d39SAndroid Build Coastguard Worker private:
656*0e209d39SAndroid Build Coastguard Worker     H *ptr;
657*0e209d39SAndroid Build Coastguard Worker     int32_t capacity;
658*0e209d39SAndroid Build Coastguard Worker     UBool needToRelease;
659*0e209d39SAndroid Build Coastguard Worker     // stackHeader must precede stackArray immediately.
660*0e209d39SAndroid Build Coastguard Worker     H stackHeader;
661*0e209d39SAndroid Build Coastguard Worker     T stackArray[stackCapacity];
releaseMemory()662*0e209d39SAndroid Build Coastguard Worker     void releaseMemory() {
663*0e209d39SAndroid Build Coastguard Worker         if(needToRelease) {
664*0e209d39SAndroid Build Coastguard Worker             uprv_free(ptr);
665*0e209d39SAndroid Build Coastguard Worker         }
666*0e209d39SAndroid Build Coastguard Worker     }
667*0e209d39SAndroid Build Coastguard Worker     /* No comparison operators with other MaybeStackHeaderAndArray's. */
668*0e209d39SAndroid Build Coastguard Worker     bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return false;}
669*0e209d39SAndroid Build Coastguard Worker     bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return true;}
670*0e209d39SAndroid Build Coastguard Worker     /* No ownership transfer: No copy constructor, no assignment operator. */
MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray &)671*0e209d39SAndroid Build Coastguard Worker     MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
672*0e209d39SAndroid Build Coastguard Worker     void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
673*0e209d39SAndroid Build Coastguard Worker };
674*0e209d39SAndroid Build Coastguard Worker 
675*0e209d39SAndroid Build Coastguard Worker template<typename H, typename T, int32_t stackCapacity>
resize(int32_t newCapacity,int32_t length)676*0e209d39SAndroid Build Coastguard Worker inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
677*0e209d39SAndroid Build Coastguard Worker                                                                 int32_t length) {
678*0e209d39SAndroid Build Coastguard Worker     if(newCapacity>=0) {
679*0e209d39SAndroid Build Coastguard Worker #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
680*0e209d39SAndroid Build Coastguard Worker       ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
681*0e209d39SAndroid Build Coastguard Worker #endif
682*0e209d39SAndroid Build Coastguard Worker         H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
683*0e209d39SAndroid Build Coastguard Worker         if(p!=nullptr) {
684*0e209d39SAndroid Build Coastguard Worker             if(length<0) {
685*0e209d39SAndroid Build Coastguard Worker                 length=0;
686*0e209d39SAndroid Build Coastguard Worker             } else if(length>0) {
687*0e209d39SAndroid Build Coastguard Worker                 if(length>capacity) {
688*0e209d39SAndroid Build Coastguard Worker                     length=capacity;
689*0e209d39SAndroid Build Coastguard Worker                 }
690*0e209d39SAndroid Build Coastguard Worker                 if(length>newCapacity) {
691*0e209d39SAndroid Build Coastguard Worker                     length=newCapacity;
692*0e209d39SAndroid Build Coastguard Worker                 }
693*0e209d39SAndroid Build Coastguard Worker             }
694*0e209d39SAndroid Build Coastguard Worker             uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
695*0e209d39SAndroid Build Coastguard Worker             releaseMemory();
696*0e209d39SAndroid Build Coastguard Worker             ptr=p;
697*0e209d39SAndroid Build Coastguard Worker             capacity=newCapacity;
698*0e209d39SAndroid Build Coastguard Worker             needToRelease=true;
699*0e209d39SAndroid Build Coastguard Worker         }
700*0e209d39SAndroid Build Coastguard Worker         return p;
701*0e209d39SAndroid Build Coastguard Worker     } else {
702*0e209d39SAndroid Build Coastguard Worker         return nullptr;
703*0e209d39SAndroid Build Coastguard Worker     }
704*0e209d39SAndroid Build Coastguard Worker }
705*0e209d39SAndroid Build Coastguard Worker 
706*0e209d39SAndroid Build Coastguard Worker template<typename H, typename T, int32_t stackCapacity>
orphanOrClone(int32_t length,int32_t & resultCapacity)707*0e209d39SAndroid Build Coastguard Worker inline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
708*0e209d39SAndroid Build Coastguard Worker                                                                        int32_t &resultCapacity) {
709*0e209d39SAndroid Build Coastguard Worker     H *p;
710*0e209d39SAndroid Build Coastguard Worker     if(needToRelease) {
711*0e209d39SAndroid Build Coastguard Worker         p=ptr;
712*0e209d39SAndroid Build Coastguard Worker     } else {
713*0e209d39SAndroid Build Coastguard Worker         if(length<0) {
714*0e209d39SAndroid Build Coastguard Worker             length=0;
715*0e209d39SAndroid Build Coastguard Worker         } else if(length>capacity) {
716*0e209d39SAndroid Build Coastguard Worker             length=capacity;
717*0e209d39SAndroid Build Coastguard Worker         }
718*0e209d39SAndroid Build Coastguard Worker #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
719*0e209d39SAndroid Build Coastguard Worker       ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
720*0e209d39SAndroid Build Coastguard Worker #endif
721*0e209d39SAndroid Build Coastguard Worker         p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
722*0e209d39SAndroid Build Coastguard Worker         if(p==nullptr) {
723*0e209d39SAndroid Build Coastguard Worker             return nullptr;
724*0e209d39SAndroid Build Coastguard Worker         }
725*0e209d39SAndroid Build Coastguard Worker         uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
726*0e209d39SAndroid Build Coastguard Worker     }
727*0e209d39SAndroid Build Coastguard Worker     resultCapacity=length;
728*0e209d39SAndroid Build Coastguard Worker     ptr=&stackHeader;
729*0e209d39SAndroid Build Coastguard Worker     capacity=stackCapacity;
730*0e209d39SAndroid Build Coastguard Worker     needToRelease=false;
731*0e209d39SAndroid Build Coastguard Worker     return p;
732*0e209d39SAndroid Build Coastguard Worker }
733*0e209d39SAndroid Build Coastguard Worker 
734*0e209d39SAndroid Build Coastguard Worker /**
735*0e209d39SAndroid Build Coastguard Worker  * A simple memory management class that creates new heap allocated objects (of
736*0e209d39SAndroid Build Coastguard Worker  * any class that has a public constructor), keeps track of them and eventually
737*0e209d39SAndroid Build Coastguard Worker  * deletes them all in its own destructor.
738*0e209d39SAndroid Build Coastguard Worker  *
739*0e209d39SAndroid Build Coastguard Worker  * A typical use-case would be code like this:
740*0e209d39SAndroid Build Coastguard Worker  *
741*0e209d39SAndroid Build Coastguard Worker  *     MemoryPool<MyType> pool;
742*0e209d39SAndroid Build Coastguard Worker  *
743*0e209d39SAndroid Build Coastguard Worker  *     MyType* o1 = pool.create();
744*0e209d39SAndroid Build Coastguard Worker  *     if (o1 != nullptr) {
745*0e209d39SAndroid Build Coastguard Worker  *         foo(o1);
746*0e209d39SAndroid Build Coastguard Worker  *     }
747*0e209d39SAndroid Build Coastguard Worker  *
748*0e209d39SAndroid Build Coastguard Worker  *     MyType* o2 = pool.create(1, 2, 3);
749*0e209d39SAndroid Build Coastguard Worker  *     if (o2 != nullptr) {
750*0e209d39SAndroid Build Coastguard Worker  *         bar(o2);
751*0e209d39SAndroid Build Coastguard Worker  *     }
752*0e209d39SAndroid Build Coastguard Worker  *
753*0e209d39SAndroid Build Coastguard Worker  *     // MemoryPool will take care of deleting the MyType objects.
754*0e209d39SAndroid Build Coastguard Worker  *
755*0e209d39SAndroid Build Coastguard Worker  * It doesn't do anything more than that, and is intentionally kept minimalist.
756*0e209d39SAndroid Build Coastguard Worker  */
757*0e209d39SAndroid Build Coastguard Worker template<typename T, int32_t stackCapacity = 8>
758*0e209d39SAndroid Build Coastguard Worker class MemoryPool : public UMemory {
759*0e209d39SAndroid Build Coastguard Worker public:
MemoryPool()760*0e209d39SAndroid Build Coastguard Worker     MemoryPool() : fCount(0), fPool() {}
761*0e209d39SAndroid Build Coastguard Worker 
~MemoryPool()762*0e209d39SAndroid Build Coastguard Worker     ~MemoryPool() {
763*0e209d39SAndroid Build Coastguard Worker         for (int32_t i = 0; i < fCount; ++i) {
764*0e209d39SAndroid Build Coastguard Worker             delete fPool[i];
765*0e209d39SAndroid Build Coastguard Worker         }
766*0e209d39SAndroid Build Coastguard Worker     }
767*0e209d39SAndroid Build Coastguard Worker 
768*0e209d39SAndroid Build Coastguard Worker     MemoryPool(const MemoryPool&) = delete;
769*0e209d39SAndroid Build Coastguard Worker     MemoryPool& operator=(const MemoryPool&) = delete;
770*0e209d39SAndroid Build Coastguard Worker 
MemoryPool(MemoryPool && other)771*0e209d39SAndroid Build Coastguard Worker     MemoryPool(MemoryPool&& other) noexcept : fCount(other.fCount),
772*0e209d39SAndroid Build Coastguard Worker                                                 fPool(std::move(other.fPool)) {
773*0e209d39SAndroid Build Coastguard Worker         other.fCount = 0;
774*0e209d39SAndroid Build Coastguard Worker     }
775*0e209d39SAndroid Build Coastguard Worker 
776*0e209d39SAndroid Build Coastguard Worker     MemoryPool& operator=(MemoryPool&& other) noexcept {
777*0e209d39SAndroid Build Coastguard Worker         // Since `this` may contain instances that need to be deleted, we can't
778*0e209d39SAndroid Build Coastguard Worker         // just throw them away and replace them with `other`. The normal way of
779*0e209d39SAndroid Build Coastguard Worker         // dealing with this in C++ is to swap `this` and `other`, rather than
780*0e209d39SAndroid Build Coastguard Worker         // simply overwrite: the destruction of `other` can then take care of
781*0e209d39SAndroid Build Coastguard Worker         // running MemoryPool::~MemoryPool() over the still-to-be-deallocated
782*0e209d39SAndroid Build Coastguard Worker         // instances.
783*0e209d39SAndroid Build Coastguard Worker         std::swap(fCount, other.fCount);
784*0e209d39SAndroid Build Coastguard Worker         std::swap(fPool, other.fPool);
785*0e209d39SAndroid Build Coastguard Worker         return *this;
786*0e209d39SAndroid Build Coastguard Worker     }
787*0e209d39SAndroid Build Coastguard Worker 
788*0e209d39SAndroid Build Coastguard Worker     /**
789*0e209d39SAndroid Build Coastguard Worker      * Creates a new object of typename T, by forwarding any and all arguments
790*0e209d39SAndroid Build Coastguard Worker      * to the typename T constructor.
791*0e209d39SAndroid Build Coastguard Worker      *
792*0e209d39SAndroid Build Coastguard Worker      * @param args Arguments to be forwarded to the typename T constructor.
793*0e209d39SAndroid Build Coastguard Worker      * @return A pointer to the newly created object, or nullptr on error.
794*0e209d39SAndroid Build Coastguard Worker      */
795*0e209d39SAndroid Build Coastguard Worker     template<typename... Args>
create(Args &&...args)796*0e209d39SAndroid Build Coastguard Worker     T* create(Args&&... args) {
797*0e209d39SAndroid Build Coastguard Worker         int32_t capacity = fPool.getCapacity();
798*0e209d39SAndroid Build Coastguard Worker         if (fCount == capacity &&
799*0e209d39SAndroid Build Coastguard Worker             fPool.resize(capacity == stackCapacity ? 4 * capacity : 2 * capacity,
800*0e209d39SAndroid Build Coastguard Worker                          capacity) == nullptr) {
801*0e209d39SAndroid Build Coastguard Worker             return nullptr;
802*0e209d39SAndroid Build Coastguard Worker         }
803*0e209d39SAndroid Build Coastguard Worker         return fPool[fCount++] = new T(std::forward<Args>(args)...);
804*0e209d39SAndroid Build Coastguard Worker     }
805*0e209d39SAndroid Build Coastguard Worker 
806*0e209d39SAndroid Build Coastguard Worker     template <typename... Args>
createAndCheckErrorCode(UErrorCode & status,Args &&...args)807*0e209d39SAndroid Build Coastguard Worker     T* createAndCheckErrorCode(UErrorCode &status, Args &&... args) {
808*0e209d39SAndroid Build Coastguard Worker         if (U_FAILURE(status)) {
809*0e209d39SAndroid Build Coastguard Worker             return nullptr;
810*0e209d39SAndroid Build Coastguard Worker         }
811*0e209d39SAndroid Build Coastguard Worker         T *pointer = this->create(args...);
812*0e209d39SAndroid Build Coastguard Worker         if (U_SUCCESS(status) && pointer == nullptr) {
813*0e209d39SAndroid Build Coastguard Worker             status = U_MEMORY_ALLOCATION_ERROR;
814*0e209d39SAndroid Build Coastguard Worker         }
815*0e209d39SAndroid Build Coastguard Worker         return pointer;
816*0e209d39SAndroid Build Coastguard Worker     }
817*0e209d39SAndroid Build Coastguard Worker 
818*0e209d39SAndroid Build Coastguard Worker     /**
819*0e209d39SAndroid Build Coastguard Worker      * @return Number of elements that have been allocated.
820*0e209d39SAndroid Build Coastguard Worker      */
count()821*0e209d39SAndroid Build Coastguard Worker     int32_t count() const {
822*0e209d39SAndroid Build Coastguard Worker         return fCount;
823*0e209d39SAndroid Build Coastguard Worker     }
824*0e209d39SAndroid Build Coastguard Worker 
825*0e209d39SAndroid Build Coastguard Worker protected:
826*0e209d39SAndroid Build Coastguard Worker     int32_t fCount;
827*0e209d39SAndroid Build Coastguard Worker     MaybeStackArray<T*, stackCapacity> fPool;
828*0e209d39SAndroid Build Coastguard Worker };
829*0e209d39SAndroid Build Coastguard Worker 
830*0e209d39SAndroid Build Coastguard Worker /**
831*0e209d39SAndroid Build Coastguard Worker  * An internal Vector-like implementation based on MemoryPool.
832*0e209d39SAndroid Build Coastguard Worker  *
833*0e209d39SAndroid Build Coastguard Worker  * Heap-allocates each element and stores pointers.
834*0e209d39SAndroid Build Coastguard Worker  *
835*0e209d39SAndroid Build Coastguard Worker  * To append an item to the vector, use emplaceBack.
836*0e209d39SAndroid Build Coastguard Worker  *
837*0e209d39SAndroid Build Coastguard Worker  *     MaybeStackVector<MyType> vector;
838*0e209d39SAndroid Build Coastguard Worker  *     MyType* element = vector.emplaceBack();
839*0e209d39SAndroid Build Coastguard Worker  *     if (!element) {
840*0e209d39SAndroid Build Coastguard Worker  *         status = U_MEMORY_ALLOCATION_ERROR;
841*0e209d39SAndroid Build Coastguard Worker  *     }
842*0e209d39SAndroid Build Coastguard Worker  *     // do stuff with element
843*0e209d39SAndroid Build Coastguard Worker  *
844*0e209d39SAndroid Build Coastguard Worker  * To loop over the vector, use a for loop with indices:
845*0e209d39SAndroid Build Coastguard Worker  *
846*0e209d39SAndroid Build Coastguard Worker  *     for (int32_t i = 0; i < vector.length(); i++) {
847*0e209d39SAndroid Build Coastguard Worker  *         MyType* element = vector[i];
848*0e209d39SAndroid Build Coastguard Worker  *     }
849*0e209d39SAndroid Build Coastguard Worker  */
850*0e209d39SAndroid Build Coastguard Worker template<typename T, int32_t stackCapacity = 8>
851*0e209d39SAndroid Build Coastguard Worker class MaybeStackVector : protected MemoryPool<T, stackCapacity> {
852*0e209d39SAndroid Build Coastguard Worker public:
853*0e209d39SAndroid Build Coastguard Worker     template<typename... Args>
emplaceBack(Args &&...args)854*0e209d39SAndroid Build Coastguard Worker     T* emplaceBack(Args&&... args) {
855*0e209d39SAndroid Build Coastguard Worker         return this->create(args...);
856*0e209d39SAndroid Build Coastguard Worker     }
857*0e209d39SAndroid Build Coastguard Worker 
858*0e209d39SAndroid Build Coastguard Worker     template <typename... Args>
emplaceBackAndCheckErrorCode(UErrorCode & status,Args &&...args)859*0e209d39SAndroid Build Coastguard Worker     T *emplaceBackAndCheckErrorCode(UErrorCode &status, Args &&... args) {
860*0e209d39SAndroid Build Coastguard Worker         return this->createAndCheckErrorCode(status, args...);
861*0e209d39SAndroid Build Coastguard Worker     }
862*0e209d39SAndroid Build Coastguard Worker 
length()863*0e209d39SAndroid Build Coastguard Worker     int32_t length() const {
864*0e209d39SAndroid Build Coastguard Worker         return this->fCount;
865*0e209d39SAndroid Build Coastguard Worker     }
866*0e209d39SAndroid Build Coastguard Worker 
getAlias()867*0e209d39SAndroid Build Coastguard Worker     T** getAlias() {
868*0e209d39SAndroid Build Coastguard Worker         return this->fPool.getAlias();
869*0e209d39SAndroid Build Coastguard Worker     }
870*0e209d39SAndroid Build Coastguard Worker 
getAlias()871*0e209d39SAndroid Build Coastguard Worker     const T *const *getAlias() const {
872*0e209d39SAndroid Build Coastguard Worker         return this->fPool.getAlias();
873*0e209d39SAndroid Build Coastguard Worker     }
874*0e209d39SAndroid Build Coastguard Worker 
875*0e209d39SAndroid Build Coastguard Worker     /**
876*0e209d39SAndroid Build Coastguard Worker      * Array item access (read-only).
877*0e209d39SAndroid Build Coastguard Worker      * No index bounds check.
878*0e209d39SAndroid Build Coastguard Worker      * @param i array index
879*0e209d39SAndroid Build Coastguard Worker      * @return reference to the array item
880*0e209d39SAndroid Build Coastguard Worker      */
881*0e209d39SAndroid Build Coastguard Worker     const T* operator[](ptrdiff_t i) const {
882*0e209d39SAndroid Build Coastguard Worker         return this->fPool[i];
883*0e209d39SAndroid Build Coastguard Worker     }
884*0e209d39SAndroid Build Coastguard Worker 
885*0e209d39SAndroid Build Coastguard Worker     /**
886*0e209d39SAndroid Build Coastguard Worker      * Array item access (writable).
887*0e209d39SAndroid Build Coastguard Worker      * No index bounds check.
888*0e209d39SAndroid Build Coastguard Worker      * @param i array index
889*0e209d39SAndroid Build Coastguard Worker      * @return reference to the array item
890*0e209d39SAndroid Build Coastguard Worker      */
891*0e209d39SAndroid Build Coastguard Worker     T* operator[](ptrdiff_t i) {
892*0e209d39SAndroid Build Coastguard Worker         return this->fPool[i];
893*0e209d39SAndroid Build Coastguard Worker     }
894*0e209d39SAndroid Build Coastguard Worker };
895*0e209d39SAndroid Build Coastguard Worker 
896*0e209d39SAndroid Build Coastguard Worker 
897*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END
898*0e209d39SAndroid Build Coastguard Worker 
899*0e209d39SAndroid Build Coastguard Worker #endif  /* __cplusplus */
900*0e209d39SAndroid Build Coastguard Worker #endif  /* CMEMORY_H */
901