freetype2/src/cache/ftcmru.c

314 lines
5.9 KiB
C
Raw Normal View History

#include <ft2build.h>
#include FT_CACHE_H
#include FT_CACHE_INTERNAL_MRU_H
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "ftcerror.h"
2003-12-21 02:41:32 +01:00
FT_EXPORT_DEF( void )
FTC_MruNode_Prepend( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
if ( first )
{
FTC_MruNode last = first->prev;
last->next = node;
first->prev = node;
node->prev = last;
node->next = first;
}
else
{
node->next = node;
node->prev = node;
}
*plist = node;
}
FT_EXPORT_DEF( void )
FTC_MruNode_Up( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FT_ASSERT( first != NULL );
if ( node != first )
{
FTC_MruNode prev = node->prev;
FTC_MruNode next = node->next;
FTC_MruNode last;
prev->next = next;
next->prev = prev;
last = first->prev;
first->prev = node;
last->next = node;
node->prev = last;
node->next = first;
*plist = node;
}
}
FT_EXPORT( void )
FTC_MruNode_Remove( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FTC_MruNode prev, next;
FT_ASSERT( first != NULL );
next = node->next;
prev = node->prev;
if ( node == next )
{
FT_ASSERT( node == prev );
FT_ASSERT( node == first );
*plist = NULL;
}
else
{
prev->next = next;
next->prev = prev;
if ( node == first )
*plist = next;
}
node->prev = NULL;
node->next = NULL;
}
FT_EXPORT_DEF( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
FT_Pointer data,
FT_Memory memory )
{
list->num_nodes = 0;
list->max_nodes = max_nodes;
list->nodes = NULL;
list->clazz = *clazz;
list->data = data;
list->memory = memory;
}
2003-12-21 02:41:32 +01:00
FT_EXPORT( void )
FTC_MruList_Reset( FTC_MruList list )
{
2003-12-21 02:41:32 +01:00
FT_Memory memory = list->memory;
FTC_MruNode first = list->nodes;
2003-12-21 02:41:32 +01:00
if ( first )
{
2003-12-21 02:41:32 +01:00
FTC_MruNode node = first;
FTC_MruNode next;
2003-12-21 02:41:32 +01:00
do
{
next = node->next;
2003-12-21 02:41:32 +01:00
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
2003-12-21 02:41:32 +01:00
node = next;
}
while ( node != first );
}
2003-12-21 02:41:32 +01:00
list->nodes = NULL;
list->num_nodes = 0;
}
FT_EXPORT( void )
2003-12-21 02:41:32 +01:00
FTC_MruList_Done( FTC_MruList list )
{
2003-12-21 02:41:32 +01:00
FTC_MruList_Reset( list );
}
2003-12-21 02:41:32 +01:00
FT_EXPORT_DEF( void )
FTC_MruList_Up( FTC_MruList list,
FTC_MruNode node )
{
2003-12-21 02:41:32 +01:00
FTC_MruNode_Up( &list->nodes, node );
}
2003-12-21 02:41:32 +01:00
FT_EXPORT_DEF( FTC_MruNode )
FTC_MruList_Lookup( FTC_MruList list,
FT_Pointer key )
{
FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
2003-12-21 02:41:32 +01:00
FTC_MruNode node, first;
2003-12-21 02:41:32 +01:00
first = list->nodes;
node = NULL;
2003-12-21 02:41:32 +01:00
if ( first )
{
2003-12-21 02:41:32 +01:00
node = first;
do
{
if ( compare( node, key ) )
goto Exit;
2003-12-21 02:41:32 +01:00
node = node->next;
} while ( node != first );
node = NULL;
}
2003-12-21 02:41:32 +01:00
Exit:
return node;
}
FT_EXPORT_DEF( FT_Error )
FTC_MruList_New( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FT_Memory memory = list->memory;
FT_Error error;
FTC_MruNode node;
if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
{
2003-12-21 02:41:32 +01:00
FT_ASSERT( list->nodes != NULL );
2003-12-21 02:41:32 +01:00
node = list->nodes->prev; /* last node */
if ( list->clazz.node_reset )
{
2003-12-21 02:41:32 +01:00
FTC_MruNode_Up( &list->nodes, node );
error = list->clazz.node_reset( node, key, list->data );
if ( !error )
goto Exit;
}
2003-12-21 02:41:32 +01:00
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
2003-12-21 02:41:32 +01:00
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
}
2003-12-21 02:41:32 +01:00
else
{
if ( FT_ALLOC( node, list->clazz.node_size ) )
goto Exit;
}
error = list->clazz.node_init( node, key, list->data );
2003-12-21 02:41:32 +01:00
if ( !error )
{
2003-12-21 02:41:32 +01:00
FTC_MruNode_Prepend( &list->nodes, node );
list->num_nodes++;
goto Exit;
}
2003-12-21 02:41:32 +01:00
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
Exit:
*anode = node;
return error;
}
2003-12-21 02:41:32 +01:00
FT_EXPORT_DEF( FT_Error )
FTC_MruList_Get( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
2003-12-21 02:41:32 +01:00
FT_Error error = 0;
FTC_MruNode node;
2003-12-21 02:41:32 +01:00
node = FTC_MruList_Lookup( list, key );
if ( node == NULL )
{
2003-12-21 02:41:32 +01:00
error = FTC_MruList_New( list, key, &node );
if ( error )
node = NULL;
}
*anode = node;
return error;
}
2003-12-21 02:41:32 +01:00
FT_EXPORT_DEF( void )
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node )
{
FT_Memory memory = list->memory;
2003-12-21 02:41:32 +01:00
FT_ASSERT( list->nodes != NULL && list->num_nodes > 0 );
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
2003-12-21 02:41:32 +01:00
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
2003-12-21 02:41:32 +01:00
FT_FREE( node );
}
FT_EXPORT_DEF( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
FTC_MruNode_CompareFunc select,
FT_Pointer key )
{
2003-12-21 02:41:32 +01:00
FTC_MruNode first = list->nodes;
2003-12-21 02:41:32 +01:00
while ( first && select( first, key ) )
{
2003-12-21 02:41:32 +01:00
FTC_MruList_Remove( list, first );
first = list->nodes;
}
2003-12-21 02:41:32 +01:00
if ( first )
{
FTC_MruNode node = first->next;
FTC_MruNode next;
while ( node != first )
{
next = node->next;
if ( select( node, key ) )
2003-12-21 02:41:32 +01:00
FTC_MruList_Remove( list, node );
node = next;
}
}
}
/* END */