source: mainline/uspace/app/sbi/src/list.c@ 38aaacc2

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 38aaacc2 was 1ebc1a62, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Update SBI to rev. 157.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/** @file Doubly linked list.
30 *
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.
34 */
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <assert.h>
39#include "mytypes.h"
40
41#include "list.h"
42
43static list_node_t *list_node_new(void *data);
44static void list_node_delete(list_node_t *node);
45static void list_node_insert_between(list_node_t *n, list_node_t *a, list_node_t *b);
46static void list_node_unlink(list_node_t *n);
47static bool_t list_node_present(list_t *list, list_node_t *node);
48
49/** Initialize list.
50 *
51 * @param list List to initialize.
52 */
53void list_init(list_t *list)
54{
55 list->head.prev = &list->head;
56 list->head.next = &list->head;
57}
58
59/** Append data to list.
60 *
61 * Create a new list node and append it at the end of the list.
62 *
63 * @param list Linked list.
64 * @param data Data for the new node.
65 */
66void list_append(list_t *list, void *data)
67{
68 list_node_t *node;
69
70 node = list_node_new(data);
71 list_node_insert_between(node, list->head.prev, &list->head);
72}
73
74/** Prepend data to list.
75 *
76 * Create a new list node and prepend it at the beginning of the list.
77 *
78 * @param list Linked list.
79 * @param data Data for the new node.
80 */
81void list_prepend(list_t *list, void *data)
82{
83 list_node_t *node;
84
85 node = list_node_new(data);
86 list_node_insert_between(node, list->head.prev, &list->head);
87}
88
89/** Remove data from list.
90 *
91 * Removes the given node from a list and destroys it. Any data the node might
92 * have is ignored. If asserts are on, we check wheter node is really present
93 * in the list the caller is requesting us to remove it from.
94 *
95 * @param list Linked list.
96 * @param node List node to remove.
97 */
98void list_remove(list_t *list, list_node_t *node)
99{
100 /* Check whether node is in the list as claimed. */
101 assert(list_node_present(list, node));
102 list_node_unlink(node);
103 node->data = NULL;
104 list_node_delete(node);
105}
106
107/** Return first list node or NULL if list is empty.
108 *
109 * @param list Linked list.
110 * @return First node of the list or @c NULL if the list is empty.
111 */
112list_node_t *list_first(list_t *list)
113{
114 list_node_t *node;
115
116 assert(list != NULL);
117 node = list->head.next;
118
119 return (node != &list->head) ? node : NULL;
120}
121
122/** Return last list node or NULL if list is empty.
123 *
124 * @param list Linked list.
125 * @return Last node of the list or @c NULL if the list is empty.
126 */
127list_node_t *list_last(list_t *list)
128{
129 list_node_t *node;
130
131 assert(list != NULL);
132 node = list->head.prev;
133
134 return (node != &list->head) ? node : NULL;
135}
136
137/** Return next list node or NULL if this was the last one.
138 *
139 * @param list Linked list.
140 * @param node Node whose successor we are interested in.
141 * @return Following list node or @c NULL if @a node is last.
142 */
143list_node_t *list_next(list_t *list, list_node_t *node)
144{
145 (void) list;
146 assert(list != NULL);
147 assert(node != NULL);
148
149 return (node->next != &list->head) ? node->next : NULL;
150}
151
152/** Return previous list node or NULL if this was the last one.
153 *
154 * @param list Linked list.
155 * @param node Node whose predecessor we are interested in.
156 * @return Preceding list node or @c NULL if @a node is last.
157 */
158list_node_t *list_prev(list_t *list, list_node_t *node)
159{
160 (void) list;
161 assert(list != NULL);
162 assert(node != NULL);
163
164 return (node->prev != &list->head) ? node->prev : NULL;
165}
166
167/** Return b_true if list is empty.
168 *
169 * @param list Linked list.
170 * @return @c b_true if list is empty, @c b_false otherwise.
171 */
172bool_t list_is_empty(list_t *list)
173{
174 return (list_first(list) == NULL);
175}
176
177/** Change node data.
178 *
179 * Change the data associated with a node.
180 *
181 * @param node List node.
182 * @param data New data for node.
183 */
184void list_node_setdata(list_node_t *node, void *data)
185{
186 node->data = data;
187}
188
189/** Create new node.
190 *
191 * @param data Initial data for node.
192 * @return New list node.
193 */
194static list_node_t *list_node_new(void *data)
195{
196 list_node_t *node;
197
198 node = malloc(sizeof(list_node_t));
199 if (node == NULL) {
200 printf("Memory allocation failed.\n");
201 exit(1);
202 }
203
204 node->prev = NULL;
205 node->next = NULL;
206 node->data = data;
207
208 return node;
209}
210
211/** Delete node.
212 *
213 * @param node List node. Must not take part in any list.
214 */
215static void list_node_delete(list_node_t *node)
216{
217 assert(node->prev == NULL);
218 assert(node->next == NULL);
219 assert(node->data == NULL);
220 free(node);
221}
222
223/** Insert node between two other nodes.
224 *
225 * Inserts @a n between neighboring nodes @a a and @a b.
226 *
227 * @param n Node to insert.
228 * @param a Node to precede @a n.
229 * @param b Node to follow @a n.
230 */
231static void list_node_insert_between(list_node_t *n, list_node_t *a,
232 list_node_t *b)
233{
234 assert(n->prev == NULL);
235 assert(n->next == NULL);
236 n->prev = a;
237 n->next = b;
238
239 assert(a->next == b);
240 assert(b->prev == a);
241 a->next = n;
242 b->prev = n;
243}
244
245/** Unlink node.
246 *
247 * Unlink node from the list it is currently in.
248 *
249 * @param n Node to unlink from its current list.
250 */
251static void list_node_unlink(list_node_t *n)
252{
253 list_node_t *a, *b;
254 assert(n->prev != NULL);
255 assert(n->next != NULL);
256
257 a = n->prev;
258 b = n->next;
259
260 assert(a->next == n);
261 assert(b->prev == n);
262
263 a->next = b;
264 b->prev = a;
265
266 n->prev = NULL;
267 n->next = NULL;
268}
269
270/** Check whether @a node is in list @a list.
271 *
272 * @param list Linked list.
273 * @param node Node.
274 * @return @c b_true if @a node is part of @a list, @c b_false otherwise.
275 */
276static bool_t list_node_present(list_t *list, list_node_t *node)
277{
278 list_node_t *m;
279
280 m = list->head.next;
281 while (m != &list->head) {
282 if (m == node)
283 return b_true;
284 m = m->next;
285 }
286
287 return b_false;
288}
Note: See TracBrowser for help on using the repository browser.