1 /* list.c -- doubly linked list routines for vlock,
2 * the VT locking program for linux
4 * This program is copyright (C) 2007 Frank Benkstein, and is free
5 * software which is freely distributable under the terms of the
6 * GNU General Public License version 2, included as the file COPYING in this
7 * distribution. It is NOT public domain software, and any
8 * redistribution not permitted by the GNU General Public License is
9 * expressly forbidden without prior written permission from
14 /* Inspired by the doubly linked list code from glib:
16 * GLIB - Library of useful routines for C programming
17 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
19 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GLib Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GLib at ftp://ftp.gtk.org/pub/gtk/.
32 struct list
*list_new(void)
34 struct list
*l
= ensure_malloc(sizeof *l
);
40 void list_free(struct list
*l
, list_free_item_function free_item
)
42 list_for_each(l
, item
) {
43 if (free_item
!= NULL
&& item
->previous
!= NULL
)
44 free_item(item
->previous
->data
);
49 if (free_item
!= NULL
&& l
->last
!= NULL
)
56 void list_append(struct list
*l
, void *data
)
58 struct list_item
*item
= ensure_malloc(sizeof *item
);
61 item
->previous
= l
->last
;
73 size_t list_length(struct list
*l
)
77 list_for_each(l
, item
)
83 struct list_item
*list_delete_item(struct list
*l
, struct list_item
*item
)
85 struct list_item
*next
= item
->next
;
87 if (item
->previous
!= NULL
)
88 item
->previous
->next
= item
->next
;
90 if (item
->next
!= NULL
)
91 item
->next
->previous
= item
->previous
;
94 l
->first
= item
->next
;
97 l
->last
= item
->previous
;
105 /* Like list_append() but returns the item that was added instead of the start
107 static struct List
*__list_append(struct List
*list
, void *data
)
109 struct List
*new_item
= malloc(sizeof (struct List
));
110 struct List
*last
= list_last(list
);
112 if (new_item
== NULL
) {
113 fprintf(stderr
, "%s:%d failed to allocate new list item\n", __FILE__
,
118 new_item
->data
= data
;
119 new_item
->next
= NULL
;
120 new_item
->previous
= last
;
123 last
->next
= new_item
;
128 struct List
*list_append(struct List
*list
, void *data
)
130 struct List
*new_item
= __list_append(list
, data
);
138 struct List
*list_copy(struct List
*list
)
140 struct List
*new_list
= NULL
;
141 struct List
*last
= NULL
;
142 struct List
*item
= list_first(list
);
144 /* Make a copy of the first item. It is now also the last item of the new
147 last
= new_list
= list_append(new_list
, item
->data
);
149 /* Append all further items to the first. */
150 for (item
= list_next(item
); item
!= NULL
; item
= list_next(item
))
151 last
= __list_append(last
, item
->data
);
153 return list_first(new_list
);
156 struct List
*list_first(struct List
*list
)
159 while (list
->previous
!= NULL
)
160 list
= list
->previous
;
166 struct List
*list_last(struct List
*list
)
169 while (list
->next
!= NULL
)
176 struct List
*list_next(struct List
*list
)
184 struct List
*list_previous(struct List
*list
)
189 return list
->previous
;
192 struct List
*list_find(struct List
*list
, void *data
)
194 list_for_each(list
, item
) {
195 if (item
->data
== data
)
202 struct List
*list_delete_link(struct List
*list
, struct List
*item
)
205 if (item
->previous
!= NULL
)
206 item
->previous
->next
= item
->next
;
207 if (item
->next
!= NULL
)
208 item
->next
->previous
= item
->previous
;
210 if (item
->next
!= NULL
)
212 else if (item
->previous
!= NULL
)
213 list
= item
->previous
;
224 struct List
*list_remove(struct List
*list
, void *data
)
226 struct List
*item
= list_find(list
, data
);
227 return list_delete_link(list
, item
);
230 void list_free(struct List
*list
)
233 list
= list_delete_link(list
, list_first(list
));