src/list.c: actually put item at the end of the list in list_append
[vlock.git] / src / list.c
blobacf2f0e9530fc70c77a94e065c4a7163c09e27c6
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
10 * the author.
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/.
25 #include <stdlib.h>
26 #include <stdio.h>
28 #include "util.h"
30 #include "list.h"
32 struct list *list_new(void)
34 struct list *l = ensure_malloc(sizeof *l);
35 l->first = NULL;
36 l->last = NULL;
37 return 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);
46 free(item->previous);
49 if (free_item != NULL && l->last != NULL)
50 free(l->last);
52 free(l->last);
53 free(l);
56 void list_append(struct list *l, void *data)
58 struct list_item *item = ensure_malloc(sizeof *item);
60 item->data = data;
61 item->previous = l->last;
62 item->next = NULL;
64 if (l->last != NULL)
65 l->last->next = item;
67 l->last = item;
69 if (l->first == NULL)
70 l->first = item;
73 size_t list_length(struct list *l)
75 size_t length = 0;
77 list_for_each(l, item)
78 length++;
80 return length;
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;
93 if (l->first == item)
94 l->first = item->next;
96 if (l->last == item)
97 l->last = item->previous;
99 free(item);
101 return next;
104 #if 0
105 /* Like list_append() but returns the item that was added instead of the start
106 * of the list. */
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__,
114 __LINE__);
115 abort();
118 new_item->data = data;
119 new_item->next = NULL;
120 new_item->previous = last;
122 if (last != NULL)
123 last->next = new_item;
125 return new_item;
128 struct List *list_append(struct List *list, void *data)
130 struct List *new_item = __list_append(list, data);
132 if (list != NULL)
133 return list;
134 else
135 return new_item;
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
145 * list. */
146 if (item != NULL)
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)
158 if (list != NULL) {
159 while (list->previous != NULL)
160 list = list->previous;
163 return list;
166 struct List *list_last(struct List *list)
168 if (list != NULL) {
169 while (list->next != NULL)
170 list = list->next;
173 return list;
176 struct List *list_next(struct List *list)
178 if (list == NULL)
179 return NULL;
180 else
181 return list->next;
184 struct List *list_previous(struct List *list)
186 if (list == NULL)
187 return NULL;
188 else
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)
196 return item;
199 return NULL;
202 struct List *list_delete_link(struct List *list, struct List *item)
204 if (item != NULL) {
205 if (item->previous != NULL)
206 item->previous->next = item->next;
207 if (item->next != NULL)
208 item->next->previous = item->previous;
209 if (item == list) {
210 if (item->next != NULL)
211 list = item->next;
212 else if (item->previous != NULL)
213 list = item->previous;
214 else
215 list = NULL;
218 free(item);
221 return list;
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)
232 while (list != NULL)
233 list = list_delete_link(list, list_first(list));
235 #endif