comparison include/sys/ilist.h @ 20687:ac1492488560 draft

ilist: add generic circular doubly-linked list with a sentinel node
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Sun, 22 Mar 2020 10:48:20 -0400
parents
children
comparison
equal deleted inserted replaced
18357:11a2d819935f 20687:ac1492488560
1 /*
2 * Copyright 2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #ifndef _SYS_ILIST_H
18 #define _SYS_ILIST_H
19
20 /*
21 * Generic circular doubly-linked list with a sentinel node.
22 *
23 * The entire implementation is here as C99 static inline functions. We
24 * hide them if we are not using a C99 compiler to expose the list_node
25 * struct for list.h's benefit.
26 *
27 * Here's the summary of differences:
28 *
29 * (1) both ilist.h and list.h use the same struct list_node
30 * (1) ilist.h uses static inlines while list.h uses normal functions
31 * (2) list.h uses struct list to keep track of offsets into objects for the
32 * struct list_node
33 * (3) ilist.h uses struct list_head as a sentinel node and has no idea
34 * about the structures containing each of the list entries
35 */
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40
41 struct list_node {
42 struct list_node *list_next;
43 struct list_node *list_prev;
44 };
45
46 #ifdef _STDC_C99
47
48 #include <sys/null.h>
49
50 static inline void ilist_init(struct list_node *node)
51 {
52 node->list_next = node;
53 node->list_prev = node;
54 }
55
56 static inline int ilist_is_empty(struct list_node *list)
57 {
58 return list->list_next == list;
59 }
60
61 static int ilist_link_active(struct list_node *node)
62 {
63 return node->list_next != NULL;
64 }
65
66 static inline struct list_node *ilist_head(struct list_node *list)
67 {
68 if (ilist_is_empty(list))
69 return NULL;
70
71 return list->list_next;
72 }
73
74 static inline struct list_node *ilist_tail(struct list_node *list)
75 {
76 if (ilist_is_empty(list))
77 return NULL;
78
79 return list->list_prev;
80 }
81
82 static inline struct list_node *ilist_next(struct list_node *list,
83 struct list_node *cur)
84 {
85 if (cur->list_next == list)
86 return NULL;
87
88 return cur->list_next;
89 }
90
91 static inline struct list_node *ilist_prev(struct list_node *list,
92 struct list_node *cur)
93 {
94 if (cur->list_prev == list)
95 return NULL;
96
97 return cur->list_prev;
98 }
99
100 static inline void __ilist_insert(struct list_node *before,
101 struct list_node *after,
102 struct list_node *newnode)
103 {
104 before->list_next = newnode;
105 newnode->list_prev = before;
106 newnode->list_next = after;
107 after->list_prev = newnode;
108 }
109
110 static inline void ilist_insert_after(struct list_node *reference,
111 struct list_node *newnode)
112 {
113 __ilist_insert(reference, reference->list_next, newnode);
114 }
115
116 static inline void ilist_insert_before(struct list_node *reference,
117 struct list_node *newnode)
118 {
119 __ilist_insert(reference->list_prev, reference, newnode);
120 }
121
122 #define ilist_insert_head(list, newnode) ilist_insert_after((list), (newnode))
123 #define ilist_insert_tail(list, newnode) ilist_insert_before((list), (newnode))
124
125 static inline void ilist_remove(struct list_node *node)
126 {
127 node->list_prev->list_next = node->list_next;
128 node->list_next->list_prev = node->list_prev;
129
130 node->list_prev = NULL;
131 node->list_next = NULL;
132 }
133
134 static inline struct list_node *__ilist_remove(struct list_node *list,
135 struct list_node *node)
136 {
137 if (ilist_is_empty(list))
138 return NULL;
139
140 ilist_remove(node);
141 return node;
142 }
143
144 static inline struct list_node *ilist_remove_head(struct list_node *list)
145 {
146 return __ilist_remove(list, list->list_next);
147 }
148
149 static inline struct list_node *ilist_remove_tail(struct list_node *list)
150 {
151 return __ilist_remove(list, list->list_prev);
152 }
153
154 #endif
155
156 #ifdef __cplusplus
157 }
158 #endif
159
160 #endif /* _SYS_ILIST_H */