Imported Upstream version 58.1
[platform/upstream/icu.git] / source / common / cmemory.c
1 // Copyright (C) 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 #if U_DEBUG
45
46 static char gValidMemorySink = 0;
47
48 U_CAPI void uprv_checkValidMemory(const void *p, size_t n) {
49     /*
50      * Access the memory to ensure that it's all valid.
51      * Load and save a computed value to try to ensure that the compiler
52      * does not throw away the whole loop.
53      * A thread analyzer might complain about un-mutexed access to gValidMemorySink
54      * which is true but harmless because no one ever uses the value in gValidMemorySink.
55      */
56     const char *s = (const char *)p;
57     char c = gValidMemorySink;
58     size_t i;
59     U_ASSERT(p != NULL);
60     for(i = 0; i < n; ++i) {
61         c ^= s[i];
62     }
63     gValidMemorySink = c;
64 }
65
66 #endif  /* U_DEBUG */
67
68 U_CAPI void * U_EXPORT2
69 uprv_malloc(size_t s) {
70 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
71 #if 1
72   putchar('>');
73   fflush(stdout);
74 #else
75   fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr);
76 #endif
77 #endif
78     if (s > 0) {
79         if (pAlloc) {
80             return (*pAlloc)(pContext, s);
81         } else {
82             return uprv_default_malloc(s);
83         }
84     } else {
85         return (void *)zeroMem;
86     }
87 }
88
89 U_CAPI void * U_EXPORT2
90 uprv_realloc(void * buffer, size_t size) {
91 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
92   putchar('~');
93   fflush(stdout);
94 #endif
95     if (buffer == zeroMem) {
96         return uprv_malloc(size);
97     } else if (size == 0) {
98         if (pFree) {
99             (*pFree)(pContext, buffer);
100         } else {
101             uprv_default_free(buffer);
102         }
103         return (void *)zeroMem;
104     } else {
105         if (pRealloc) {
106             return (*pRealloc)(pContext, buffer, size);
107         } else {
108             return uprv_default_realloc(buffer, size);
109         }
110     }
111 }
112
113 U_CAPI void U_EXPORT2
114 uprv_free(void *buffer) {
115 #if U_DEBUG && defined(UPRV_MALLOC_COUNT)
116   putchar('<');
117   fflush(stdout);
118 #endif
119     if (buffer != zeroMem) {
120         if (pFree) {
121             (*pFree)(pContext, buffer);
122         } else {
123             uprv_default_free(buffer);
124         }
125     }
126 }
127
128 U_CAPI void * U_EXPORT2
129 uprv_calloc(size_t num, size_t size) {
130     void *mem = NULL;
131     size *= num;
132     mem = uprv_malloc(size);
133     if (mem) {
134         uprv_memset(mem, 0, size);
135     }
136     return mem;
137 }
138
139 U_CAPI void U_EXPORT2
140 u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f,  UErrorCode *status)
141 {
142     if (U_FAILURE(*status)) {
143         return;
144     }
145     if (a==NULL || r==NULL || f==NULL) {
146         *status = U_ILLEGAL_ARGUMENT_ERROR;
147         return;
148     }
149     pContext  = context;
150     pAlloc    = a;
151     pRealloc  = r;
152     pFree     = f;
153 }
154
155
156 U_CFUNC UBool cmemory_cleanup(void) {
157     pContext   = NULL;
158     pAlloc     = NULL;
159     pRealloc   = NULL;
160     pFree      = NULL;
161     return TRUE;
162 }