2 * Copyright (c) 2011 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @file Doubly linked list.
31 * Circular, with a head. Nodes structures are allocated separately from data.
32 * Data is stored as 'void *'. We implement several sanity checks to prevent
33 * common usage errors.
43 static list_node_t
*list_node_new(void *data
);
44 static void list_node_delete(list_node_t
*node
);
45 static void list_node_insert_between(list_node_t
*n
, list_node_t
*a
, list_node_t
*b
);
46 static void list_node_unlink(list_node_t
*n
);
47 static bool_t
list_node_present(list_t
*list
, list_node_t
*node
);
51 * @param list List to initialize.
53 void list_init(list_t
*list
)
55 list
->head
.prev
= &list
->head
;
56 list
->head
.next
= &list
->head
;
59 /** Deinitialize list.
61 * @param list List to deinitialize.
63 void list_fini(list_t
*list
)
65 assert(list_is_empty(list
));
67 list
->head
.prev
= NULL
;
68 list
->head
.next
= NULL
;
71 /** Append data to list.
73 * Create a new list node and append it at the end of the list.
75 * @param list Linked list.
76 * @param data Data for the new node.
78 void list_append(list_t
*list
, void *data
)
82 node
= list_node_new(data
);
83 list_node_insert_between(node
, list
->head
.prev
, &list
->head
);
86 /** Prepend data to list.
88 * Create a new list node and prepend it at the beginning of the list.
90 * @param list Linked list.
91 * @param data Data for the new node.
93 void list_prepend(list_t
*list
, void *data
)
97 node
= list_node_new(data
);
98 list_node_insert_between(node
, list
->head
.prev
, &list
->head
);
101 /** Remove data from list.
103 * Removes the given node from a list and destroys it. Any data the node might
104 * have is ignored. If asserts are on, we check wheter node is really present
105 * in the list the caller is requesting us to remove it from.
107 * @param list Linked list.
108 * @param node List node to remove.
110 void list_remove(list_t
*list
, list_node_t
*node
)
112 /* Check whether node is in the list as claimed. */
113 assert(list_node_present(list
, node
));
114 list_node_unlink(node
);
116 list_node_delete(node
);
119 /** Return first list node or NULL if list is empty.
121 * @param list Linked list.
122 * @return First node of the list or @c NULL if the list is empty.
124 list_node_t
*list_first(list_t
*list
)
128 assert(list
!= NULL
);
129 node
= list
->head
.next
;
131 return (node
!= &list
->head
) ? node
: NULL
;
134 /** Return last list node or NULL if list is empty.
136 * @param list Linked list.
137 * @return Last node of the list or @c NULL if the list is empty.
139 list_node_t
*list_last(list_t
*list
)
143 assert(list
!= NULL
);
144 node
= list
->head
.prev
;
146 return (node
!= &list
->head
) ? node
: NULL
;
149 /** Return next list node or NULL if this was the last one.
151 * @param list Linked list.
152 * @param node Node whose successor we are interested in.
153 * @return Following list node or @c NULL if @a node is last.
155 list_node_t
*list_next(list_t
*list
, list_node_t
*node
)
158 assert(list
!= NULL
);
159 assert(node
!= NULL
);
161 return (node
->next
!= &list
->head
) ? node
->next
: NULL
;
164 /** Return previous list node or NULL if this was the last one.
166 * @param list Linked list.
167 * @param node Node whose predecessor we are interested in.
168 * @return Preceding list node or @c NULL if @a node is last.
170 list_node_t
*list_prev(list_t
*list
, list_node_t
*node
)
173 assert(list
!= NULL
);
174 assert(node
!= NULL
);
176 return (node
->prev
!= &list
->head
) ? node
->prev
: NULL
;
179 /** Return b_true if list is empty.
181 * @param list Linked list.
182 * @return @c b_true if list is empty, @c b_false otherwise.
184 bool_t
list_is_empty(list_t
*list
)
186 return (list_first(list
) == NULL
);
189 /** Change node data.
191 * Change the data associated with a node.
193 * @param node List node.
194 * @param data New data for node.
196 void list_node_setdata(list_node_t
*node
, void *data
)
203 * @param data Initial data for node.
204 * @return New list node.
206 static list_node_t
*list_node_new(void *data
)
210 node
= malloc(sizeof(list_node_t
));
212 printf("Memory allocation failed.\n");
225 * @param node List node. Must not take part in any list.
227 static void list_node_delete(list_node_t
*node
)
229 assert(node
->prev
== NULL
);
230 assert(node
->next
== NULL
);
231 assert(node
->data
== NULL
);
235 /** Insert node between two other nodes.
237 * Inserts @a n between neighboring nodes @a a and @a b.
239 * @param n Node to insert.
240 * @param a Node to precede @a n.
241 * @param b Node to follow @a n.
243 static void list_node_insert_between(list_node_t
*n
, list_node_t
*a
,
246 assert(n
->prev
== NULL
);
247 assert(n
->next
== NULL
);
251 assert(a
->next
== b
);
252 assert(b
->prev
== a
);
259 * Unlink node from the list it is currently in.
261 * @param n Node to unlink from its current list.
263 static void list_node_unlink(list_node_t
*n
)
266 assert(n
->prev
!= NULL
);
267 assert(n
->next
!= NULL
);
272 assert(a
->next
== n
);
273 assert(b
->prev
== n
);
282 /** Check whether @a node is in list @a list.
284 * @param list Linked list.
286 * @return @c b_true if @a node is part of @a list, @c b_false otherwise.
288 static bool_t
list_node_present(list_t
*list
, list_node_t
*node
)
293 while (m
!= &list
->head
) {