/* ****************************************************************************** * * Copyright (C) 2002-2011, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** * * File cmemory.c ICU Heap allocation. * All ICU heap allocation, both for C and C++ new of ICU * class types, comes through these functions. * * If you have a need to replace ICU allocation, this is the * place to do it. * * Note that uprv_malloc(0) returns a non-NULL pointer, and * that a subsequent free of that pointer value is a NOP. * ****************************************************************************** */ #include "unicode/uclean.h" #include "cmemory.h" #include "putilimp.h" #include <stdlib.h> /* uprv_malloc(0) returns a pointer to this read-only data. */ static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; /* Function Pointers for user-supplied heap functions */ static const void *pContext; static UMemAllocFn *pAlloc; static UMemReallocFn *pRealloc; static UMemFreeFn *pFree; /* Flag indicating whether any heap allocations have happened. * Used to prevent changing out the heap functions after allocations have been made */ static UBool gHeapInUse; U_CAPI void * U_EXPORT2 uprv_malloc(size_t s) { if (s > 0) { gHeapInUse = TRUE; if (pAlloc) { return (*pAlloc)(pContext, s); } else { return uprv_default_malloc(s); } } else { return (void *)zeroMem; } } U_CAPI void * U_EXPORT2 uprv_realloc(void * buffer, size_t size) { if (buffer == zeroMem) { return uprv_malloc(size); } else if (size == 0) { if (pFree) { (*pFree)(pContext, buffer); } else { uprv_default_free(buffer); } return (void *)zeroMem; } else { gHeapInUse = TRUE; if (pRealloc) { return (*pRealloc)(pContext, buffer, size); } else { return uprv_default_realloc(buffer, size); } } } U_CAPI void U_EXPORT2 uprv_free(void *buffer) { if (buffer != zeroMem) { if (pFree) { (*pFree)(pContext, buffer); } else { uprv_default_free(buffer); } } } U_CAPI void U_EXPORT2 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) { if (U_FAILURE(*status)) { return; } if (a==NULL || r==NULL || f==NULL) { *status = U_ILLEGAL_ARGUMENT_ERROR; return; } if (gHeapInUse) { *status = U_INVALID_STATE_ERROR; return; } pContext = context; pAlloc = a; pRealloc = r; pFree = f; } U_CFUNC UBool cmemory_cleanup(void) { pContext = NULL; pAlloc = NULL; pRealloc = NULL; pFree = NULL; gHeapInUse = FALSE; return TRUE; } /* * gHeapInUse * Return True if ICU has allocated any memory. * Used by u_SetMutexFunctions() and similar to verify that ICU has not * been used, that it is in a pristine initial state. */ U_CFUNC UBool cmemory_inUse() { return gHeapInUse; }