cmemory.cpp (3540B)
1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ****************************************************************************** 5 * 6 * Copyright (C) 2002-2015, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 * 9 ****************************************************************************** 10 * 11 * File cmemory.c ICU Heap allocation. 12 * All ICU heap allocation, both for C and C++ new of ICU 13 * class types, comes through these functions. 14 * 15 * If you have a need to replace ICU allocation, this is the 16 * place to do it. 17 * 18 * Note that uprv_malloc(0) returns a non-nullptr pointer, 19 * and that a subsequent free of that pointer value is a NOP. 20 * 21 ****************************************************************************** 22 */ 23 #include "unicode/uclean.h" 24 #include "cmemory.h" 25 #include "putilimp.h" 26 #include "uassert.h" 27 #include <stdlib.h> 28 29 /* uprv_malloc(0) returns a pointer to this read-only data. */ 30 static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; 31 32 /* Function Pointers for user-supplied heap functions */ 33 static const void *pContext; 34 static UMemAllocFn *pAlloc; 35 static UMemReallocFn *pRealloc; 36 static UMemFreeFn *pFree; 37 38 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 39 #include <stdio.h> 40 static int n=0; 41 static long b=0; 42 #endif 43 44 U_CAPI void * U_EXPORT2 45 uprv_malloc(size_t s) { 46 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 47 #if 1 48 putchar('>'); 49 fflush(stdout); 50 #else 51 fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr); 52 #endif 53 #endif 54 if (s > 0) { 55 if (pAlloc) { 56 return (*pAlloc)(pContext, s); 57 } else { 58 return uprv_default_malloc(s); 59 } 60 } else { 61 return (void *)zeroMem; 62 } 63 } 64 65 U_CAPI void * U_EXPORT2 66 uprv_realloc(void * buffer, size_t size) { 67 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 68 putchar('~'); 69 fflush(stdout); 70 #endif 71 if (buffer == zeroMem) { 72 return uprv_malloc(size); 73 } else if (size == 0) { 74 if (pFree) { 75 (*pFree)(pContext, buffer); 76 } else { 77 uprv_default_free(buffer); 78 } 79 return (void *)zeroMem; 80 } else { 81 if (pRealloc) { 82 return (*pRealloc)(pContext, buffer, size); 83 } else { 84 return uprv_default_realloc(buffer, size); 85 } 86 } 87 } 88 89 U_CAPI void U_EXPORT2 90 uprv_free(void *buffer) { 91 #if U_DEBUG && defined(UPRV_MALLOC_COUNT) 92 putchar('<'); 93 fflush(stdout); 94 #endif 95 if (buffer != zeroMem) { 96 if (pFree) { 97 (*pFree)(pContext, buffer); 98 } else { 99 uprv_default_free(buffer); 100 } 101 } 102 } 103 104 U_CAPI void * U_EXPORT2 105 uprv_calloc(size_t num, size_t size) { 106 void *mem = nullptr; 107 size *= num; 108 mem = uprv_malloc(size); 109 if (mem) { 110 uprv_memset(mem, 0, size); 111 } 112 return mem; 113 } 114 115 U_CAPI void U_EXPORT2 116 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) 117 { 118 if (U_FAILURE(*status)) { 119 return; 120 } 121 if (a==nullptr || r==nullptr || f==nullptr) { 122 *status = U_ILLEGAL_ARGUMENT_ERROR; 123 return; 124 } 125 pContext = context; 126 pAlloc = a; 127 pRealloc = r; 128 pFree = f; 129 } 130 131 132 U_CFUNC UBool cmemory_cleanup() { 133 pContext = nullptr; 134 pAlloc = nullptr; 135 pRealloc = nullptr; 136 pFree = nullptr; 137 return true; 138 }