• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
uprv_malloc(size_t s)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
uprv_realloc(void * buffer,size_t size)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
uprv_free(void * buffer)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
u_setMemoryFunctions(const void * context,UMemAllocFn * a,UMemReallocFn * r,UMemFreeFn * f,UErrorCode * status)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 
cmemory_cleanup(void)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  */
cmemory_inUse()121 U_CFUNC UBool cmemory_inUse() {
122     return gHeapInUse;
123 }
124 
125