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