xref: /inferno-os/libfreetype/ftlru.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ftlru.c                                                                */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    Simple LRU list-cache (body).                                        */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2000-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_CACHE_H
21*37da2899SCharles.Forsyth #include FT_CACHE_INTERNAL_LRU_H
22*37da2899SCharles.Forsyth #include FT_LIST_H
23*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth #include "ftcerror.h"
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_LruList_New(FT_LruList_Class clazz,FT_UInt max_nodes,FT_Pointer user_data,FT_Memory memory,FT_LruList * alist)29*37da2899SCharles.Forsyth   FT_LruList_New( FT_LruList_Class  clazz,
30*37da2899SCharles.Forsyth                   FT_UInt           max_nodes,
31*37da2899SCharles.Forsyth                   FT_Pointer        user_data,
32*37da2899SCharles.Forsyth                   FT_Memory         memory,
33*37da2899SCharles.Forsyth                   FT_LruList       *alist )
34*37da2899SCharles.Forsyth   {
35*37da2899SCharles.Forsyth     FT_Error    error;
36*37da2899SCharles.Forsyth     FT_LruList  list;
37*37da2899SCharles.Forsyth 
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth     if ( !alist || !clazz )
40*37da2899SCharles.Forsyth       return FTC_Err_Invalid_Argument;
41*37da2899SCharles.Forsyth 
42*37da2899SCharles.Forsyth     *alist = NULL;
43*37da2899SCharles.Forsyth     if ( !FT_ALLOC( list, clazz->list_size ) )
44*37da2899SCharles.Forsyth     {
45*37da2899SCharles.Forsyth       /* initialize common fields */
46*37da2899SCharles.Forsyth       list->clazz      = clazz;
47*37da2899SCharles.Forsyth       list->memory     = memory;
48*37da2899SCharles.Forsyth       list->max_nodes  = max_nodes;
49*37da2899SCharles.Forsyth       list->data       = user_data;
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth       if ( clazz->list_init )
52*37da2899SCharles.Forsyth       {
53*37da2899SCharles.Forsyth         error = clazz->list_init( list );
54*37da2899SCharles.Forsyth         if ( error )
55*37da2899SCharles.Forsyth         {
56*37da2899SCharles.Forsyth           if ( clazz->list_done )
57*37da2899SCharles.Forsyth             clazz->list_done( list );
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth           FT_FREE( list );
60*37da2899SCharles.Forsyth         }
61*37da2899SCharles.Forsyth       }
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth       *alist = list;
64*37da2899SCharles.Forsyth     }
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth     return error;
67*37da2899SCharles.Forsyth   }
68*37da2899SCharles.Forsyth 
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_LruList_Destroy(FT_LruList list)71*37da2899SCharles.Forsyth   FT_LruList_Destroy( FT_LruList  list )
72*37da2899SCharles.Forsyth   {
73*37da2899SCharles.Forsyth     FT_Memory         memory;
74*37da2899SCharles.Forsyth     FT_LruList_Class  clazz;
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth 
77*37da2899SCharles.Forsyth     if ( !list )
78*37da2899SCharles.Forsyth       return;
79*37da2899SCharles.Forsyth 
80*37da2899SCharles.Forsyth     memory = list->memory;
81*37da2899SCharles.Forsyth     clazz  = list->clazz;
82*37da2899SCharles.Forsyth 
83*37da2899SCharles.Forsyth     FT_LruList_Reset( list );
84*37da2899SCharles.Forsyth 
85*37da2899SCharles.Forsyth     if ( clazz->list_done )
86*37da2899SCharles.Forsyth       clazz->list_done( list );
87*37da2899SCharles.Forsyth 
88*37da2899SCharles.Forsyth     FT_FREE( list );
89*37da2899SCharles.Forsyth   }
90*37da2899SCharles.Forsyth 
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_LruList_Reset(FT_LruList list)93*37da2899SCharles.Forsyth   FT_LruList_Reset( FT_LruList  list )
94*37da2899SCharles.Forsyth   {
95*37da2899SCharles.Forsyth     FT_LruNode        node;
96*37da2899SCharles.Forsyth     FT_LruList_Class  clazz;
97*37da2899SCharles.Forsyth     FT_Memory         memory;
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth     if ( !list )
101*37da2899SCharles.Forsyth       return;
102*37da2899SCharles.Forsyth 
103*37da2899SCharles.Forsyth     node   = list->nodes;
104*37da2899SCharles.Forsyth     clazz  = list->clazz;
105*37da2899SCharles.Forsyth     memory = list->memory;
106*37da2899SCharles.Forsyth 
107*37da2899SCharles.Forsyth     while ( node )
108*37da2899SCharles.Forsyth     {
109*37da2899SCharles.Forsyth       FT_LruNode  next = node->next;
110*37da2899SCharles.Forsyth 
111*37da2899SCharles.Forsyth 
112*37da2899SCharles.Forsyth       if ( clazz->node_done )
113*37da2899SCharles.Forsyth         clazz->node_done( node, list->data );
114*37da2899SCharles.Forsyth 
115*37da2899SCharles.Forsyth       FT_FREE( node );
116*37da2899SCharles.Forsyth       node = next;
117*37da2899SCharles.Forsyth     }
118*37da2899SCharles.Forsyth 
119*37da2899SCharles.Forsyth     list->nodes     = NULL;
120*37da2899SCharles.Forsyth     list->num_nodes = 0;
121*37da2899SCharles.Forsyth   }
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth 
124*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_LruList_Lookup(FT_LruList list,FT_LruKey key,FT_LruNode * anode)125*37da2899SCharles.Forsyth   FT_LruList_Lookup( FT_LruList   list,
126*37da2899SCharles.Forsyth                      FT_LruKey    key,
127*37da2899SCharles.Forsyth                      FT_LruNode  *anode )
128*37da2899SCharles.Forsyth   {
129*37da2899SCharles.Forsyth     FT_Error          error = 0;
130*37da2899SCharles.Forsyth     FT_LruNode        node, *pnode;
131*37da2899SCharles.Forsyth     FT_LruList_Class  clazz;
132*37da2899SCharles.Forsyth     FT_LruNode*       plast;
133*37da2899SCharles.Forsyth     FT_LruNode        result = NULL;
134*37da2899SCharles.Forsyth     FT_Memory         memory;
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth     if ( !list || !key || !anode )
138*37da2899SCharles.Forsyth       return FTC_Err_Invalid_Argument;
139*37da2899SCharles.Forsyth 
140*37da2899SCharles.Forsyth     pnode  = &list->nodes;
141*37da2899SCharles.Forsyth     plast  = pnode;
142*37da2899SCharles.Forsyth     node   = NULL;
143*37da2899SCharles.Forsyth     clazz  = list->clazz;
144*37da2899SCharles.Forsyth     memory = list->memory;
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth     if ( clazz->node_compare )
147*37da2899SCharles.Forsyth     {
148*37da2899SCharles.Forsyth       for (;;)
149*37da2899SCharles.Forsyth       {
150*37da2899SCharles.Forsyth         node = *pnode;
151*37da2899SCharles.Forsyth         if ( node == NULL )
152*37da2899SCharles.Forsyth           break;
153*37da2899SCharles.Forsyth 
154*37da2899SCharles.Forsyth         if ( clazz->node_compare( node, key, list->data ) )
155*37da2899SCharles.Forsyth           break;
156*37da2899SCharles.Forsyth 
157*37da2899SCharles.Forsyth         plast = pnode;
158*37da2899SCharles.Forsyth         pnode = &(*pnode)->next;
159*37da2899SCharles.Forsyth       }
160*37da2899SCharles.Forsyth     }
161*37da2899SCharles.Forsyth     else
162*37da2899SCharles.Forsyth     {
163*37da2899SCharles.Forsyth       for (;;)
164*37da2899SCharles.Forsyth       {
165*37da2899SCharles.Forsyth         node = *pnode;
166*37da2899SCharles.Forsyth         if ( node == NULL )
167*37da2899SCharles.Forsyth           break;
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth         if ( node->key == key )
170*37da2899SCharles.Forsyth           break;
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth         plast = pnode;
173*37da2899SCharles.Forsyth         pnode = &(*pnode)->next;
174*37da2899SCharles.Forsyth       }
175*37da2899SCharles.Forsyth     }
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth     if ( node )
178*37da2899SCharles.Forsyth     {
179*37da2899SCharles.Forsyth       /* move element to top of list */
180*37da2899SCharles.Forsyth       if ( list->nodes != node )
181*37da2899SCharles.Forsyth       {
182*37da2899SCharles.Forsyth         *pnode      = node->next;
183*37da2899SCharles.Forsyth         node->next  = list->nodes;
184*37da2899SCharles.Forsyth         list->nodes = node;
185*37da2899SCharles.Forsyth       }
186*37da2899SCharles.Forsyth       result = node;
187*37da2899SCharles.Forsyth       goto Exit;
188*37da2899SCharles.Forsyth     }
189*37da2899SCharles.Forsyth 
190*37da2899SCharles.Forsyth     /* we haven't found the relevant element.  We will now try */
191*37da2899SCharles.Forsyth     /* to create a new one.                                    */
192*37da2899SCharles.Forsyth     /*                                                         */
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth     /* first, check if our list if full, when appropriate */
195*37da2899SCharles.Forsyth     if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
196*37da2899SCharles.Forsyth     {
197*37da2899SCharles.Forsyth       /* this list list is full; we will now flush */
198*37da2899SCharles.Forsyth       /* the oldest node, if there's one!          */
199*37da2899SCharles.Forsyth       FT_LruNode  last = *plast;
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth 
202*37da2899SCharles.Forsyth       if ( last )
203*37da2899SCharles.Forsyth       {
204*37da2899SCharles.Forsyth         if ( clazz->node_flush )
205*37da2899SCharles.Forsyth         {
206*37da2899SCharles.Forsyth           error = clazz->node_flush( last, key, list->data );
207*37da2899SCharles.Forsyth         }
208*37da2899SCharles.Forsyth         else
209*37da2899SCharles.Forsyth         {
210*37da2899SCharles.Forsyth           if ( clazz->node_done )
211*37da2899SCharles.Forsyth             clazz->node_done( last, list->data );
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth           last->key  = key;
214*37da2899SCharles.Forsyth           error = clazz->node_init( last, key, list->data );
215*37da2899SCharles.Forsyth         }
216*37da2899SCharles.Forsyth 
217*37da2899SCharles.Forsyth         if ( !error )
218*37da2899SCharles.Forsyth         {
219*37da2899SCharles.Forsyth           /* move it to the top of the list */
220*37da2899SCharles.Forsyth           *plast      = NULL;
221*37da2899SCharles.Forsyth           last->next  = list->nodes;
222*37da2899SCharles.Forsyth           list->nodes = last;
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth           result = last;
225*37da2899SCharles.Forsyth           goto Exit;
226*37da2899SCharles.Forsyth         }
227*37da2899SCharles.Forsyth 
228*37da2899SCharles.Forsyth         /* in case of error during the flush or done/init cycle, */
229*37da2899SCharles.Forsyth         /* we need to discard the node                           */
230*37da2899SCharles.Forsyth         if ( clazz->node_done )
231*37da2899SCharles.Forsyth           clazz->node_done( last, list->data );
232*37da2899SCharles.Forsyth 
233*37da2899SCharles.Forsyth         *plast = NULL;
234*37da2899SCharles.Forsyth         list->num_nodes--;
235*37da2899SCharles.Forsyth 
236*37da2899SCharles.Forsyth         FT_FREE( last );
237*37da2899SCharles.Forsyth         goto Exit;
238*37da2899SCharles.Forsyth       }
239*37da2899SCharles.Forsyth     }
240*37da2899SCharles.Forsyth 
241*37da2899SCharles.Forsyth     /* otherwise, simply allocate a new node */
242*37da2899SCharles.Forsyth     if ( FT_ALLOC( node, clazz->node_size ) )
243*37da2899SCharles.Forsyth       goto Exit;
244*37da2899SCharles.Forsyth 
245*37da2899SCharles.Forsyth     node->key = key;
246*37da2899SCharles.Forsyth     error = clazz->node_init( node, key, list->data );
247*37da2899SCharles.Forsyth     if ( error )
248*37da2899SCharles.Forsyth     {
249*37da2899SCharles.Forsyth       FT_FREE( node );
250*37da2899SCharles.Forsyth       goto Exit;
251*37da2899SCharles.Forsyth     }
252*37da2899SCharles.Forsyth 
253*37da2899SCharles.Forsyth     result      = node;
254*37da2899SCharles.Forsyth     node->next  = list->nodes;
255*37da2899SCharles.Forsyth     list->nodes = node;
256*37da2899SCharles.Forsyth     list->num_nodes++;
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth   Exit:
259*37da2899SCharles.Forsyth     *anode = result;
260*37da2899SCharles.Forsyth     return error;
261*37da2899SCharles.Forsyth   }
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth 
264*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_LruList_Remove(FT_LruList list,FT_LruNode node)265*37da2899SCharles.Forsyth   FT_LruList_Remove( FT_LruList  list,
266*37da2899SCharles.Forsyth                      FT_LruNode  node )
267*37da2899SCharles.Forsyth   {
268*37da2899SCharles.Forsyth     FT_LruNode  *pnode;
269*37da2899SCharles.Forsyth 
270*37da2899SCharles.Forsyth 
271*37da2899SCharles.Forsyth     if ( !list || !node )
272*37da2899SCharles.Forsyth       return;
273*37da2899SCharles.Forsyth 
274*37da2899SCharles.Forsyth     pnode = &list->nodes;
275*37da2899SCharles.Forsyth     for (;;)
276*37da2899SCharles.Forsyth     {
277*37da2899SCharles.Forsyth       if ( *pnode == node )
278*37da2899SCharles.Forsyth       {
279*37da2899SCharles.Forsyth         FT_Memory         memory = list->memory;
280*37da2899SCharles.Forsyth         FT_LruList_Class  clazz  = list->clazz;
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth 
283*37da2899SCharles.Forsyth         *pnode     = node->next;
284*37da2899SCharles.Forsyth         node->next = NULL;
285*37da2899SCharles.Forsyth 
286*37da2899SCharles.Forsyth         if ( clazz->node_done )
287*37da2899SCharles.Forsyth           clazz->node_done( node, list->data );
288*37da2899SCharles.Forsyth 
289*37da2899SCharles.Forsyth         FT_FREE( node );
290*37da2899SCharles.Forsyth         list->num_nodes--;
291*37da2899SCharles.Forsyth         break;
292*37da2899SCharles.Forsyth       }
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth       pnode = &(*pnode)->next;
295*37da2899SCharles.Forsyth     }
296*37da2899SCharles.Forsyth   }
297*37da2899SCharles.Forsyth 
298*37da2899SCharles.Forsyth 
299*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_LruList_Remove_Selection(FT_LruList list,FT_LruNode_SelectFunc select_func,FT_Pointer select_data)300*37da2899SCharles.Forsyth   FT_LruList_Remove_Selection( FT_LruList             list,
301*37da2899SCharles.Forsyth                                FT_LruNode_SelectFunc  select_func,
302*37da2899SCharles.Forsyth                                FT_Pointer             select_data )
303*37da2899SCharles.Forsyth   {
304*37da2899SCharles.Forsyth     FT_LruNode       *pnode, node;
305*37da2899SCharles.Forsyth     FT_LruList_Class  clazz;
306*37da2899SCharles.Forsyth     FT_Memory         memory;
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth 
309*37da2899SCharles.Forsyth     if ( !list || !select_func )
310*37da2899SCharles.Forsyth       return;
311*37da2899SCharles.Forsyth 
312*37da2899SCharles.Forsyth     memory = list->memory;
313*37da2899SCharles.Forsyth     clazz  = list->clazz;
314*37da2899SCharles.Forsyth     pnode  = &list->nodes;
315*37da2899SCharles.Forsyth 
316*37da2899SCharles.Forsyth     for (;;)
317*37da2899SCharles.Forsyth     {
318*37da2899SCharles.Forsyth       node = *pnode;
319*37da2899SCharles.Forsyth       if ( node == NULL )
320*37da2899SCharles.Forsyth         break;
321*37da2899SCharles.Forsyth 
322*37da2899SCharles.Forsyth       if ( select_func( node, select_data, list->data ) )
323*37da2899SCharles.Forsyth       {
324*37da2899SCharles.Forsyth         *pnode     = node->next;
325*37da2899SCharles.Forsyth         node->next = NULL;
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth         if ( clazz->node_done )
328*37da2899SCharles.Forsyth           clazz->node_done( node, list );
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth         FT_FREE( node );
331*37da2899SCharles.Forsyth       }
332*37da2899SCharles.Forsyth       else
333*37da2899SCharles.Forsyth         pnode = &(*pnode)->next;
334*37da2899SCharles.Forsyth     }
335*37da2899SCharles.Forsyth   }
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth 
338*37da2899SCharles.Forsyth /* END */
339