summaryrefslogtreecommitdiffstats
path: root/src/cache/ftcmru.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache/ftcmru.c')
-rw-r--r--src/cache/ftcmru.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c
new file mode 100644
index 0000000..3a6c625
--- /dev/null
+++ b/src/cache/ftcmru.c
@@ -0,0 +1,357 @@
+/***************************************************************************/
+/* */
+/* ftcmru.c */
+/* */
+/* FreeType MRU support (body). */
+/* */
+/* Copyright 2003, 2004, 2006 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 <ft2build.h>
+#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 */