Proper x86_64 mnemonics
[cacao.git] / src / toolbox / list.c
1 /* src/toolbox/list.c - double linked list
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30 #include <stdlib.h>
31
32 #include "mm/memory.h"
33
34 #include "threads/lock-common.h"
35
36 #include "toolbox/list.h"
37
38
39 /* list_create *****************************************************************
40
41    Allocates a new list and initializes the lock object.
42
43 *******************************************************************************/
44
45 list_t *list_create(int nodeoffset)
46 {
47         list_t *l;
48
49         l = NEW(list_t);
50
51         LOCK_INIT_OBJECT_LOCK(l);
52
53         l->first      = NULL;
54         l->last       = NULL;
55         l->nodeoffset = nodeoffset;
56         l->size       = 0;
57
58         return l;
59 }
60
61
62 /* list_free *******************************************************************
63
64    Free a list.
65
66 *******************************************************************************/
67
68 void list_free(list_t *l)
69 {
70         assert(l != NULL);
71
72         FREE(l, list_t);
73 }
74
75
76 /* list_create_dump ************************************************************
77
78    Allocates a new list on the dump memory.
79
80    ATTENTION: This list does NOT initialize the locking object!!!
81
82 *******************************************************************************/
83
84 list_t *list_create_dump(int nodeoffset)
85 {
86         list_t *l;
87
88         l = DNEW(list_t);
89
90         l->first      = NULL;
91         l->last       = NULL;
92         l->nodeoffset = nodeoffset;
93         l->size       = 0;
94
95         return l;
96 }
97
98
99 /* list_lock *******************************************************************
100
101    Locks the list.
102
103 *******************************************************************************/
104
105 void list_lock(list_t *l)
106 {
107         LOCK_MONITOR_ENTER(l);
108 }
109
110
111 /* list_unlock *****************************************************************
112
113    Unlocks the list.
114
115 *******************************************************************************/
116
117 void list_unlock(list_t *l)
118 {
119         LOCK_MONITOR_EXIT(l);
120 }
121
122
123 /* list_add_first **************************************************************
124
125    Adds the element as first element.
126
127 *******************************************************************************/
128
129 void list_add_first(list_t *l, void *element)
130 {
131         listnode_t *ln;
132
133         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
134
135         if (l->first) {
136                 ln->prev       = NULL;
137                 ln->next       = l->first;
138                 l->first->prev = ln;
139                 l->first       = ln;
140         }
141         else {
142                 ln->prev = NULL;
143                 ln->next = NULL;
144                 l->last  = ln;
145                 l->first = ln;
146         }
147
148         /* Increase number of elements. */
149
150         l->size++;
151 }
152
153
154 /* list_add_last ***************************************************************
155
156    Adds the element as last element.
157
158 *******************************************************************************/
159
160 void list_add_last(list_t *l, void *element)
161 {
162         listnode_t *ln;
163
164         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
165
166         if (l->last) {
167                 ln->prev      = l->last;
168                 ln->next      = NULL;
169                 l->last->next = ln;
170                 l->last       = ln;
171         }
172         else {
173                 ln->prev = NULL;
174                 ln->next = NULL;
175                 l->last  = ln;
176                 l->first = ln;
177         }
178
179         /* Increase number of elements. */
180
181         l->size++;
182 }
183
184
185 /* list_add_before *************************************************************
186
187    Adds the element newelement to the list l before element.
188
189    [ A ] <-> [ newn ] <-> [ n ] <-> [ B ]
190
191 *******************************************************************************/
192
193 void list_add_before(list_t *l, void *element, void *newelement)
194 {
195         listnode_t *ln;
196         listnode_t *newln;
197
198         ln    = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
199         newln = (listnode_t *) (((uint8_t *) newelement) + l->nodeoffset);
200
201         /* Set the new links. */
202
203         newln->prev = ln->prev;
204         newln->next = ln;
205
206         if (newln->prev)
207                 newln->prev->next = newln;
208
209         ln->prev = newln;
210
211         /* set list's first and last if necessary */
212
213         if (l->first == ln)
214                 l->first = newln;
215
216         if (l->last == ln)
217                 l->last = newln;
218
219         /* Increase number of elements. */
220
221         l->size++;
222 }
223
224
225 /* list_remove ***************************************************************
226
227    Removes the element.
228
229 *******************************************************************************/
230
231 void list_remove(list_t *l, void *element)
232 {
233         listnode_t *ln;
234
235         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
236         
237         if (ln->next)
238                 ln->next->prev = ln->prev;
239         else
240                 l->last = ln->prev;
241
242         if (ln->prev)
243                 ln->prev->next = ln->next;
244         else
245                 l->first = ln->next;
246
247         ln->next = NULL;
248         ln->prev = NULL;
249
250         /* Decrease number of elements. */
251
252         l->size--;
253 }
254
255  
256 /* list_first ******************************************************************
257
258    Returns the first element of the list.
259
260 *******************************************************************************/
261
262 void *list_first(list_t *l)
263 {
264         void *el;
265
266         if (l->first == NULL)
267                 el = NULL;
268         else
269                 el = ((uint8_t *) l->first) - l->nodeoffset;
270
271         return el;
272 }
273
274
275 /* list_last *******************************************************************
276
277    Returns the last element of the list.
278
279 *******************************************************************************/
280
281 void *list_last(list_t *l)
282 {
283         void *el;
284
285         if (l->last == NULL)
286                 el = NULL;
287         else
288                 el = ((uint8_t *) l->last) - l->nodeoffset;
289
290         return el;
291 }
292
293
294 /* list_next *******************************************************************
295
296    Returns the next element of element from the list.
297
298 *******************************************************************************/
299
300 void *list_next(list_t *l, void *element)
301 {
302         listnode_t *ln;
303         void       *el;
304
305         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
306
307         if (ln->next == NULL)
308                 el = NULL;
309         else
310                 el = ((uint8_t *) ln->next) - l->nodeoffset;
311
312         return el;
313 }
314
315         
316 /* list_prev *******************************************************************
317
318    Returns the previous element of element from the list.
319
320 *******************************************************************************/
321
322 void *list_prev(list_t *l, void *element)
323 {
324         listnode_t *ln;
325         void       *el;
326
327         ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
328
329         if (ln->prev == NULL)
330                 el = NULL;
331         else
332                 el = ((uint8_t *) ln->prev) - l->nodeoffset;
333
334         return el;
335 }
336
337
338 /*
339  * These are local overrides for various environment variables in Emacs.
340  * Please do not remove this and leave it at the end of the file, where
341  * Emacs will automagically detect them.
342  * ---------------------------------------------------------------------
343  * Local variables:
344  * mode: c
345  * indent-tabs-mode: t
346  * c-basic-offset: 4
347  * tab-width: 4
348  * End:
349  */