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