1 /* 2 ****************************************************************************** 3 * 4 * Copyright (C) 2002-2003, International Business Machines 5 * Corporation and others. All Rights Reserved. 6 * 7 ****************************************************************************** 8 * 9 * File cmemory.c ICU Heap allocation. 10 * All ICU heap allocation, both for C and C++ new of ICU 11 * class types, comes through these functions. 12 * 13 * If you have a need to replace ICU allocation, this is the 14 * place to do it. 15 * 16 * Note that uprv_malloc(0) returns a non-NULL pointer, and 17 * that a subsequent free of that pointer value is a NOP. 18 * 19 ****************************************************************************** 20 */ 21 #include "unicode/uclean.h" 22 #include "cmemory.h" 23 #include <stdlib.h> 24 25 /* uprv_malloc(0) returns a pointer to this read-only data. */ 26 static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; 27 28 /* Function Pointers for user-supplied heap functions */ 29 static const void *pContext; 30 static UMemAllocFn *pAlloc; 31 static UMemReallocFn *pRealloc; 32 static UMemFreeFn *pFree; 33 34 /* Flag indicating whether any heap allocations have happened. 35 * Used to prevent changing out the heap functions after allocations have been made */ 36 static UBool gHeapInUse; 37 38 U_CAPI void * U_EXPORT2 39 uprv_malloc(size_t s) { 40 if (s > 0) { 41 gHeapInUse = TRUE; 42 if (pAlloc) { 43 return (*pAlloc)(pContext, s); 44 } else { 45 return malloc(s); 46 } 47 } else { 48 return (void *)zeroMem; 49 } 50 } 51 52 U_CAPI void * U_EXPORT2 53 uprv_realloc(void * buffer, size_t size) { 54 if (buffer == zeroMem) { 55 return uprv_malloc(size); 56 } else if (size == 0) { 57 if (pFree) { 58 (*pFree)(pContext, buffer); 59 } else { 60 free(buffer); 61 } 62 return (void *)zeroMem; 63 } else { 64 gHeapInUse = TRUE; 65 if (pRealloc) { 66 return (*pRealloc)(pContext, buffer, size); 67 } else { 68 return realloc(buffer, size); 69 } 70 } 71 } 72 73 U_CAPI void U_EXPORT2 74 uprv_free(void *buffer) { 75 if (buffer != zeroMem) { 76 if (pFree) { 77 (*pFree)(pContext, buffer); 78 } else { 79 free(buffer); 80 } 81 } 82 } 83 84 U_CAPI void U_EXPORT2 85 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) 86 { 87 if (U_FAILURE(*status)) { 88 return; 89 } 90 if (a==NULL || r==NULL || f==NULL) { 91 *status = U_ILLEGAL_ARGUMENT_ERROR; 92 return; 93 } 94 if (gHeapInUse) { 95 *status = U_INVALID_STATE_ERROR; 96 return; 97 } 98 pContext = context; 99 pAlloc = a; 100 pRealloc = r; 101 pFree = f; 102 } 103 104 105 U_CFUNC UBool cmemory_cleanup(void) { 106 pContext = NULL; 107 pAlloc = NULL; 108 pRealloc = NULL; 109 pFree = NULL; 110 gHeapInUse = FALSE; 111 return TRUE; 112 } 113 114 115 /* 116 * gHeapInUse 117 * Return True if ICU has allocated any memory. 118 * Used by u_SetMutexFunctions() and similar to verify that ICU has not 119 * been used, that it is in a pristine initial state. 120 */ 121 U_CFUNC UBool cmemory_inUse() { 122 return gHeapInUse; 123 } 124 125