2015-04-23 21:32:58 -05:00
// 4 december 2014
# include "uipriv_windows.h"
// wrappers for allocator of choice
// panics on memory exhausted, undefined on heap corruption or other unreliably-detected malady (see http://stackoverflow.com/questions/28761680/is-there-a-windows-api-memory-allocator-deallocator-i-can-use-that-will-just-giv)
// new memory is set to zero
// passing NULL to tableRealloc() acts like tableAlloc()
// passing NULL to tableFree() is a no-op
2015-05-02 11:27:53 -05:00
static HANDLE heap ;
2015-05-02 11:29:55 -05:00
int initAlloc ( void )
2015-05-02 11:27:53 -05:00
{
heap = HeapCreate ( 0 , 0 , 0 ) ;
return heap ! = NULL ;
}
2015-05-08 09:34:32 -05:00
# define UINT8(p) ((uint8_t *) (p))
# define PVOID(p) ((void *) (p))
# define EXTRA (sizeof (const char **))
# define DATA(p) PVOID(UINT8(p) + EXTRA)
# define BASE(p) PVOID(UINT8(p) - EXTRA)
# define CCHAR(p) ((const char **) (p))
# define TYPE(p) CCHAR(UINT8(p))
2015-05-08 13:05:16 -05:00
void uninitAlloc ( void )
{
BOOL hasEntry ;
PROCESS_HEAP_ENTRY phe ;
DWORD le ;
hasEntry = FALSE ;
ZeroMemory ( & phe , sizeof ( PROCESS_HEAP_ENTRY ) ) ;
while ( HeapWalk ( heap , & phe ) ! = 0 ) {
// skip non-allocations
if ( ( phe . wFlags & PROCESS_HEAP_ENTRY_BUSY ) = = 0 )
continue ;
if ( ! hasEntry ) {
fprintf ( stderr , " [libui] leaked allocations: \n " ) ;
hasEntry = TRUE ;
}
fprintf ( stderr , " [libui] %p %s \n " , phe . lpData , * TYPE ( phe . lpData ) ) ;
}
le = GetLastError ( ) ;
SetLastError ( le ) ; // just in case
if ( le ! = ERROR_NO_MORE_ITEMS )
logLastError ( " error walking heap in uninitAlloc() " ) ;
if ( hasEntry )
complain ( " either you left something around or there's a bug in libui " ) ;
if ( HeapDestroy ( heap ) = = 0 )
logLastError ( " error destroying heap in uninitAlloc() " ) ;
}
2015-05-08 09:34:32 -05:00
void * uiAlloc ( size_t size , const char * type )
2015-04-23 21:32:58 -05:00
{
void * out ;
2015-05-08 09:34:32 -05:00
out = HeapAlloc ( heap , HEAP_ZERO_MEMORY , EXTRA + size ) ;
2015-04-23 21:32:58 -05:00
if ( out = = NULL ) {
2015-05-03 18:52:24 -05:00
fprintf ( stderr , " memory exhausted in uiAlloc() \n " ) ;
2015-04-23 21:32:58 -05:00
abort ( ) ;
}
2015-05-08 09:34:32 -05:00
* TYPE ( out ) = type ;
return DATA ( out ) ;
2015-04-23 21:32:58 -05:00
}
2015-05-08 09:34:32 -05:00
void * uiRealloc ( void * p , size_t size , const char * type )
2015-04-23 21:32:58 -05:00
{
void * out ;
if ( p = = NULL )
2015-05-08 09:34:32 -05:00
return uiAlloc ( size , type ) ;
p = BASE ( p ) ;
out = HeapReAlloc ( heap , HEAP_ZERO_MEMORY , p , EXTRA + size ) ;
2015-04-23 21:32:58 -05:00
if ( out = = NULL ) {
2015-05-03 18:52:24 -05:00
fprintf ( stderr , " memory exhausted in uiRealloc() \n " ) ;
2015-04-23 21:32:58 -05:00
abort ( ) ;
}
2015-05-16 21:54:43 -05:00
return DATA ( out ) ;
2015-04-23 21:32:58 -05:00
}
void uiFree ( void * p )
{
if ( p = = NULL )
2015-05-07 16:45:34 -05:00
complain ( " attempt to uiFree(NULL); there's a bug somewhere " ) ;
2015-05-08 09:34:32 -05:00
p = BASE ( p ) ;
2015-05-02 11:27:53 -05:00
if ( HeapFree ( heap , 0 , p ) = = 0 )
logLastError ( " error freeing memory in uiFree() " ) ;
2015-04-23 21:32:58 -05:00
}