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 */ |
|