💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Menkar › files › bfd287458f895883e1ee1b41e44… captured on 2022-07-16 at 17:11:01. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
0 #if !defined(LIST_H)
1 #define LIST_H
2
3 /*
4 * Doubly-linked list macros
5 */
6
7 /*
8 * Copyright 2006 Johan Veenhuizen
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28
29 /*
30 * Doubly-linked list type
31 *
32 * Both lists and nodes of lists are of type LIST.
33 *
34 * Doubly-linked list macros
35 *
36 * LIST_DEFINE(listname)
37 * Define and initialize an empty list at load time.
38 *
39 * LIST_INIT([list | node])
40 * Initialize a list or node at run time.
41 *
42 * LIST_EMPTY(list)
43 * Test if list is empty.
44 *
45 * LIST_HEAD(list)
46 * Return the first element of list, or NULL if empty.
47 *
48 * LIST_TAIL(list)
49 * Return the last element of list, or NULL if empty.
50 *
51 * LIST_INSERT(list, node)
52 * Insert node somewhere in list (order not important).
53 *
54 * LIST_INSERT_HEAD(list, node)
55 * Insert node at the head of list.
56 *
57 * LIST_INSERT_TAIL(list, node)
58 * Insert node at the tail of list.
59 *
60 * LIST_INSERT_BEFORE(elem, node)
61 * Insert node before elem.
62 *
63 * LIST_INSERT_AFTER(elem, node)
64 * Insert node after elem.
65 *
66 * LIST_REMOVE(node)
67 * Remove node from its list.
68 *
69 * LIST_MEMBER(node)
70 * Test if node is a member of a list.
71 *
72 * LIST_ITEM(node, type, memb)
73 * Return the structure of the given type, containing
74 * node as member memb.
75 *
76 * LIST_FOREACH(node, list)
77 * Iterate over the nodes of list (for loop).
78 */
79
80 #include <stdio.h>
81
82 /* The exported LIST type. */
83 typedef struct listnode LIST;
84
85 /* The internal list type. Don't use this in code. */
86 struct listnode {
87 struct listnode *ln_prev, *ln_next;
88 };
89
90 /* Define and initialize an empty list at load time. */
91 #define LIST_DEFINE(name) LIST name = { &name, &name }
92
93 /* Initialize a list or list node at run time. */
94 #define LIST_INIT(lp) ((lp)->ln_prev = (lp)->ln_next = (lp))
95
96 /* Return the first node of list, or NULL if empty. */
97 #define LIST_HEAD(list) ((list)->ln_next == (list) ? NULL : (list)->ln_next)
98
99 /* Return the last node of list, or NULL if empty. */
100 #define LIST_TAIL(list) ((list)->ln_prev == (list) ? NULL : (list)->ln_prev)
101
102 /* Insert node before elem. */
103 #define LIST_INSERT_BEFORE(elem, node) do { \
104 (node)->ln_next = (elem); \
105 (node)->ln_prev = (elem)->ln_prev; \
106 (elem)->ln_prev->ln_next = (node); \
107 (elem)->ln_prev = (node); \
108 } while (0)
109
110 /* Insert node after elem. */
111 #define LIST_INSERT_AFTER(elem, node) do { \
112 (node)->ln_prev = (elem); \
113 (node)->ln_next = (elem)->ln_next; \
114 (elem)->ln_next->ln_prev = (node); \
115 (elem)->ln_next = (node); \
116 } while (0)
117
118 /* Insert node at the head of list. */
119 #define LIST_INSERT_HEAD(list, node) LIST_INSERT_AFTER((list), (node))
120
121 /* Insert node at the tail of list. */
122 #define LIST_INSERT_TAIL(list, node) LIST_INSERT_BEFORE((list), (node))
123
124 /* Use this when order is not important. */
125 #define LIST_INSERT(list, node) LIST_INSERT_TAIL((list), (node))
126
127 /* Delete node from its list. */
128 #define LIST_REMOVE(node) do { \
129 (node)->ln_prev->ln_next = (node)->ln_next; \
130 (node)->ln_next->ln_prev = (node)->ln_prev; \
131 LIST_INIT(node); \
132 } while (0)
133
134 /* Test if list if empty. */
135 #define LIST_EMPTY(list) ((list)->ln_next == (list))
136
137 /* Test if node is a member of a list. */
138 #define LIST_MEMBER(node) ((node)->ln_next != (node))
139
140 #define LIST_ITEM(node, type, memb) \
141 ((type *)((char *)(node) - (char *)&(((type *)0)->memb)))
142
143 #define LIST_FOREACH(node, list) \
144 for ((node) = (list)->ln_next; \
145 (node) != (list); \
146 (node) = (node)->ln_next)
147
148 #endif /* defined(LIST_H) */
149