ftcmru.c (6615B)
1 /**************************************************************************** 2 * 3 * ftcmru.c 4 * 5 * FreeType MRU support (body). 6 * 7 * Copyright (C) 2003-2025 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 <freetype/ftcache.h> 20 #include "ftcmru.h" 21 #include <freetype/internal/ftobjs.h> 22 #include <freetype/internal/ftdebug.h> 23 24 #include "ftcerror.h" 25 26 27 FT_LOCAL_DEF( void ) 28 FTC_MruNode_Prepend( FTC_MruNode *plist, 29 FTC_MruNode node ) 30 { 31 FTC_MruNode first = *plist; 32 33 34 if ( first ) 35 { 36 FTC_MruNode last = first->prev; 37 38 39 #ifdef FT_DEBUG_ERROR 40 { 41 FTC_MruNode cnode = first; 42 43 44 do 45 { 46 if ( cnode == node ) 47 { 48 fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" ); 49 exit( 2 ); 50 } 51 cnode = cnode->next; 52 53 } while ( cnode != first ); 54 } 55 #endif 56 57 first->prev = node; 58 last->next = node; 59 node->next = first; 60 node->prev = last; 61 } 62 else 63 { 64 node->next = node; 65 node->prev = node; 66 } 67 *plist = node; 68 } 69 70 71 FT_LOCAL_DEF( void ) 72 FTC_MruNode_Up( FTC_MruNode *plist, 73 FTC_MruNode node ) 74 { 75 FTC_MruNode first = *plist; 76 77 78 FT_ASSERT( first ); 79 80 if ( first != node ) 81 { 82 FTC_MruNode prev, next, last; 83 84 85 #ifdef FT_DEBUG_ERROR 86 { 87 FTC_MruNode cnode = first; 88 do 89 { 90 if ( cnode == node ) 91 goto Ok; 92 cnode = cnode->next; 93 94 } while ( cnode != first ); 95 96 fprintf( stderr, "FTC_MruNode_Up: invalid action\n" ); 97 exit( 2 ); 98 Ok: 99 } 100 #endif 101 prev = node->prev; 102 next = node->next; 103 104 prev->next = next; 105 next->prev = prev; 106 107 last = first->prev; 108 109 last->next = node; 110 first->prev = node; 111 112 node->next = first; 113 node->prev = last; 114 115 *plist = node; 116 } 117 } 118 119 120 FT_LOCAL_DEF( void ) 121 FTC_MruNode_Remove( FTC_MruNode *plist, 122 FTC_MruNode node ) 123 { 124 FTC_MruNode first = *plist; 125 FTC_MruNode prev, next; 126 127 128 FT_ASSERT( first ); 129 130 #ifdef FT_DEBUG_ERROR 131 { 132 FTC_MruNode cnode = first; 133 134 135 do 136 { 137 if ( cnode == node ) 138 goto Ok; 139 cnode = cnode->next; 140 141 } while ( cnode != first ); 142 143 fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" ); 144 exit( 2 ); 145 Ok: 146 } 147 #endif 148 149 prev = node->prev; 150 next = node->next; 151 152 prev->next = next; 153 next->prev = prev; 154 155 if ( node == next ) 156 { 157 FT_ASSERT( first == node ); 158 FT_ASSERT( prev == node ); 159 160 *plist = NULL; 161 } 162 else if ( node == first ) 163 *plist = next; 164 } 165 166 167 FT_LOCAL_DEF( void ) 168 FTC_MruList_Init( FTC_MruList list, 169 FTC_MruListClass clazz, 170 FT_UInt max_nodes, 171 FT_Pointer data, 172 FT_Memory memory ) 173 { 174 list->num_nodes = 0; 175 list->max_nodes = max_nodes; 176 list->nodes = NULL; 177 list->clazz = *clazz; 178 list->data = data; 179 list->memory = memory; 180 } 181 182 183 FT_LOCAL_DEF( void ) 184 FTC_MruList_Reset( FTC_MruList list ) 185 { 186 while ( list->nodes ) 187 FTC_MruList_Remove( list, list->nodes ); 188 189 FT_ASSERT( list->num_nodes == 0 ); 190 } 191 192 193 FT_LOCAL_DEF( void ) 194 FTC_MruList_Done( FTC_MruList list ) 195 { 196 FTC_MruList_Reset( list ); 197 } 198 199 200 #ifndef FTC_INLINE 201 FT_LOCAL_DEF( FTC_MruNode ) 202 FTC_MruList_Find( FTC_MruList list, 203 FT_Pointer key ) 204 { 205 FTC_MruNode_CompareFunc compare = list->clazz.node_compare; 206 FTC_MruNode first, node; 207 208 209 first = list->nodes; 210 node = NULL; 211 212 if ( first ) 213 { 214 node = first; 215 do 216 { 217 if ( compare( node, key ) ) 218 { 219 if ( node != first ) 220 FTC_MruNode_Up( &list->nodes, node ); 221 222 return node; 223 } 224 225 node = node->next; 226 227 } while ( node != first); 228 } 229 230 return NULL; 231 } 232 #endif 233 234 FT_LOCAL_DEF( FT_Error ) 235 FTC_MruList_New( FTC_MruList list, 236 FT_Pointer key, 237 FTC_MruNode *anode ) 238 { 239 FT_Error error; 240 FTC_MruNode node = NULL; 241 FTC_MruNode prev = NULL; 242 FT_Memory memory = list->memory; 243 244 245 /* zero new node in case of node_init failure */ 246 if ( FT_ALLOC( node, list->clazz.node_size ) ) 247 goto Exit; 248 249 error = list->clazz.node_init( node, key, list->data ); 250 if ( error ) 251 { 252 prev = node; 253 node = NULL; 254 255 goto Clean; 256 } 257 else if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes ) 258 prev = list->nodes->prev; 259 260 FTC_MruNode_Prepend( &list->nodes, node ); 261 list->num_nodes++; 262 263 if ( !prev ) 264 goto Exit; 265 266 FTC_MruNode_Remove( &list->nodes, prev ); 267 list->num_nodes--; 268 269 Clean: 270 if ( list->clazz.node_done ) 271 list->clazz.node_done( prev, list->data ); 272 273 FT_FREE( prev ); 274 275 Exit: 276 *anode = node; 277 return error; 278 } 279 280 281 #ifndef FTC_INLINE 282 FT_LOCAL_DEF( FT_Error ) 283 FTC_MruList_Lookup( FTC_MruList list, 284 FT_Pointer key, 285 FTC_MruNode *anode ) 286 { 287 FTC_MruNode node; 288 289 290 node = FTC_MruList_Find( list, key ); 291 if ( !node ) 292 return FTC_MruList_New( list, key, anode ); 293 294 *anode = node; 295 return 0; 296 } 297 #endif /* FTC_INLINE */ 298 299 FT_LOCAL_DEF( void ) 300 FTC_MruList_Remove( FTC_MruList list, 301 FTC_MruNode node ) 302 { 303 FT_Memory memory = list->memory; 304 305 306 FTC_MruNode_Remove( &list->nodes, node ); 307 list->num_nodes--; 308 309 if ( list->clazz.node_done ) 310 list->clazz.node_done( node, list->data ); 311 312 FT_FREE( node ); 313 } 314 315 316 FT_LOCAL_DEF( void ) 317 FTC_MruList_RemoveSelection( FTC_MruList list, 318 FTC_MruNode_CompareFunc selection, 319 FT_Pointer key ) 320 { 321 FTC_MruNode first = list->nodes; 322 FTC_MruNode prev, node; 323 324 325 if ( !first || !selection ) 326 return; 327 328 prev = first->prev; 329 do 330 { 331 node = prev; 332 prev = node->prev; 333 334 if ( selection( node, key ) ) 335 FTC_MruList_Remove( list, node ); 336 337 } while ( node != first ); 338 } 339 340 341 /* END */