Index: src/cache/ftcmru.c |
diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c |
new file mode 100644 |
index 0000000000000000000000000000000000000000..dc8b4cc3970912dead7166f14110a5baeab8de64 |
--- /dev/null |
+++ b/src/cache/ftcmru.c |
@@ -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 <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 = NULL; |
+ 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 */ |