1/****************************************************************************
2 *
3 * ftcmru.h
4 *
5 * Simple MRU list-cache (specification).
6 *
7 * Copyright (C) 2000-2023 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
59FT_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
242FT_END_HEADER
243
244
245#endif /* FTCMRU_H_ */
246
247
248/* END */
249