diff -r f9283dc4860d -r 88f2e05288ba misc/libfreetype/src/cache/ftcmru.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/libfreetype/src/cache/ftcmru.c Mon Apr 25 01:46:54 2011 +0200 @@ -0,0 +1,357 @@ +/***************************************************************************/ +/* */ +/* ftcmru.c */ +/* */ +/* FreeType MRU support (body). */ +/* */ +/* Copyright 2003, 2004, 2006, 2009 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. */ +/* */ +/***************************************************************************/ + + +#include +#include FT_CACHE_H +#include "ftcmru.h" +#include FT_INTERNAL_OBJECTS_H +#include FT_INTERNAL_DEBUG_H + +#include "ftcerror.h" + + + FT_LOCAL_DEF( void ) + FTC_MruNode_Prepend( FTC_MruNode *plist, + FTC_MruNode node ) + { + FTC_MruNode first = *plist; + + + if ( first ) + { + FTC_MruNode last = first->prev; + + +#ifdef FT_DEBUG_ERROR + { + FTC_MruNode cnode = first; + + + do + { + if ( cnode == node ) + { + fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" ); + exit( 2 ); + } + cnode = cnode->next; + + } while ( cnode != first ); + } +#endif + + first->prev = node; + last->next = node; + node->next = first; + node->prev = last; + } + else + { + node->next = node; + node->prev = node; + } + *plist = node; + } + + + FT_LOCAL_DEF( void ) + FTC_MruNode_Up( FTC_MruNode *plist, + FTC_MruNode node ) + { + FTC_MruNode first = *plist; + + + FT_ASSERT( first != NULL ); + + if ( first != node ) + { + FTC_MruNode prev, next, last; + + +#ifdef FT_DEBUG_ERROR + { + FTC_MruNode cnode = first; + do + { + if ( cnode == node ) + goto Ok; + cnode = cnode->next; + + } while ( cnode != first ); + + fprintf( stderr, "FTC_MruNode_Up: invalid action\n" ); + exit( 2 ); + Ok: + } +#endif + prev = node->prev; + next = node->next; + + prev->next = next; + next->prev = prev; + + last = first->prev; + + last->next = node; + first->prev = node; + + node->next = first; + node->prev = last; + + *plist = node; + } + } + + + FT_LOCAL_DEF( void ) + FTC_MruNode_Remove( FTC_MruNode *plist, + FTC_MruNode node ) + { + FTC_MruNode first = *plist; + FTC_MruNode prev, next; + + + FT_ASSERT( first != NULL ); + +#ifdef FT_DEBUG_ERROR + { + FTC_MruNode cnode = first; + + + do + { + if ( cnode == node ) + goto Ok; + cnode = cnode->next; + + } while ( cnode != first ); + + fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" ); + exit( 2 ); + Ok: + } +#endif + + prev = node->prev; + next = node->next; + + prev->next = next; + next->prev = prev; + + if ( node == next ) + { + FT_ASSERT( first == node ); + FT_ASSERT( prev == node ); + + *plist = NULL; + } + else if ( node == first ) + *plist = next; + } + + + FT_LOCAL_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; + } + + + FT_LOCAL_DEF( void ) + FTC_MruList_Reset( FTC_MruList list ) + { + while ( list->nodes ) + FTC_MruList_Remove( list, list->nodes ); + + FT_ASSERT( list->num_nodes == 0 ); + } + + + FT_LOCAL_DEF( void ) + FTC_MruList_Done( FTC_MruList list ) + { + FTC_MruList_Reset( list ); + } + + +#ifndef FTC_INLINE + FT_LOCAL_DEF( FTC_MruNode ) + FTC_MruList_Find( FTC_MruList list, + FT_Pointer key ) + { + FTC_MruNode_CompareFunc compare = list->clazz.node_compare; + FTC_MruNode first, node; + + + first = list->nodes; + node = NULL; + + if ( first ) + { + node = first; + do + { + if ( compare( node, key ) ) + { + if ( node != first ) + FTC_MruNode_Up( &list->nodes, node ); + + return node; + } + + node = node->next; + + } while ( node != first); + } + + return NULL; + } +#endif + + FT_LOCAL_DEF( FT_Error ) + FTC_MruList_New( FTC_MruList list, + FT_Pointer key, + FTC_MruNode *anode ) + { + FT_Error error; + FTC_MruNode node; + FT_Memory memory = list->memory; + + + if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 ) + { + node = list->nodes->prev; + + FT_ASSERT( node ); + + if ( list->clazz.node_reset ) + { + FTC_MruNode_Up( &list->nodes, node ); + + error = list->clazz.node_reset( node, key, list->data ); + if ( !error ) + goto Exit; + } + + FTC_MruNode_Remove( &list->nodes, node ); + list->num_nodes--; + + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); + } + else if ( FT_ALLOC( node, list->clazz.node_size ) ) + goto Exit; + + error = list->clazz.node_init( node, key, list->data ); + if ( error ) + goto Fail; + + FTC_MruNode_Prepend( &list->nodes, node ); + list->num_nodes++; + + Exit: + *anode = node; + return error; + + Fail: + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); + + FT_FREE( node ); + goto Exit; + } + + +#ifndef FTC_INLINE + FT_LOCAL_DEF( FT_Error ) + FTC_MruList_Lookup( FTC_MruList list, + FT_Pointer key, + FTC_MruNode *anode ) + { + FTC_MruNode node; + + + node = FTC_MruList_Find( list, key ); + if ( node == NULL ) + return FTC_MruList_New( list, key, anode ); + + *anode = node; + return 0; + } +#endif /* FTC_INLINE */ + + FT_LOCAL_DEF( void ) + FTC_MruList_Remove( FTC_MruList list, + FTC_MruNode node ) + { + FTC_MruNode_Remove( &list->nodes, node ); + list->num_nodes--; + + { + FT_Memory memory = list->memory; + + + if ( list->clazz.node_done ) + list->clazz.node_done( node, list->data ); + + FT_FREE( node ); + } + } + + + FT_LOCAL_DEF( void ) + FTC_MruList_RemoveSelection( FTC_MruList list, + FTC_MruNode_CompareFunc selection, + FT_Pointer key ) + { + FTC_MruNode first, node, next; + + + first = list->nodes; + while ( first && ( selection == NULL || selection( first, key ) ) ) + { + FTC_MruList_Remove( list, first ); + first = list->nodes; + } + + if ( first ) + { + node = first->next; + while ( node != first ) + { + next = node->next; + + if ( selection( node, key ) ) + FTC_MruList_Remove( list, node ); + + node = next; + } + } + } + + +/* END */