/* MikMod sound library (c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for complete list. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*============================================================================== $Id$ Dynamic memory routines ==============================================================================*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_POSIX_MEMALIGN #define _XOPEN_SOURCE 600 /* for posix_memalign */ #endif #include "string.h" #include "mikmod_internals.h" #if defined(HAVE_SSE2) || defined(HAVE_ALTIVEC) #undef WIN32_ALIGNED_MALLOC #if defined(_WIN32) && !defined(_WIN32_WCE) # if defined(_WIN64) /* OK with MSVC and MinGW */ # define WIN32_ALIGNED_MALLOC # elif defined(_MSC_VER) && (_MSC_VER >= 1300) # define WIN32_ALIGNED_MALLOC # elif defined(__MINGW32__) /* no guarantees that msvcrt.dll will have it */ # endif #endif #define PTRSIZE (sizeof(void*)) /* return a 16 byte aligned address */ void* MikMod_amalloc(size_t size) { void *d; #if defined(HAVE_POSIX_MEMALIGN) if (!posix_memalign(&d, 16, size)) { memset(d, 0, size); return d; } #elif defined(WIN32_ALIGNED_MALLOC) d = _aligned_malloc(size, 16); if (d) { ZeroMemory(d, size); return d; } #else size_t s = (size)? ((size + (PTRSIZE-1)) & ~(PTRSIZE-1)) : PTRSIZE; s += PTRSIZE + 16; d = calloc(1, s); if (d) { char *pptr = (char *)d + PTRSIZE; size_t err = ((size_t)pptr) & 15; char *fptr = pptr + (16 - err); *(size_t*)(fptr - PTRSIZE) = (size_t)d; return fptr; } #endif _mm_errno = MMERR_OUT_OF_MEMORY; if(_mm_errorhandler) _mm_errorhandler(); return NULL; } void MikMod_afree(void *data) { if (!data) return; #if defined(HAVE_POSIX_MEMALIGN) free(data); #elif defined(WIN32_ALIGNED_MALLOC) _aligned_free(data); #else free((void *) *(size_t*)((unsigned char *)data - PTRSIZE)); #endif } #endif /* (HAVE_SSE2) || (HAVE_ALTIVEC) */ void* MikMod_realloc(void *data, size_t size) { if (data) return realloc(data, size); return calloc(1, size); } /* Same as malloc, but sets error variable _mm_error when fails */ void* MikMod_malloc(size_t size) { return MikMod_calloc(1, size); } /* Same as calloc, but sets error variable _mm_error when fails */ void* MikMod_calloc(size_t nitems, size_t size) { void *d = calloc(nitems, size); if (d) return d; _mm_errno = MMERR_OUT_OF_MEMORY; if(_mm_errorhandler) _mm_errorhandler(); return NULL; } void MikMod_free(void *data) { if (data) free(data); } /* like strdup(), but the result must be freed using MikMod_free() */ CHAR *MikMod_strdup(const CHAR *s) { size_t l; CHAR *d; if (!s) return NULL; l = strlen(s) + 1; d = (CHAR *) MikMod_calloc(1, l * sizeof(CHAR)); if (d) strcpy(d, s); return d; } /* ex:set ts=4: */