1 /* 2 ****************************************************************************** 3 * 4 * Copyright (C) 2002-2011, 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 "putilimp.h" 24 #include <stdlib.h> 25 26 /* uprv_malloc(0) returns a pointer to this read-only data. */ 27 static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; 28 29 /* Function Pointers for user-supplied heap functions */ 30 static const void *pContext; 31 static UMemAllocFn *pAlloc; 32 static UMemReallocFn *pRealloc; 33 static UMemFreeFn *pFree; 34 35 /* Flag indicating whether any heap allocations have happened. 36 * Used to prevent changing out the heap functions after allocations have been made */ 37 static UBool gHeapInUse; 38 39 U_CAPI void * U_EXPORT2 40 uprv_malloc(size_t s) { 41 if (s > 0) { 42 gHeapInUse = TRUE; 43 if (pAlloc) { 44 return (*pAlloc)(pContext, s); 45 } else { 46 return uprv_default_malloc(s); 47 } 48 } else { 49 return (void *)zeroMem; 50 } 51 } 52 53 U_CAPI void * U_EXPORT2 54 uprv_realloc(void * buffer, size_t size) { 55 if (buffer == zeroMem) { 56 return uprv_malloc(size); 57 } else if (size == 0) { 58 if (pFree) { 59 (*pFree)(pContext, buffer); 60 } else { 61 uprv_default_free(buffer); 62 } 63 return (void *)zeroMem; 64 } else { 65 gHeapInUse = TRUE; 66 if (pRealloc) { 67 return (*pRealloc)(pContext, buffer, size); 68 } else { 69 return uprv_default_realloc(buffer, size); 70 } 71 } 72 } 73 74 U_CAPI void U_EXPORT2 75 uprv_free(void *buffer) { 76 if (buffer != zeroMem) { 77 if (pFree) { 78 (*pFree)(pContext, buffer); 79 } else { 80 uprv_default_free(buffer); 81 } 82 } 83 } 84 85 U_CAPI void U_EXPORT2 86 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) 87 { 88 if (U_FAILURE(*status)) { 89 return; 90 } 91 if (a==NULL || r==NULL || f==NULL) { 92 *status = U_ILLEGAL_ARGUMENT_ERROR; 93 return; 94 } 95 if (gHeapInUse) { 96 *status = U_INVALID_STATE_ERROR; 97 return; 98 } 99 pContext = context; 100 pAlloc = a; 101 pRealloc = r; 102 pFree = f; 103 } 104 105 106 U_CFUNC UBool cmemory_cleanup(void) { 107 pContext = NULL; 108 pAlloc = NULL; 109 pRealloc = NULL; 110 pFree = NULL; 111 gHeapInUse = FALSE; 112 return TRUE; 113 } 114 115 116 /* 117 * gHeapInUse 118 * Return True if ICU has allocated any memory. 119 * Used by u_SetMutexFunctions() and similar to verify that ICU has not 120 * been used, that it is in a pristine initial state. 121 */ 122 U_CFUNC UBool cmemory_inUse() { 123 return gHeapInUse; 124 } 125 126