FreeType 1.31.1
This commit is contained in:
397
lib/ttmemory.c
Normal file
397
lib/ttmemory.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/*******************************************************************
|
||||
*
|
||||
* ttmemory.c 1.2
|
||||
*
|
||||
* Memory management component (body).
|
||||
*
|
||||
* Copyright 1996-1999 by
|
||||
* David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
*
|
||||
* This file is part of the FreeType project, and may only be used
|
||||
* modified and distributed under the terms of the FreeType project
|
||||
* license, LICENSE.TXT. By continuing to use, modify, or distribute
|
||||
* this file you indicate that you have read the license and
|
||||
* understand and accept it fully.
|
||||
*
|
||||
*
|
||||
* Changes between 1.1 and 1.2:
|
||||
*
|
||||
* - the font pool is gone.
|
||||
*
|
||||
* - introduced the FREE macro and the Free function for
|
||||
* future use in destructors.
|
||||
*
|
||||
* - Init_FontPool() is now a macro to allow the compilation of
|
||||
* 'legacy' applications (all four test programs have been updated).
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
#include "ttdebug.h"
|
||||
#include "ttmemory.h"
|
||||
#include "ttengine.h"
|
||||
|
||||
/* required by the tracing mode */
|
||||
#undef TT_COMPONENT
|
||||
#define TT_COMPONENT trace_memory
|
||||
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_TRACKED_BLOCKS 1024
|
||||
|
||||
struct TMemRec_
|
||||
{
|
||||
void* base;
|
||||
Long size;
|
||||
};
|
||||
|
||||
typedef struct TMemRec_ TMemRec;
|
||||
|
||||
static TMemRec pointers[MAX_TRACKED_BLOCKS + 1];
|
||||
|
||||
static Int num_alloc;
|
||||
static Int num_free;
|
||||
static Int num_realloc; /* counts only `real' reallocations
|
||||
(i.e., an existing buffer will be resized
|
||||
to a value larger than zero */
|
||||
|
||||
static Int fail_alloc;
|
||||
static Int fail_realloc;
|
||||
static Int fail_free;
|
||||
|
||||
#endif /* DEBUG_MEMORY */
|
||||
|
||||
|
||||
#ifndef TT_CONFIG_OPTION_THREAD_SAFE
|
||||
Long TTMemory_Allocated;
|
||||
Long TTMemory_MaxAllocated;
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Function : TT_Alloc
|
||||
*
|
||||
* Description : Allocates memory from the heap buffer.
|
||||
*
|
||||
* Input : Size size of the memory to be allocated
|
||||
* P pointer to a buffer pointer
|
||||
*
|
||||
* Output : Error code.
|
||||
*
|
||||
* NOTE : The newly allocated block should _always_ be zeroed
|
||||
* on return. Many parts of the engine rely on this to
|
||||
* work properly.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
EXPORT_FUNC
|
||||
TT_Error TT_Alloc( ULong Size, void** P )
|
||||
{
|
||||
#ifdef DEBUG_MEMORY
|
||||
Int i;
|
||||
#endif
|
||||
|
||||
|
||||
if ( !P )
|
||||
return TT_Err_Invalid_Argument;
|
||||
|
||||
if ( Size > (size_t)-1 )
|
||||
return TT_Err_Out_Of_Memory;
|
||||
if ( Size > 0 )
|
||||
{
|
||||
*P = (void*)malloc( Size );
|
||||
if ( !*P )
|
||||
return TT_Err_Out_Of_Memory;
|
||||
|
||||
#ifndef TT_CONFIG_OPTION_THREAD_SAFE
|
||||
TTMemory_Allocated += Size;
|
||||
TTMemory_MaxAllocated += Size;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
|
||||
num_alloc++;
|
||||
|
||||
i = 0;
|
||||
while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != NULL )
|
||||
i++;
|
||||
|
||||
if ( i >= MAX_TRACKED_BLOCKS )
|
||||
fail_alloc++;
|
||||
else
|
||||
{
|
||||
pointers[i].base = *P;
|
||||
pointers[i].size = Size;
|
||||
}
|
||||
|
||||
#endif /* DEBUG_MEMORY */
|
||||
|
||||
MEM_Set( *P, 0, Size );
|
||||
}
|
||||
else
|
||||
*P = NULL;
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Function : TT_Realloc
|
||||
*
|
||||
* Description : Reallocates memory from the heap buffer.
|
||||
*
|
||||
* Input : Size new size of the memory to be allocated;
|
||||
* if zero, TT_Free() will be called
|
||||
* P pointer to a buffer pointer; if *P == NULL,
|
||||
* TT_Alloc() will be called
|
||||
*
|
||||
* Output : Error code.
|
||||
*
|
||||
* NOTES : It's not necessary to zero the memory in case the
|
||||
* reallocated buffer is larger than before -- the
|
||||
* application has to take care of this.
|
||||
*
|
||||
* If the memory request fails, TT_Free() will be
|
||||
* called on *P, and TT_Err_Out_Of_Memory returned.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
EXPORT_FUNC
|
||||
TT_Error TT_Realloc( ULong Size, void** P )
|
||||
{
|
||||
void* Q;
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
Int i;
|
||||
#endif
|
||||
|
||||
|
||||
if ( !P )
|
||||
return TT_Err_Invalid_Argument;
|
||||
|
||||
if ( !*P )
|
||||
return TT_Alloc( Size, P );
|
||||
|
||||
if ( Size == 0 )
|
||||
return TT_Free( P );
|
||||
|
||||
if ( Size > (size_t)-1 )
|
||||
{
|
||||
TT_Free( *P );
|
||||
return TT_Err_Out_Of_Memory;
|
||||
}
|
||||
|
||||
Q = (void*)realloc( *P, Size );
|
||||
if ( !Q )
|
||||
{
|
||||
TT_Free( *P );
|
||||
return TT_Err_Out_Of_Memory;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
|
||||
num_realloc++;
|
||||
|
||||
i = 0;
|
||||
while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P )
|
||||
i++;
|
||||
|
||||
if ( i >= MAX_TRACKED_BLOCKS )
|
||||
fail_realloc++;
|
||||
else
|
||||
{
|
||||
#ifndef TT_CONFIG_OPTION_THREAD_SAFE
|
||||
TTMemory_Allocated += Size - pointers[i].size;
|
||||
if ( Size > pointers[i].size )
|
||||
TTMemory_MaxAllocated += Size - pointers[i].size;
|
||||
#endif
|
||||
|
||||
pointers[i].base = Q;
|
||||
pointers[i].size = size;
|
||||
}
|
||||
#endif /* DEBUG_MEMORY */
|
||||
|
||||
*P = Q;
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
#endif /* TT_CONFIG_OPTION_EXTEND_ENGINE */
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Function : TT_Free
|
||||
*
|
||||
* Description : Releases a previously allocated block of memory.
|
||||
*
|
||||
* Input : P pointer to memory block
|
||||
*
|
||||
* Output : Always SUCCESS.
|
||||
*
|
||||
* Note : The pointer must _always_ be set to NULL by this function.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
EXPORT_FUNC
|
||||
TT_Error TT_Free( void** P )
|
||||
{
|
||||
#ifdef DEBUG_MEMORY
|
||||
Int i;
|
||||
#endif /* DEBUG_MEMORY */
|
||||
|
||||
|
||||
if ( !P || !*P )
|
||||
return TT_Err_Ok;
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
|
||||
num_free++;
|
||||
|
||||
i = 0;
|
||||
while ( i < MAX_TRACKED_BLOCKS && pointers[i].base != *P )
|
||||
i++;
|
||||
|
||||
if ( i >= MAX_TRACKED_BLOCKS )
|
||||
fail_free++;
|
||||
else
|
||||
{
|
||||
#ifndef TT_CONFIG_OPTION_THREAD_SAFE
|
||||
TTMemory_Allocated -= pointers[i].size;
|
||||
#endif
|
||||
|
||||
pointers[i].base = NULL;
|
||||
pointers[i].size = 0;
|
||||
}
|
||||
#endif /* DEBUG_MEMORY */
|
||||
|
||||
free( *P );
|
||||
|
||||
*P = NULL;
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Function : TTMemory_Init
|
||||
*
|
||||
* Description : Initializes the memory.
|
||||
*
|
||||
* Output : Always SUCCESS.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
LOCAL_FUNC
|
||||
TT_Error TTMemory_Init( void )
|
||||
{
|
||||
#ifdef DEBUG_MEMORY
|
||||
Int i;
|
||||
|
||||
|
||||
for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ )
|
||||
{
|
||||
pointers[i].base = NULL;
|
||||
pointers[i].size = 0;
|
||||
}
|
||||
|
||||
num_alloc = 0;
|
||||
num_realloc = 0;
|
||||
num_free = 0;
|
||||
|
||||
fail_alloc = 0;
|
||||
fail_realloc = 0;
|
||||
fail_free = 0;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TT_CONFIG_OPTION_THREAD_SAFE
|
||||
TTMemory_Allocated = 0;
|
||||
TTMemory_MaxAllocated = 0;
|
||||
#endif
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Function : TTMemory_Done
|
||||
*
|
||||
* Description : Finalizes memory usage.
|
||||
*
|
||||
* Output : Always SUCCESS.
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
LOCAL_FUNC
|
||||
TT_Error TTMemory_Done( void )
|
||||
{
|
||||
#ifdef DEBUG_MEMORY
|
||||
Int i, num_leaked, tot_leaked;
|
||||
|
||||
|
||||
num_leaked = 0;
|
||||
tot_leaked = 0;
|
||||
|
||||
for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ )
|
||||
{
|
||||
if ( pointers[i].base )
|
||||
{
|
||||
num_leaked ++;
|
||||
tot_leaked += pointers[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf( stderr,
|
||||
"%d memory allocations, of which %d failed\n",
|
||||
num_alloc,
|
||||
fail_alloc );
|
||||
|
||||
fprintf( stderr,
|
||||
"%d memory reallocations, of which %d failed\n",
|
||||
num_realloc,
|
||||
fail_realloc );
|
||||
|
||||
fprintf( stderr,
|
||||
"%d memory frees, of which %d failed\n",
|
||||
num_free,
|
||||
fail_free );
|
||||
|
||||
if ( num_leaked > 0 )
|
||||
{
|
||||
fprintf( stderr,
|
||||
"There are %d leaked memory blocks, totalizing %d bytes\n",
|
||||
num_leaked, tot_leaked );
|
||||
|
||||
for ( i = 0; i < MAX_TRACKED_BLOCKS; i++ )
|
||||
{
|
||||
if ( pointers[i].base )
|
||||
{
|
||||
fprintf( stderr,
|
||||
"index: %4d (base: $%08lx, size: %08ld)\n",
|
||||
i,
|
||||
(long)pointers[i].base,
|
||||
pointers[i].size );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf( stderr, "No memory leaks !\n" );
|
||||
|
||||
#endif /* DEBUG_MEMORY */
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
Reference in New Issue
Block a user