misc/libfreetype/src/cache/ftcmru.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ftcmru.c                                                               */
       
     4 /*                                                                         */
       
     5 /*    FreeType MRU support (body).                                         */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2003, 2004, 2006, 2009 by                                    */
       
     8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
     9 /*                                                                         */
       
    10 /*  This file is part of the FreeType project, and may only be used,       */
       
    11 /*  modified, and distributed under the terms of the FreeType project      */
       
    12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    13 /*  this file you indicate that you have read the license and              */
       
    14 /*  understand and accept it fully.                                        */
       
    15 /*                                                                         */
       
    16 /***************************************************************************/
       
    17 
       
    18 
       
    19 #include <ft2build.h>
       
    20 #include FT_CACHE_H
       
    21 #include "ftcmru.h"
       
    22 #include FT_INTERNAL_OBJECTS_H
       
    23 #include FT_INTERNAL_DEBUG_H
       
    24 
       
    25 #include "ftcerror.h"
       
    26 
       
    27 
       
    28   FT_LOCAL_DEF( void )
       
    29   FTC_MruNode_Prepend( FTC_MruNode  *plist,
       
    30                        FTC_MruNode   node )
       
    31   {
       
    32     FTC_MruNode  first = *plist;
       
    33 
       
    34 
       
    35     if ( first )
       
    36     {
       
    37       FTC_MruNode  last = first->prev;
       
    38 
       
    39 
       
    40 #ifdef FT_DEBUG_ERROR
       
    41       {
       
    42         FTC_MruNode  cnode = first;
       
    43 
       
    44 
       
    45         do
       
    46         {
       
    47           if ( cnode == node )
       
    48           {
       
    49             fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" );
       
    50             exit( 2 );
       
    51           }
       
    52           cnode = cnode->next;
       
    53 
       
    54         } while ( cnode != first );
       
    55       }
       
    56 #endif
       
    57 
       
    58       first->prev = node;
       
    59       last->next  = node;
       
    60       node->next  = first;
       
    61       node->prev  = last;
       
    62     }
       
    63     else
       
    64     {
       
    65       node->next = node;
       
    66       node->prev = node;
       
    67     }
       
    68     *plist = node;
       
    69   }
       
    70 
       
    71 
       
    72   FT_LOCAL_DEF( void )
       
    73   FTC_MruNode_Up( FTC_MruNode  *plist,
       
    74                   FTC_MruNode   node )
       
    75   {
       
    76     FTC_MruNode  first = *plist;
       
    77 
       
    78 
       
    79     FT_ASSERT( first != NULL );
       
    80 
       
    81     if ( first != node )
       
    82     {
       
    83       FTC_MruNode  prev, next, last;
       
    84 
       
    85 
       
    86 #ifdef FT_DEBUG_ERROR
       
    87       {
       
    88         FTC_MruNode  cnode = first;
       
    89         do
       
    90         {
       
    91           if ( cnode == node )
       
    92             goto Ok;
       
    93           cnode = cnode->next;
       
    94 
       
    95         } while ( cnode != first );
       
    96 
       
    97         fprintf( stderr, "FTC_MruNode_Up: invalid action\n" );
       
    98         exit( 2 );
       
    99       Ok:
       
   100       }
       
   101 #endif
       
   102       prev = node->prev;
       
   103       next = node->next;
       
   104 
       
   105       prev->next = next;
       
   106       next->prev = prev;
       
   107 
       
   108       last = first->prev;
       
   109 
       
   110       last->next  = node;
       
   111       first->prev = node;
       
   112 
       
   113       node->next = first;
       
   114       node->prev = last;
       
   115 
       
   116       *plist = node;
       
   117     }
       
   118   }
       
   119 
       
   120 
       
   121   FT_LOCAL_DEF( void )
       
   122   FTC_MruNode_Remove( FTC_MruNode  *plist,
       
   123                       FTC_MruNode   node )
       
   124   {
       
   125     FTC_MruNode  first = *plist;
       
   126     FTC_MruNode  prev, next;
       
   127 
       
   128 
       
   129     FT_ASSERT( first != NULL );
       
   130 
       
   131 #ifdef FT_DEBUG_ERROR
       
   132       {
       
   133         FTC_MruNode  cnode = first;
       
   134 
       
   135 
       
   136         do
       
   137         {
       
   138           if ( cnode == node )
       
   139             goto Ok;
       
   140           cnode = cnode->next;
       
   141 
       
   142         } while ( cnode != first );
       
   143 
       
   144         fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" );
       
   145         exit( 2 );
       
   146       Ok:
       
   147       }
       
   148 #endif
       
   149 
       
   150     prev = node->prev;
       
   151     next = node->next;
       
   152 
       
   153     prev->next = next;
       
   154     next->prev = prev;
       
   155 
       
   156     if ( node == next )
       
   157     {
       
   158       FT_ASSERT( first == node );
       
   159       FT_ASSERT( prev  == node );
       
   160 
       
   161       *plist = NULL;
       
   162     }
       
   163     else if ( node == first )
       
   164         *plist = next;
       
   165   }
       
   166 
       
   167 
       
   168   FT_LOCAL_DEF( void )
       
   169   FTC_MruList_Init( FTC_MruList       list,
       
   170                     FTC_MruListClass  clazz,
       
   171                     FT_UInt           max_nodes,
       
   172                     FT_Pointer        data,
       
   173                     FT_Memory         memory )
       
   174   {
       
   175     list->num_nodes = 0;
       
   176     list->max_nodes = max_nodes;
       
   177     list->nodes     = NULL;
       
   178     list->clazz     = *clazz;
       
   179     list->data      = data;
       
   180     list->memory    = memory;
       
   181   }
       
   182 
       
   183 
       
   184   FT_LOCAL_DEF( void )
       
   185   FTC_MruList_Reset( FTC_MruList  list )
       
   186   {
       
   187     while ( list->nodes )
       
   188       FTC_MruList_Remove( list, list->nodes );
       
   189 
       
   190     FT_ASSERT( list->num_nodes == 0 );
       
   191   }
       
   192 
       
   193 
       
   194   FT_LOCAL_DEF( void )
       
   195   FTC_MruList_Done( FTC_MruList  list )
       
   196   {
       
   197     FTC_MruList_Reset( list );
       
   198   }
       
   199 
       
   200 
       
   201 #ifndef FTC_INLINE
       
   202   FT_LOCAL_DEF( FTC_MruNode )
       
   203   FTC_MruList_Find( FTC_MruList  list,
       
   204                     FT_Pointer   key )
       
   205   {
       
   206     FTC_MruNode_CompareFunc  compare = list->clazz.node_compare;
       
   207     FTC_MruNode              first, node;
       
   208 
       
   209 
       
   210     first = list->nodes;
       
   211     node  = NULL;
       
   212 
       
   213     if ( first )
       
   214     {
       
   215       node = first;
       
   216       do
       
   217       {
       
   218         if ( compare( node, key ) )
       
   219         {
       
   220           if ( node != first )
       
   221             FTC_MruNode_Up( &list->nodes, node );
       
   222 
       
   223           return node;
       
   224         }
       
   225 
       
   226         node = node->next;
       
   227 
       
   228       } while ( node != first);
       
   229     }
       
   230 
       
   231     return NULL;
       
   232   }
       
   233 #endif
       
   234 
       
   235   FT_LOCAL_DEF( FT_Error )
       
   236   FTC_MruList_New( FTC_MruList   list,
       
   237                    FT_Pointer    key,
       
   238                    FTC_MruNode  *anode )
       
   239   {
       
   240     FT_Error     error;
       
   241     FTC_MruNode  node;
       
   242     FT_Memory    memory = list->memory;
       
   243 
       
   244 
       
   245     if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
       
   246     {
       
   247       node = list->nodes->prev;
       
   248 
       
   249       FT_ASSERT( node );
       
   250 
       
   251       if ( list->clazz.node_reset )
       
   252       {
       
   253         FTC_MruNode_Up( &list->nodes, node );
       
   254 
       
   255         error = list->clazz.node_reset( node, key, list->data );
       
   256         if ( !error )
       
   257           goto Exit;
       
   258       }
       
   259 
       
   260       FTC_MruNode_Remove( &list->nodes, node );
       
   261       list->num_nodes--;
       
   262 
       
   263       if ( list->clazz.node_done )
       
   264         list->clazz.node_done( node, list->data );
       
   265     }
       
   266     else if ( FT_ALLOC( node, list->clazz.node_size ) )
       
   267         goto Exit;
       
   268 
       
   269     error = list->clazz.node_init( node, key, list->data );
       
   270     if ( error )
       
   271       goto Fail;
       
   272 
       
   273       FTC_MruNode_Prepend( &list->nodes, node );
       
   274       list->num_nodes++;
       
   275 
       
   276   Exit:
       
   277     *anode = node;
       
   278     return error;
       
   279 
       
   280   Fail:
       
   281     if ( list->clazz.node_done )
       
   282       list->clazz.node_done( node, list->data );
       
   283 
       
   284     FT_FREE( node );
       
   285     goto Exit;
       
   286   }
       
   287 
       
   288 
       
   289 #ifndef FTC_INLINE
       
   290   FT_LOCAL_DEF( FT_Error )
       
   291   FTC_MruList_Lookup( FTC_MruList   list,
       
   292                       FT_Pointer    key,
       
   293                       FTC_MruNode  *anode )
       
   294   {
       
   295     FTC_MruNode  node;
       
   296 
       
   297 
       
   298     node = FTC_MruList_Find( list, key );
       
   299     if ( node == NULL )
       
   300       return FTC_MruList_New( list, key, anode );
       
   301 
       
   302     *anode = node;
       
   303     return 0;
       
   304   }
       
   305 #endif /* FTC_INLINE */
       
   306 
       
   307   FT_LOCAL_DEF( void )
       
   308   FTC_MruList_Remove( FTC_MruList  list,
       
   309                       FTC_MruNode  node )
       
   310   {
       
   311     FTC_MruNode_Remove( &list->nodes, node );
       
   312     list->num_nodes--;
       
   313 
       
   314     {
       
   315       FT_Memory  memory = list->memory;
       
   316 
       
   317 
       
   318       if ( list->clazz.node_done )
       
   319        list->clazz.node_done( node, list->data );
       
   320 
       
   321       FT_FREE( node );
       
   322     }
       
   323   }
       
   324 
       
   325 
       
   326   FT_LOCAL_DEF( void )
       
   327   FTC_MruList_RemoveSelection( FTC_MruList              list,
       
   328                                FTC_MruNode_CompareFunc  selection,
       
   329                                FT_Pointer               key )
       
   330   {
       
   331     FTC_MruNode  first, node, next;
       
   332 
       
   333 
       
   334     first = list->nodes;
       
   335     while ( first && ( selection == NULL || selection( first, key ) ) )
       
   336     {
       
   337       FTC_MruList_Remove( list, first );
       
   338       first = list->nodes;
       
   339     }
       
   340 
       
   341     if ( first )
       
   342     {
       
   343       node = first->next;
       
   344       while ( node != first )
       
   345       {
       
   346         next = node->next;
       
   347 
       
   348         if ( selection( node, key ) )
       
   349           FTC_MruList_Remove( list, node );
       
   350 
       
   351         node = next;
       
   352       }
       
   353     }
       
   354   }
       
   355 
       
   356 
       
   357 /* END */