1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 *
6 *   Copyright (C) 2002-2015, International Business Machines
7 *   Corporation and others.  All Rights Reserved.
8 *
9 ******************************************************************************
10 *
11 * File cmemory.c      ICU Heap allocation.
12 *                     All ICU heap allocation, both for C and C++ new of ICU
13 *                     class types, comes through these functions.
14 *
15 *                     If you have a need to replace ICU allocation, this is the
16 *                     place to do it.
17 *
18 *                     Note that uprv_malloc(0) returns a non-NULL pointer, and
19 *                     that a subsequent free of that pointer value is a NOP.
20 *
21 ******************************************************************************
22 */
23 #include "unicode/uclean.h"
24 #include "cmemory.h"
25 #include "putilimp.h"
26 #include "uassert.h"
27 #include <stdlib.h>
28 
29 /* uprv_malloc(0) returns a pointer to this read-only data. */
30 static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0};
31 
32 /* Function Pointers for user-supplied heap functions  */
33 static const void     *pContext;
34 static UMemAllocFn    *pAlloc;
35 static UMemReallocFn  *pRealloc;
36 static UMemFreeFn     *pFree;
37 
38 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
39 #include <stdio.h>
40 static int n=0;
41 static long b=0;
42 #endif
43 
44 U_CAPI void * U_EXPORT2
uprv_malloc(size_t s)45 uprv_malloc(size_t s) {
46 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
47 #if 1
48   putchar('>');
49   fflush(stdout);
50 #else
51   fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr);
52 #endif
53 #endif
54     if (s > 0) {
55         if (pAlloc) {
56             return (*pAlloc)(pContext, s);
57         } else {
58             return uprv_default_malloc(s);
59         }
60     } else {
61         return (void *)zeroMem;
62     }
63 }
64 
65 U_CAPI void * U_EXPORT2
uprv_realloc(void * buffer,size_t size)66 uprv_realloc(void * buffer, size_t size) {
67 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
68   putchar('~');
69   fflush(stdout);
70 #endif
71     if (buffer == zeroMem) {
72         return uprv_malloc(size);
73     } else if (size == 0) {
74         if (pFree) {
75             (*pFree)(pContext, buffer);
76         } else {
77             uprv_default_free(buffer);
78         }
79         return (void *)zeroMem;
80     } else {
81         if (pRealloc) {
82             return (*pRealloc)(pContext, buffer, size);
83         } else {
84             return uprv_default_realloc(buffer, size);
85         }
86     }
87 }
88 
89 U_CAPI void U_EXPORT2
uprv_free(void * buffer)90 uprv_free(void *buffer) {
91 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
92   putchar('<');
93   fflush(stdout);
94 #endif
95     if (buffer != zeroMem) {
96         if (pFree) {
97             (*pFree)(pContext, buffer);
98         } else {
99             uprv_default_free(buffer);
100         }
101     }
102 }
103 
104 U_CAPI void * U_EXPORT2
uprv_calloc(size_t num,size_t size)105 uprv_calloc(size_t num, size_t size) {
106     void *mem = NULL;
107     size *= num;
108     mem = uprv_malloc(size);
109     if (mem) {
110         uprv_memset(mem, 0, size);
111     }
112     return mem;
113 }
114 
115 U_CAPI void U_EXPORT2
u_setMemoryFunctions(const void * context,UMemAllocFn * a,UMemReallocFn * r,UMemFreeFn * f,UErrorCode * status)116 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f,  UErrorCode *status)
117 {
118     if (U_FAILURE(*status)) {
119         return;
120     }
121     if (a==NULL || r==NULL || f==NULL) {
122         *status = U_ILLEGAL_ARGUMENT_ERROR;
123         return;
124     }
125     pContext  = context;
126     pAlloc    = a;
127     pRealloc  = r;
128     pFree     = f;
129 }
130 
131 
cmemory_cleanup(void)132 U_CFUNC UBool cmemory_cleanup(void) {
133     pContext   = NULL;
134     pAlloc     = NULL;
135     pRealloc   = NULL;
136     pFree      = NULL;
137     return TRUE;
138 }
139