Home | History | Annotate | Download | only in common
      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