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