2 llist.h - simple intrusive cyclic double linked list
4 Copyright (C) 2003, 2005, Christian Thaeter <chth@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, contact me.
26 #ifndef LLIST_SPECIAL_BUILD
27 #define LLIST_INTERFACE
28 #define LLIST_IMPLEMENTATION
32 # define LLIST_MACRO static inline
35 # define LLIST_MACRO static __inline__
37 # define LLIST_MACRO static
41 #ifdef LLIST_INTERFACE
43 /* we have a llist node in a structure and want to get the structure which embedds it */
51 LLIST_TO_STRUCTP (&x.l, foo, l)->bar
53 #define LLIST_TO_STRUCTP(llist, type, member) \
54 ((type*)(((char*)(llist)) - offsetof(type, member)))
56 #define LLIST_FOREACH(list, node) \
58 for (LList node = llist_get_head (list); \
59 ! llist_is_end (node, list); \
60 llist_forward (&node))
62 #define LLIST_FOREACH_REV(list, node) \
64 for (LList node = llist_get_tail (list); \
65 ! llist_is_end (node, list); \
66 llist_backward (&node))
68 #define LLIST_WHILE_HEAD(list, head) \
70 for (LList head = llist_get_head (list); \
71 !llist_is_empty (list); \
72 head = llist_get_head (list))
74 #define LLIST_WHILE_TAIL(list, tail) \
76 for (LList tail = llist_get_tail (list); \
77 !llist_is_empty (list); \
78 tail = llist_get_tail (list))
82 * Type of a llist node.
86 struct llist_struct
*next
;
87 struct llist_struct
*prev
;
89 typedef struct llist_struct llist
;
90 typedef llist
* LList
;
91 typedef const llist
* const_LList
;
92 typedef llist
** LList_ref
;
95 * handy macro to instantiate a local llist 'name' becomes a LList handle and
96 * the underlying instance is hidden as name_llist_, this list is statically initialized
98 #define LLIST_INITIALIZER(name) {&name,&name}
99 #define LLIST_AUTO(name) \
100 llist name##_llist_ = LLIST_STATIC_INITIALIZER(name##_llist_);\
101 LList name = &name##_llist_
103 LLIST_MACRO
void llist_init (LList self
);
104 LLIST_MACRO
int llist_is_empty (const_LList self
);
105 LLIST_MACRO
int llist_is_single (const_LList self
);
106 LLIST_MACRO
int llist_is_head (const_LList self
, const_LList list
);
107 LLIST_MACRO
int llist_is_tail (const_LList self
, const_LList list
);
108 LLIST_MACRO
int llist_is_end (const_LList self
, const_LList list
);
109 LLIST_MACRO
int llist_is_member (const_LList self
, const_LList list
);
110 LLIST_MACRO
int llist_is_before (const_LList self
, const_LList other
, const_LList list
);
111 LLIST_MACRO
int llist_is_after (const_LList self
, const_LList other
, const_LList list
);
112 LLIST_MACRO
unsigned llist_count (const_LList self
);
113 LLIST_MACRO
unsigned llist_distance (const_LList self
, const_LList other
, const_LList list
);
114 LLIST_MACRO
void llist_unlink_fast_ (LList self
);
115 LLIST_MACRO LList
llist_unlink (LList self
);
116 LLIST_MACRO LList
llist_relocate (LList self
);
117 LLIST_MACRO LList
llist_insert_before (LList self
, LList successor
);
118 LLIST_MACRO LList
llist_insert_after (LList self
, LList predcessor
);
119 LLIST_MACRO LList
llist_insert_list_before (LList self
, LList successor
);
120 LLIST_MACRO LList
llist_insert_list_after (LList self
, LList predcessor
);
121 LLIST_MACRO LList
llist_insert_range_before (LList self
, LList start
, LList end
);
122 LLIST_MACRO LList
llist_insert_range_after (LList self
, LList start
, LList end
);
123 LLIST_MACRO LList
llist_advance (LList self
);
124 LLIST_MACRO LList
llist_retreat (LList self
);
125 LLIST_MACRO LList
llist_get_next (const_LList self
);
126 LLIST_MACRO LList
llist_get_prev (const_LList self
);
127 LLIST_MACRO
void llist_forward (LList_ref self
);
128 LLIST_MACRO
void llist_backward (LList_ref self
);
129 LLIST_MACRO LList
llist_get_nth (LList self
, int n
);
130 LLIST_MACRO LList
llist_get_nth_stop (LList self
, int n
, const_LList stop
);
132 #endif /*LLIST_INTERFACE*/
136 #ifdef LLIST_IMPLEMENTATION
138 #define llist_insert_head(list,element) llist_insert_after(element,list)
139 #define llist_insert_tail(list,element) llist_insert_before(element,list)
140 #define llist_get_head llist_get_next
141 #define llist_get_tail llist_get_prev
145 * initialize a new llist. Must not be
146 * applied to a list which is not empty! Lists need to be initialized
147 * before any other operation on them is called.
150 llist_init (LList self
)
152 self
->next
= self
->prev
= self
;
156 * check if a node is linked with some other node
159 llist_is_empty (const_LList self
)
161 return self
->next
== self
;
165 * check if self is the only node in a list or self is not in a list
168 llist_is_single (const_LList self
)
170 return self
->next
->next
== self
;
174 * check if self is the head of list
177 llist_is_head (const_LList self
, const_LList list
)
179 return list
->next
== self
;
183 * check if self is the tail of list
186 llist_is_tail (const_LList self
, const_LList list
)
188 return list
->prev
== self
;
192 * check if self is the end of list
195 llist_is_end (const_LList self
, const_LList list
)
201 * check if self is a member of list
204 llist_is_member (const_LList self
, const_LList list
)
206 const_LList i
= self
->next
;
207 for (; i
!= self
; i
= i
->next
)
216 * check if self is before other in list
219 llist_is_before (const_LList self
, const_LList other
, const_LList list
)
221 assert (llist_is_member (self
, list
));
222 assert (llist_is_member (other
, list
));
223 const_LList i
= self
->next
;
226 for (; i
!= list
; i
= i
->next
)
236 * check if self is after other in list
239 llist_is_after (const_LList self
, const_LList other
, const_LList list
)
241 assert (llist_is_member (self
, list
));
242 assert (llist_is_member (other
, list
));
243 const_LList i
= self
->prev
;
246 for (; i
!= list
; i
= i
->prev
)
257 * count the nodes of self
260 llist_count (const_LList self
)
263 const_LList i
= self
;
264 for (; i
->next
!= self
; ++cnt
, i
= i
->next
);
269 * count distance from self to other in list
272 llist_distance (const_LList self
, const_LList other
, const_LList list
)
274 assert (llist_is_member (self
, list
));
275 assert (llist_is_member (other
, list
));
278 const_LList i
= self
;
279 for (; i
->next
!= other
&& i
->next
!= list
; ++cnt
, i
= i
->next
);
281 for (cnt
= 0, i
= self
; i
->prev
!= other
; ++cnt
, i
= i
->prev
);
287 llist_unlink_fast_ (LList self
)
289 LList nxt
= self
->next
, pre
= self
->prev
;
295 * removes self from its list
298 llist_unlink (LList self
)
300 llist_unlink_fast_ (self
);
301 return self
->next
= self
->prev
= self
;
305 * fixes a list if self got relocated in memory
308 llist_relocate (LList self
)
310 return self
->next
->prev
= self
->prev
->next
= self
;
314 * inserts self before successor,
315 * self can already linked to a list where it will be removed
318 llist_insert_before (LList self
, LList successor
)
320 llist_unlink_fast_ (self
);
321 self
->prev
= successor
->prev
;
322 self
->next
= successor
;
323 return successor
->prev
= self
->prev
->next
= self
;
328 * inserts self after predcessor,
329 * self can already linked to a list where it will be removed
332 llist_insert_after (LList self
, LList predcessor
)
334 llist_unlink_fast_ (self
);
335 self
->next
= predcessor
->next
;
336 self
->prev
= predcessor
;
337 return predcessor
->next
= self
->next
->prev
= self
;
341 * move the content of list self before node successor
344 llist_insert_list_before (LList self
, LList successor
)
346 if (!llist_is_empty (self
))
348 self
->next
->prev
= successor
->prev
;
349 self
->prev
->next
= successor
;
350 successor
->prev
->next
= self
->next
;
351 successor
->prev
= self
->prev
;
352 self
->prev
= self
->next
= self
;
358 * move the content of list self after node predcessor
361 llist_insert_list_after (LList self
, LList predcessor
)
363 if (!llist_is_empty (self
))
365 self
->prev
->next
= predcessor
->next
;
366 self
->next
->prev
= predcessor
;
367 predcessor
->next
->prev
= self
->prev
;
368 predcessor
->next
= self
->next
;
369 self
->prev
= self
->next
= self
;
375 * move members from start to end->prev before self
378 LList
llist_insert_range_before (LList self
, LList start
, LList end
)
380 LList tmp
= self
->prev
;
381 start
->prev
->next
= end
;
382 end
->prev
->next
= self
;
383 self
->prev
->next
= start
;
385 self
->prev
= end
->prev
;
386 end
->prev
= start
->prev
;
393 * move members from start to end->prev after self
396 LList
llist_insert_range_after (LList self
, LList start
, LList end
)
398 start
->prev
->next
= end
;
399 end
->prev
->next
= self
->next
;
400 self
->next
->prev
= end
->prev
;
402 end
->prev
= start
->prev
;
408 * swap a node with its next node
411 llist_advance (LList self
)
413 LList tmp
= self
->next
->next
;
415 self
->next
->prev
= self
->prev
;
416 self
->prev
->next
= self
->next
;
417 self
->prev
= self
->next
;
418 self
->next
->next
= self
;
424 * swap a node with its previous node
427 llist_retreat (LList self
)
429 LList tmp
= self
->prev
->prev
;
431 self
->prev
->next
= self
->next
;
432 self
->next
->prev
= self
->prev
;
433 self
->next
= self
->prev
;
434 self
->prev
->prev
= self
;
442 * return the member after self
445 llist_get_next (const_LList self
)
451 * return the member before self
454 llist_get_prev (const_LList self
)
460 * put self to the next node
463 llist_forward (LList_ref self
)
465 *self
= (*self
)->next
;
469 * put self to the previous node
472 llist_backward (LList_ref self
)
474 *self
= (*self
)->prev
;
478 * get the nth element after (positive n) or before (negative n) self
481 llist_get_nth (LList self
, int n
)
485 self
= llist_get_next (self
);
488 self
= llist_get_prev (self
);
494 * get the nth element after (positive n) or before (negative n) self
495 * return NULL if node stop is hit
498 llist_get_nth_stop (LList self
, int n
, const_LList stop
)
503 self
= llist_get_next (self
);
510 self
= llist_get_prev (self
);
517 #endif /*LLIST_IMPLEMENTATION*/
523 // c-file-style: "gnu"
525 // arch-tag: e8fe4a59-fd55-4c45-b860-5cd1e0771213