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