libacfutils
A general purpose library of utility functions designed to make it easier to develop addons for the X-Plane flight simulator.
Loading...
Searching...
No Matches
list.c
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license in the file COPYING
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file COPYING.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24/*
25 * Copyright 2023 Saso Kiselkov. All rights reserved.
26 */
27/*
28 * Generic doubly-linked list implementation
29 */
30
31#include <acfutils/list.h>
32#include <acfutils/list_impl.h>
33
34#include <sys/types.h>
35#include <stdlib.h>
36#ifdef _KERNEL
37#include <sys/debug.h>
38#else
39#include <assert.h>
40#ifdef DEBUG
41#define ASSERT(a) assert(a)
42#else /* !DEBUG */
43#define ASSERT(a)
44#endif /* !DEBUG */
45#endif
46
47#ifdef lint
48extern list_node_t *list_d2l(list_t *list, void *obj);
49#else
50#define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset))
51#endif
52#define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset))
53#define list_empty(a) ((a)->list_head.list_next == &(a)->list_head)
54
55#define list_insert_after_node(list, node, object) { \
56 list_node_t *lnew = list_d2l(list, object); \
57 lnew->list_prev = (node); \
58 lnew->list_next = (node)->list_next; \
59 (node)->list_next->list_prev = lnew; \
60 (node)->list_next = lnew; \
61 (list)->list_count++; \
62}
63
64#define list_insert_before_node(list, node, object) { \
65 list_node_t *lnew = list_d2l(list, object); \
66 lnew->list_next = (node); \
67 lnew->list_prev = (node)->list_prev; \
68 (node)->list_prev->list_next = lnew; \
69 (node)->list_prev = lnew; \
70 (list)->list_count++; \
71}
72
73#define list_remove_node(node) \
74 (node)->list_prev->list_next = (node)->list_next; \
75 (node)->list_next->list_prev = (node)->list_prev; \
76 (node)->list_next = (node)->list_prev = NULL
77
112void
113list_create(list_t *list, size_t size, size_t offset)
114{
115 ASSERT(list);
116 ASSERT(size > 0);
117 ASSERT(size >= offset + sizeof (list_node_t));
118
119 list->list_size = size;
120 list->list_offset = offset;
121 list->list_count = 0;
122 list->list_head.list_next = list->list_head.list_prev =
123 &list->list_head;
124}
125
135void
137{
138 list_node_t *node = &list->list_head;
139
140 ASSERT(list);
141 ASSERT(list->list_head.list_next == node);
142 ASSERT(list->list_head.list_prev == node);
143 ASSERT(list->list_count == 0);
144
145 node->list_next = node->list_prev = NULL;
146}
147
158void
159list_insert_after(list_t *list, void *object, void *nobject)
160{
161 if (object == NULL) {
162 list_insert_head(list, nobject);
163 } else {
164 list_node_t *lold = list_d2l(list, object);
165 list_insert_after_node(list, lold, nobject);
166 }
167}
168
180void
181list_insert_before(list_t *list, void *object, void *nobject)
182{
183 if (object == NULL) {
184 list_insert_tail(list, nobject);
185 } else {
186 list_node_t *lold = list_d2l(list, object);
187 list_insert_before_node(list, lold, nobject);
188 }
189}
190
198void
200{
201 list_node_t *lold = &list->list_head;
202 list_insert_after_node(list, lold, object);
203}
204
212void
214{
215 list_node_t *lold = &list->list_head;
216 list_insert_before_node(list, lold, object);
217}
218
225void
226list_remove(list_t *list, void *object)
227{
228 list_node_t *lold = list_d2l(list, object);
229 ASSERT(!list_empty(list));
230 ASSERT(lold->list_next != NULL);
231 list_remove_node(lold);
232 list->list_count--;
233}
234
250void *
252{
253 list_node_t *head = list->list_head.list_next;
254 if (head == &list->list_head)
255 return (NULL);
256 list_remove_node(head);
257 list->list_count--;
258 return (list_object(list, head));
259}
260
276void *
278{
279 list_node_t *tail = list->list_head.list_prev;
280 if (tail == &list->list_head)
281 return (NULL);
282 list_remove_node(tail);
283 list->list_count--;
284 return (list_object(list, tail));
285}
286
291void *
293{
294 if (list_empty(list))
295 return (NULL);
296 return (list_object(list, list->list_head.list_next));
297}
298
303void *
305{
306 if (list_empty(list))
307 return (NULL);
308 return (list_object(list, list->list_head.list_prev));
309}
310
343void *
344list_next(const list_t *list, const void *object)
345{
346 list_node_t *node = list_d2l(list, object);
347
349 if (node->list_next != &list->list_head)
350 return (list_object(list, node->list_next));
351
352 return (NULL);
353}
354
387void *
388list_prev(const list_t *list, const void *object)
389{
390 list_node_t *node = list_d2l(list, object);
391
393 if (node->list_prev != &list->list_head)
394 return (list_object(list, node->list_prev));
395
396 return (NULL);
397}
398
411void *
412list_get_i(const list_t *list, size_t i)
413{
414 void *obj;
415
416 ASSERT(list != NULL);
417 ASSERT(i < list_count(list));
418
419 obj = list_head(list);
420 for (unsigned j = 0; j < i; j++)
421 obj = list_next(list, obj);
422
423 return (obj);
424}
425
435void
437{
438 list_node_t *dstnode = &dst->list_head;
439 list_node_t *srcnode = &src->list_head;
440
441 ASSERT(dst->list_size == src->list_size);
442 ASSERT(dst->list_offset == src->list_offset);
443
444 if (list_empty(src))
445 return;
446
447 dstnode->list_prev->list_next = srcnode->list_next;
448 srcnode->list_next->list_prev = dstnode->list_prev;
449 dstnode->list_prev = srcnode->list_prev;
450 srcnode->list_prev->list_next = dstnode;
451 dst->list_count += src->list_count;
452
453 /* empty src list */
454 srcnode->list_next = srcnode->list_prev = srcnode;
455 src->list_count = 0;
456}
457
488void
490{
492 ASSERT(!list_link_active(lnew));
493
494 lnew->list_next = lold->list_next;
495 lnew->list_prev = lold->list_prev;
496 lold->list_prev->list_next = lnew;
497 lold->list_next->list_prev = lnew;
498 lold->list_next = lold->list_prev = NULL;
499}
500
509void
511{
512 link->list_next = NULL;
513 link->list_prev = NULL;
514}
515
524int
526{
527 return (link->list_next != NULL);
528}
529
533int
535{
536 return (list_empty(list));
537}
538
542size_t
544{
545 return (list->list_count);
546}
#define ASSERT(x)
Definition assert.h:208
void list_link_replace(list_node_t *, list_node_t *)
Definition list.c:489
int list_link_active(const list_node_t *)
Definition list.c:525
void * list_tail(const list_t *)
Definition list.c:304
void * list_get_i(const list_t *, size_t)
Definition list.c:412
void list_destroy(list_t *)
Definition list.c:136
void * list_head(const list_t *)
Definition list.c:292
int list_is_empty(const list_t *)
Definition list.c:534
void list_create(list_t *, size_t, size_t)
Definition list.c:113
void list_move_tail(list_t *, list_t *)
Definition list.c:436
void list_insert_after(list_t *, void *, void *)
Definition list.c:159
void list_insert_before(list_t *, void *, void *)
Definition list.c:181
void * list_remove_tail(list_t *)
Definition list.c:277
void * list_prev(const list_t *, const void *)
Definition list.c:388
void list_insert_head(list_t *, void *)
Definition list.c:199
void * list_next(const list_t *, const void *)
Definition list.c:344
void list_link_init(list_node_t *)
Definition list.c:510
size_t list_count(const list_t *)
Definition list.c:543
void list_remove(list_t *, void *)
Definition list.c:226
void * list_remove_head(list_t *)
Definition list.c:251
void list_insert_tail(list_t *, void *)
Definition list.c:213