00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_CACHE_H
00021 #include "ftcmru.h"
00022 #include FT_INTERNAL_OBJECTS_H
00023 #include FT_INTERNAL_DEBUG_H
00024
00025 #include "ftcerror.h"
00026
00027
00028 FT_LOCAL_DEF( void )
00029 FTC_MruNode_Prepend( FTC_MruNode *plist,
00030 FTC_MruNode node )
00031 {
00032 FTC_MruNode first = *plist;
00033
00034
00035 if ( first )
00036 {
00037 FTC_MruNode last = first->prev;
00038
00039
00040 #ifdef FT_DEBUG_ERROR
00041 {
00042 FTC_MruNode cnode = first;
00043
00044
00045 do
00046 {
00047 if ( cnode == node )
00048 {
00049 fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" );
00050 exit( 2 );
00051 }
00052 cnode = cnode->next;
00053
00054 } while ( cnode != first );
00055 }
00056 #endif
00057
00058 first->prev = node;
00059 last->next = node;
00060 node->next = first;
00061 node->prev = last;
00062 }
00063 else
00064 {
00065 node->next = node;
00066 node->prev = node;
00067 }
00068 *plist = node;
00069 }
00070
00071
00072 FT_LOCAL_DEF( void )
00073 FTC_MruNode_Up( FTC_MruNode *plist,
00074 FTC_MruNode node )
00075 {
00076 FTC_MruNode first = *plist;
00077
00078
00079 FT_ASSERT( first != NULL );
00080
00081 if ( first != node )
00082 {
00083 FTC_MruNode prev, next, last;
00084
00085
00086 #ifdef FT_DEBUG_ERROR
00087 {
00088 FTC_MruNode cnode = first;
00089 do
00090 {
00091 if ( cnode == node )
00092 goto Ok;
00093 cnode = cnode->next;
00094
00095 } while ( cnode != first );
00096
00097 fprintf( stderr, "FTC_MruNode_Up: invalid action\n" );
00098 exit( 2 );
00099 Ok:
00100 }
00101 #endif
00102 prev = node->prev;
00103 next = node->next;
00104
00105 prev->next = next;
00106 next->prev = prev;
00107
00108 last = first->prev;
00109
00110 last->next = node;
00111 first->prev = node;
00112
00113 node->next = first;
00114 node->prev = last;
00115
00116 *plist = node;
00117 }
00118 }
00119
00120
00121 FT_LOCAL_DEF( void )
00122 FTC_MruNode_Remove( FTC_MruNode *plist,
00123 FTC_MruNode node )
00124 {
00125 FTC_MruNode first = *plist;
00126 FTC_MruNode prev, next;
00127
00128
00129 FT_ASSERT( first != NULL );
00130
00131 #ifdef FT_DEBUG_ERROR
00132 {
00133 FTC_MruNode cnode = first;
00134
00135
00136 do
00137 {
00138 if ( cnode == node )
00139 goto Ok;
00140 cnode = cnode->next;
00141
00142 } while ( cnode != first );
00143
00144 fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" );
00145 exit( 2 );
00146 Ok:
00147 }
00148 #endif
00149
00150 prev = node->prev;
00151 next = node->next;
00152
00153 prev->next = next;
00154 next->prev = prev;
00155
00156 if ( node == next )
00157 {
00158 FT_ASSERT( first == node );
00159 FT_ASSERT( prev == node );
00160
00161 *plist = NULL;
00162 }
00163 else if ( node == first )
00164 *plist = next;
00165 }
00166
00167
00168 FT_LOCAL_DEF( void )
00169 FTC_MruList_Init( FTC_MruList list,
00170 FTC_MruListClass clazz,
00171 FT_UInt max_nodes,
00172 FT_Pointer data,
00173 FT_Memory memory )
00174 {
00175 list->num_nodes = 0;
00176 list->max_nodes = max_nodes;
00177 list->nodes = NULL;
00178 list->clazz = *clazz;
00179 list->data = data;
00180 list->memory = memory;
00181 }
00182
00183
00184 FT_LOCAL_DEF( void )
00185 FTC_MruList_Reset( FTC_MruList list )
00186 {
00187 while ( list->nodes )
00188 FTC_MruList_Remove( list, list->nodes );
00189
00190 FT_ASSERT( list->num_nodes == 0 );
00191 }
00192
00193
00194 FT_LOCAL_DEF( void )
00195 FTC_MruList_Done( FTC_MruList list )
00196 {
00197 FTC_MruList_Reset( list );
00198 }
00199
00200
00201 #ifndef FTC_INLINE
00202 FT_LOCAL_DEF( FTC_MruNode )
00203 FTC_MruList_Find( FTC_MruList list,
00204 FT_Pointer key )
00205 {
00206 FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
00207 FTC_MruNode first, node;
00208
00209
00210 first = list->nodes;
00211 node = NULL;
00212
00213 if ( first )
00214 {
00215 node = first;
00216 do
00217 {
00218 if ( compare( node, key ) )
00219 {
00220 if ( node != first )
00221 FTC_MruNode_Up( &list->nodes, node );
00222
00223 return node;
00224 }
00225
00226 node = node->next;
00227
00228 } while ( node != first);
00229 }
00230
00231 return NULL;
00232 }
00233 #endif
00234
00235 FT_LOCAL_DEF( FT_Error )
00236 FTC_MruList_New( FTC_MruList list,
00237 FT_Pointer key,
00238 FTC_MruNode *anode )
00239 {
00240 FT_Error error;
00241 FTC_MruNode node;
00242 FT_Memory memory = list->memory;
00243
00244
00245 if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
00246 {
00247 node = list->nodes->prev;
00248
00249 FT_ASSERT( node );
00250
00251 if ( list->clazz.node_reset )
00252 {
00253 FTC_MruNode_Up( &list->nodes, node );
00254
00255 error = list->clazz.node_reset( node, key, list->data );
00256 if ( !error )
00257 goto Exit;
00258 }
00259
00260 FTC_MruNode_Remove( &list->nodes, node );
00261 list->num_nodes--;
00262
00263 if ( list->clazz.node_done )
00264 list->clazz.node_done( node, list->data );
00265 }
00266 else if ( FT_ALLOC( node, list->clazz.node_size ) )
00267 goto Exit;
00268
00269 error = list->clazz.node_init( node, key, list->data );
00270 if ( error )
00271 goto Fail;
00272
00273 FTC_MruNode_Prepend( &list->nodes, node );
00274 list->num_nodes++;
00275
00276 Exit:
00277 *anode = node;
00278 return error;
00279
00280 Fail:
00281 if ( list->clazz.node_done )
00282 list->clazz.node_done( node, list->data );
00283
00284 FT_FREE( node );
00285 goto Exit;
00286 }
00287
00288
00289 #ifndef FTC_INLINE
00290 FT_LOCAL_DEF( FT_Error )
00291 FTC_MruList_Lookup( FTC_MruList list,
00292 FT_Pointer key,
00293 FTC_MruNode *anode )
00294 {
00295 FTC_MruNode node;
00296
00297
00298 node = FTC_MruList_Find( list, key );
00299 if ( node == NULL )
00300 return FTC_MruList_New( list, key, anode );
00301
00302 *anode = node;
00303 return 0;
00304 }
00305 #endif
00306
00307 FT_LOCAL_DEF( void )
00308 FTC_MruList_Remove( FTC_MruList list,
00309 FTC_MruNode node )
00310 {
00311 FTC_MruNode_Remove( &list->nodes, node );
00312 list->num_nodes--;
00313
00314 {
00315 FT_Memory memory = list->memory;
00316
00317
00318 if ( list->clazz.node_done )
00319 list->clazz.node_done( node, list->data );
00320
00321 FT_FREE( node );
00322 }
00323 }
00324
00325
00326 FT_LOCAL_DEF( void )
00327 FTC_MruList_RemoveSelection( FTC_MruList list,
00328 FTC_MruNode_CompareFunc selection,
00329 FT_Pointer key )
00330 {
00331 FTC_MruNode first, node, next;
00332
00333
00334 first = list->nodes;
00335 while ( first && ( selection == NULL || selection( first, key ) ) )
00336 {
00337 FTC_MruList_Remove( list, first );
00338 first = list->nodes;
00339 }
00340
00341 if ( first )
00342 {
00343 node = first->next;
00344 while ( node != first )
00345 {
00346 next = node->next;
00347
00348 if ( selection( node, key ) )
00349 FTC_MruList_Remove( list, node );
00350
00351 node = next;
00352 }
00353 }
00354 }
00355
00356
00357