diff options
Diffstat (limited to 'intl/icu/source/common/cmemory.c')
-rw-r--r-- | intl/icu/source/common/cmemory.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/intl/icu/source/common/cmemory.c b/intl/icu/source/common/cmemory.c new file mode 100644 index 000000000..b40994a1e --- /dev/null +++ b/intl/icu/source/common/cmemory.c @@ -0,0 +1,162 @@ +// Copyright (C) 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +/* +****************************************************************************** +* +* Copyright (C) 2002-2015, International Business Machines +* Corporation and others. All Rights Reserved. +* +****************************************************************************** +* +* File cmemory.c ICU Heap allocation. +* All ICU heap allocation, both for C and C++ new of ICU +* class types, comes through these functions. +* +* If you have a need to replace ICU allocation, this is the +* place to do it. +* +* Note that uprv_malloc(0) returns a non-NULL pointer, and +* that a subsequent free of that pointer value is a NOP. +* +****************************************************************************** +*/ +#include "unicode/uclean.h" +#include "cmemory.h" +#include "putilimp.h" +#include "uassert.h" +#include <stdlib.h> + +/* uprv_malloc(0) returns a pointer to this read-only data. */ +static const int32_t zeroMem[] = {0, 0, 0, 0, 0, 0}; + +/* Function Pointers for user-supplied heap functions */ +static const void *pContext; +static UMemAllocFn *pAlloc; +static UMemReallocFn *pRealloc; +static UMemFreeFn *pFree; + +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) +#include <stdio.h> +static int n=0; +static long b=0; +#endif + +#if U_DEBUG + +static char gValidMemorySink = 0; + +U_CAPI void uprv_checkValidMemory(const void *p, size_t n) { + /* + * Access the memory to ensure that it's all valid. + * Load and save a computed value to try to ensure that the compiler + * does not throw away the whole loop. + * A thread analyzer might complain about un-mutexed access to gValidMemorySink + * which is true but harmless because no one ever uses the value in gValidMemorySink. + */ + const char *s = (const char *)p; + char c = gValidMemorySink; + size_t i; + U_ASSERT(p != NULL); + for(i = 0; i < n; ++i) { + c ^= s[i]; + } + gValidMemorySink = c; +} + +#endif /* U_DEBUG */ + +U_CAPI void * U_EXPORT2 +uprv_malloc(size_t s) { +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) +#if 1 + putchar('>'); + fflush(stdout); +#else + fprintf(stderr,"MALLOC\t#%d\t%ul bytes\t%ul total\n", ++n,s,(b+=s)); fflush(stderr); +#endif +#endif + if (s > 0) { + if (pAlloc) { + return (*pAlloc)(pContext, s); + } else { + return uprv_default_malloc(s); + } + } else { + return (void *)zeroMem; + } +} + +U_CAPI void * U_EXPORT2 +uprv_realloc(void * buffer, size_t size) { +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) + putchar('~'); + fflush(stdout); +#endif + if (buffer == zeroMem) { + return uprv_malloc(size); + } else if (size == 0) { + if (pFree) { + (*pFree)(pContext, buffer); + } else { + uprv_default_free(buffer); + } + return (void *)zeroMem; + } else { + if (pRealloc) { + return (*pRealloc)(pContext, buffer, size); + } else { + return uprv_default_realloc(buffer, size); + } + } +} + +U_CAPI void U_EXPORT2 +uprv_free(void *buffer) { +#if U_DEBUG && defined(UPRV_MALLOC_COUNT) + putchar('<'); + fflush(stdout); +#endif + if (buffer != zeroMem) { + if (pFree) { + (*pFree)(pContext, buffer); + } else { + uprv_default_free(buffer); + } + } +} + +U_CAPI void * U_EXPORT2 +uprv_calloc(size_t num, size_t size) { + void *mem = NULL; + size *= num; + mem = uprv_malloc(size); + if (mem) { + uprv_memset(mem, 0, size); + } + return mem; +} + +U_CAPI void U_EXPORT2 +u_setMemoryFunctions(const void *context, UMemAllocFn *a, UMemReallocFn *r, UMemFreeFn *f, UErrorCode *status) +{ + if (U_FAILURE(*status)) { + return; + } + if (a==NULL || r==NULL || f==NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + pContext = context; + pAlloc = a; + pRealloc = r; + pFree = f; +} + + +U_CFUNC UBool cmemory_cleanup(void) { + pContext = NULL; + pAlloc = NULL; + pRealloc = NULL; + pFree = NULL; + return TRUE; +} |