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) \
57 for (LList node = llist_get_head (list); \
58 ! llist_is_end (node, list); \
59 llist_forward (&node))
61 #define LLIST_FOREACH_REV(list, node) \
62 for (LList node = llist_get_tail (list); \
63 ! llist_is_end (node, list); \
64 llist_backward (&node))
67 * Type of a llist node.
71 struct llist_struct
*next
;
72 struct llist_struct
*prev
;
74 typedef struct llist_struct llist
;
75 typedef llist
* LList
;
76 typedef const llist
* const_LList
;
77 typedef llist
** LList_ref
;
80 * handy macro to instantiate a local llist 'name' becomes a LList handle and
81 * the underlying instance is hidden as name_llist_, this list is statically initialized
83 #define LLIST_STATIC_INITIALIZER(name) {&name,&name}
84 #define LLIST_AUTO(name) \
85 llist name##_llist_ = LLIST_STATIC_INITIALIZER(name##_llist_);\
86 LList name = &name##_llist_
88 LLIST_MACRO
void llist_init (LList self
);
89 LLIST_MACRO
int llist_is_empty (const_LList self
);
90 LLIST_MACRO
int llist_is_single (const_LList self
);
91 LLIST_MACRO
int llist_is_head (const_LList self
, const_LList list
);
92 LLIST_MACRO
int llist_is_tail (const_LList self
, const_LList list
);
93 LLIST_MACRO
int llist_is_end (const_LList self
, const_LList list
);
94 LLIST_MACRO
int llist_is_member (const_LList self
, const_LList list
);
95 LLIST_MACRO
int llist_is_before (const_LList self
, const_LList other
, const_LList list
);
96 LLIST_MACRO
int llist_is_after (const_LList self
, const_LList other
, const_LList list
);
97 LLIST_MACRO
unsigned llist_count (const_LList self
);
98 LLIST_MACRO
unsigned llist_distance (const_LList self
, const_LList other
, const_LList list
);
99 LLIST_MACRO
void llist_unlink_fast_ (LList self
);
100 LLIST_MACRO LList
llist_unlink (LList self
);
101 LLIST_MACRO LList
llist_relocate (LList self
);
102 LLIST_MACRO LList
llist_insert_before (LList self
, LList successor
);
103 LLIST_MACRO LList
llist_insert_after (LList self
, LList predcessor
);
104 LLIST_MACRO LList
llist_insert_list_before (LList self
, LList successor
);
105 LLIST_MACRO LList
llist_insert_list_after (LList self
, LList predcessor
);
106 LLIST_MACRO LList
llist_insert_range_before (LList self
, LList start
, LList end
);
107 LLIST_MACRO LList
llist_insert_range_after (LList self
, LList start
, LList end
);
108 LLIST_MACRO LList
llist_advance (LList self
);
109 LLIST_MACRO LList
llist_retreat (LList self
);
110 LLIST_MACRO LList
llist_get_next (const_LList self
);
111 LLIST_MACRO LList
llist_get_prev (const_LList self
);
112 LLIST_MACRO
void llist_forward (LList_ref self
);
113 LLIST_MACRO
void llist_backward (LList_ref self
);
114 LLIST_MACRO LList
llist_get_nth (LList self
, int n
);
116 #endif /*LLIST_INTERFACE*/
120 #ifdef LLIST_IMPLEMENTATION
122 #define llist_insert_head(list,element) llist_insert_after(element,list)
123 #define llist_insert_tail(list,element) llist_insert_before(element,list)
124 #define llist_get_head llist_get_next
125 #define llist_get_tail llist_get_prev
129 * initialize a new llist. Must not be
130 * applied to a list which is not empty! Lists need to be initialized
131 * before any other operation on them is called.
134 llist_init (LList self
)
136 self
->next
= self
->prev
= self
;
140 * check if a node is linked with some other node
143 llist_is_empty (const_LList self
)
145 return self
->next
== self
;
149 * check if self is the only node in a list or self is not in a list
152 llist_is_single (const_LList self
)
154 return self
->next
->next
== self
;
158 * check if self is the head of list
161 llist_is_head (const_LList self
, const_LList list
)
163 return list
->next
== self
;
167 * check if self is the tail of list
170 llist_is_tail (const_LList self
, const_LList list
)
172 return list
->prev
== self
;
176 * check if self is the end of list
179 llist_is_end (const_LList self
, const_LList list
)
185 * check if self is a member of list
188 llist_is_member (const_LList self
, const_LList list
)
190 const_LList i
= self
->next
;
191 for (; i
!= self
; i
= i
->next
)
200 * check if self is before other in list
203 llist_is_before (const_LList self
, const_LList other
, const_LList list
)
205 assert (llist_is_member (self
, list
));
206 assert (llist_is_member (other
, list
));
207 const_LList i
= self
->next
;
210 for (; i
!= list
; i
= i
->next
)
220 * check if self is after other in list
223 llist_is_after (const_LList self
, const_LList other
, const_LList list
)
225 assert (llist_is_member (self
, list
));
226 assert (llist_is_member (other
, list
));
227 const_LList i
= self
->prev
;
230 for (; i
!= list
; i
= i
->prev
)
241 * count the nodes of self
244 llist_count (const_LList self
)
247 const_LList i
= self
;
248 for (; i
->next
!= self
; ++cnt
, i
= i
->next
);
253 * count distance from self to other in list
256 llist_distance (const_LList self
, const_LList other
, const_LList list
)
258 assert (llist_is_member (self
, list
));
259 assert (llist_is_member (other
, list
));
262 const_LList i
= self
;
263 for (; i
->next
!= other
&& i
->next
!= list
; ++cnt
, i
= i
->next
);
265 for (cnt
= 0, i
= self
; i
->prev
!= other
; ++cnt
, i
= i
->prev
);
271 llist_unlink_fast_ (LList self
)
273 LList nxt
= self
->next
, pre
= self
->prev
;
279 * removes self from its list
282 llist_unlink (LList self
)
284 llist_unlink_fast_ (self
);
285 return self
->next
= self
->prev
= self
;
289 * fixes a list if self got relocated in memory
292 llist_relocate (LList self
)
294 return self
->next
->prev
= self
->prev
->next
= self
;
298 * inserts self before successor,
299 * self can already linked to a list where it will be removed
302 llist_insert_before (LList self
, LList successor
)
304 llist_unlink_fast_ (self
);
305 self
->prev
= successor
->prev
;
306 self
->next
= successor
;
307 return successor
->prev
= self
->prev
->next
= self
;
312 * inserts self after predcessor,
313 * self can already linked to a list where it will be removed
316 llist_insert_after (LList self
, LList predcessor
)
318 llist_unlink_fast_ (self
);
319 self
->next
= predcessor
->next
;
320 self
->prev
= predcessor
;
321 return predcessor
->next
= self
->next
->prev
= self
;
325 * move the content of list self before node successor
328 llist_insert_list_before (LList self
, LList successor
)
330 self
->next
->prev
= successor
->prev
;
331 self
->prev
->next
= successor
;
332 successor
->prev
->next
= self
->next
;
333 successor
->prev
= self
->prev
;
334 self
->prev
= self
->next
= self
;
339 * move the content of list self after node predcessor
342 llist_insert_list_after (LList self
, LList predcessor
)
344 self
->prev
->next
= predcessor
->next
;
345 self
->next
->prev
= predcessor
;
346 predcessor
->next
->prev
= self
->prev
;
347 predcessor
->next
= self
->next
;
348 self
->prev
= self
->next
= self
;
353 * move members from start to end->prev before self
356 LList
llist_insert_range_before (LList self
, LList start
, LList end
)
358 LList tmp
= self
->prev
;
359 start
->prev
->next
= end
;
360 end
->prev
->next
= self
;
361 self
->prev
->next
= start
;
363 self
->prev
= end
->prev
;
364 end
->prev
= start
->prev
;
371 * move members from start to end->prev after self
374 LList
llist_insert_range_after (LList self
, LList start
, LList end
)
376 start
->prev
->next
= end
;
377 end
->prev
->next
= self
->next
;
378 self
->next
->prev
= end
->prev
;
380 end
->prev
= start
->prev
;
386 * swap a node with its next node
389 llist_advance (LList self
)
391 LList tmp
= self
->next
->next
;
393 self
->next
->prev
= self
->prev
;
394 self
->prev
->next
= self
->next
;
395 self
->prev
= self
->next
;
396 self
->next
->next
= self
;
402 * swap a node with its previous node
405 llist_retreat (LList self
)
407 LList tmp
= self
->prev
->prev
;
409 self
->prev
->next
= self
->next
;
410 self
->next
->prev
= self
->prev
;
411 self
->next
= self
->prev
;
412 self
->prev
->prev
= self
;
420 * return the member after self
423 llist_get_next (const_LList self
)
429 * return the member before self
432 llist_get_prev (const_LList self
)
438 * put self to the next node
441 llist_forward (LList_ref self
)
443 *self
= (*self
)->next
;
447 * put self to the previous node
450 llist_backward (LList_ref self
)
452 *self
= (*self
)->prev
;
456 * get the nth element after (positive n) or before (negative n) self
459 llist_get_nth (LList self
, int n
)
463 self
= llist_get_next (self
);
466 self
= llist_get_prev (self
);
471 #endif /*LLIST_IMPLEMENTATION*/
477 // c-file-style: "gnu"
479 // arch-tag: e8fe4a59-fd55-4c45-b860-5cd1e0771213