11cb0ef41Sopenharmony_ci// © 2016 and later: Unicode, Inc. and others.
21cb0ef41Sopenharmony_ci// License & terms of use: http://www.unicode.org/copyright.html
31cb0ef41Sopenharmony_ci/*
41cb0ef41Sopenharmony_ci******************************************************************************
51cb0ef41Sopenharmony_ci*
61cb0ef41Sopenharmony_ci*   Copyright (C) 1997-2016, International Business Machines
71cb0ef41Sopenharmony_ci*   Corporation and others.  All Rights Reserved.
81cb0ef41Sopenharmony_ci*
91cb0ef41Sopenharmony_ci******************************************************************************
101cb0ef41Sopenharmony_ci*
111cb0ef41Sopenharmony_ci* File CMEMORY.H
121cb0ef41Sopenharmony_ci*
131cb0ef41Sopenharmony_ci*  Contains stdlib.h/string.h memory functions
141cb0ef41Sopenharmony_ci*
151cb0ef41Sopenharmony_ci* @author       Bertrand A. Damiba
161cb0ef41Sopenharmony_ci*
171cb0ef41Sopenharmony_ci* Modification History:
181cb0ef41Sopenharmony_ci*
191cb0ef41Sopenharmony_ci*   Date        Name        Description
201cb0ef41Sopenharmony_ci*   6/20/98     Bertrand    Created.
211cb0ef41Sopenharmony_ci*  05/03/99     stephen     Changed from functions to macros.
221cb0ef41Sopenharmony_ci*
231cb0ef41Sopenharmony_ci******************************************************************************
241cb0ef41Sopenharmony_ci*/
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci#ifndef CMEMORY_H
271cb0ef41Sopenharmony_ci#define CMEMORY_H
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci#include "unicode/utypes.h"
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci#include <stddef.h>
321cb0ef41Sopenharmony_ci#include <string.h>
331cb0ef41Sopenharmony_ci#include "unicode/localpointer.h"
341cb0ef41Sopenharmony_ci#include "uassert.h"
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
371cb0ef41Sopenharmony_ci#include <stdio.h>
381cb0ef41Sopenharmony_ci#endif
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci// uprv_memcpy and uprv_memmove
411cb0ef41Sopenharmony_ci#if defined(__clang__)
421cb0ef41Sopenharmony_ci#define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
431cb0ef41Sopenharmony_ci    /* Suppress warnings about addresses that will never be NULL */ \
441cb0ef41Sopenharmony_ci    _Pragma("clang diagnostic push") \
451cb0ef41Sopenharmony_ci    _Pragma("clang diagnostic ignored \"-Waddress\"") \
461cb0ef41Sopenharmony_ci    U_ASSERT(dst != NULL); \
471cb0ef41Sopenharmony_ci    U_ASSERT(src != NULL); \
481cb0ef41Sopenharmony_ci    _Pragma("clang diagnostic pop") \
491cb0ef41Sopenharmony_ci    U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \
501cb0ef41Sopenharmony_ci} UPRV_BLOCK_MACRO_END
511cb0ef41Sopenharmony_ci#define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
521cb0ef41Sopenharmony_ci    /* Suppress warnings about addresses that will never be NULL */ \
531cb0ef41Sopenharmony_ci    _Pragma("clang diagnostic push") \
541cb0ef41Sopenharmony_ci    _Pragma("clang diagnostic ignored \"-Waddress\"") \
551cb0ef41Sopenharmony_ci    U_ASSERT(dst != NULL); \
561cb0ef41Sopenharmony_ci    U_ASSERT(src != NULL); \
571cb0ef41Sopenharmony_ci    _Pragma("clang diagnostic pop") \
581cb0ef41Sopenharmony_ci    U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \
591cb0ef41Sopenharmony_ci} UPRV_BLOCK_MACRO_END
601cb0ef41Sopenharmony_ci#elif defined(__GNUC__)
611cb0ef41Sopenharmony_ci#define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
621cb0ef41Sopenharmony_ci    /* Suppress warnings about addresses that will never be NULL */ \
631cb0ef41Sopenharmony_ci    _Pragma("GCC diagnostic push") \
641cb0ef41Sopenharmony_ci    _Pragma("GCC diagnostic ignored \"-Waddress\"") \
651cb0ef41Sopenharmony_ci    U_ASSERT(dst != NULL); \
661cb0ef41Sopenharmony_ci    U_ASSERT(src != NULL); \
671cb0ef41Sopenharmony_ci    _Pragma("GCC diagnostic pop") \
681cb0ef41Sopenharmony_ci    U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \
691cb0ef41Sopenharmony_ci} UPRV_BLOCK_MACRO_END
701cb0ef41Sopenharmony_ci#define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
711cb0ef41Sopenharmony_ci    /* Suppress warnings about addresses that will never be NULL */ \
721cb0ef41Sopenharmony_ci    _Pragma("GCC diagnostic push") \
731cb0ef41Sopenharmony_ci    _Pragma("GCC diagnostic ignored \"-Waddress\"") \
741cb0ef41Sopenharmony_ci    U_ASSERT(dst != NULL); \
751cb0ef41Sopenharmony_ci    U_ASSERT(src != NULL); \
761cb0ef41Sopenharmony_ci    _Pragma("GCC diagnostic pop") \
771cb0ef41Sopenharmony_ci    U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \
781cb0ef41Sopenharmony_ci} UPRV_BLOCK_MACRO_END
791cb0ef41Sopenharmony_ci#else
801cb0ef41Sopenharmony_ci#define uprv_memcpy(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
811cb0ef41Sopenharmony_ci    U_ASSERT(dst != NULL); \
821cb0ef41Sopenharmony_ci    U_ASSERT(src != NULL); \
831cb0ef41Sopenharmony_ci    U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size); \
841cb0ef41Sopenharmony_ci} UPRV_BLOCK_MACRO_END
851cb0ef41Sopenharmony_ci#define uprv_memmove(dst, src, size) UPRV_BLOCK_MACRO_BEGIN { \
861cb0ef41Sopenharmony_ci    U_ASSERT(dst != NULL); \
871cb0ef41Sopenharmony_ci    U_ASSERT(src != NULL); \
881cb0ef41Sopenharmony_ci    U_STANDARD_CPP_NAMESPACE memmove(dst, src, size); \
891cb0ef41Sopenharmony_ci} UPRV_BLOCK_MACRO_END
901cb0ef41Sopenharmony_ci#endif
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci/**
931cb0ef41Sopenharmony_ci * \def UPRV_LENGTHOF
941cb0ef41Sopenharmony_ci * Convenience macro to determine the length of a fixed array at compile-time.
951cb0ef41Sopenharmony_ci * @param array A fixed length array
961cb0ef41Sopenharmony_ci * @return The length of the array, in elements
971cb0ef41Sopenharmony_ci * @internal
981cb0ef41Sopenharmony_ci */
991cb0ef41Sopenharmony_ci#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
1001cb0ef41Sopenharmony_ci#define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
1011cb0ef41Sopenharmony_ci#define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
1021cb0ef41Sopenharmony_ci#define uprv_memchr(ptr, value, num) U_STANDARD_CPP_NAMESPACE memchr(ptr, value, num)
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ciU_CAPI void * U_EXPORT2
1051cb0ef41Sopenharmony_ciuprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ciU_CAPI void * U_EXPORT2
1081cb0ef41Sopenharmony_ciuprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
1111cb0ef41Sopenharmony_ciuprv_free(void *mem);
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ciU_CAPI void * U_EXPORT2
1141cb0ef41Sopenharmony_ciuprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ci/**
1171cb0ef41Sopenharmony_ci * Get the least significant bits of a pointer (a memory address).
1181cb0ef41Sopenharmony_ci * For example, with a mask of 3, the macro gets the 2 least significant bits,
1191cb0ef41Sopenharmony_ci * which will be 0 if the pointer is 32-bit (4-byte) aligned.
1201cb0ef41Sopenharmony_ci *
1211cb0ef41Sopenharmony_ci * uintptr_t is the most appropriate integer type to cast to.
1221cb0ef41Sopenharmony_ci */
1231cb0ef41Sopenharmony_ci#define U_POINTER_MASK_LSB(ptr, mask) ((uintptr_t)(ptr) & (mask))
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci/**
1261cb0ef41Sopenharmony_ci * Create & return an instance of "type" in statically allocated storage.
1271cb0ef41Sopenharmony_ci * e.g.
1281cb0ef41Sopenharmony_ci *    static std::mutex *myMutex = STATIC_NEW(std::mutex);
1291cb0ef41Sopenharmony_ci * To destroy an object created in this way, invoke the destructor explicitly, e.g.
1301cb0ef41Sopenharmony_ci *    myMutex->~mutex();
1311cb0ef41Sopenharmony_ci * DO NOT use delete.
1321cb0ef41Sopenharmony_ci * DO NOT use with class UMutex, which has specific support for static instances.
1331cb0ef41Sopenharmony_ci *
1341cb0ef41Sopenharmony_ci * STATIC_NEW is intended for use when
1351cb0ef41Sopenharmony_ci *   - We want a static (or global) object.
1361cb0ef41Sopenharmony_ci *   - We don't want it to ever be destructed, or to explicitly control destruction,
1371cb0ef41Sopenharmony_ci *     to avoid use-after-destruction problems.
1381cb0ef41Sopenharmony_ci *   - We want to avoid an ordinary heap allocated object,
1391cb0ef41Sopenharmony_ci *     to avoid the possibility of memory allocation failures, and
1401cb0ef41Sopenharmony_ci *     to avoid memory leak reports, from valgrind, for example.
1411cb0ef41Sopenharmony_ci * This is defined as a macro rather than a template function because each invocation
1421cb0ef41Sopenharmony_ci * must define distinct static storage for the object being returned.
1431cb0ef41Sopenharmony_ci */
1441cb0ef41Sopenharmony_ci#define STATIC_NEW(type) [] () { \
1451cb0ef41Sopenharmony_ci    alignas(type) static char storage[sizeof(type)]; \
1461cb0ef41Sopenharmony_ci    return new(storage) type();} ()
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci/**
1491cb0ef41Sopenharmony_ci  *  Heap clean up function, called from u_cleanup()
1501cb0ef41Sopenharmony_ci  *    Clears any user heap functions from u_setMemoryFunctions()
1511cb0ef41Sopenharmony_ci  *    Does NOT deallocate any remaining allocated memory.
1521cb0ef41Sopenharmony_ci  */
1531cb0ef41Sopenharmony_ciU_CFUNC UBool
1541cb0ef41Sopenharmony_cicmemory_cleanup(void);
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci/**
1571cb0ef41Sopenharmony_ci * A function called by <TT>uhash_remove</TT>,
1581cb0ef41Sopenharmony_ci * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
1591cb0ef41Sopenharmony_ci * an existing key or value.
1601cb0ef41Sopenharmony_ci * @param obj A key or value stored in a hashtable
1611cb0ef41Sopenharmony_ci * @see uprv_deleteUObject
1621cb0ef41Sopenharmony_ci */
1631cb0ef41Sopenharmony_citypedef void U_CALLCONV UObjectDeleter(void* obj);
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci/**
1661cb0ef41Sopenharmony_ci * Deleter for UObject instances.
1671cb0ef41Sopenharmony_ci * Works for all subclasses of UObject because it has a virtual destructor.
1681cb0ef41Sopenharmony_ci */
1691cb0ef41Sopenharmony_ciU_CAPI void U_EXPORT2
1701cb0ef41Sopenharmony_ciuprv_deleteUObject(void *obj);
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci#ifdef __cplusplus
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci#include <utility>
1751cb0ef41Sopenharmony_ci#include "unicode/uobject.h"
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ciU_NAMESPACE_BEGIN
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci/**
1801cb0ef41Sopenharmony_ci * "Smart pointer" class, deletes memory via uprv_free().
1811cb0ef41Sopenharmony_ci * For most methods see the LocalPointerBase base class.
1821cb0ef41Sopenharmony_ci * Adds operator[] for array item access.
1831cb0ef41Sopenharmony_ci *
1841cb0ef41Sopenharmony_ci * @see LocalPointerBase
1851cb0ef41Sopenharmony_ci */
1861cb0ef41Sopenharmony_citemplate<typename T>
1871cb0ef41Sopenharmony_ciclass LocalMemory : public LocalPointerBase<T> {
1881cb0ef41Sopenharmony_cipublic:
1891cb0ef41Sopenharmony_ci    using LocalPointerBase<T>::operator*;
1901cb0ef41Sopenharmony_ci    using LocalPointerBase<T>::operator->;
1911cb0ef41Sopenharmony_ci    /**
1921cb0ef41Sopenharmony_ci     * Constructor takes ownership.
1931cb0ef41Sopenharmony_ci     * @param p simple pointer to an array of T items that is adopted
1941cb0ef41Sopenharmony_ci     */
1951cb0ef41Sopenharmony_ci    explicit LocalMemory(T *p=nullptr) : LocalPointerBase<T>(p) {}
1961cb0ef41Sopenharmony_ci    /**
1971cb0ef41Sopenharmony_ci     * Move constructor, leaves src with isNull().
1981cb0ef41Sopenharmony_ci     * @param src source smart pointer
1991cb0ef41Sopenharmony_ci     */
2001cb0ef41Sopenharmony_ci    LocalMemory(LocalMemory<T> &&src) noexcept : LocalPointerBase<T>(src.ptr) {
2011cb0ef41Sopenharmony_ci        src.ptr=nullptr;
2021cb0ef41Sopenharmony_ci    }
2031cb0ef41Sopenharmony_ci    /**
2041cb0ef41Sopenharmony_ci     * Destructor deletes the memory it owns.
2051cb0ef41Sopenharmony_ci     */
2061cb0ef41Sopenharmony_ci    ~LocalMemory() {
2071cb0ef41Sopenharmony_ci        uprv_free(LocalPointerBase<T>::ptr);
2081cb0ef41Sopenharmony_ci    }
2091cb0ef41Sopenharmony_ci    /**
2101cb0ef41Sopenharmony_ci     * Move assignment operator, leaves src with isNull().
2111cb0ef41Sopenharmony_ci     * The behavior is undefined if *this and src are the same object.
2121cb0ef41Sopenharmony_ci     * @param src source smart pointer
2131cb0ef41Sopenharmony_ci     * @return *this
2141cb0ef41Sopenharmony_ci     */
2151cb0ef41Sopenharmony_ci    LocalMemory<T> &operator=(LocalMemory<T> &&src) noexcept {
2161cb0ef41Sopenharmony_ci        uprv_free(LocalPointerBase<T>::ptr);
2171cb0ef41Sopenharmony_ci        LocalPointerBase<T>::ptr=src.ptr;
2181cb0ef41Sopenharmony_ci        src.ptr=nullptr;
2191cb0ef41Sopenharmony_ci        return *this;
2201cb0ef41Sopenharmony_ci    }
2211cb0ef41Sopenharmony_ci    /**
2221cb0ef41Sopenharmony_ci     * Swap pointers.
2231cb0ef41Sopenharmony_ci     * @param other other smart pointer
2241cb0ef41Sopenharmony_ci     */
2251cb0ef41Sopenharmony_ci    void swap(LocalMemory<T> &other) noexcept {
2261cb0ef41Sopenharmony_ci        T *temp=LocalPointerBase<T>::ptr;
2271cb0ef41Sopenharmony_ci        LocalPointerBase<T>::ptr=other.ptr;
2281cb0ef41Sopenharmony_ci        other.ptr=temp;
2291cb0ef41Sopenharmony_ci    }
2301cb0ef41Sopenharmony_ci    /**
2311cb0ef41Sopenharmony_ci     * Non-member LocalMemory swap function.
2321cb0ef41Sopenharmony_ci     * @param p1 will get p2's pointer
2331cb0ef41Sopenharmony_ci     * @param p2 will get p1's pointer
2341cb0ef41Sopenharmony_ci     */
2351cb0ef41Sopenharmony_ci    friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) noexcept {
2361cb0ef41Sopenharmony_ci        p1.swap(p2);
2371cb0ef41Sopenharmony_ci    }
2381cb0ef41Sopenharmony_ci    /**
2391cb0ef41Sopenharmony_ci     * Deletes the array it owns,
2401cb0ef41Sopenharmony_ci     * and adopts (takes ownership of) the one passed in.
2411cb0ef41Sopenharmony_ci     * @param p simple pointer to an array of T items that is adopted
2421cb0ef41Sopenharmony_ci     */
2431cb0ef41Sopenharmony_ci    void adoptInstead(T *p) {
2441cb0ef41Sopenharmony_ci        uprv_free(LocalPointerBase<T>::ptr);
2451cb0ef41Sopenharmony_ci        LocalPointerBase<T>::ptr=p;
2461cb0ef41Sopenharmony_ci    }
2471cb0ef41Sopenharmony_ci    /**
2481cb0ef41Sopenharmony_ci     * Deletes the array it owns, allocates a new one and reset its bytes to 0.
2491cb0ef41Sopenharmony_ci     * Returns the new array pointer.
2501cb0ef41Sopenharmony_ci     * If the allocation fails, then the current array is unchanged and
2511cb0ef41Sopenharmony_ci     * this method returns nullptr.
2521cb0ef41Sopenharmony_ci     * @param newCapacity must be >0
2531cb0ef41Sopenharmony_ci     * @return the allocated array pointer, or nullptr if the allocation failed
2541cb0ef41Sopenharmony_ci     */
2551cb0ef41Sopenharmony_ci    inline T *allocateInsteadAndReset(int32_t newCapacity=1);
2561cb0ef41Sopenharmony_ci    /**
2571cb0ef41Sopenharmony_ci     * Deletes the array it owns and allocates a new one, copying length T items.
2581cb0ef41Sopenharmony_ci     * Returns the new array pointer.
2591cb0ef41Sopenharmony_ci     * If the allocation fails, then the current array is unchanged and
2601cb0ef41Sopenharmony_ci     * this method returns nullptr.
2611cb0ef41Sopenharmony_ci     * @param newCapacity must be >0
2621cb0ef41Sopenharmony_ci     * @param length number of T items to be copied from the old array to the new one;
2631cb0ef41Sopenharmony_ci     *               must be no more than the capacity of the old array,
2641cb0ef41Sopenharmony_ci     *               which the caller must track because the LocalMemory does not track it
2651cb0ef41Sopenharmony_ci     * @return the allocated array pointer, or nullptr if the allocation failed
2661cb0ef41Sopenharmony_ci     */
2671cb0ef41Sopenharmony_ci    inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
2681cb0ef41Sopenharmony_ci    /**
2691cb0ef41Sopenharmony_ci     * Array item access (writable).
2701cb0ef41Sopenharmony_ci     * No index bounds check.
2711cb0ef41Sopenharmony_ci     * @param i array index
2721cb0ef41Sopenharmony_ci     * @return reference to the array item
2731cb0ef41Sopenharmony_ci     */
2741cb0ef41Sopenharmony_ci    T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
2751cb0ef41Sopenharmony_ci};
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_citemplate<typename T>
2781cb0ef41Sopenharmony_ciinline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
2791cb0ef41Sopenharmony_ci    if(newCapacity>0) {
2801cb0ef41Sopenharmony_ci        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
2811cb0ef41Sopenharmony_ci        if(p!=nullptr) {
2821cb0ef41Sopenharmony_ci            uprv_memset(p, 0, newCapacity*sizeof(T));
2831cb0ef41Sopenharmony_ci            uprv_free(LocalPointerBase<T>::ptr);
2841cb0ef41Sopenharmony_ci            LocalPointerBase<T>::ptr=p;
2851cb0ef41Sopenharmony_ci        }
2861cb0ef41Sopenharmony_ci        return p;
2871cb0ef41Sopenharmony_ci    } else {
2881cb0ef41Sopenharmony_ci        return nullptr;
2891cb0ef41Sopenharmony_ci    }
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_citemplate<typename T>
2941cb0ef41Sopenharmony_ciinline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
2951cb0ef41Sopenharmony_ci    if(newCapacity>0) {
2961cb0ef41Sopenharmony_ci        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
2971cb0ef41Sopenharmony_ci        if(p!=nullptr) {
2981cb0ef41Sopenharmony_ci            if(length>0) {
2991cb0ef41Sopenharmony_ci                if(length>newCapacity) {
3001cb0ef41Sopenharmony_ci                    length=newCapacity;
3011cb0ef41Sopenharmony_ci                }
3021cb0ef41Sopenharmony_ci                uprv_memcpy(p, LocalPointerBase<T>::ptr, (size_t)length*sizeof(T));
3031cb0ef41Sopenharmony_ci            }
3041cb0ef41Sopenharmony_ci            uprv_free(LocalPointerBase<T>::ptr);
3051cb0ef41Sopenharmony_ci            LocalPointerBase<T>::ptr=p;
3061cb0ef41Sopenharmony_ci        }
3071cb0ef41Sopenharmony_ci        return p;
3081cb0ef41Sopenharmony_ci    } else {
3091cb0ef41Sopenharmony_ci        return nullptr;
3101cb0ef41Sopenharmony_ci    }
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci/**
3141cb0ef41Sopenharmony_ci * Simple array/buffer management class using uprv_malloc() and uprv_free().
3151cb0ef41Sopenharmony_ci * Provides an internal array with fixed capacity. Can alias another array
3161cb0ef41Sopenharmony_ci * or allocate one.
3171cb0ef41Sopenharmony_ci *
3181cb0ef41Sopenharmony_ci * The array address is properly aligned for type T. It might not be properly
3191cb0ef41Sopenharmony_ci * aligned for types larger than T (or larger than the largest subtype of T).
3201cb0ef41Sopenharmony_ci *
3211cb0ef41Sopenharmony_ci * Unlike LocalMemory and LocalArray, this class never adopts
3221cb0ef41Sopenharmony_ci * (takes ownership of) another array.
3231cb0ef41Sopenharmony_ci *
3241cb0ef41Sopenharmony_ci * WARNING: MaybeStackArray only works with primitive (plain-old data) types.
3251cb0ef41Sopenharmony_ci * It does NOT know how to call a destructor! If you work with classes with
3261cb0ef41Sopenharmony_ci * destructors, consider:
3271cb0ef41Sopenharmony_ci *
3281cb0ef41Sopenharmony_ci * - LocalArray in localpointer.h if you know the length ahead of time
3291cb0ef41Sopenharmony_ci * - MaybeStackVector if you know the length at runtime
3301cb0ef41Sopenharmony_ci */
3311cb0ef41Sopenharmony_citemplate<typename T, int32_t stackCapacity>
3321cb0ef41Sopenharmony_ciclass MaybeStackArray {
3331cb0ef41Sopenharmony_cipublic:
3341cb0ef41Sopenharmony_ci    // No heap allocation. Use only on the stack.
3351cb0ef41Sopenharmony_ci    static void* U_EXPORT2 operator new(size_t) noexcept = delete;
3361cb0ef41Sopenharmony_ci    static void* U_EXPORT2 operator new[](size_t) noexcept = delete;
3371cb0ef41Sopenharmony_ci#if U_HAVE_PLACEMENT_NEW
3381cb0ef41Sopenharmony_ci    static void* U_EXPORT2 operator new(size_t, void*) noexcept = delete;
3391cb0ef41Sopenharmony_ci#endif
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci    /**
3421cb0ef41Sopenharmony_ci     * Default constructor initializes with internal T[stackCapacity] buffer.
3431cb0ef41Sopenharmony_ci     */
3441cb0ef41Sopenharmony_ci    MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(false) {}
3451cb0ef41Sopenharmony_ci    /**
3461cb0ef41Sopenharmony_ci     * Automatically allocates the heap array if the argument is larger than the stack capacity.
3471cb0ef41Sopenharmony_ci     * Intended for use when an approximate capacity is known at compile time but the true
3481cb0ef41Sopenharmony_ci     * capacity is not known until runtime.
3491cb0ef41Sopenharmony_ci     */
3501cb0ef41Sopenharmony_ci    MaybeStackArray(int32_t newCapacity, UErrorCode status) : MaybeStackArray() {
3511cb0ef41Sopenharmony_ci        if (U_FAILURE(status)) {
3521cb0ef41Sopenharmony_ci            return;
3531cb0ef41Sopenharmony_ci        }
3541cb0ef41Sopenharmony_ci        if (capacity < newCapacity) {
3551cb0ef41Sopenharmony_ci            if (resize(newCapacity) == nullptr) {
3561cb0ef41Sopenharmony_ci                status = U_MEMORY_ALLOCATION_ERROR;
3571cb0ef41Sopenharmony_ci            }
3581cb0ef41Sopenharmony_ci        }
3591cb0ef41Sopenharmony_ci    }
3601cb0ef41Sopenharmony_ci    /**
3611cb0ef41Sopenharmony_ci     * Destructor deletes the array (if owned).
3621cb0ef41Sopenharmony_ci     */
3631cb0ef41Sopenharmony_ci    ~MaybeStackArray() { releaseArray(); }
3641cb0ef41Sopenharmony_ci    /**
3651cb0ef41Sopenharmony_ci     * Move constructor: transfers ownership or copies the stack array.
3661cb0ef41Sopenharmony_ci     */
3671cb0ef41Sopenharmony_ci    MaybeStackArray(MaybeStackArray<T, stackCapacity> &&src) noexcept;
3681cb0ef41Sopenharmony_ci    /**
3691cb0ef41Sopenharmony_ci     * Move assignment: transfers ownership or copies the stack array.
3701cb0ef41Sopenharmony_ci     */
3711cb0ef41Sopenharmony_ci    MaybeStackArray<T, stackCapacity> &operator=(MaybeStackArray<T, stackCapacity> &&src) noexcept;
3721cb0ef41Sopenharmony_ci    /**
3731cb0ef41Sopenharmony_ci     * Returns the array capacity (number of T items).
3741cb0ef41Sopenharmony_ci     * @return array capacity
3751cb0ef41Sopenharmony_ci     */
3761cb0ef41Sopenharmony_ci    int32_t getCapacity() const { return capacity; }
3771cb0ef41Sopenharmony_ci    /**
3781cb0ef41Sopenharmony_ci     * Access without ownership change.
3791cb0ef41Sopenharmony_ci     * @return the array pointer
3801cb0ef41Sopenharmony_ci     */
3811cb0ef41Sopenharmony_ci    T *getAlias() const { return ptr; }
3821cb0ef41Sopenharmony_ci    /**
3831cb0ef41Sopenharmony_ci     * Returns the array limit. Simple convenience method.
3841cb0ef41Sopenharmony_ci     * @return getAlias()+getCapacity()
3851cb0ef41Sopenharmony_ci     */
3861cb0ef41Sopenharmony_ci    T *getArrayLimit() const { return getAlias()+capacity; }
3871cb0ef41Sopenharmony_ci    // No "operator T *() const" because that can make
3881cb0ef41Sopenharmony_ci    // expressions like mbs[index] ambiguous for some compilers.
3891cb0ef41Sopenharmony_ci    /**
3901cb0ef41Sopenharmony_ci     * Array item access (const).
3911cb0ef41Sopenharmony_ci     * No index bounds check.
3921cb0ef41Sopenharmony_ci     * @param i array index
3931cb0ef41Sopenharmony_ci     * @return reference to the array item
3941cb0ef41Sopenharmony_ci     */
3951cb0ef41Sopenharmony_ci    const T &operator[](ptrdiff_t i) const { return ptr[i]; }
3961cb0ef41Sopenharmony_ci    /**
3971cb0ef41Sopenharmony_ci     * Array item access (writable).
3981cb0ef41Sopenharmony_ci     * No index bounds check.
3991cb0ef41Sopenharmony_ci     * @param i array index
4001cb0ef41Sopenharmony_ci     * @return reference to the array item
4011cb0ef41Sopenharmony_ci     */
4021cb0ef41Sopenharmony_ci    T &operator[](ptrdiff_t i) { return ptr[i]; }
4031cb0ef41Sopenharmony_ci    /**
4041cb0ef41Sopenharmony_ci     * Deletes the array (if owned) and aliases another one, no transfer of ownership.
4051cb0ef41Sopenharmony_ci     * If the arguments are illegal, then the current array is unchanged.
4061cb0ef41Sopenharmony_ci     * @param otherArray must not be nullptr
4071cb0ef41Sopenharmony_ci     * @param otherCapacity must be >0
4081cb0ef41Sopenharmony_ci     */
4091cb0ef41Sopenharmony_ci    void aliasInstead(T *otherArray, int32_t otherCapacity) {
4101cb0ef41Sopenharmony_ci        if(otherArray!=nullptr && otherCapacity>0) {
4111cb0ef41Sopenharmony_ci            releaseArray();
4121cb0ef41Sopenharmony_ci            ptr=otherArray;
4131cb0ef41Sopenharmony_ci            capacity=otherCapacity;
4141cb0ef41Sopenharmony_ci            needToRelease=false;
4151cb0ef41Sopenharmony_ci        }
4161cb0ef41Sopenharmony_ci    }
4171cb0ef41Sopenharmony_ci    /**
4181cb0ef41Sopenharmony_ci     * Deletes the array (if owned) and allocates a new one, copying length T items.
4191cb0ef41Sopenharmony_ci     * Returns the new array pointer.
4201cb0ef41Sopenharmony_ci     * If the allocation fails, then the current array is unchanged and
4211cb0ef41Sopenharmony_ci     * this method returns nullptr.
4221cb0ef41Sopenharmony_ci     * @param newCapacity can be less than or greater than the current capacity;
4231cb0ef41Sopenharmony_ci     *                    must be >0
4241cb0ef41Sopenharmony_ci     * @param length number of T items to be copied from the old array to the new one
4251cb0ef41Sopenharmony_ci     * @return the allocated array pointer, or nullptr if the allocation failed
4261cb0ef41Sopenharmony_ci     */
4271cb0ef41Sopenharmony_ci    inline T *resize(int32_t newCapacity, int32_t length=0);
4281cb0ef41Sopenharmony_ci    /**
4291cb0ef41Sopenharmony_ci     * Gives up ownership of the array if owned, or else clones it,
4301cb0ef41Sopenharmony_ci     * copying length T items; resets itself to the internal stack array.
4311cb0ef41Sopenharmony_ci     * Returns nullptr if the allocation failed.
4321cb0ef41Sopenharmony_ci     * @param length number of T items to copy when cloning,
4331cb0ef41Sopenharmony_ci     *        and capacity of the clone when cloning
4341cb0ef41Sopenharmony_ci     * @param resultCapacity will be set to the returned array's capacity (output-only)
4351cb0ef41Sopenharmony_ci     * @return the array pointer;
4361cb0ef41Sopenharmony_ci     *         caller becomes responsible for deleting the array
4371cb0ef41Sopenharmony_ci     */
4381cb0ef41Sopenharmony_ci    inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ciprotected:
4411cb0ef41Sopenharmony_ci    // Resizes the array to the size of src, then copies the contents of src.
4421cb0ef41Sopenharmony_ci    void copyFrom(const MaybeStackArray &src, UErrorCode &status) {
4431cb0ef41Sopenharmony_ci        if (U_FAILURE(status)) {
4441cb0ef41Sopenharmony_ci            return;
4451cb0ef41Sopenharmony_ci        }
4461cb0ef41Sopenharmony_ci        if (this->resize(src.capacity, 0) == nullptr) {
4471cb0ef41Sopenharmony_ci            status = U_MEMORY_ALLOCATION_ERROR;
4481cb0ef41Sopenharmony_ci            return;
4491cb0ef41Sopenharmony_ci        }
4501cb0ef41Sopenharmony_ci        uprv_memcpy(this->ptr, src.ptr, (size_t)capacity * sizeof(T));
4511cb0ef41Sopenharmony_ci    }
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ciprivate:
4541cb0ef41Sopenharmony_ci    T *ptr;
4551cb0ef41Sopenharmony_ci    int32_t capacity;
4561cb0ef41Sopenharmony_ci    UBool needToRelease;
4571cb0ef41Sopenharmony_ci    T stackArray[stackCapacity];
4581cb0ef41Sopenharmony_ci    void releaseArray() {
4591cb0ef41Sopenharmony_ci        if(needToRelease) {
4601cb0ef41Sopenharmony_ci            uprv_free(ptr);
4611cb0ef41Sopenharmony_ci        }
4621cb0ef41Sopenharmony_ci    }
4631cb0ef41Sopenharmony_ci    void resetToStackArray() {
4641cb0ef41Sopenharmony_ci        ptr=stackArray;
4651cb0ef41Sopenharmony_ci        capacity=stackCapacity;
4661cb0ef41Sopenharmony_ci        needToRelease=false;
4671cb0ef41Sopenharmony_ci    }
4681cb0ef41Sopenharmony_ci    /* No comparison operators with other MaybeStackArray's. */
4691cb0ef41Sopenharmony_ci    bool operator==(const MaybeStackArray & /*other*/) = delete;
4701cb0ef41Sopenharmony_ci    bool operator!=(const MaybeStackArray & /*other*/) = delete;
4711cb0ef41Sopenharmony_ci    /* No ownership transfer: No copy constructor, no assignment operator. */
4721cb0ef41Sopenharmony_ci    MaybeStackArray(const MaybeStackArray & /*other*/) = delete;
4731cb0ef41Sopenharmony_ci    void operator=(const MaybeStackArray & /*other*/) = delete;
4741cb0ef41Sopenharmony_ci};
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_citemplate<typename T, int32_t stackCapacity>
4771cb0ef41Sopenharmony_ciicu::MaybeStackArray<T, stackCapacity>::MaybeStackArray(
4781cb0ef41Sopenharmony_ci        MaybeStackArray <T, stackCapacity>&& src) noexcept
4791cb0ef41Sopenharmony_ci        : ptr(src.ptr), capacity(src.capacity), needToRelease(src.needToRelease) {
4801cb0ef41Sopenharmony_ci    if (src.ptr == src.stackArray) {
4811cb0ef41Sopenharmony_ci        ptr = stackArray;
4821cb0ef41Sopenharmony_ci        uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity);
4831cb0ef41Sopenharmony_ci    } else {
4841cb0ef41Sopenharmony_ci        src.resetToStackArray();  // take ownership away from src
4851cb0ef41Sopenharmony_ci    }
4861cb0ef41Sopenharmony_ci}
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_citemplate<typename T, int32_t stackCapacity>
4891cb0ef41Sopenharmony_ciinline MaybeStackArray <T, stackCapacity>&
4901cb0ef41Sopenharmony_ciMaybeStackArray<T, stackCapacity>::operator=(MaybeStackArray <T, stackCapacity>&& src) noexcept {
4911cb0ef41Sopenharmony_ci    releaseArray();  // in case this instance had its own memory allocated
4921cb0ef41Sopenharmony_ci    capacity = src.capacity;
4931cb0ef41Sopenharmony_ci    needToRelease = src.needToRelease;
4941cb0ef41Sopenharmony_ci    if (src.ptr == src.stackArray) {
4951cb0ef41Sopenharmony_ci        ptr = stackArray;
4961cb0ef41Sopenharmony_ci        uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity);
4971cb0ef41Sopenharmony_ci    } else {
4981cb0ef41Sopenharmony_ci        ptr = src.ptr;
4991cb0ef41Sopenharmony_ci        src.resetToStackArray();  // take ownership away from src
5001cb0ef41Sopenharmony_ci    }
5011cb0ef41Sopenharmony_ci    return *this;
5021cb0ef41Sopenharmony_ci}
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_citemplate<typename T, int32_t stackCapacity>
5051cb0ef41Sopenharmony_ciinline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
5061cb0ef41Sopenharmony_ci    if(newCapacity>0) {
5071cb0ef41Sopenharmony_ci#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
5081cb0ef41Sopenharmony_ci        ::fprintf(::stderr, "MaybeStackArray (resize) alloc %d * %lu\n", newCapacity, sizeof(T));
5091cb0ef41Sopenharmony_ci#endif
5101cb0ef41Sopenharmony_ci        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
5111cb0ef41Sopenharmony_ci        if(p!=nullptr) {
5121cb0ef41Sopenharmony_ci            if(length>0) {
5131cb0ef41Sopenharmony_ci                if(length>capacity) {
5141cb0ef41Sopenharmony_ci                    length=capacity;
5151cb0ef41Sopenharmony_ci                }
5161cb0ef41Sopenharmony_ci                if(length>newCapacity) {
5171cb0ef41Sopenharmony_ci                    length=newCapacity;
5181cb0ef41Sopenharmony_ci                }
5191cb0ef41Sopenharmony_ci                uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
5201cb0ef41Sopenharmony_ci            }
5211cb0ef41Sopenharmony_ci            releaseArray();
5221cb0ef41Sopenharmony_ci            ptr=p;
5231cb0ef41Sopenharmony_ci            capacity=newCapacity;
5241cb0ef41Sopenharmony_ci            needToRelease=true;
5251cb0ef41Sopenharmony_ci        }
5261cb0ef41Sopenharmony_ci        return p;
5271cb0ef41Sopenharmony_ci    } else {
5281cb0ef41Sopenharmony_ci        return nullptr;
5291cb0ef41Sopenharmony_ci    }
5301cb0ef41Sopenharmony_ci}
5311cb0ef41Sopenharmony_ci
5321cb0ef41Sopenharmony_citemplate<typename T, int32_t stackCapacity>
5331cb0ef41Sopenharmony_ciinline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
5341cb0ef41Sopenharmony_ci    T *p;
5351cb0ef41Sopenharmony_ci    if(needToRelease) {
5361cb0ef41Sopenharmony_ci        p=ptr;
5371cb0ef41Sopenharmony_ci    } else if(length<=0) {
5381cb0ef41Sopenharmony_ci        return nullptr;
5391cb0ef41Sopenharmony_ci    } else {
5401cb0ef41Sopenharmony_ci        if(length>capacity) {
5411cb0ef41Sopenharmony_ci            length=capacity;
5421cb0ef41Sopenharmony_ci        }
5431cb0ef41Sopenharmony_ci        p=(T *)uprv_malloc(length*sizeof(T));
5441cb0ef41Sopenharmony_ci#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
5451cb0ef41Sopenharmony_ci      ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
5461cb0ef41Sopenharmony_ci#endif
5471cb0ef41Sopenharmony_ci        if(p==nullptr) {
5481cb0ef41Sopenharmony_ci            return nullptr;
5491cb0ef41Sopenharmony_ci        }
5501cb0ef41Sopenharmony_ci        uprv_memcpy(p, ptr, (size_t)length*sizeof(T));
5511cb0ef41Sopenharmony_ci    }
5521cb0ef41Sopenharmony_ci    resultCapacity=length;
5531cb0ef41Sopenharmony_ci    resetToStackArray();
5541cb0ef41Sopenharmony_ci    return p;
5551cb0ef41Sopenharmony_ci}
5561cb0ef41Sopenharmony_ci
5571cb0ef41Sopenharmony_ci/**
5581cb0ef41Sopenharmony_ci * Variant of MaybeStackArray that allocates a header struct and an array
5591cb0ef41Sopenharmony_ci * in one contiguous memory block, using uprv_malloc() and uprv_free().
5601cb0ef41Sopenharmony_ci * Provides internal memory with fixed array capacity. Can alias another memory
5611cb0ef41Sopenharmony_ci * block or allocate one.
5621cb0ef41Sopenharmony_ci * The stackCapacity is the number of T items in the internal memory,
5631cb0ef41Sopenharmony_ci * not counting the H header.
5641cb0ef41Sopenharmony_ci * Unlike LocalMemory and LocalArray, this class never adopts
5651cb0ef41Sopenharmony_ci * (takes ownership of) another memory block.
5661cb0ef41Sopenharmony_ci */
5671cb0ef41Sopenharmony_citemplate<typename H, typename T, int32_t stackCapacity>
5681cb0ef41Sopenharmony_ciclass MaybeStackHeaderAndArray {
5691cb0ef41Sopenharmony_cipublic:
5701cb0ef41Sopenharmony_ci    // No heap allocation. Use only on the stack.
5711cb0ef41Sopenharmony_ci    static void* U_EXPORT2 operator new(size_t) noexcept = delete;
5721cb0ef41Sopenharmony_ci    static void* U_EXPORT2 operator new[](size_t) noexcept = delete;
5731cb0ef41Sopenharmony_ci#if U_HAVE_PLACEMENT_NEW
5741cb0ef41Sopenharmony_ci    static void* U_EXPORT2 operator new(size_t, void*) noexcept = delete;
5751cb0ef41Sopenharmony_ci#endif
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ci    /**
5781cb0ef41Sopenharmony_ci     * Default constructor initializes with internal H+T[stackCapacity] buffer.
5791cb0ef41Sopenharmony_ci     */
5801cb0ef41Sopenharmony_ci    MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(false) {}
5811cb0ef41Sopenharmony_ci    /**
5821cb0ef41Sopenharmony_ci     * Destructor deletes the memory (if owned).
5831cb0ef41Sopenharmony_ci     */
5841cb0ef41Sopenharmony_ci    ~MaybeStackHeaderAndArray() { releaseMemory(); }
5851cb0ef41Sopenharmony_ci    /**
5861cb0ef41Sopenharmony_ci     * Returns the array capacity (number of T items).
5871cb0ef41Sopenharmony_ci     * @return array capacity
5881cb0ef41Sopenharmony_ci     */
5891cb0ef41Sopenharmony_ci    int32_t getCapacity() const { return capacity; }
5901cb0ef41Sopenharmony_ci    /**
5911cb0ef41Sopenharmony_ci     * Access without ownership change.
5921cb0ef41Sopenharmony_ci     * @return the header pointer
5931cb0ef41Sopenharmony_ci     */
5941cb0ef41Sopenharmony_ci    H *getAlias() const { return ptr; }
5951cb0ef41Sopenharmony_ci    /**
5961cb0ef41Sopenharmony_ci     * Returns the array start.
5971cb0ef41Sopenharmony_ci     * @return array start, same address as getAlias()+1
5981cb0ef41Sopenharmony_ci     */
5991cb0ef41Sopenharmony_ci    T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
6001cb0ef41Sopenharmony_ci    /**
6011cb0ef41Sopenharmony_ci     * Returns the array limit.
6021cb0ef41Sopenharmony_ci     * @return array limit
6031cb0ef41Sopenharmony_ci     */
6041cb0ef41Sopenharmony_ci    T *getArrayLimit() const { return getArrayStart()+capacity; }
6051cb0ef41Sopenharmony_ci    /**
6061cb0ef41Sopenharmony_ci     * Access without ownership change. Same as getAlias().
6071cb0ef41Sopenharmony_ci     * A class instance can be used directly in expressions that take a T *.
6081cb0ef41Sopenharmony_ci     * @return the header pointer
6091cb0ef41Sopenharmony_ci     */
6101cb0ef41Sopenharmony_ci    operator H *() const { return ptr; }
6111cb0ef41Sopenharmony_ci    /**
6121cb0ef41Sopenharmony_ci     * Array item access (writable).
6131cb0ef41Sopenharmony_ci     * No index bounds check.
6141cb0ef41Sopenharmony_ci     * @param i array index
6151cb0ef41Sopenharmony_ci     * @return reference to the array item
6161cb0ef41Sopenharmony_ci     */
6171cb0ef41Sopenharmony_ci    T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
6181cb0ef41Sopenharmony_ci    /**
6191cb0ef41Sopenharmony_ci     * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
6201cb0ef41Sopenharmony_ci     * If the arguments are illegal, then the current memory is unchanged.
6211cb0ef41Sopenharmony_ci     * @param otherArray must not be nullptr
6221cb0ef41Sopenharmony_ci     * @param otherCapacity must be >0
6231cb0ef41Sopenharmony_ci     */
6241cb0ef41Sopenharmony_ci    void aliasInstead(H *otherMemory, int32_t otherCapacity) {
6251cb0ef41Sopenharmony_ci        if(otherMemory!=nullptr && otherCapacity>0) {
6261cb0ef41Sopenharmony_ci            releaseMemory();
6271cb0ef41Sopenharmony_ci            ptr=otherMemory;
6281cb0ef41Sopenharmony_ci            capacity=otherCapacity;
6291cb0ef41Sopenharmony_ci            needToRelease=false;
6301cb0ef41Sopenharmony_ci        }
6311cb0ef41Sopenharmony_ci    }
6321cb0ef41Sopenharmony_ci    /**
6331cb0ef41Sopenharmony_ci     * Deletes the memory block (if owned) and allocates a new one,
6341cb0ef41Sopenharmony_ci     * copying the header and length T array items.
6351cb0ef41Sopenharmony_ci     * Returns the new header pointer.
6361cb0ef41Sopenharmony_ci     * If the allocation fails, then the current memory is unchanged and
6371cb0ef41Sopenharmony_ci     * this method returns nullptr.
6381cb0ef41Sopenharmony_ci     * @param newCapacity can be less than or greater than the current capacity;
6391cb0ef41Sopenharmony_ci     *                    must be >0
6401cb0ef41Sopenharmony_ci     * @param length number of T items to be copied from the old array to the new one
6411cb0ef41Sopenharmony_ci     * @return the allocated pointer, or nullptr if the allocation failed
6421cb0ef41Sopenharmony_ci     */
6431cb0ef41Sopenharmony_ci    inline H *resize(int32_t newCapacity, int32_t length=0);
6441cb0ef41Sopenharmony_ci    /**
6451cb0ef41Sopenharmony_ci     * Gives up ownership of the memory if owned, or else clones it,
6461cb0ef41Sopenharmony_ci     * copying the header and length T array items; resets itself to the internal memory.
6471cb0ef41Sopenharmony_ci     * Returns nullptr if the allocation failed.
6481cb0ef41Sopenharmony_ci     * @param length number of T items to copy when cloning,
6491cb0ef41Sopenharmony_ci     *        and array capacity of the clone when cloning
6501cb0ef41Sopenharmony_ci     * @param resultCapacity will be set to the returned array's capacity (output-only)
6511cb0ef41Sopenharmony_ci     * @return the header pointer;
6521cb0ef41Sopenharmony_ci     *         caller becomes responsible for deleting the array
6531cb0ef41Sopenharmony_ci     */
6541cb0ef41Sopenharmony_ci    inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
6551cb0ef41Sopenharmony_ciprivate:
6561cb0ef41Sopenharmony_ci    H *ptr;
6571cb0ef41Sopenharmony_ci    int32_t capacity;
6581cb0ef41Sopenharmony_ci    UBool needToRelease;
6591cb0ef41Sopenharmony_ci    // stackHeader must precede stackArray immediately.
6601cb0ef41Sopenharmony_ci    H stackHeader;
6611cb0ef41Sopenharmony_ci    T stackArray[stackCapacity];
6621cb0ef41Sopenharmony_ci    void releaseMemory() {
6631cb0ef41Sopenharmony_ci        if(needToRelease) {
6641cb0ef41Sopenharmony_ci            uprv_free(ptr);
6651cb0ef41Sopenharmony_ci        }
6661cb0ef41Sopenharmony_ci    }
6671cb0ef41Sopenharmony_ci    /* No comparison operators with other MaybeStackHeaderAndArray's. */
6681cb0ef41Sopenharmony_ci    bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return false;}
6691cb0ef41Sopenharmony_ci    bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return true;}
6701cb0ef41Sopenharmony_ci    /* No ownership transfer: No copy constructor, no assignment operator. */
6711cb0ef41Sopenharmony_ci    MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
6721cb0ef41Sopenharmony_ci    void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
6731cb0ef41Sopenharmony_ci};
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_citemplate<typename H, typename T, int32_t stackCapacity>
6761cb0ef41Sopenharmony_ciinline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
6771cb0ef41Sopenharmony_ci                                                                int32_t length) {
6781cb0ef41Sopenharmony_ci    if(newCapacity>=0) {
6791cb0ef41Sopenharmony_ci#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
6801cb0ef41Sopenharmony_ci      ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
6811cb0ef41Sopenharmony_ci#endif
6821cb0ef41Sopenharmony_ci        H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
6831cb0ef41Sopenharmony_ci        if(p!=nullptr) {
6841cb0ef41Sopenharmony_ci            if(length<0) {
6851cb0ef41Sopenharmony_ci                length=0;
6861cb0ef41Sopenharmony_ci            } else if(length>0) {
6871cb0ef41Sopenharmony_ci                if(length>capacity) {
6881cb0ef41Sopenharmony_ci                    length=capacity;
6891cb0ef41Sopenharmony_ci                }
6901cb0ef41Sopenharmony_ci                if(length>newCapacity) {
6911cb0ef41Sopenharmony_ci                    length=newCapacity;
6921cb0ef41Sopenharmony_ci                }
6931cb0ef41Sopenharmony_ci            }
6941cb0ef41Sopenharmony_ci            uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
6951cb0ef41Sopenharmony_ci            releaseMemory();
6961cb0ef41Sopenharmony_ci            ptr=p;
6971cb0ef41Sopenharmony_ci            capacity=newCapacity;
6981cb0ef41Sopenharmony_ci            needToRelease=true;
6991cb0ef41Sopenharmony_ci        }
7001cb0ef41Sopenharmony_ci        return p;
7011cb0ef41Sopenharmony_ci    } else {
7021cb0ef41Sopenharmony_ci        return nullptr;
7031cb0ef41Sopenharmony_ci    }
7041cb0ef41Sopenharmony_ci}
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_citemplate<typename H, typename T, int32_t stackCapacity>
7071cb0ef41Sopenharmony_ciinline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
7081cb0ef41Sopenharmony_ci                                                                       int32_t &resultCapacity) {
7091cb0ef41Sopenharmony_ci    H *p;
7101cb0ef41Sopenharmony_ci    if(needToRelease) {
7111cb0ef41Sopenharmony_ci        p=ptr;
7121cb0ef41Sopenharmony_ci    } else {
7131cb0ef41Sopenharmony_ci        if(length<0) {
7141cb0ef41Sopenharmony_ci            length=0;
7151cb0ef41Sopenharmony_ci        } else if(length>capacity) {
7161cb0ef41Sopenharmony_ci            length=capacity;
7171cb0ef41Sopenharmony_ci        }
7181cb0ef41Sopenharmony_ci#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
7191cb0ef41Sopenharmony_ci      ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
7201cb0ef41Sopenharmony_ci#endif
7211cb0ef41Sopenharmony_ci        p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
7221cb0ef41Sopenharmony_ci        if(p==nullptr) {
7231cb0ef41Sopenharmony_ci            return nullptr;
7241cb0ef41Sopenharmony_ci        }
7251cb0ef41Sopenharmony_ci        uprv_memcpy(p, ptr, sizeof(H)+(size_t)length*sizeof(T));
7261cb0ef41Sopenharmony_ci    }
7271cb0ef41Sopenharmony_ci    resultCapacity=length;
7281cb0ef41Sopenharmony_ci    ptr=&stackHeader;
7291cb0ef41Sopenharmony_ci    capacity=stackCapacity;
7301cb0ef41Sopenharmony_ci    needToRelease=false;
7311cb0ef41Sopenharmony_ci    return p;
7321cb0ef41Sopenharmony_ci}
7331cb0ef41Sopenharmony_ci
7341cb0ef41Sopenharmony_ci/**
7351cb0ef41Sopenharmony_ci * A simple memory management class that creates new heap allocated objects (of
7361cb0ef41Sopenharmony_ci * any class that has a public constructor), keeps track of them and eventually
7371cb0ef41Sopenharmony_ci * deletes them all in its own destructor.
7381cb0ef41Sopenharmony_ci *
7391cb0ef41Sopenharmony_ci * A typical use-case would be code like this:
7401cb0ef41Sopenharmony_ci *
7411cb0ef41Sopenharmony_ci *     MemoryPool<MyType> pool;
7421cb0ef41Sopenharmony_ci *
7431cb0ef41Sopenharmony_ci *     MyType* o1 = pool.create();
7441cb0ef41Sopenharmony_ci *     if (o1 != nullptr) {
7451cb0ef41Sopenharmony_ci *         foo(o1);
7461cb0ef41Sopenharmony_ci *     }
7471cb0ef41Sopenharmony_ci *
7481cb0ef41Sopenharmony_ci *     MyType* o2 = pool.create(1, 2, 3);
7491cb0ef41Sopenharmony_ci *     if (o2 != nullptr) {
7501cb0ef41Sopenharmony_ci *         bar(o2);
7511cb0ef41Sopenharmony_ci *     }
7521cb0ef41Sopenharmony_ci *
7531cb0ef41Sopenharmony_ci *     // MemoryPool will take care of deleting the MyType objects.
7541cb0ef41Sopenharmony_ci *
7551cb0ef41Sopenharmony_ci * It doesn't do anything more than that, and is intentionally kept minimalist.
7561cb0ef41Sopenharmony_ci */
7571cb0ef41Sopenharmony_citemplate<typename T, int32_t stackCapacity = 8>
7581cb0ef41Sopenharmony_ciclass MemoryPool : public UMemory {
7591cb0ef41Sopenharmony_cipublic:
7601cb0ef41Sopenharmony_ci    MemoryPool() : fCount(0), fPool() {}
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci    ~MemoryPool() {
7631cb0ef41Sopenharmony_ci        for (int32_t i = 0; i < fCount; ++i) {
7641cb0ef41Sopenharmony_ci            delete fPool[i];
7651cb0ef41Sopenharmony_ci        }
7661cb0ef41Sopenharmony_ci    }
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_ci    MemoryPool(const MemoryPool&) = delete;
7691cb0ef41Sopenharmony_ci    MemoryPool& operator=(const MemoryPool&) = delete;
7701cb0ef41Sopenharmony_ci
7711cb0ef41Sopenharmony_ci    MemoryPool(MemoryPool&& other) noexcept : fCount(other.fCount),
7721cb0ef41Sopenharmony_ci                                                fPool(std::move(other.fPool)) {
7731cb0ef41Sopenharmony_ci        other.fCount = 0;
7741cb0ef41Sopenharmony_ci    }
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci    MemoryPool& operator=(MemoryPool&& other) noexcept {
7771cb0ef41Sopenharmony_ci        // Since `this` may contain instances that need to be deleted, we can't
7781cb0ef41Sopenharmony_ci        // just throw them away and replace them with `other`. The normal way of
7791cb0ef41Sopenharmony_ci        // dealing with this in C++ is to swap `this` and `other`, rather than
7801cb0ef41Sopenharmony_ci        // simply overwrite: the destruction of `other` can then take care of
7811cb0ef41Sopenharmony_ci        // running MemoryPool::~MemoryPool() over the still-to-be-deallocated
7821cb0ef41Sopenharmony_ci        // instances.
7831cb0ef41Sopenharmony_ci        std::swap(fCount, other.fCount);
7841cb0ef41Sopenharmony_ci        std::swap(fPool, other.fPool);
7851cb0ef41Sopenharmony_ci        return *this;
7861cb0ef41Sopenharmony_ci    }
7871cb0ef41Sopenharmony_ci
7881cb0ef41Sopenharmony_ci    /**
7891cb0ef41Sopenharmony_ci     * Creates a new object of typename T, by forwarding any and all arguments
7901cb0ef41Sopenharmony_ci     * to the typename T constructor.
7911cb0ef41Sopenharmony_ci     *
7921cb0ef41Sopenharmony_ci     * @param args Arguments to be forwarded to the typename T constructor.
7931cb0ef41Sopenharmony_ci     * @return A pointer to the newly created object, or nullptr on error.
7941cb0ef41Sopenharmony_ci     */
7951cb0ef41Sopenharmony_ci    template<typename... Args>
7961cb0ef41Sopenharmony_ci    T* create(Args&&... args) {
7971cb0ef41Sopenharmony_ci        int32_t capacity = fPool.getCapacity();
7981cb0ef41Sopenharmony_ci        if (fCount == capacity &&
7991cb0ef41Sopenharmony_ci            fPool.resize(capacity == stackCapacity ? 4 * capacity : 2 * capacity,
8001cb0ef41Sopenharmony_ci                         capacity) == nullptr) {
8011cb0ef41Sopenharmony_ci            return nullptr;
8021cb0ef41Sopenharmony_ci        }
8031cb0ef41Sopenharmony_ci        return fPool[fCount++] = new T(std::forward<Args>(args)...);
8041cb0ef41Sopenharmony_ci    }
8051cb0ef41Sopenharmony_ci
8061cb0ef41Sopenharmony_ci    template <typename... Args>
8071cb0ef41Sopenharmony_ci    T* createAndCheckErrorCode(UErrorCode &status, Args &&... args) {
8081cb0ef41Sopenharmony_ci        if (U_FAILURE(status)) {
8091cb0ef41Sopenharmony_ci            return nullptr;
8101cb0ef41Sopenharmony_ci        }
8111cb0ef41Sopenharmony_ci        T *pointer = this->create(args...);
8121cb0ef41Sopenharmony_ci        if (U_SUCCESS(status) && pointer == nullptr) {
8131cb0ef41Sopenharmony_ci            status = U_MEMORY_ALLOCATION_ERROR;
8141cb0ef41Sopenharmony_ci        }
8151cb0ef41Sopenharmony_ci        return pointer;
8161cb0ef41Sopenharmony_ci    }
8171cb0ef41Sopenharmony_ci
8181cb0ef41Sopenharmony_ci    /**
8191cb0ef41Sopenharmony_ci     * @return Number of elements that have been allocated.
8201cb0ef41Sopenharmony_ci     */
8211cb0ef41Sopenharmony_ci    int32_t count() const {
8221cb0ef41Sopenharmony_ci        return fCount;
8231cb0ef41Sopenharmony_ci    }
8241cb0ef41Sopenharmony_ci
8251cb0ef41Sopenharmony_ciprotected:
8261cb0ef41Sopenharmony_ci    int32_t fCount;
8271cb0ef41Sopenharmony_ci    MaybeStackArray<T*, stackCapacity> fPool;
8281cb0ef41Sopenharmony_ci};
8291cb0ef41Sopenharmony_ci
8301cb0ef41Sopenharmony_ci/**
8311cb0ef41Sopenharmony_ci * An internal Vector-like implementation based on MemoryPool.
8321cb0ef41Sopenharmony_ci *
8331cb0ef41Sopenharmony_ci * Heap-allocates each element and stores pointers.
8341cb0ef41Sopenharmony_ci *
8351cb0ef41Sopenharmony_ci * To append an item to the vector, use emplaceBack.
8361cb0ef41Sopenharmony_ci *
8371cb0ef41Sopenharmony_ci *     MaybeStackVector<MyType> vector;
8381cb0ef41Sopenharmony_ci *     MyType* element = vector.emplaceBack();
8391cb0ef41Sopenharmony_ci *     if (!element) {
8401cb0ef41Sopenharmony_ci *         status = U_MEMORY_ALLOCATION_ERROR;
8411cb0ef41Sopenharmony_ci *     }
8421cb0ef41Sopenharmony_ci *     // do stuff with element
8431cb0ef41Sopenharmony_ci *
8441cb0ef41Sopenharmony_ci * To loop over the vector, use a for loop with indices:
8451cb0ef41Sopenharmony_ci *
8461cb0ef41Sopenharmony_ci *     for (int32_t i = 0; i < vector.length(); i++) {
8471cb0ef41Sopenharmony_ci *         MyType* element = vector[i];
8481cb0ef41Sopenharmony_ci *     }
8491cb0ef41Sopenharmony_ci */
8501cb0ef41Sopenharmony_citemplate<typename T, int32_t stackCapacity = 8>
8511cb0ef41Sopenharmony_ciclass MaybeStackVector : protected MemoryPool<T, stackCapacity> {
8521cb0ef41Sopenharmony_cipublic:
8531cb0ef41Sopenharmony_ci    template<typename... Args>
8541cb0ef41Sopenharmony_ci    T* emplaceBack(Args&&... args) {
8551cb0ef41Sopenharmony_ci        return this->create(args...);
8561cb0ef41Sopenharmony_ci    }
8571cb0ef41Sopenharmony_ci
8581cb0ef41Sopenharmony_ci    template <typename... Args>
8591cb0ef41Sopenharmony_ci    T *emplaceBackAndCheckErrorCode(UErrorCode &status, Args &&... args) {
8601cb0ef41Sopenharmony_ci        return this->createAndCheckErrorCode(status, args...);
8611cb0ef41Sopenharmony_ci    }
8621cb0ef41Sopenharmony_ci
8631cb0ef41Sopenharmony_ci    int32_t length() const {
8641cb0ef41Sopenharmony_ci        return this->fCount;
8651cb0ef41Sopenharmony_ci    }
8661cb0ef41Sopenharmony_ci
8671cb0ef41Sopenharmony_ci    T** getAlias() {
8681cb0ef41Sopenharmony_ci        return this->fPool.getAlias();
8691cb0ef41Sopenharmony_ci    }
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_ci    const T *const *getAlias() const {
8721cb0ef41Sopenharmony_ci        return this->fPool.getAlias();
8731cb0ef41Sopenharmony_ci    }
8741cb0ef41Sopenharmony_ci
8751cb0ef41Sopenharmony_ci    /**
8761cb0ef41Sopenharmony_ci     * Array item access (read-only).
8771cb0ef41Sopenharmony_ci     * No index bounds check.
8781cb0ef41Sopenharmony_ci     * @param i array index
8791cb0ef41Sopenharmony_ci     * @return reference to the array item
8801cb0ef41Sopenharmony_ci     */
8811cb0ef41Sopenharmony_ci    const T* operator[](ptrdiff_t i) const {
8821cb0ef41Sopenharmony_ci        return this->fPool[i];
8831cb0ef41Sopenharmony_ci    }
8841cb0ef41Sopenharmony_ci
8851cb0ef41Sopenharmony_ci    /**
8861cb0ef41Sopenharmony_ci     * Array item access (writable).
8871cb0ef41Sopenharmony_ci     * No index bounds check.
8881cb0ef41Sopenharmony_ci     * @param i array index
8891cb0ef41Sopenharmony_ci     * @return reference to the array item
8901cb0ef41Sopenharmony_ci     */
8911cb0ef41Sopenharmony_ci    T* operator[](ptrdiff_t i) {
8921cb0ef41Sopenharmony_ci        return this->fPool[i];
8931cb0ef41Sopenharmony_ci    }
8941cb0ef41Sopenharmony_ci};
8951cb0ef41Sopenharmony_ci
8961cb0ef41Sopenharmony_ci
8971cb0ef41Sopenharmony_ciU_NAMESPACE_END
8981cb0ef41Sopenharmony_ci
8991cb0ef41Sopenharmony_ci#endif  /* __cplusplus */
9001cb0ef41Sopenharmony_ci#endif  /* CMEMORY_H */
901