1 /**************************************************************************** 2 * 3 * ftcmru.h 4 * 5 * Simple MRU list-cache (specification). 6 * 7 * Copyright (C) 2000-2020 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 /************************************************************************** 20 * 21 * An MRU is a list that cannot hold more than a certain number of 22 * elements (`max_elements'). All elements in the list are sorted in 23 * least-recently-used order, i.e., the `oldest' element is at the tail 24 * of the list. 25 * 26 * When doing a lookup (either through `Lookup()' or `Lookup_Node()'), 27 * the list is searched for an element with the corresponding key. If 28 * it is found, the element is moved to the head of the list and is 29 * returned. 30 * 31 * If no corresponding element is found, the lookup routine will try to 32 * obtain a new element with the relevant key. If the list is already 33 * full, the oldest element from the list is discarded and replaced by a 34 * new one; a new element is added to the list otherwise. 35 * 36 * Note that it is possible to pre-allocate the element list nodes. 37 * This is handy if `max_elements' is sufficiently small, as it saves 38 * allocations/releases during the lookup process. 39 * 40 */ 41 42 43 #ifndef FTCMRU_H_ 44 #define FTCMRU_H_ 45 46 47 #include <freetype/freetype.h> 48 #include <freetype/internal/compiler-macros.h> 49 50 #ifdef FREETYPE_H 51 #error "freetype.h of FreeType 1 has been loaded!" 52 #error "Please fix the directory search order for header files" 53 #error "so that freetype.h of FreeType 2 is found first." 54 #endif 55 56 #define xxFT_DEBUG_ERROR 57 #define FTC_INLINE 58 59 FT_BEGIN_HEADER 60 61 typedef struct FTC_MruNodeRec_* FTC_MruNode; 62 63 typedef struct FTC_MruNodeRec_ 64 { 65 FTC_MruNode next; 66 FTC_MruNode prev; 67 68 } FTC_MruNodeRec; 69 70 71 FT_LOCAL( void ) 72 FTC_MruNode_Prepend( FTC_MruNode *plist, 73 FTC_MruNode node ); 74 75 FT_LOCAL( void ) 76 FTC_MruNode_Up( FTC_MruNode *plist, 77 FTC_MruNode node ); 78 79 FT_LOCAL( void ) 80 FTC_MruNode_Remove( FTC_MruNode *plist, 81 FTC_MruNode node ); 82 83 84 typedef struct FTC_MruListRec_* FTC_MruList; 85 86 typedef struct FTC_MruListClassRec_ const * FTC_MruListClass; 87 88 89 typedef FT_Bool 90 (*FTC_MruNode_CompareFunc)( FTC_MruNode node, 91 FT_Pointer key ); 92 93 typedef FT_Error 94 (*FTC_MruNode_InitFunc)( FTC_MruNode node, 95 FT_Pointer key, 96 FT_Pointer data ); 97 98 typedef FT_Error 99 (*FTC_MruNode_ResetFunc)( FTC_MruNode node, 100 FT_Pointer key, 101 FT_Pointer data ); 102 103 typedef void 104 (*FTC_MruNode_DoneFunc)( FTC_MruNode node, 105 FT_Pointer data ); 106 107 108 typedef struct FTC_MruListClassRec_ 109 { 110 FT_Offset node_size; 111 112 FTC_MruNode_CompareFunc node_compare; 113 FTC_MruNode_InitFunc node_init; 114 FTC_MruNode_ResetFunc node_reset; 115 FTC_MruNode_DoneFunc node_done; 116 117 } FTC_MruListClassRec; 118 119 120 typedef struct FTC_MruListRec_ 121 { 122 FT_UInt num_nodes; 123 FT_UInt max_nodes; 124 FTC_MruNode nodes; 125 FT_Pointer data; 126 FTC_MruListClassRec clazz; 127 FT_Memory memory; 128 129 } FTC_MruListRec; 130 131 132 FT_LOCAL( void ) 133 FTC_MruList_Init( FTC_MruList list, 134 FTC_MruListClass clazz, 135 FT_UInt max_nodes, 136 FT_Pointer data, 137 FT_Memory memory ); 138 139 FT_LOCAL( void ) 140 FTC_MruList_Reset( FTC_MruList list ); 141 142 143 FT_LOCAL( void ) 144 FTC_MruList_Done( FTC_MruList list ); 145 146 147 FT_LOCAL( FT_Error ) 148 FTC_MruList_New( FTC_MruList list, 149 FT_Pointer key, 150 FTC_MruNode *anode ); 151 152 FT_LOCAL( void ) 153 FTC_MruList_Remove( FTC_MruList list, 154 FTC_MruNode node ); 155 156 FT_LOCAL( void ) 157 FTC_MruList_RemoveSelection( FTC_MruList list, 158 FTC_MruNode_CompareFunc selection, 159 FT_Pointer key ); 160 161 162 #ifdef FTC_INLINE 163 164 #define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error ) \ 165 FT_BEGIN_STMNT \ 166 FTC_MruNode* _pfirst = &(list)->nodes; \ 167 FTC_MruNode_CompareFunc _compare = (FTC_MruNode_CompareFunc)(compare); \ 168 FTC_MruNode _first, _node; \ 169 \ 170 \ 171 error = FT_Err_Ok; \ 172 _first = *(_pfirst); \ 173 _node = NULL; \ 174 \ 175 if ( _first ) \ 176 { \ 177 _node = _first; \ 178 do \ 179 { \ 180 if ( _compare( _node, (key) ) ) \ 181 { \ 182 if ( _node != _first ) \ 183 FTC_MruNode_Up( _pfirst, _node ); \ 184 \ 185 node = _node; \ 186 goto MruOk_; \ 187 } \ 188 _node = _node->next; \ 189 \ 190 } while ( _node != _first); \ 191 } \ 192 \ 193 error = FTC_MruList_New( (list), (key), (FTC_MruNode*)(void*)&(node) ); \ 194 MruOk_: \ 195 ; \ 196 FT_END_STMNT 197 198 #define FTC_MRULIST_LOOKUP( list, key, node, error ) \ 199 FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error ) 200 201 #else /* !FTC_INLINE */ 202 203 FT_LOCAL( FTC_MruNode ) 204 FTC_MruList_Find( FTC_MruList list, 205 FT_Pointer key ); 206 207 FT_LOCAL( FT_Error ) 208 FTC_MruList_Lookup( FTC_MruList list, 209 FT_Pointer key, 210 FTC_MruNode *pnode ); 211 212 #define FTC_MRULIST_LOOKUP( list, key, node, error ) \ 213 error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) ) 214 215 #endif /* !FTC_INLINE */ 216 217 218 #define FTC_MRULIST_LOOP( list, node ) \ 219 FT_BEGIN_STMNT \ 220 FTC_MruNode _first = (list)->nodes; \ 221 \ 222 \ 223 if ( _first ) \ 224 { \ 225 FTC_MruNode _node = _first; \ 226 \ 227 \ 228 do \ 229 { \ 230 *(FTC_MruNode*)&(node) = _node; 231 232 233 #define FTC_MRULIST_LOOP_END() \ 234 _node = _node->next; \ 235 \ 236 } while ( _node != _first ); \ 237 } \ 238 FT_END_STMNT 239 240 /* */ 241 242 FT_END_HEADER 243 244 245 #endif /* FTCMRU_H_ */ 246 247 248 /* END */ 249