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  Copyright (C) Lumiera.org
7  2008, Christian Thaeter <ct@pipapo.org>
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of
12  the License, or (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23 
24 #ifndef LLIST_H
25 #define LLIST_H
26 
27 #include <stddef.h>
28 
52 /* TODO __STDC_VERSION__ 199901L
53 150) This macro was not specified in ISO/IEC 9899:1990 and was specified as 199409L in
54 ISO/IEC 9899/AMD1:1995. The intention is that this will remain an integer constant of type long
55 int that is increased with each revision of this International Standard.
56 */
57 #ifdef HAVE_INLINE
58 # define LLIST_MACRO static inline
59 #else
60 # ifdef __GNUC__
61 # define LLIST_MACRO static __inline__
62 # else
63 # define LLIST_MACRO static
64 # endif
65 #endif
66 
67 #if defined(LLIST_INTERFACE)
68 /* only the interface is generated */
69 #define LLIST_FUNC(proto, ...) proto
70 #elif defined(LLIST_IMPLEMENTATION)
71 /* generate a non inlined implementation */
72 #define LLIST_FUNC(proto, ...) proto { __VA_ARGS__ }
73 #else
74 /* all functions are macro-like inlined */
75 #define LLIST_FUNC(proto, ...) LLIST_MACRO proto { __VA_ARGS__ }
76 #endif
77 
78 
79 /*
80  * Type of a llist node.
81  */
82 #ifndef LLIST_DEFINED
83 #define LLIST_DEFINED
85 {
86  struct llist_struct *next;
87  struct llist_struct *prev;
88 };
89 #endif
90 typedef struct llist_struct llist;
91 typedef llist * LList;
92 typedef const llist * const_LList;
93 typedef llist ** LList_ref;
94 
99 #define LLIST_AUTO(name) llist name = {&name,&name}
100 
101 
102 /*
103  some macros for convenience
104 */
105 #define llist_insert_head(list, element) llist_insert_next (list, element)
106 #define llist_insert_tail(list, element) llist_insert_prev (list, element)
107 #define llist_head llist_next
108 #define llist_tail llist_prev
109 
113 /* example:
114  struct foo
115  {
116  int bar;
117  llist l;
118  } x;
119  LLIST_TO_STRUCTP (&x.l, foo, l)->bar
120 */
121 #define LLIST_TO_STRUCTP(llist, type, member) \
122  ((type*)(((char*)(llist)) - offsetof(type, member)))
123 
129 #define LLIST_FOREACH(list, node) \
130  for (LList node = llist_head (list); \
131  ! llist_is_end (node, list); \
132  llist_forward (&node))
133 
139 #define LLIST_FOREACH_REV(list, node) \
140  for (LList node = llist_tail (list); \
141  ! llist_is_end (node, list); \
142  llist_backward (&node))
143 
144 
151 #define LLIST_FORRANGE(start, end, node) \
152  for (LList node = start; \
153  node != end; \
154  llist_forward (&node))
155 
162 #define LLIST_FORRANGE_REV(rstart, rend, node) \
163  for (LList node = rstart; \
164  node != rend; \
165  llist_backward (&node))
166 
167 
174 #define LLIST_WHILE_HEAD(list, head) \
175  for (LList head = llist_head (list); \
176  !llist_is_empty (list); \
177  head = llist_head (list))
178 
185 #define LLIST_WHILE_TAIL(list, tail) \
186  for (LList tail = llist_tail (list); \
187  !llist_is_empty (list); \
188  tail = llist_tail (list))
189 
196 LLIST_FUNC (LList llist_init (LList self),
197  return self->next = self->prev = self;
198 );
199 
203 LLIST_FUNC (int llist_is_empty (const_LList self),
204  return self->next == self;
205 );
206 
211 LLIST_FUNC (int llist_is_single (const_LList self),
212  return self->next->next == self;
213 );
214 
220 LLIST_FUNC (int llist_is_head (const_LList self, const_LList head),
221  return self->next == head;
222 );
223 
229 LLIST_FUNC (int llist_is_tail (const_LList self, const_LList tail),
230  return self->prev == tail;
231 );
232 
239 LLIST_FUNC (int llist_is_end (const_LList self, const_LList end),
240  return self == end;
241 );
242 
248 LLIST_FUNC (int llist_is_member (const_LList self, const_LList member),
249  for (const_LList i = member->next; i != member; i = i->next)
250  {
251  if (i == self)
252  return 1;
253  }
254  return 0;
255 );
256 
263 LLIST_FUNC (int llist_is_before_after (const_LList self, const_LList before, const_LList after),
264  for (const_LList i = before->next; i != self; i = i->next)
265  {
266  if (i == after)
267  return 1;
268  }
269  return 0;
270 );
271 
277 LLIST_FUNC (unsigned llist_count (const_LList self),
278  unsigned cnt = 0;
279  const_LList i = self;
280  for (; i->next != self; ++cnt, i = i->next);
281  return cnt;
282 );
283 
284 /* private, unlink self some any list but leaves self in a uninitialised state */
285 LLIST_FUNC (void llist_unlink_fast_ (LList self),
286  LList nxt = self->next, pre = self->prev;
287  nxt->prev = pre;
288  pre->next = nxt;
289 );
290 
296 LLIST_FUNC (LList llist_unlink (LList self),
297  llist_unlink_fast_ (self);
298  return self->next = self->prev = self;
299 );
300 
310 LLIST_FUNC (LList llist_relocate (LList self),
311  return self->next->prev = self->prev->next = self;
312 );
313 
314 
321 LLIST_FUNC (LList llist_insert_next (LList self, LList next),
322  llist_unlink_fast_ (next);
323  self->next->prev = next;
324  next->prev = self;
325  next->next = self->next;
326  self->next = next;
327  return self;
328 );
329 
336 LLIST_FUNC (LList llist_insert_prev (LList self, LList prev),
337  llist_unlink_fast_ (prev);
338  self->prev->next = prev;
339  prev->next = self;
340  prev->prev = self->prev;
341  self->prev = prev;
342  return self;
343 );
344 
345 
353 LLIST_FUNC (LList llist_insertlist_next (LList self, LList next),
354  if (!llist_is_empty (next))
355  {
356  self->next->prev = next->prev;
357  next->prev->next = self->next;
358  self->next = next->next;
359  next->next->prev = self;
360 
361  next->prev = next->next = next;
362  }
363  return self;
364 );
365 
373 LLIST_FUNC (LList llist_insertlist_prev (LList self, LList prev),
374  if (!llist_is_empty (prev))
375  {
376  self->prev->next = prev->next;
377  prev->next->prev = self->prev;
378  self->prev = prev->prev;
379  prev->prev->next = self;
380 
381  prev->prev = prev->next = prev;
382  }
383  return self;
384 );
385 
386 #if 0 //BUG("needs temporary")
387 
393 LLIST_FUNC (LList llist_insertafter_range (LList self, LList start, LList end),
394  self->next->prev = end->prev;
395  end->prev->next = self->next;
396  end->prev = start->prev;
397  start->prev->next = end;
398  self->next = start;
399  start->prev = self;
400  return self;
401 );
402 #endif
403 
404 #if 0 //BUG("needs temporary")
405 
411 LLIST_FUNC (LList llist_inserbefore_range (LList self, LList start, LList end),
412  self->prev->next = start;
413  start->prev->next = end;
414  end->prev = start->prev;
415  start->prev = self->prev;
416  self->prev = end->prev;
417  end->prev->next = self;
418  return self;
419 );
420 #endif
421 
428 LLIST_FUNC (LList llist_advance (LList self),
429  LList tmp = self->next->next;
430  tmp->prev = self;
431  self->next->prev = self->prev;
432  self->prev->next = self->next;
433  self->prev = self->next;
434  self->next->next = self;
435  self->next = tmp;
436  return self;
437 );
438 
445 LLIST_FUNC (LList llist_retreat (LList self),
446  LList tmp = self->prev->prev;
447  tmp->next = self;
448  self->prev->next = self->next;
449  self->next->prev = self->prev;
450  self->next = self->prev;
451  self->prev->prev = self;
452  self->prev = tmp;
453  return self;
454 );
455 
456 
463 LLIST_FUNC (LList llist_next (const_LList self),
464  return self->next;
465 );
466 
473 LLIST_FUNC (LList llist_prev (const_LList self),
474  return self->prev;
475 );
476 
482 LLIST_FUNC (void llist_forward (LList_ref self),
483  *self = (*self)->next;
484 );
485 
491 LLIST_FUNC (void llist_backward (LList_ref self),
492  *self = (*self)->prev;
493 );
494 
501 LLIST_FUNC (LList llist_nth (LList self, int n),
502  if (n>0)
503  while (n--)
504  self = llist_next (self);
505  else
506  while (n++)
507  self = llist_prev (self);
508  return self;
509 );
510 
517 LLIST_FUNC (LList llist_get_nth_stop (LList self, int n, const_LList stop),
518  if (n>0)
519  while (n--)
520  {
521  self = llist_next (self);
522  if (self == stop)
523  return NULL;
524  }
525  else
526  while (n++)
527  {
528  self = llist_prev (self);
529  if (self == stop)
530  return NULL;
531  }
532  return self;
533 );
534 
535 
545 typedef int (*llist_cmpfn)(const_LList a, const_LList b, void* extra);
546 
547 
555 LLIST_FUNC (LList llist_sort (LList self, llist_cmpfn cmp, void* extra),
556  llist left;
557  llist right;
558  llist_init (&left);
559  llist_init (&right);
560  unsigned n = 0;
561  if (!llist_is_single (self))
562  {
563  LLIST_WHILE_HEAD (self, head)
564  llist_insert_prev (++n & 1 ? &left : &right, head);
565 
566  llist_sort (&left, cmp, extra);
567  llist_sort (&right, cmp, extra);
568 
569  while (!llist_is_empty (&left) && !llist_is_empty (&right))
570  llist_insert_prev (self, cmp (left.next, right.next, extra) < 0 ? left.next : right.next);
571 
572  if (!llist_is_empty (&left))
573  llist_insertlist_prev (self, &left);
574  if (!llist_is_empty (&right))
575  llist_insertlist_prev (self, &right);
576  }
577  return self;
578 )
579 
580 
590 LLIST_FUNC (LList llist_find (const_LList self, const_LList templ, llist_cmpfn cmp, void* extra),
591  LLIST_FOREACH(self, node)
592  {
593  if (!cmp (node, templ, extra))
594  return node;
595  }
596  return NULL;
597 )
598 
599 
609 LLIST_FUNC (LList llist_ufind (LList self, const_LList templ, llist_cmpfn cmp, void* extra),
610  LLIST_FOREACH(self, node)
611  {
612  if (!cmp (node, templ, extra))
613  {
614  if (llist_next(self) != node)
615  llist_insert_next (self, node);
616  return node;
617  }
618  }
619  return NULL;
620 )
621 
622 
632 LLIST_FUNC (LList llist_sfind (const_LList self, const_LList templ, llist_cmpfn cmp, void* extra),
633  LLIST_FOREACH(self, node)
634  {
635  int c = cmp (node, templ, extra);
636  if (!c)
637  return node;
638  else if (c>0)
639  break;
640  }
641  return NULL;
642 )
643 
644 
645 
646 #endif /* LLIST_H */
647 /*
648 // Local Variables:
649 // mode: C
650 // c-file-style: "gnu"
651 // indent-tabs-mode: nil
652 // End:
653 */
int(* llist_cmpfn)(const_LList a, const_LList b, void *extra)
The comparison function function type.
Definition: llist.h:545
#define LLIST_FOREACH(list, node)
Iterate forward over a list.
Definition: llist.h:129
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:174