1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
41b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert*   Copyright (C) 1997-2015, 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
62f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius/**
63f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * \def UPRV_LENGTHOF
64f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Convenience macro to determine the length of a fixed array at compile-time.
65f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * @param array A fixed length array
66f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * @return The length of the array, in elements
67f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * @internal
68f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */
69f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#define UPRV_LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define uprv_memset(buffer, mark, size) U_STANDARD_CPP_NAMESPACE memset(buffer, mark, size)
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define uprv_memcmp(buffer1, buffer2, size) U_STANDARD_CPP_NAMESPACE memcmp(buffer1, buffer2,size)
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void * U_EXPORT2
7454dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusuprv_malloc(size_t s) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR(1);
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void * U_EXPORT2
7754dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusuprv_realloc(void *mem, size_t size) U_ALLOC_SIZE_ATTR(2);
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CAPI void U_EXPORT2
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruuprv_free(void *mem);
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
82103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI void * U_EXPORT2
8354dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusuprv_calloc(size_t num, size_t size) U_MALLOC_ATTR U_ALLOC_SIZE_ATTR2(1,2);
84103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This should align the memory properly on any machine.
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is very useful for the safeClone functions.
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querutypedef union {
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    long    t1;
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    double  t2;
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    void   *t3;
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} UAlignedMemory;
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Get the least significant bits of a pointer (a memory address).
97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * For example, with a mask of 3, the macro gets the 2 least significant bits,
98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * which will be 0 if the pointer is 32-bit (4-byte) aligned.
99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *
100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * ptrdiff_t is the most appropriate integer type to cast to.
101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * size_t should work too, since on most (or all?) platforms it has the same
102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * width as ptrdiff_t.
103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */
104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define U_POINTER_MASK_LSB(ptr, mask) (((ptrdiff_t)(char *)(ptr)) & (mask))
105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru
106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/**
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Get the amount of bytes that a pointer is off by from
108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * the previous UAlignedMemory-aligned pointer.
109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define U_ALIGNMENT_OFFSET(ptr) U_POINTER_MASK_LSB(ptr, sizeof(UAlignedMemory) - 1)
111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Get the amount of bytes to add to a pointer
114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * in order to get the next UAlignedMemory-aligned address.
115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_ALIGNMENT_OFFSET_UP(ptr) (sizeof(UAlignedMemory) - U_ALIGNMENT_OFFSET(ptr))
117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *  Heap clean up function, called from u_cleanup()
120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *    Clears any user heap functions from u_setMemoryFunctions()
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  *    Does NOT deallocate any remaining allocated memory.
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  */
123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CFUNC UBool
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querucmemory_cleanup(void);
125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
126103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/**
127103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * A function called by <TT>uhash_remove</TT>,
128103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * <TT>uhash_close</TT>, or <TT>uhash_put</TT> to delete
129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * an existing key or value.
130103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * @param obj A key or value stored in a hashtable
131103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * @see uprv_deleteUObject
132103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */
133103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliustypedef void U_CALLCONV UObjectDeleter(void* obj);
134103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
135103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius/**
136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Deleter for UObject instances.
137103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius * Works for all subclasses of UObject because it has a virtual destructor.
138103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius */
139103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusU_CAPI void U_EXPORT2
140103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusuprv_deleteUObject(void *obj);
141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
142103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#ifdef __cplusplus
14350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
14450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_BEGIN
14550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
14650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/**
14750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * "Smart pointer" class, deletes memory via uprv_free().
14850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * For most methods see the LocalPointerBase base class.
14950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Adds operator[] for array item access.
15050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
15150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * @see LocalPointerBase
15250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
15350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T>
15450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass LocalMemory : public LocalPointerBase<T> {
15550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehopublic:
15650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
15750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Constructor takes ownership.
15850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param p simple pointer to an array of T items that is adopted
15950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
16050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    explicit LocalMemory(T *p=NULL) : LocalPointerBase<T>(p) {}
161c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#if U_HAVE_RVALUE_REFERENCES
162c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    /**
163c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * Move constructor, leaves src with isNull().
164c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @param src source smart pointer
165c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     */
166c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory(LocalMemory<T> &&src) U_NOEXCEPT : LocalPointerBase<T>(src.ptr) {
167c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        src.ptr=NULL;
168c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
169c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#endif
17050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
17150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Destructor deletes the memory it owns.
17250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
17350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ~LocalMemory() {
17450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uprv_free(LocalPointerBase<T>::ptr);
17550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
176c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#if U_HAVE_RVALUE_REFERENCES
177c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    /**
178c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * Move assignment operator, leaves src with isNull().
179c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * The behavior is undefined if *this and src are the same object.
180c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @param src source smart pointer
181c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @return *this
182c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     */
183c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<T> &operator=(LocalMemory<T> &&src) U_NOEXCEPT {
184c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return moveFrom(src);
185c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
186c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#endif
187c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    /**
188c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * Move assignment, leaves src with isNull().
189c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * The behavior is undefined if *this and src are the same object.
190c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     *
191c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * Can be called explicitly, does not need C++11 support.
192c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @param src source smart pointer
193c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @return *this
194c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     */
195c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    LocalMemory<T> &moveFrom(LocalMemory<T> &src) U_NOEXCEPT {
196c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete[] LocalPointerBase<T>::ptr;
197c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        LocalPointerBase<T>::ptr=src.ptr;
198c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        src.ptr=NULL;
199c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return *this;
200c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
201c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    /**
202c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * Swap pointers.
203c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @param other other smart pointer
204c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     */
205c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    void swap(LocalMemory<T> &other) U_NOEXCEPT {
206c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        T *temp=LocalPointerBase<T>::ptr;
207c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        LocalPointerBase<T>::ptr=other.ptr;
208c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        other.ptr=temp;
209c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
210c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    /**
211c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * Non-member LocalMemory swap function.
212c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @param p1 will get p2's pointer
213c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     * @param p2 will get p1's pointer
214c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert     */
215c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    friend inline void swap(LocalMemory<T> &p1, LocalMemory<T> &p2) U_NOEXCEPT {
216c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        p1.swap(p2);
217c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
21850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
21950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array it owns,
22050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * and adopts (takes ownership of) the one passed in.
22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param p simple pointer to an array of T items that is adopted
22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
22350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    void adoptInstead(T *p) {
22450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uprv_free(LocalPointerBase<T>::ptr);
22550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        LocalPointerBase<T>::ptr=p;
22650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
22750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
22850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array it owns, allocates a new one and reset its bytes to 0.
22950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the new array pointer.
23050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the allocation fails, then the current array is unchanged and
23150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * this method returns NULL.
23250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param newCapacity must be >0
23350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the allocated array pointer, or NULL if the allocation failed
23450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
23550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *allocateInsteadAndReset(int32_t newCapacity=1);
23650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
23750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array it owns and allocates a new one, copying length T items.
23850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the new array pointer.
23950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the allocation fails, then the current array is unchanged and
24050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * this method returns NULL.
24150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param newCapacity must be >0
24250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param length number of T items to be copied from the old array to the new one;
24350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *               must be no more than the capacity of the old array,
24450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *               which the caller must track because the LocalMemory does not track it
24550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the allocated array pointer, or NULL if the allocation failed
24650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
24750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *allocateInsteadAndCopy(int32_t newCapacity=1, int32_t length=0);
24850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
24950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Array item access (writable).
25050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * No index bounds check.
25150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param i array index
25250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return reference to the array item
25350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
25450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T &operator[](ptrdiff_t i) const { return LocalPointerBase<T>::ptr[i]; }
25550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho};
25650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
25727f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename T>
25827f654740f2a26ad62a5c155af9199af9e69b889clairehoinline T *LocalMemory<T>::allocateInsteadAndReset(int32_t newCapacity) {
25927f654740f2a26ad62a5c155af9199af9e69b889claireho    if(newCapacity>0) {
26027f654740f2a26ad62a5c155af9199af9e69b889claireho        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
26127f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p!=NULL) {
26227f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_memset(p, 0, newCapacity*sizeof(T));
26327f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_free(LocalPointerBase<T>::ptr);
26427f654740f2a26ad62a5c155af9199af9e69b889claireho            LocalPointerBase<T>::ptr=p;
26527f654740f2a26ad62a5c155af9199af9e69b889claireho        }
26627f654740f2a26ad62a5c155af9199af9e69b889claireho        return p;
26727f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
26827f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
26927f654740f2a26ad62a5c155af9199af9e69b889claireho    }
27027f654740f2a26ad62a5c155af9199af9e69b889claireho}
27127f654740f2a26ad62a5c155af9199af9e69b889claireho
27227f654740f2a26ad62a5c155af9199af9e69b889claireho
27327f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename T>
27427f654740f2a26ad62a5c155af9199af9e69b889clairehoinline T *LocalMemory<T>::allocateInsteadAndCopy(int32_t newCapacity, int32_t length) {
27527f654740f2a26ad62a5c155af9199af9e69b889claireho    if(newCapacity>0) {
27627f654740f2a26ad62a5c155af9199af9e69b889claireho        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
27727f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p!=NULL) {
27827f654740f2a26ad62a5c155af9199af9e69b889claireho            if(length>0) {
27927f654740f2a26ad62a5c155af9199af9e69b889claireho                if(length>newCapacity) {
28027f654740f2a26ad62a5c155af9199af9e69b889claireho                    length=newCapacity;
28127f654740f2a26ad62a5c155af9199af9e69b889claireho                }
28227f654740f2a26ad62a5c155af9199af9e69b889claireho                uprv_memcpy(p, LocalPointerBase<T>::ptr, length*sizeof(T));
28327f654740f2a26ad62a5c155af9199af9e69b889claireho            }
28427f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_free(LocalPointerBase<T>::ptr);
28527f654740f2a26ad62a5c155af9199af9e69b889claireho            LocalPointerBase<T>::ptr=p;
28627f654740f2a26ad62a5c155af9199af9e69b889claireho        }
28727f654740f2a26ad62a5c155af9199af9e69b889claireho        return p;
28827f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
28927f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
29027f654740f2a26ad62a5c155af9199af9e69b889claireho    }
29127f654740f2a26ad62a5c155af9199af9e69b889claireho}
29227f654740f2a26ad62a5c155af9199af9e69b889claireho
29350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/**
29450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Simple array/buffer management class using uprv_malloc() and uprv_free().
29550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Provides an internal array with fixed capacity. Can alias another array
29650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * or allocate one.
29727f654740f2a26ad62a5c155af9199af9e69b889claireho *
29827f654740f2a26ad62a5c155af9199af9e69b889claireho * The array address is properly aligned for type T. It might not be properly
29927f654740f2a26ad62a5c155af9199af9e69b889claireho * aligned for types larger than T (or larger than the largest subtype of T).
30027f654740f2a26ad62a5c155af9199af9e69b889claireho *
30150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Unlike LocalMemory and LocalArray, this class never adopts
30250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * (takes ownership of) another array.
30350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho */
30450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T, int32_t stackCapacity>
30550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoclass MaybeStackArray {
30650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehopublic:
30750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
30850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Default constructor initializes with internal T[stackCapacity] buffer.
30950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
31027f654740f2a26ad62a5c155af9199af9e69b889claireho    MaybeStackArray() : ptr(stackArray), capacity(stackCapacity), needToRelease(FALSE) {}
31150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
31250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Destructor deletes the array (if owned).
31350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
31450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ~MaybeStackArray() { releaseArray(); }
31550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
31650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the array capacity (number of T items).
31750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return array capacity
31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
31950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t getCapacity() const { return capacity; }
32050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
32150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Access without ownership change.
32250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the array pointer
32350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
32450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *getAlias() const { return ptr; }
32550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
32650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the array limit. Simple convenience method.
32750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return getAlias()+getCapacity()
32850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
32950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *getArrayLimit() const { return getAlias()+capacity; }
33054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    // No "operator T *() const" because that can make
33154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    // expressions like mbs[index] ambiguous for some compilers.
33250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
33354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * Array item access (const).
33454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * No index bounds check.
33554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * @param i array index
33654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius     * @return reference to the array item
33750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
33854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    const T &operator[](ptrdiff_t i) const { return ptr[i]; }
33950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
34050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Array item access (writable).
34150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * No index bounds check.
34250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param i array index
34350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return reference to the array item
34450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
34550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T &operator[](ptrdiff_t i) { return ptr[i]; }
34650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
34750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array (if owned) and aliases another one, no transfer of ownership.
34850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the arguments are illegal, then the current array is unchanged.
34950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param otherArray must not be NULL
35050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param otherCapacity must be >0
35150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
35250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    void aliasInstead(T *otherArray, int32_t otherCapacity) {
35350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(otherArray!=NULL && otherCapacity>0) {
35450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            releaseArray();
35550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ptr=otherArray;
35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            capacity=otherCapacity;
35750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            needToRelease=FALSE;
35850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
36050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
36150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Deletes the array (if owned) and allocates a new one, copying length T items.
36250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns the new array pointer.
36350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * If the allocation fails, then the current array is unchanged and
36450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * this method returns NULL.
36550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param newCapacity can be less than or greater than the current capacity;
36650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *                    must be >0
36750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param length number of T items to be copied from the old array to the new one
36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the allocated array pointer, or NULL if the allocation failed
36950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
37050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *resize(int32_t newCapacity, int32_t length=0);
37150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /**
37250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Gives up ownership of the array if owned, or else clones it,
37350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * copying length T items; resets itself to the internal stack array.
37450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * Returns NULL if the allocation failed.
37550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param length number of T items to copy when cloning,
37650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *        and capacity of the clone when cloning
37750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @param resultCapacity will be set to the returned array's capacity (output-only)
37850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     * @return the array pointer;
37950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     *         caller becomes responsible for deleting the array
38050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho     */
38150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    inline T *orphanOrClone(int32_t length, int32_t &resultCapacity);
38250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoprivate:
38350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *ptr;
38427f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t capacity;
38527f654740f2a26ad62a5c155af9199af9e69b889claireho    UBool needToRelease;
38650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T stackArray[stackCapacity];
38750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    void releaseArray() {
38850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(needToRelease) {
38950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            uprv_free(ptr);
39050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
39150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
39250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* No comparison operators with other MaybeStackArray's. */
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator==(const MaybeStackArray & /*other*/) {return FALSE;}
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;}
39550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    /* No ownership transfer: No copy constructor, no assignment operator. */
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MaybeStackArray(const MaybeStackArray & /*other*/) {}
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void operator=(const MaybeStackArray & /*other*/) {}
39850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // No heap allocation. Use only on the stack.
40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //   (Declaring these functions private triggers a cascade of problems:
40150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      MSVC insists on exporting an instantiation of MaybeStackArray, which
40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      requires that all functions be defined.
40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      An empty implementation of new() is rejected, it must return a value.
40450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      Returning NULL is rejected by gcc for operator new.
40550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      The expedient thing is just not to override operator new.
40650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    //      While relatively pointless, heap allocated instances will function.
40750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // static void * U_EXPORT2 operator new(size_t size);
40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // static void * U_EXPORT2 operator new[](size_t size);
40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#if U_HAVE_PLACEMENT_NEW
41050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // static void * U_EXPORT2 operator new(size_t, void *ptr);
411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
41250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho};
41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
41450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T, int32_t stackCapacity>
41550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoinline T *MaybeStackArray<T, stackCapacity>::resize(int32_t newCapacity, int32_t length) {
41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(newCapacity>0) {
417103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
418103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStacArray (resize) alloc %d * %lu\n", newCapacity,sizeof(T));
419103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
42050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        T *p=(T *)uprv_malloc(newCapacity*sizeof(T));
42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(p!=NULL) {
42250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            if(length>0) {
42350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(length>capacity) {
42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    length=capacity;
42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if(length>newCapacity) {
42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    length=newCapacity;
42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                uprv_memcpy(p, ptr, length*sizeof(T));
43050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
43150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            releaseArray();
43250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            ptr=p;
43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            capacity=newCapacity;
43450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            needToRelease=TRUE;
43550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return p;
43750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
43850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return NULL;
43950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
44250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehotemplate<typename T, int32_t stackCapacity>
44350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoinline T *MaybeStackArray<T, stackCapacity>::orphanOrClone(int32_t length, int32_t &resultCapacity) {
44450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    T *p;
44550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    if(needToRelease) {
44650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=ptr;
44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else if(length<=0) {
44850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        return NULL;
44950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    } else {
45050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(length>capacity) {
45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            length=capacity;
45250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
45350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        p=(T *)uprv_malloc(length*sizeof(T));
454103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
455103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStacArray (orphan) alloc %d * %lu\n", length,sizeof(T));
456103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
45750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if(p==NULL) {
45850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            return NULL;
45950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        }
46050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        uprv_memcpy(p, ptr, length*sizeof(T));
46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
46250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    resultCapacity=length;
46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ptr=stackArray;
46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    capacity=stackCapacity;
46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    needToRelease=FALSE;
46650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return p;
46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
46927f654740f2a26ad62a5c155af9199af9e69b889claireho/**
47027f654740f2a26ad62a5c155af9199af9e69b889claireho * Variant of MaybeStackArray that allocates a header struct and an array
47127f654740f2a26ad62a5c155af9199af9e69b889claireho * in one contiguous memory block, using uprv_malloc() and uprv_free().
47227f654740f2a26ad62a5c155af9199af9e69b889claireho * Provides internal memory with fixed array capacity. Can alias another memory
47327f654740f2a26ad62a5c155af9199af9e69b889claireho * block or allocate one.
47427f654740f2a26ad62a5c155af9199af9e69b889claireho * The stackCapacity is the number of T items in the internal memory,
47527f654740f2a26ad62a5c155af9199af9e69b889claireho * not counting the H header.
47627f654740f2a26ad62a5c155af9199af9e69b889claireho * Unlike LocalMemory and LocalArray, this class never adopts
47727f654740f2a26ad62a5c155af9199af9e69b889claireho * (takes ownership of) another memory block.
47827f654740f2a26ad62a5c155af9199af9e69b889claireho */
47927f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename H, typename T, int32_t stackCapacity>
48027f654740f2a26ad62a5c155af9199af9e69b889clairehoclass MaybeStackHeaderAndArray {
48127f654740f2a26ad62a5c155af9199af9e69b889clairehopublic:
48227f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
48327f654740f2a26ad62a5c155af9199af9e69b889claireho     * Default constructor initializes with internal H+T[stackCapacity] buffer.
48427f654740f2a26ad62a5c155af9199af9e69b889claireho     */
48527f654740f2a26ad62a5c155af9199af9e69b889claireho    MaybeStackHeaderAndArray() : ptr(&stackHeader), capacity(stackCapacity), needToRelease(FALSE) {}
48627f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
48727f654740f2a26ad62a5c155af9199af9e69b889claireho     * Destructor deletes the memory (if owned).
48827f654740f2a26ad62a5c155af9199af9e69b889claireho     */
48927f654740f2a26ad62a5c155af9199af9e69b889claireho    ~MaybeStackHeaderAndArray() { releaseMemory(); }
49027f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
49127f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the array capacity (number of T items).
49227f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return array capacity
49327f654740f2a26ad62a5c155af9199af9e69b889claireho     */
49427f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t getCapacity() const { return capacity; }
49527f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
49627f654740f2a26ad62a5c155af9199af9e69b889claireho     * Access without ownership change.
49727f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the header pointer
49827f654740f2a26ad62a5c155af9199af9e69b889claireho     */
49927f654740f2a26ad62a5c155af9199af9e69b889claireho    H *getAlias() const { return ptr; }
50027f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
50127f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the array start.
50227f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return array start, same address as getAlias()+1
50327f654740f2a26ad62a5c155af9199af9e69b889claireho     */
50427f654740f2a26ad62a5c155af9199af9e69b889claireho    T *getArrayStart() const { return reinterpret_cast<T *>(getAlias()+1); }
50527f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
50627f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the array limit.
50727f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return array limit
50827f654740f2a26ad62a5c155af9199af9e69b889claireho     */
50927f654740f2a26ad62a5c155af9199af9e69b889claireho    T *getArrayLimit() const { return getArrayStart()+capacity; }
51027f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
51127f654740f2a26ad62a5c155af9199af9e69b889claireho     * Access without ownership change. Same as getAlias().
51227f654740f2a26ad62a5c155af9199af9e69b889claireho     * A class instance can be used directly in expressions that take a T *.
51327f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the header pointer
51427f654740f2a26ad62a5c155af9199af9e69b889claireho     */
51527f654740f2a26ad62a5c155af9199af9e69b889claireho    operator H *() const { return ptr; }
51627f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
51727f654740f2a26ad62a5c155af9199af9e69b889claireho     * Array item access (writable).
51827f654740f2a26ad62a5c155af9199af9e69b889claireho     * No index bounds check.
51927f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param i array index
52027f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return reference to the array item
52127f654740f2a26ad62a5c155af9199af9e69b889claireho     */
52227f654740f2a26ad62a5c155af9199af9e69b889claireho    T &operator[](ptrdiff_t i) { return getArrayStart()[i]; }
52327f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
52427f654740f2a26ad62a5c155af9199af9e69b889claireho     * Deletes the memory block (if owned) and aliases another one, no transfer of ownership.
52527f654740f2a26ad62a5c155af9199af9e69b889claireho     * If the arguments are illegal, then the current memory is unchanged.
52627f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param otherArray must not be NULL
52727f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param otherCapacity must be >0
52827f654740f2a26ad62a5c155af9199af9e69b889claireho     */
52927f654740f2a26ad62a5c155af9199af9e69b889claireho    void aliasInstead(H *otherMemory, int32_t otherCapacity) {
53027f654740f2a26ad62a5c155af9199af9e69b889claireho        if(otherMemory!=NULL && otherCapacity>0) {
53127f654740f2a26ad62a5c155af9199af9e69b889claireho            releaseMemory();
53227f654740f2a26ad62a5c155af9199af9e69b889claireho            ptr=otherMemory;
53327f654740f2a26ad62a5c155af9199af9e69b889claireho            capacity=otherCapacity;
53427f654740f2a26ad62a5c155af9199af9e69b889claireho            needToRelease=FALSE;
53527f654740f2a26ad62a5c155af9199af9e69b889claireho        }
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
53727f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
53827f654740f2a26ad62a5c155af9199af9e69b889claireho     * Deletes the memory block (if owned) and allocates a new one,
53927f654740f2a26ad62a5c155af9199af9e69b889claireho     * copying the header and length T array items.
54027f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns the new header pointer.
54127f654740f2a26ad62a5c155af9199af9e69b889claireho     * If the allocation fails, then the current memory is unchanged and
54227f654740f2a26ad62a5c155af9199af9e69b889claireho     * this method returns NULL.
54327f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param newCapacity can be less than or greater than the current capacity;
54427f654740f2a26ad62a5c155af9199af9e69b889claireho     *                    must be >0
54527f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param length number of T items to be copied from the old array to the new one
54627f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the allocated pointer, or NULL if the allocation failed
54727f654740f2a26ad62a5c155af9199af9e69b889claireho     */
54827f654740f2a26ad62a5c155af9199af9e69b889claireho    inline H *resize(int32_t newCapacity, int32_t length=0);
54927f654740f2a26ad62a5c155af9199af9e69b889claireho    /**
55027f654740f2a26ad62a5c155af9199af9e69b889claireho     * Gives up ownership of the memory if owned, or else clones it,
55127f654740f2a26ad62a5c155af9199af9e69b889claireho     * copying the header and length T array items; resets itself to the internal memory.
55227f654740f2a26ad62a5c155af9199af9e69b889claireho     * Returns NULL if the allocation failed.
55327f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param length number of T items to copy when cloning,
55427f654740f2a26ad62a5c155af9199af9e69b889claireho     *        and array capacity of the clone when cloning
55527f654740f2a26ad62a5c155af9199af9e69b889claireho     * @param resultCapacity will be set to the returned array's capacity (output-only)
55627f654740f2a26ad62a5c155af9199af9e69b889claireho     * @return the header pointer;
55727f654740f2a26ad62a5c155af9199af9e69b889claireho     *         caller becomes responsible for deleting the array
55827f654740f2a26ad62a5c155af9199af9e69b889claireho     */
55927f654740f2a26ad62a5c155af9199af9e69b889claireho    inline H *orphanOrClone(int32_t length, int32_t &resultCapacity);
56027f654740f2a26ad62a5c155af9199af9e69b889clairehoprivate:
56127f654740f2a26ad62a5c155af9199af9e69b889claireho    H *ptr;
56227f654740f2a26ad62a5c155af9199af9e69b889claireho    int32_t capacity;
56327f654740f2a26ad62a5c155af9199af9e69b889claireho    UBool needToRelease;
56427f654740f2a26ad62a5c155af9199af9e69b889claireho    // stackHeader must precede stackArray immediately.
56527f654740f2a26ad62a5c155af9199af9e69b889claireho    H stackHeader;
56627f654740f2a26ad62a5c155af9199af9e69b889claireho    T stackArray[stackCapacity];
56727f654740f2a26ad62a5c155af9199af9e69b889claireho    void releaseMemory() {
56827f654740f2a26ad62a5c155af9199af9e69b889claireho        if(needToRelease) {
56927f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_free(ptr);
57027f654740f2a26ad62a5c155af9199af9e69b889claireho        }
57127f654740f2a26ad62a5c155af9199af9e69b889claireho    }
57227f654740f2a26ad62a5c155af9199af9e69b889claireho    /* No comparison operators with other MaybeStackHeaderAndArray's. */
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator==(const MaybeStackHeaderAndArray & /*other*/) {return FALSE;}
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    bool operator!=(const MaybeStackHeaderAndArray & /*other*/) {return TRUE;}
57527f654740f2a26ad62a5c155af9199af9e69b889claireho    /* No ownership transfer: No copy constructor, no assignment operator. */
576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {}
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void operator=(const MaybeStackHeaderAndArray & /*other*/) {}
57827f654740f2a26ad62a5c155af9199af9e69b889claireho
57927f654740f2a26ad62a5c155af9199af9e69b889claireho    // No heap allocation. Use only on the stack.
58027f654740f2a26ad62a5c155af9199af9e69b889claireho    //   (Declaring these functions private triggers a cascade of problems;
58127f654740f2a26ad62a5c155af9199af9e69b889claireho    //    see the MaybeStackArray class for details.)
58227f654740f2a26ad62a5c155af9199af9e69b889claireho    // static void * U_EXPORT2 operator new(size_t size);
58327f654740f2a26ad62a5c155af9199af9e69b889claireho    // static void * U_EXPORT2 operator new[](size_t size);
58427f654740f2a26ad62a5c155af9199af9e69b889claireho#if U_HAVE_PLACEMENT_NEW
58527f654740f2a26ad62a5c155af9199af9e69b889claireho    // static void * U_EXPORT2 operator new(size_t, void *ptr);
58627f654740f2a26ad62a5c155af9199af9e69b889claireho#endif
58727f654740f2a26ad62a5c155af9199af9e69b889claireho};
58827f654740f2a26ad62a5c155af9199af9e69b889claireho
58927f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename H, typename T, int32_t stackCapacity>
59027f654740f2a26ad62a5c155af9199af9e69b889clairehoinline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::resize(int32_t newCapacity,
59127f654740f2a26ad62a5c155af9199af9e69b889claireho                                                                int32_t length) {
59227f654740f2a26ad62a5c155af9199af9e69b889claireho    if(newCapacity>=0) {
593103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
594103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStackHeaderAndArray alloc %d + %d * %ul\n", sizeof(H),newCapacity,sizeof(T));
595103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
59627f654740f2a26ad62a5c155af9199af9e69b889claireho        H *p=(H *)uprv_malloc(sizeof(H)+newCapacity*sizeof(T));
59727f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p!=NULL) {
59827f654740f2a26ad62a5c155af9199af9e69b889claireho            if(length<0) {
59927f654740f2a26ad62a5c155af9199af9e69b889claireho                length=0;
60027f654740f2a26ad62a5c155af9199af9e69b889claireho            } else if(length>0) {
60127f654740f2a26ad62a5c155af9199af9e69b889claireho                if(length>capacity) {
60227f654740f2a26ad62a5c155af9199af9e69b889claireho                    length=capacity;
60327f654740f2a26ad62a5c155af9199af9e69b889claireho                }
60427f654740f2a26ad62a5c155af9199af9e69b889claireho                if(length>newCapacity) {
60527f654740f2a26ad62a5c155af9199af9e69b889claireho                    length=newCapacity;
60627f654740f2a26ad62a5c155af9199af9e69b889claireho                }
60727f654740f2a26ad62a5c155af9199af9e69b889claireho            }
60827f654740f2a26ad62a5c155af9199af9e69b889claireho            uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
60927f654740f2a26ad62a5c155af9199af9e69b889claireho            releaseMemory();
61027f654740f2a26ad62a5c155af9199af9e69b889claireho            ptr=p;
61127f654740f2a26ad62a5c155af9199af9e69b889claireho            capacity=newCapacity;
61227f654740f2a26ad62a5c155af9199af9e69b889claireho            needToRelease=TRUE;
61327f654740f2a26ad62a5c155af9199af9e69b889claireho        }
61427f654740f2a26ad62a5c155af9199af9e69b889claireho        return p;
61527f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
61627f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
61727f654740f2a26ad62a5c155af9199af9e69b889claireho    }
61827f654740f2a26ad62a5c155af9199af9e69b889claireho}
61927f654740f2a26ad62a5c155af9199af9e69b889claireho
62027f654740f2a26ad62a5c155af9199af9e69b889clairehotemplate<typename H, typename T, int32_t stackCapacity>
62127f654740f2a26ad62a5c155af9199af9e69b889clairehoinline H *MaybeStackHeaderAndArray<H, T, stackCapacity>::orphanOrClone(int32_t length,
62227f654740f2a26ad62a5c155af9199af9e69b889claireho                                                                       int32_t &resultCapacity) {
62327f654740f2a26ad62a5c155af9199af9e69b889claireho    H *p;
62427f654740f2a26ad62a5c155af9199af9e69b889claireho    if(needToRelease) {
62527f654740f2a26ad62a5c155af9199af9e69b889claireho        p=ptr;
62627f654740f2a26ad62a5c155af9199af9e69b889claireho    } else {
62727f654740f2a26ad62a5c155af9199af9e69b889claireho        if(length<0) {
62827f654740f2a26ad62a5c155af9199af9e69b889claireho            length=0;
62927f654740f2a26ad62a5c155af9199af9e69b889claireho        } else if(length>capacity) {
63027f654740f2a26ad62a5c155af9199af9e69b889claireho            length=capacity;
63127f654740f2a26ad62a5c155af9199af9e69b889claireho        }
632103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_DEBUG && defined(UPRV_MALLOC_COUNT)
633103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius      ::fprintf(::stderr,"MaybeStackHeaderAndArray (orphan) alloc %ul + %d * %lu\n", sizeof(H),length,sizeof(T));
634103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif
63527f654740f2a26ad62a5c155af9199af9e69b889claireho        p=(H *)uprv_malloc(sizeof(H)+length*sizeof(T));
63627f654740f2a26ad62a5c155af9199af9e69b889claireho        if(p==NULL) {
63727f654740f2a26ad62a5c155af9199af9e69b889claireho            return NULL;
63827f654740f2a26ad62a5c155af9199af9e69b889claireho        }
63927f654740f2a26ad62a5c155af9199af9e69b889claireho        uprv_memcpy(p, ptr, sizeof(H)+length*sizeof(T));
64027f654740f2a26ad62a5c155af9199af9e69b889claireho    }
64127f654740f2a26ad62a5c155af9199af9e69b889claireho    resultCapacity=length;
64227f654740f2a26ad62a5c155af9199af9e69b889claireho    ptr=&stackHeader;
64327f654740f2a26ad62a5c155af9199af9e69b889claireho    capacity=stackCapacity;
64427f654740f2a26ad62a5c155af9199af9e69b889claireho    needToRelease=FALSE;
64527f654740f2a26ad62a5c155af9199af9e69b889claireho    return p;
64627f654740f2a26ad62a5c155af9199af9e69b889claireho}
64727f654740f2a26ad62a5c155af9199af9e69b889claireho
64850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_NAMESPACE_END
64950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
650103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#endif  /* __cplusplus */
65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif  /* CMEMORY_H */
652