1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
4103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius*   Copyright (C) 1997-2012, International Business Machines
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Corporation and others.  All Rights Reserved.
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File CMEMORY.H
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  Contains stdlib.h/string.h memory functions
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* @author       Bertrand A. Damiba
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   6/20/98     Bertrand    Created.
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  05/03/99     stephen     Changed from functions to macros.
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifndef CMEMORY_H
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define CMEMORY_H
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
2754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "unicode/utypes.h"
2854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include <stddef.h>
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include <string.h>
3127f654740f2a26ad62a5c155af9199af9e69b889claireho#include "unicode/localpointer.h"
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
33103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
34103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include <stdio.h>
35103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
36103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
3754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#if U_DEBUG
3854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
3954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius/*
4054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * The C++ standard requires that the source pointer for memcpy() & memmove()
4154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * is valid, not NULL, and not at the end of an allocated memory block.
4254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * In debug mode, we read one byte from the source point to verify that it's
4354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * a valid, readable pointer.
4454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius */
4554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
4654dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusU_CAPI void uprv_checkValidMemory(const void *p, size_t n);
4754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
4854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#define uprv_memcpy(dst, src, size) ( \
4954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    uprv_checkValidMemory(src, 1), \
5054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size))
5154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#define uprv_memmove(dst, src, size) ( \
5254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    uprv_checkValidMemory(src, 1), \
5354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    U_STANDARD_CPP_NAMESPACE memmove(dst, src, size))
5454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
5554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#else
5654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define uprv_memcpy(dst, src, size) U_STANDARD_CPP_NAMESPACE memcpy(dst, src, size)
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define uprv_memmove(dst, src, size) U_STANDARD_CPP_NAMESPACE memmove(dst, src, size)
5954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
6054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#endif  /* U_DEBUG */
6154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void * U_EXPORT2
6654dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusuprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void * U_EXPORT2
6954dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusuprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_free(void *mem);
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
74103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI void * U_EXPORT2
7554dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusuprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
76103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This should align the memory properly on any machine.
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is very useful for the safeClone functions.
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef union {
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    long    t1;
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double  t2;
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    void   *t3;
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} UAlignedMemory;
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Get the least significant bits of a pointer (a memory address).
89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * For example, with a mask of 3, the macro gets the 2 least significant bits,
90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * which will be 0 if the pointer is 32-bit (4-byte) aligned.
91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *
92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ptrdiff_t is the most appropriate integer type to cast to.
93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * size_t should work too, since on most (or all?) platforms it has the same
94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * width as ptrdiff_t.
95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/**
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Get the amount of bytes that a pointer is off by from
100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * the previous UAlignedMemory-aligned pointer.
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Get the amount of bytes to add to a pointer
106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * in order to get the next UAlignedMemory-aligned address.
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *  Indicate whether the ICU allocation functions have been used.
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *  This is used to determine whether ICU is in an initial, unused state.
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  */
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC UBool
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querucmemory_inUse(void);
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *  Heap clean up function, called from u_cleanup()
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *    Clears any user heap functions from u_setMemoryFunctions()
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *    Does NOT deallocate any remaining allocated memory.
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  */
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC UBool
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querucmemory_cleanup(void);
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
125103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/**
126103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * A function called by <TT>uhash_remove</TT>,
127103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
128103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * an existing key or value.
129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * @param obj A key or value stored in a hashtable
130103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * @see uprv_deleteUObject
131103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */
132103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliustypedef void U_CALLCONV UObjectDeleter(void* obj);
133103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
134103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/**
135103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Deleter for UObject instances.
136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Works for all subclasses of UObject because it has a virtual destructor.
137103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */
138103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI void U_EXPORT2
139103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuprv_deleteUObject(void *obj);
140103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#ifdef __cplusplus
14250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
14350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_BEGIN
14450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
14550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/**
14650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * "Smart pointer" class, deletes memory via uprv_free().
14750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * For most methods see the LocalPointerBase base class.
14850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Adds operator[] for array item access.
14950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
15050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * @see LocalPointerBase
15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
15250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T>
15350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass LocalMemory : public LocalPointerBase<T> {
15450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehopublic:
15550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Constructor takes ownership.
15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param p simple pointer to an array of T items that is adopted
15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
16050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
16150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Destructor deletes the memory it owns.
16250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
16350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ~LocalMemory() {
16450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uprv_free(LocalPointerBase<T>::ptr);
16550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
16650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
16750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array it owns,
16850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * and adopts (takes ownership of) the one passed in.
16950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param p simple pointer to an array of T items that is adopted
17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    void adoptInstead(T *p) {
17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uprv_free(LocalPointerBase<T>::ptr);
17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalPointerBase<T>::ptr=p;
17450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
17650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array it owns, allocates a new one and reset its bytes to 0.
17750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the new array pointer.
17850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the allocation fails, then the current array is unchanged and
17950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * this method returns NULL.
18050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param newCapacity must be >0
18150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the allocated array pointer, or NULL if the allocation failed
18250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
18350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *allocateInsteadAndReset(int32_t newCapacity=1);
18450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
18550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array it owns and allocates a new one, copying length T items.
18650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the new array pointer.
18750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the allocation fails, then the current array is unchanged and
18850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * this method returns NULL.
18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param newCapacity must be >0
19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param length number of T items to be copied from the old array to the new one;
19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *               must be no more than the capacity of the old array,
19250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *               which the caller must track because the LocalMemory does not track it
19350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the allocated array pointer, or NULL if the allocation failed
19450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
19550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
19650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
19750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Array item access (writable).
19850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * No index bounds check.
19950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param i array index
20050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return reference to the array item
20150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
20250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
20350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho};
20450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
20527f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename T>
20627f654740f2a26ad62a5c155af9199af9e69b889clairehoinline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
20727f654740f2a26ad62a5c155af9199af9e69b889claireho    if(newCapacity>0) {
20827f654740f2a26ad62a5c155af9199af9e69b889claireho        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
20927f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p!=NULL) {
21027f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_memset(p, 0, newCapacity*sizeof(T));
21127f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_free(LocalPointerBase<T>::ptr);
21227f654740f2a26ad62a5c155af9199af9e69b889claireho            LocalPointerBase<T>::ptr=p;
21327f654740f2a26ad62a5c155af9199af9e69b889claireho        }
21427f654740f2a26ad62a5c155af9199af9e69b889claireho        return p;
21527f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
21627f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
21727f654740f2a26ad62a5c155af9199af9e69b889claireho    }
21827f654740f2a26ad62a5c155af9199af9e69b889claireho}
21927f654740f2a26ad62a5c155af9199af9e69b889claireho
22027f654740f2a26ad62a5c155af9199af9e69b889claireho
22127f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename T>
22227f654740f2a26ad62a5c155af9199af9e69b889clairehoinline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
22327f654740f2a26ad62a5c155af9199af9e69b889claireho    if(newCapacity>0) {
22427f654740f2a26ad62a5c155af9199af9e69b889claireho        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
22527f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p!=NULL) {
22627f654740f2a26ad62a5c155af9199af9e69b889claireho            if(length>0) {
22727f654740f2a26ad62a5c155af9199af9e69b889claireho                if(length>newCapacity) {
22827f654740f2a26ad62a5c155af9199af9e69b889claireho                    length=newCapacity;
22927f654740f2a26ad62a5c155af9199af9e69b889claireho                }
23027f654740f2a26ad62a5c155af9199af9e69b889claireho                uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T));
23127f654740f2a26ad62a5c155af9199af9e69b889claireho            }
23227f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_free(LocalPointerBase<T>::ptr);
23327f654740f2a26ad62a5c155af9199af9e69b889claireho            LocalPointerBase<T>::ptr=p;
23427f654740f2a26ad62a5c155af9199af9e69b889claireho        }
23527f654740f2a26ad62a5c155af9199af9e69b889claireho        return p;
23627f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
23727f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
23827f654740f2a26ad62a5c155af9199af9e69b889claireho    }
23927f654740f2a26ad62a5c155af9199af9e69b889claireho}
24027f654740f2a26ad62a5c155af9199af9e69b889claireho
24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/**
24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Simple array/buffer management class using uprv_malloc() and uprv_free().
24350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Provides an internal array with fixed capacity. Can alias another array
24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * or allocate one.
24527f654740f2a26ad62a5c155af9199af9e69b889claireho *
24627f654740f2a26ad62a5c155af9199af9e69b889claireho * The array address is properly aligned for type T. It might not be properly
24727f654740f2a26ad62a5c155af9199af9e69b889claireho * aligned for types larger than T (or larger than the largest subtype of T).
24827f654740f2a26ad62a5c155af9199af9e69b889claireho *
24950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Unlike LocalMemory and LocalArray, this class never adopts
25050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * (takes ownership of) another array.
25150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
25250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T, int32_t stackCapacity>
25350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass MaybeStackArray {
25450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehopublic:
25550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
25650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Default constructor initializes with internal T[stackCapacity] buffer.
25750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
25827f654740f2a26ad62a5c155af9199af9e69b889claireho    MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
25950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
26050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Destructor deletes the array (if owned).
26150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
26250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ~MaybeStackArray() { releaseArray(); }
26350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
26450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the array capacity (number of T items).
26550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return array capacity
26650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
26750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t getCapacity() const { return capacity; }
26850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
26950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Access without ownership change.
27050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the array pointer
27150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
27250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *getAlias() const { return ptr; }
27350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
27450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the array limit. Simple convenience method.
27550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return getAlias()+getCapacity()
27650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *getArrayLimit() const { return getAlias()+capacity; }
27854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    // No "operator T *() const" because that can make
27954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    // expressions like mbs[index] ambiguous for some compilers.
28050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
28154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * Array item access (const).
28254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * No index bounds check.
28354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * @param i array index
28454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * @return reference to the array item
28550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
28654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    const T &operator[](ptrdiff_t i) const { return ptr[i]; }
28750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
28850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Array item access (writable).
28950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * No index bounds check.
29050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param i array index
29150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return reference to the array item
29250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T &operator[](ptrdiff_t i) { return ptr[i]; }
29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array (if owned) and aliases another one, no transfer of ownership.
29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the arguments are illegal, then the current array is unchanged.
29750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param otherArray must not be NULL
29850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param otherCapacity must be >0
29950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
30050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    void aliasInstead(T *otherArray, int32_t otherCapacity) {
30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(otherArray!=NULL && otherCapacity>0) {
30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            releaseArray();
30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ptr=otherArray;
30450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            capacity=otherCapacity;
30550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            needToRelease=FALSE;
30650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array (if owned) and allocates a new one, copying length T items.
31050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the new array pointer.
31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the allocation fails, then the current array is unchanged and
31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * this method returns NULL.
31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param newCapacity can be less than or greater than the current capacity;
31450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *                    must be >0
31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param length number of T items to be copied from the old array to the new one
31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the allocated array pointer, or NULL if the allocation failed
31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *resize(int32_t newCapacity, int32_t length=0);
31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Gives up ownership of the array if owned, or else clones it,
32150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * copying length T items; resets itself to the internal stack array.
32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns NULL if the allocation failed.
32350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param length number of T items to copy when cloning,
32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *        and capacity of the clone when cloning
32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param resultCapacity will be set to the returned array's capacity (output-only)
32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the array pointer;
32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *         caller becomes responsible for deleting the array
32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
32950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
33050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoprivate:
33150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *ptr;
33227f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t capacity;
33327f654740f2a26ad62a5c155af9199af9e69b889claireho    UBool needToRelease;
33450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T stackArray[stackCapacity];
33550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    void releaseArray() {
33650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(needToRelease) {
33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            uprv_free(ptr);
33850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* No comparison operators with other MaybeStackArray's. */
341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator==(const MaybeStackArray & /*other*/) {return FALSE;}
342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;}
34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* No ownership transfer: No copy constructor, no assignment operator. */
344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MaybeStackArray(const MaybeStackArray & /*other*/) {}
345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void operator=(const MaybeStackArray & /*other*/) {}
34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // No heap allocation. Use only on the stack.
34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //   (Declaring these functions private triggers a cascade of problems:
34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      MSVC insists on exporting an instantiation of MaybeStackArray, which
35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      requires that all functions be defined.
35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      An empty implementation of new() is rejected, it must return a value.
35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      Returning NULL is rejected by gcc for operator new.
35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      The expedient thing is just not to override operator new.
35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      While relatively pointless, heap allocated instances will function.
35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // static void * U_EXPORT2 operator new(size_t size);
35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // static void * U_EXPORT2 operator new[](size_t size);
35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if U_HAVE_PLACEMENT_NEW
35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // static void * U_EXPORT2 operator new(size_t, void *ptr);
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho};
36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
36250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T, int32_t stackCapacity>
36350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoinline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(newCapacity>0) {
365103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
366103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T));
367103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
36950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(p!=NULL) {
37050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(length>0) {
37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(length>capacity) {
37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    length=capacity;
37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(length>newCapacity) {
37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    length=newCapacity;
37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                uprv_memcpy(p, ptr, length*sizeof(T));
37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
37950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            releaseArray();
38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ptr=p;
38150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            capacity=newCapacity;
38250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            needToRelease=TRUE;
38350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
38450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return p;
38550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
38650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return NULL;
38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
39050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T, int32_t stackCapacity>
39150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoinline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
39250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *p;
39350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(needToRelease) {
39450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=ptr;
39550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else if(length<=0) {
39650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return NULL;
39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(length>capacity) {
39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            length=capacity;
40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=(T *)uprv_malloc(length*sizeof(T));
402103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
403103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
404103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(p==NULL) {
40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return NULL;
40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uprv_memcpy(p, ptr, length*sizeof(T));
40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    resultCapacity=length;
41150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ptr=stackArray;
41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    capacity=stackCapacity;
41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    needToRelease=FALSE;
41450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return p;
41550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
41727f654740f2a26ad62a5c155af9199af9e69b889claireho/**
41827f654740f2a26ad62a5c155af9199af9e69b889claireho * Variant of MaybeStackArray that allocates a header struct and an array
41927f654740f2a26ad62a5c155af9199af9e69b889claireho * in one contiguous memory block, using uprv_malloc() and uprv_free().
42027f654740f2a26ad62a5c155af9199af9e69b889claireho * Provides internal memory with fixed array capacity. Can alias another memory
42127f654740f2a26ad62a5c155af9199af9e69b889claireho * block or allocate one.
42227f654740f2a26ad62a5c155af9199af9e69b889claireho * The stackCapacity is the number of T items in the internal memory,
42327f654740f2a26ad62a5c155af9199af9e69b889claireho * not counting the H header.
42427f654740f2a26ad62a5c155af9199af9e69b889claireho * Unlike LocalMemory and LocalArray, this class never adopts
42527f654740f2a26ad62a5c155af9199af9e69b889claireho * (takes ownership of) another memory block.
42627f654740f2a26ad62a5c155af9199af9e69b889claireho */
42727f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename H, typename T, int32_t stackCapacity>
42827f654740f2a26ad62a5c155af9199af9e69b889clairehoclass MaybeStackHeaderAndArray {
42927f654740f2a26ad62a5c155af9199af9e69b889clairehopublic:
43027f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
43127f654740f2a26ad62a5c155af9199af9e69b889claireho     * Default constructor initializes with internal H+T[stackCapacity] buffer.
43227f654740f2a26ad62a5c155af9199af9e69b889claireho     */
43327f654740f2a26ad62a5c155af9199af9e69b889claireho    MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
43427f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
43527f654740f2a26ad62a5c155af9199af9e69b889claireho     * Destructor deletes the memory (if owned).
43627f654740f2a26ad62a5c155af9199af9e69b889claireho     */
43727f654740f2a26ad62a5c155af9199af9e69b889claireho    ~MaybeStackHeaderAndArray() { releaseMemory(); }
43827f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
43927f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the array capacity (number of T items).
44027f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return array capacity
44127f654740f2a26ad62a5c155af9199af9e69b889claireho     */
44227f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t getCapacity() const { return capacity; }
44327f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
44427f654740f2a26ad62a5c155af9199af9e69b889claireho     * Access without ownership change.
44527f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the header pointer
44627f654740f2a26ad62a5c155af9199af9e69b889claireho     */
44727f654740f2a26ad62a5c155af9199af9e69b889claireho    H *getAlias() const { return ptr; }
44827f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
44927f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the array start.
45027f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return array start, same address as getAlias()+1
45127f654740f2a26ad62a5c155af9199af9e69b889claireho     */
45227f654740f2a26ad62a5c155af9199af9e69b889claireho    T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
45327f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
45427f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the array limit.
45527f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return array limit
45627f654740f2a26ad62a5c155af9199af9e69b889claireho     */
45727f654740f2a26ad62a5c155af9199af9e69b889claireho    T *getArrayLimit() const { return getArrayStart()+capacity; }
45827f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
45927f654740f2a26ad62a5c155af9199af9e69b889claireho     * Access without ownership change. Same as getAlias().
46027f654740f2a26ad62a5c155af9199af9e69b889claireho     * A class instance can be used directly in expressions that take a T *.
46127f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the header pointer
46227f654740f2a26ad62a5c155af9199af9e69b889claireho     */
46327f654740f2a26ad62a5c155af9199af9e69b889claireho    operator H *() const { return ptr; }
46427f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
46527f654740f2a26ad62a5c155af9199af9e69b889claireho     * Array item access (writable).
46627f654740f2a26ad62a5c155af9199af9e69b889claireho     * No index bounds check.
46727f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param i array index
46827f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return reference to the array item
46927f654740f2a26ad62a5c155af9199af9e69b889claireho     */
47027f654740f2a26ad62a5c155af9199af9e69b889claireho    T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
47127f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
47227f654740f2a26ad62a5c155af9199af9e69b889claireho     * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
47327f654740f2a26ad62a5c155af9199af9e69b889claireho     * If the arguments are illegal, then the current memory is unchanged.
47427f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param otherArray must not be NULL
47527f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param otherCapacity must be >0
47627f654740f2a26ad62a5c155af9199af9e69b889claireho     */
47727f654740f2a26ad62a5c155af9199af9e69b889claireho    void aliasInstead(H *otherMemory, int32_t otherCapacity) {
47827f654740f2a26ad62a5c155af9199af9e69b889claireho        if(otherMemory!=NULL && otherCapacity>0) {
47927f654740f2a26ad62a5c155af9199af9e69b889claireho            releaseMemory();
48027f654740f2a26ad62a5c155af9199af9e69b889claireho            ptr=otherMemory;
48127f654740f2a26ad62a5c155af9199af9e69b889claireho            capacity=otherCapacity;
48227f654740f2a26ad62a5c155af9199af9e69b889claireho            needToRelease=FALSE;
48327f654740f2a26ad62a5c155af9199af9e69b889claireho        }
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
48527f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
48627f654740f2a26ad62a5c155af9199af9e69b889claireho     * Deletes the memory block (if owned) and allocates a new one,
48727f654740f2a26ad62a5c155af9199af9e69b889claireho     * copying the header and length T array items.
48827f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the new header pointer.
48927f654740f2a26ad62a5c155af9199af9e69b889claireho     * If the allocation fails, then the current memory is unchanged and
49027f654740f2a26ad62a5c155af9199af9e69b889claireho     * this method returns NULL.
49127f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param newCapacity can be less than or greater than the current capacity;
49227f654740f2a26ad62a5c155af9199af9e69b889claireho     *                    must be >0
49327f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param length number of T items to be copied from the old array to the new one
49427f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the allocated pointer, or NULL if the allocation failed
49527f654740f2a26ad62a5c155af9199af9e69b889claireho     */
49627f654740f2a26ad62a5c155af9199af9e69b889claireho    inline H *resize(int32_t newCapacity, int32_t length=0);
49727f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
49827f654740f2a26ad62a5c155af9199af9e69b889claireho     * Gives up ownership of the memory if owned, or else clones it,
49927f654740f2a26ad62a5c155af9199af9e69b889claireho     * copying the header and length T array items; resets itself to the internal memory.
50027f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns NULL if the allocation failed.
50127f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param length number of T items to copy when cloning,
50227f654740f2a26ad62a5c155af9199af9e69b889claireho     *        and array capacity of the clone when cloning
50327f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param resultCapacity will be set to the returned array's capacity (output-only)
50427f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the header pointer;
50527f654740f2a26ad62a5c155af9199af9e69b889claireho     *         caller becomes responsible for deleting the array
50627f654740f2a26ad62a5c155af9199af9e69b889claireho     */
50727f654740f2a26ad62a5c155af9199af9e69b889claireho    inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
50827f654740f2a26ad62a5c155af9199af9e69b889clairehoprivate:
50927f654740f2a26ad62a5c155af9199af9e69b889claireho    H *ptr;
51027f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t capacity;
51127f654740f2a26ad62a5c155af9199af9e69b889claireho    UBool needToRelease;
51227f654740f2a26ad62a5c155af9199af9e69b889claireho    // stackHeader must precede stackArray immediately.
51327f654740f2a26ad62a5c155af9199af9e69b889claireho    H stackHeader;
51427f654740f2a26ad62a5c155af9199af9e69b889claireho    T stackArray[stackCapacity];
51527f654740f2a26ad62a5c155af9199af9e69b889claireho    void releaseMemory() {
51627f654740f2a26ad62a5c155af9199af9e69b889claireho        if(needToRelease) {
51727f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_free(ptr);
51827f654740f2a26ad62a5c155af9199af9e69b889claireho        }
51927f654740f2a26ad62a5c155af9199af9e69b889claireho    }
52027f654740f2a26ad62a5c155af9199af9e69b889claireho    /* No comparison operators with other MaybeStackHeaderAndArray's. */
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;}
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;}
52327f654740f2a26ad62a5c155af9199af9e69b889claireho    /* No ownership transfer: No copy constructor, no assignment operator. */
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
52627f654740f2a26ad62a5c155af9199af9e69b889claireho
52727f654740f2a26ad62a5c155af9199af9e69b889claireho    // No heap allocation. Use only on the stack.
52827f654740f2a26ad62a5c155af9199af9e69b889claireho    //   (Declaring these functions private triggers a cascade of problems;
52927f654740f2a26ad62a5c155af9199af9e69b889claireho    //    see the MaybeStackArray class for details.)
53027f654740f2a26ad62a5c155af9199af9e69b889claireho    // static void * U_EXPORT2 operator new(size_t size);
53127f654740f2a26ad62a5c155af9199af9e69b889claireho    // static void * U_EXPORT2 operator new[](size_t size);
53227f654740f2a26ad62a5c155af9199af9e69b889claireho#if U_HAVE_PLACEMENT_NEW
53327f654740f2a26ad62a5c155af9199af9e69b889claireho    // static void * U_EXPORT2 operator new(size_t, void *ptr);
53427f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
53527f654740f2a26ad62a5c155af9199af9e69b889claireho};
53627f654740f2a26ad62a5c155af9199af9e69b889claireho
53727f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename H, typename T, int32_t stackCapacity>
53827f654740f2a26ad62a5c155af9199af9e69b889clairehoinline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
53927f654740f2a26ad62a5c155af9199af9e69b889claireho                                                                int32_t length) {
54027f654740f2a26ad62a5c155af9199af9e69b889claireho    if(newCapacity>=0) {
541103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
542103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
543103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
54427f654740f2a26ad62a5c155af9199af9e69b889claireho        H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
54527f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p!=NULL) {
54627f654740f2a26ad62a5c155af9199af9e69b889claireho            if(length<0) {
54727f654740f2a26ad62a5c155af9199af9e69b889claireho                length=0;
54827f654740f2a26ad62a5c155af9199af9e69b889claireho            } else if(length>0) {
54927f654740f2a26ad62a5c155af9199af9e69b889claireho                if(length>capacity) {
55027f654740f2a26ad62a5c155af9199af9e69b889claireho                    length=capacity;
55127f654740f2a26ad62a5c155af9199af9e69b889claireho                }
55227f654740f2a26ad62a5c155af9199af9e69b889claireho                if(length>newCapacity) {
55327f654740f2a26ad62a5c155af9199af9e69b889claireho                    length=newCapacity;
55427f654740f2a26ad62a5c155af9199af9e69b889claireho                }
55527f654740f2a26ad62a5c155af9199af9e69b889claireho            }
55627f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
55727f654740f2a26ad62a5c155af9199af9e69b889claireho            releaseMemory();
55827f654740f2a26ad62a5c155af9199af9e69b889claireho            ptr=p;
55927f654740f2a26ad62a5c155af9199af9e69b889claireho            capacity=newCapacity;
56027f654740f2a26ad62a5c155af9199af9e69b889claireho            needToRelease=TRUE;
56127f654740f2a26ad62a5c155af9199af9e69b889claireho        }
56227f654740f2a26ad62a5c155af9199af9e69b889claireho        return p;
56327f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
56427f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
56527f654740f2a26ad62a5c155af9199af9e69b889claireho    }
56627f654740f2a26ad62a5c155af9199af9e69b889claireho}
56727f654740f2a26ad62a5c155af9199af9e69b889claireho
56827f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename H, typename T, int32_t stackCapacity>
56927f654740f2a26ad62a5c155af9199af9e69b889clairehoinline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
57027f654740f2a26ad62a5c155af9199af9e69b889claireho                                                                       int32_t &resultCapacity) {
57127f654740f2a26ad62a5c155af9199af9e69b889claireho    H *p;
57227f654740f2a26ad62a5c155af9199af9e69b889claireho    if(needToRelease) {
57327f654740f2a26ad62a5c155af9199af9e69b889claireho        p=ptr;
57427f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
57527f654740f2a26ad62a5c155af9199af9e69b889claireho        if(length<0) {
57627f654740f2a26ad62a5c155af9199af9e69b889claireho            length=0;
57727f654740f2a26ad62a5c155af9199af9e69b889claireho        } else if(length>capacity) {
57827f654740f2a26ad62a5c155af9199af9e69b889claireho            length=capacity;
57927f654740f2a26ad62a5c155af9199af9e69b889claireho        }
580103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
581103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
582103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
58327f654740f2a26ad62a5c155af9199af9e69b889claireho        p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
58427f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p==NULL) {
58527f654740f2a26ad62a5c155af9199af9e69b889claireho            return NULL;
58627f654740f2a26ad62a5c155af9199af9e69b889claireho        }
58727f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
58827f654740f2a26ad62a5c155af9199af9e69b889claireho    }
58927f654740f2a26ad62a5c155af9199af9e69b889claireho    resultCapacity=length;
59027f654740f2a26ad62a5c155af9199af9e69b889claireho    ptr=&stackHeader;
59127f654740f2a26ad62a5c155af9199af9e69b889claireho    capacity=stackCapacity;
59227f654740f2a26ad62a5c155af9199af9e69b889claireho    needToRelease=FALSE;
59327f654740f2a26ad62a5c155af9199af9e69b889claireho    return p;
59427f654740f2a26ad62a5c155af9199af9e69b889claireho}
59527f654740f2a26ad62a5c155af9199af9e69b889claireho
59650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_END
59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
598103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif  /* __cplusplus */
59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif  /* CMEMORY_H */
600