Lumiera  0.pre.03
»edit your freedom«
llist.h
Go to the documentation of this file.
1 /*
2  llist.h - simple intrusive cyclic double linked list
3 
4  Copyright (C)
5  2003, 2005 Christian Thaeter <chth@gmx.net>
6  2008, Christian Thaeter <ct@pipapo.org>
7 
8   **Lumiera** is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2 of the License, or (at your
11   option) any later version. See the file COPYING for further details.
12 */
13 
14 #ifndef LLIST_H
15 #define LLIST_H
16 
17 #include <stddef.h>
18 
42 /* TODO __STDC_VERSION__ 199901L
43 150) This macro was not specified in ISO/IEC 9899:1990 and was specified as 199409L in
44 ISO/IEC 9899/AMD1:1995. The intention is that this will remain an integer constant of type long
45 int that is increased with each revision of this International Standard.
46 */
47 #ifdef HAVE_INLINE
48 # define LLIST_MACRO static inline
49 #else
50 # ifdef __GNUC__
51 # define LLIST_MACRO static __inline__
52 # else
53 # define LLIST_MACRO static
54 # endif
55 #endif
56 
57 #if defined(LLIST_INTERFACE)
58 /* only the interface is generated */
59 #define LLIST_FUNC(proto, ...) proto
60 #elif defined(LLIST_IMPLEMENTATION)
61 /* generate a non inlined implementation */
62 #define LLIST_FUNC(proto, ...) proto { __VA_ARGS__ }
63 #else
64 /* all functions are macro-like inlined */
65 #define LLIST_FUNC(proto, ...) LLIST_MACRO proto { __VA_ARGS__ }
66 #endif
67 
68 
69 /*
70  * Type of a llist node.
71  */
72 #ifndef LLIST_DEFINED
73 #define LLIST_DEFINED
75 {
76  struct llist_struct *next;
77  struct llist_struct *prev;
78 };
79 #endif
80 typedef struct llist_struct llist;
81 typedef llist * LList;
82 typedef const llist * const_LList;
83 typedef llist ** LList_ref;
84 
89 #define LLIST_AUTO(name) llist name = {&name,&name}
90 
91 
92 /*
93  some macros for convenience
94 */
95 #define llist_insert_head(list, element) llist_insert_next (list, element)
96 #define llist_insert_tail(list, element) llist_insert_prev (list, element)
97 #define llist_head llist_next
98 #define llist_tail llist_prev
99 
103 /* example:
104  struct foo
105  {
106  int bar;
107  llist l;
108  } x;
109  LLIST_TO_STRUCTP (&x.l, foo, l)->bar
110 */
111 #define LLIST_TO_STRUCTP(llist, type, member) \
112  ((type*)(((char*)(llist)) - offsetof(type, member)))
113 
119 #define LLIST_FOREACH(list, node) \
120  for (LList node = llist_head (list); \
121  ! llist_is_end (node, list); \
122  llist_forward (&node))
123 
129 #define LLIST_FOREACH_REV(list, node) \
130  for (LList node = llist_tail (list); \
131  ! llist_is_end (node, list); \
132  llist_backward (&node))
133 
134 
141 #define LLIST_FORRANGE(start, end, node) \
142  for (LList node = start; \
143  node != end; \
144  llist_forward (&node))
145 
152 #define LLIST_FORRANGE_REV(rstart, rend, node) \
153  for (LList node = rstart; \
154  node != rend; \
155  llist_backward (&node))
156 
157 
164 #define LLIST_WHILE_HEAD(list, head) \
165  for (LList head = llist_head (list); \
166  !llist_is_empty (list); \
167  head = llist_head (list))
168 
175 #define LLIST_WHILE_TAIL(list, tail) \
176  for (LList tail = llist_tail (list); \
177  !llist_is_empty (list); \
178  tail = llist_tail (list))
179 
186 LLIST_FUNC (LList llist_init (LList self),
187  return self->next = self->prev = self;
188 );
189 
193 LLIST_FUNC (int llist_is_empty (const_LList self),
194  return self->next == self;
195 );
196 
201 LLIST_FUNC (int llist_is_single (const_LList self),
202  return self->next->next == self;
203 );
204 
210 LLIST_FUNC (int llist_is_head (const_LList self, const_LList head),
211  return self->next == head;
212 );
213 
219 LLIST_FUNC (int llist_is_tail (const_LList self, const_LList tail),
220  return self->prev == tail;
221 );
222 
229 LLIST_FUNC (int llist_is_end (const_LList self, const_LList end),
230  return self == end;
231 );
232 
238 LLIST_FUNC (int llist_is_member (const_LList self, const_LList member),
239  for (const_LList i = member->next; i != member; i = i->next)
240  {
241  if (i == self)
242  return 1;
243  }
244  return 0;
245 );
246 
253 LLIST_FUNC (int llist_is_before_after (const_LList self, const_LList before, const_LList after),
254  for (const_LList i = before->next; i != self; i = i->next)
255  {
256  if (i == after)
257  return 1;
258  }
259  return 0;
260 );
261 
267 LLIST_FUNC (unsigned llist_count (const_LList self),
268  unsigned cnt = 0;
269  const_LList i = self;
270  for (; i->next != self; ++cnt, i = i->next);
271  return cnt;
272 );
273 
274 /* private, unlink self some any list but leaves self in a uninitialised state */
275 LLIST_FUNC (void llist_unlink_fast_ (LList self),
276  LList nxt = self->next, pre = self->prev;
277  nxt->prev = pre;
278  pre->next = nxt;
279 );
280 
286 LLIST_FUNC (LList llist_unlink (LList self),
287  llist_unlink_fast_ (self);
288  return self->next = self->prev = self;
289 );
290 
300 LLIST_FUNC (LList llist_relocate (LList self),
301  return self->next->prev = self->prev->next = self;
302 );
303 
304 
311 LLIST_FUNC (LList llist_insert_next (LList self, LList next),
312  llist_unlink_fast_ (next);
313  self->next->prev = next;
314  next->prev = self;
315  next->next = self->next;
316  self->next = next;
317  return self;
318 );
319 
326 LLIST_FUNC (LList llist_insert_prev (LList self, LList prev),
327  llist_unlink_fast_ (prev);
328  self->prev->next = prev;
329  prev->next = self;
330  prev->prev = self->prev;
331  self->prev = prev;
332  return self;
333 );
334 
335 
343 LLIST_FUNC (LList llist_insertlist_next (LList self, LList next),
344  if (!llist_is_empty (next))
345  {
346  self->next->prev = next->prev;
347  next->prev->next = self->next;
348  self->next = next->next;
349  next->next->prev = self;
350 
351  next->prev = next->next = next;
352  }
353  return self;
354 );
355 
363 LLIST_FUNC (LList llist_insertlist_prev (LList self, LList prev),
364  if (!llist_is_empty (prev))
365  {
366  self->prev->next = prev->next;
367  prev->next->prev = self->prev;
368  self->prev = prev->prev;
369  prev->prev->next = self;
370 
371  prev->prev = prev->next = prev;
372  }
373  return self;
374 );
375 
376 #if 0 //BUG("needs temporary")
377 
383 LLIST_FUNC (LList llist_insertafter_range (LList self, LList start, LList end),
384  self->next->prev = end->prev;
385  end->prev->next = self->next;
386  end->prev = start->prev;
387  start->prev->next = end;
388  self->next = start;
389  start->prev = self;
390  return self;
391 );
392 #endif
393 
394 #if 0 //BUG("needs temporary")
395 
401 LLIST_FUNC (LList llist_inserbefore_range (LList self, LList start, LList end),
402  self->prev->next = start;
403  start->prev->next = end;
404  end->prev = start->prev;
405  start->prev = self->prev;
406  self->prev = end->prev;
407  end->prev->next = self;
408  return self;
409 );
410 #endif
411 
418 LLIST_FUNC (LList llist_advance (LList self),
419  LList tmp = self->next->next;
420  tmp->prev = self;
421  self->next->prev = self->prev;
422  self->prev->next = self->next;
423  self->prev = self->next;
424  self->next->next = self;
425  self->next = tmp;
426  return self;
427 );
428 
435 LLIST_FUNC (LList llist_retreat (LList self),
436  LList tmp = self->prev->prev;
437  tmp->next = self;
438  self->prev->next = self->next;
439  self->next->prev = self->prev;
440  self->next = self->prev;
441  self->prev->prev = self;
442  self->prev = tmp;
443  return self;
444 );
445 
446 
453 LLIST_FUNC (LList llist_next (const_LList self),
454  return self->next;
455 );
456 
463 LLIST_FUNC (LList llist_prev (const_LList self),
464  return self->prev;
465 );
466 
472 LLIST_FUNC (void llist_forward (LList_ref self),
473  *self = (*self)->next;
474 );
475 
481 LLIST_FUNC (void llist_backward (LList_ref self),
482  *self = (*self)->prev;
483 );
484 
491 LLIST_FUNC (LList llist_nth (LList self, int n),
492  if (n>0)
493  while (n--)
494  self = llist_next (self);
495  else
496  while (n++)
497  self = llist_prev (self);
498  return self;
499 );
500 
507 LLIST_FUNC (LList llist_get_nth_stop (LList self, int n, const_LList stop),
508  if (n>0)
509  while (n--)
510  {
511  self = llist_next (self);
512  if (self == stop)
513  return NULL;
514  }
515  else
516  while (n++)
517  {
518  self = llist_prev (self);
519  if (self == stop)
520  return NULL;
521  }
522  return self;
523 );
524 
525 
535 typedef int (*llist_cmpfn)(const_LList a, const_LList b, void* extra);
536 
537 
545 LLIST_FUNC (LList llist_sort (LList self, llist_cmpfn cmp, void* extra),
546  llist left;
547  llist right;
548  llist_init (&left);
549  llist_init (&right);
550  unsigned n = 0;
551  if (!llist_is_single (self))
552  {
553  LLIST_WHILE_HEAD (self, head)
554  llist_insert_prev (++n & 1 ? &left : &right, head);
555 
556  llist_sort (&left, cmp, extra);
557  llist_sort (&right, cmp, extra);
558 
559  while (!llist_is_empty (&left) && !llist_is_empty (&right))
560  llist_insert_prev (self, cmp (left.next, right.next, extra) < 0 ? left.next : right.next);
561 
562  if (!llist_is_empty (&left))
563  llist_insertlist_prev (self, &left);
564  if (!llist_is_empty (&right))
565  llist_insertlist_prev (self, &right);
566  }
567  return self;
568 )
569 
570 
580 LLIST_FUNC (LList llist_find (const_LList self, const_LList templ, llist_cmpfn cmp, void* extra),
581  LLIST_FOREACH(self, node)
582  {
583  if (!cmp (node, templ, extra))
584  return node;
585  }
586  return NULL;
587 )
588 
589 
599 LLIST_FUNC (LList llist_ufind (LList self, const_LList templ, llist_cmpfn cmp, void* extra),
600  LLIST_FOREACH(self, node)
601  {
602  if (!cmp (node, templ, extra))
603  {
604  if (llist_next(self) != node)
605  llist_insert_next (self, node);
606  return node;
607  }
608  }
609  return NULL;
610 )
611 
612 
622 LLIST_FUNC (LList llist_sfind (const_LList self, const_LList templ, llist_cmpfn cmp, void* extra),
623  LLIST_FOREACH(self, node)
624  {
625  int c = cmp (node, templ, extra);
626  if (!c)
627  return node;
628  else if (c>0)
629  break;
630  }
631  return NULL;
632 )
633 
634 
635 
636 #endif /* LLIST_H */
637 /*
638 // Local Variables:
639 // mode: C
640 // c-file-style: "gnu"
641 // indent-tabs-mode: nil
642 // End:
643 */
int(* llist_cmpfn)(const_LList a, const_LList b, void *extra)
The comparison function function type.
Definition: llist.h:535
#define LLIST_FOREACH(list, node)
Iterate forward over a list.
Definition: llist.h:119
LLIST_FUNC(LList llist_init(LList self), return self->next=self->prev=self;)
Initialise a new llist.
#define LLIST_WHILE_HEAD(list, head)
Consume a list from head.
Definition: llist.h:164