blob: bde617fd7ef1df8b068db668132edf93a5509922 [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/***************************************************************************/
2/* */
3/* ftlist.c */
4/* */
5/* Generic list support for FreeType (body). */
6/* */
Werner Lemberg7880dd62000-01-10 17:19:45 +00007/* Copyright 1996-2000 by */
David Turnerd2b1f351999-12-16 23:11:37 +00008/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
Werner Lemberg4e6dd852000-06-05 05:26:15 +000010/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
David Turnerd2b1f351999-12-16 23:11:37 +000012/* 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
David Turnerd2b1f351999-12-16 23:11:37 +000018 /*************************************************************************/
19 /* */
20 /* This file implements functions relative to list processing. Its */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +000021 /* data structures are defined in `freetype/internal/ftlist.h'. */
David Turnerd2b1f351999-12-16 23:11:37 +000022 /* */
23 /*************************************************************************/
24
25
David Turnerefce08d2000-05-11 18:23:52 +000026#include <freetype/internal/ftlist.h>
27#include <freetype/internal/ftdebug.h>
28#include <freetype/internal/ftobjs.h>
David Turnerd2b1f351999-12-16 23:11:37 +000029
30
31 /*************************************************************************/
32 /* */
Werner Lembergeb81e372000-06-03 06:03:11 +000033 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
35 /* messages during execution. */
36 /* */
37#undef FT_COMPONENT
38#define FT_COMPONENT trace_list
39
40
41 /*************************************************************************/
42 /* */
David Turnerd2b1f351999-12-16 23:11:37 +000043 /* <Function> */
44 /* FT_List_Find */
45 /* */
46 /* <Description> */
47 /* Finds the list node for a given listed object. */
48 /* */
49 /* <Input> */
50 /* list :: A pointer to the parent list. */
51 /* data :: The address of the listed object. */
52 /* */
53 /* <Return> */
54 /* List node. NULL if it wasn't found. */
55 /* */
David Turner76a5f622000-11-04 01:55:49 +000056 FT_BASE_DEF( FT_ListNode ) FT_List_Find( FT_List list,
57 void* data )
David Turnerd2b1f351999-12-16 23:11:37 +000058 {
59 FT_ListNode cur;
60
61
62 cur = list->head;
63 while ( cur )
64 {
Werner Lemberg7880dd62000-01-10 17:19:45 +000065 if ( cur->data == data )
David Turnerd2b1f351999-12-16 23:11:37 +000066 return cur;
67
68 cur = cur->next;
69 }
70
71 return (FT_ListNode)0;
72 }
73
74
75 /*************************************************************************/
76 /* */
77 /* <Function> */
78 /* FT_List_Add */
79 /* */
80 /* <Description> */
Werner Lemberg7880dd62000-01-10 17:19:45 +000081 /* Appends an element to the end of a list. */
David Turnerd2b1f351999-12-16 23:11:37 +000082 /* */
83 /* <InOut> */
84 /* list :: A pointer to the parent list. */
85 /* node :: The node to append. */
86 /* */
David Turner76a5f622000-11-04 01:55:49 +000087 FT_BASE_DEF( void ) FT_List_Add( FT_List list,
88 FT_ListNode node )
David Turnerd2b1f351999-12-16 23:11:37 +000089 {
90 FT_ListNode before = list->tail;
91
92
93 node->next = 0;
94 node->prev = before;
95
96 if ( before )
97 before->next = node;
98 else
99 list->head = node;
100
101 list->tail = node;
102 }
103
104
105 /*************************************************************************/
106 /* */
107 /* <Function> */
108 /* FT_List_Insert */
109 /* */
110 /* <Description> */
111 /* Inserts an element at the head of a list. */
112 /* */
113 /* <InOut> */
114 /* list :: A pointer to parent list. */
115 /* node :: The node to insert. */
116 /* */
David Turner76a5f622000-11-04 01:55:49 +0000117 FT_BASE_DEF( void ) FT_List_Insert( FT_List list,
118 FT_ListNode node )
David Turnerd2b1f351999-12-16 23:11:37 +0000119 {
120 FT_ListNode after = list->head;
121
122
123 node->next = after;
124 node->prev = 0;
125
126 if ( !after )
127 list->tail = node;
128 else
129 after->prev = node;
130
131 list->head = node;
132 }
133
134
135 /*************************************************************************/
136 /* */
137 /* <Function> */
138 /* FT_List_Remove */
139 /* */
140 /* <Description> */
141 /* Removes a node from a list. This function doesn't check whether */
142 /* the node is in the list! */
143 /* */
144 /* <Input> */
145 /* node :: The node to remove. */
146 /* */
147 /* <InOut> */
148 /* list :: A pointer to the parent list. */
149 /* */
David Turner76a5f622000-11-04 01:55:49 +0000150 FT_BASE_DEF( void ) FT_List_Remove( FT_List list,
151 FT_ListNode node )
David Turnerd2b1f351999-12-16 23:11:37 +0000152 {
153 FT_ListNode before, after;
154
155
156 before = node->prev;
157 after = node->next;
158
159 if ( before )
160 before->next = after;
161 else
162 list->head = after;
163
164 if ( after )
165 after->prev = before;
166 else
167 list->tail = before;
168 }
169
170
171 /*************************************************************************/
172 /* */
173 /* <Function> */
174 /* FT_List_Up */
175 /* */
176 /* <Description> */
177 /* Moves a node to the head/top of a list. Used to maintain LRU */
178 /* lists. */
179 /* */
180 /* <InOut> */
181 /* list :: A pointer to the parent list. */
182 /* node :: The node to move. */
183 /* */
David Turner76a5f622000-11-04 01:55:49 +0000184 FT_BASE_DEF( void ) FT_List_Up( FT_List list,
185 FT_ListNode node )
David Turnerd2b1f351999-12-16 23:11:37 +0000186 {
187 FT_ListNode before, after;
188
189
190 before = node->prev;
191 after = node->next;
192
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000193 /* check whether we are already on top of the list */
David Turnerd2b1f351999-12-16 23:11:37 +0000194 if ( !before )
195 return;
196
197 before->next = after;
198
199 if ( after )
200 after->prev = before;
201 else
202 list->tail = before;
203
204 node->prev = 0;
205 node->next = list->head;
206 list->head->prev = node;
207 list->head = node;
208 }
209
210
211 /*************************************************************************/
212 /* */
213 /* <Function> */
214 /* FT_List_Iterate */
215 /* */
216 /* <Description> */
217 /* Parses a list and calls a given iterator function on each element. */
218 /* Note that parsing is stopped as soon as one of the iterator calls */
219 /* returns a non-zero value. */
220 /* */
221 /* <Input> */
222 /* list :: A handle to the list. */
223 /* iterator :: An interator function, called on each node of the */
224 /* list. */
225 /* user :: A user-supplied field which is passed as the second */
226 /* argument to the iterator. */
227 /* */
228 /* <Return> */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000229 /* The result (a FreeType error code) of the last iterator call. */
David Turnerd2b1f351999-12-16 23:11:37 +0000230 /* */
David Turner76a5f622000-11-04 01:55:49 +0000231 FT_BASE_DEF( FT_Error ) FT_List_Iterate( FT_List list,
232 FT_List_Iterator iterator,
233 void* user )
David Turnerd2b1f351999-12-16 23:11:37 +0000234 {
235 FT_ListNode cur = list->head;
236 FT_Error error = FT_Err_Ok;
237
238
239 while ( cur )
240 {
241 FT_ListNode next = cur->next;
242
243
244 error = iterator( cur, user );
245 if ( error )
246 break;
247
248 cur = next;
249 }
250
251 return error;
252 }
253
254
255 /*************************************************************************/
256 /* */
257 /* <Function> */
258 /* FT_List_Finalize */
259 /* */
260 /* <Description> */
261 /* Destroys all elements in the list as well as the list itself. */
262 /* */
263 /* <Input> */
264 /* list :: A handle to the list. */
265 /* */
266 /* destroy :: A list destructor that will be applied to each element */
267 /* of the list. */
268 /* */
Werner Lemberga3b6c6c2000-05-31 06:55:12 +0000269 /* memory :: The current memory object which handles deallocation. */
David Turnerd2b1f351999-12-16 23:11:37 +0000270 /* */
271 /* user :: A user-supplied field which is passed as the last */
272 /* argument to the destructor. */
273 /* */
David Turner76a5f622000-11-04 01:55:49 +0000274 FT_BASE_DEF( void ) FT_List_Finalize( FT_List list,
275 FT_List_Destructor destroy,
276 FT_Memory memory,
277 void* user )
David Turnerd2b1f351999-12-16 23:11:37 +0000278 {
279 FT_ListNode cur;
280
281
282 cur = list->head;
283 while ( cur )
284 {
285 FT_ListNode next = cur->next;
286 void* data = cur->data;
287
288
289 if ( destroy )
290 destroy( memory, data, user );
291
292 FREE( cur );
293 cur = next;
294 }
295
296 list->head = 0;
297 list->tail = 0;
298 }
299
300
301/* END */