| /* |
| ****************************************************************************** |
| * |
| * Copyright (C) 2002-2003, 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" |
| |
| #if defined(STARBOARD) |
| #include "starboard/memory.h" |
| #else |
| #include <stdlib.h> |
| #endif |
| |
| /* 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 { |
| #if defined(STARBOARD) |
| return SbMemoryAllocate(s); |
| #else |
| return malloc(s); |
| #endif |
| } |
| } 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 { |
| #if defined(STARBOARD) |
| SbMemoryDeallocate(buffer); |
| #else |
| free(buffer); |
| #endif |
| } |
| return (void *)zeroMem; |
| } else { |
| gHeapInUse = TRUE; |
| if (pRealloc) { |
| return (*pRealloc)(pContext, buffer, size); |
| } else { |
| #if defined(STARBOARD) |
| return SbMemoryReallocate(buffer, size); |
| #else |
| return realloc(buffer, size); |
| #endif |
| } |
| } |
| } |
| |
| U_CAPI void U_EXPORT2 |
| uprv_free(void *buffer) { |
| if (buffer != zeroMem) { |
| if (pFree) { |
| (*pFree)(pContext, buffer); |
| } else { |
| #if defined(STARBOARD) |
| SbMemoryDeallocate(buffer); |
| #else |
| free(buffer); |
| #endif |
| } |
| } |
| } |
| |
| 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; |
| } |