utlist.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2007-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10 
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
12 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
13 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
15 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 */
23 
37 #ifndef UTLIST_H
38 #define UTLIST_H
39 
41 #define UTLIST_VERSION 1.9.9
42 #include <stddef.h>
43 
44 #include <assert.h>
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /*
51  * This file contains macros to manipulate singly and doubly-linked lists.
52  *
53  * 1. LL_ macros: singly-linked lists.
54  * 2. DL_ macros: doubly-linked lists.
55  * 3. CDL_ macros: circular doubly-linked lists.
56  *
57  * To use singly-linked lists, your structure must have a "next" pointer.
58  * To use doubly-linked lists, your structure must "prev" and "next" pointers.
59  * Either way, the pointer to the head of the list must be initialized to NULL.
60  *
61  * ----------------.EXAMPLE -------------------------
62  * struct item {
63  * int id;
64  * struct item *prev, *next;
65  * }
66  *
67  * struct item *list = NULL:
68  *
69  * int main() {
70  * struct item *item;
71  * ... allocate and populate item ...
72  * DL_APPEND(list, item);
73  * }
74  * --------------------------------------------------
75  *
76  * For doubly-linked lists, the append and delete macros are O(1)
77  * For singly-linked lists, append and delete are O(n) but prepend is O(1)
78  * The sort macro is O(n log(n)) for all types of single/double/circular lists.
79  */
80 
94 #ifdef _MSC_VER /* MS compiler */
95 #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
96 #define LDECLTYPE(x) decltype(x)
97 #else /* VS2008 or older (or VS2010 in C mode) */
98 #define NO_DECLTYPE
99 #define LDECLTYPE(x) char*
100 #endif
101 #elif defined(__ICCARM__)
102 #define NO_DECLTYPE
103 #define LDECLTYPE(x) char*
104 #else /* GNU, Sun and other compilers */
105 #define LDECLTYPE(x) __typeof(x)
106 #endif
107 
108 #ifdef NO_DECLTYPE
109 #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
110 #define _NEXT(elt,list,next) ((char*)((list)->next))
111 #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
112 /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
113 #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
114 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
115 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
116 #else
117 #define _SV(elt,list)
118 #define _NEXT(elt,list,next) ((elt)->next)
119 #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
120 /* #define _PREV(elt,list,prev) ((elt)->prev) */
121 #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
122 #define _RS(list)
123 #define _CASTASGN(a,b) (a)=(b)
124 #endif
134 #define LL_SORT(list, cmp) \
135  LL_SORT2(list, cmp, next)
136 
137 #define LL_SORT2(list, cmp, next) \
138 do { \
139  LDECLTYPE(list) _ls_p; \
140  LDECLTYPE(list) _ls_q; \
141  LDECLTYPE(list) _ls_e; \
142  LDECLTYPE(list) _ls_tail; \
143  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
144  if (list) { \
145  _ls_insize = 1; \
146  _ls_looping = 1; \
147  while (_ls_looping) { \
148  _CASTASGN(_ls_p,list); \
149  list = NULL; \
150  _ls_tail = NULL; \
151  _ls_nmerges = 0; \
152  while (_ls_p) { \
153  _ls_nmerges++; \
154  _ls_q = _ls_p; \
155  _ls_psize = 0; \
156  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
157  _ls_psize++; \
158  _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
159  if (!_ls_q) break; \
160  } \
161  _ls_qsize = _ls_insize; \
162  while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
163  if (_ls_psize == 0) { \
164  _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
165  _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
166  } else if (_ls_qsize == 0 || !_ls_q) { \
167  _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
168  _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
169  } else if (cmp(_ls_p,_ls_q) <= 0) { \
170  _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
171  _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
172  } else { \
173  _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
174  _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
175  } \
176  if (_ls_tail) { \
177  _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
178  } else { \
179  _CASTASGN(list,_ls_e); \
180  } \
181  _ls_tail = _ls_e; \
182  } \
183  _ls_p = _ls_q; \
184  } \
185  if (_ls_tail) { \
186  _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
187  } \
188  if (_ls_nmerges <= 1) { \
189  _ls_looping=0; \
190  } \
191  _ls_insize *= 2; \
192  } \
193  } \
194 } while (0)
195 
196 #define DL_SORT(list, cmp) \
197  DL_SORT2(list, cmp, prev, next)
198 
199 #define DL_SORT2(list, cmp, prev, next) \
200 do { \
201  LDECLTYPE(list) _ls_p; \
202  LDECLTYPE(list) _ls_q; \
203  LDECLTYPE(list) _ls_e; \
204  LDECLTYPE(list) _ls_tail; \
205  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
206  if (list) { \
207  _ls_insize = 1; \
208  _ls_looping = 1; \
209  while (_ls_looping) { \
210  _CASTASGN(_ls_p,list); \
211  list = NULL; \
212  _ls_tail = NULL; \
213  _ls_nmerges = 0; \
214  while (_ls_p) { \
215  _ls_nmerges++; \
216  _ls_q = _ls_p; \
217  _ls_psize = 0; \
218  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
219  _ls_psize++; \
220  _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
221  if (!_ls_q) break; \
222  } \
223  _ls_qsize = _ls_insize; \
224  while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
225  if (_ls_psize == 0) { \
226  _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
227  _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
228  } else if (_ls_qsize == 0 || !_ls_q) { \
229  _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
230  _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
231  } else if (cmp(_ls_p,_ls_q) <= 0) { \
232  _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
233  _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
234  } else { \
235  _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
236  _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
237  } \
238  if (_ls_tail) { \
239  _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
240  } else { \
241  _CASTASGN(list,_ls_e); \
242  } \
243  _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
244  _ls_tail = _ls_e; \
245  } \
246  _ls_p = _ls_q; \
247  } \
248  _CASTASGN(list->prev, _ls_tail); \
249  _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
250  if (_ls_nmerges <= 1) { \
251  _ls_looping=0; \
252  } \
253  _ls_insize *= 2; \
254  } \
255  } \
256 } while (0)
257 
258 #define CDL_SORT(list, cmp) \
259  CDL_SORT2(list, cmp, prev, next)
260 
261 #define CDL_SORT2(list, cmp, prev, next) \
262 do { \
263  LDECLTYPE(list) _ls_p; \
264  LDECLTYPE(list) _ls_q; \
265  LDECLTYPE(list) _ls_e; \
266  LDECLTYPE(list) _ls_tail; \
267  LDECLTYPE(list) _ls_oldhead; \
268  LDECLTYPE(list) _tmp; \
269  int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
270  if (list) { \
271  _ls_insize = 1; \
272  _ls_looping = 1; \
273  while (_ls_looping) { \
274  _CASTASGN(_ls_p,list); \
275  _CASTASGN(_ls_oldhead,list); \
276  list = NULL; \
277  _ls_tail = NULL; \
278  _ls_nmerges = 0; \
279  while (_ls_p) { \
280  _ls_nmerges++; \
281  _ls_q = _ls_p; \
282  _ls_psize = 0; \
283  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
284  _ls_psize++; \
285  _SV(_ls_q,list); \
286  if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
287  _ls_q = NULL; \
288  } else { \
289  _ls_q = _NEXT(_ls_q,list,next); \
290  } \
291  _RS(list); \
292  if (!_ls_q) break; \
293  } \
294  _ls_qsize = _ls_insize; \
295  while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
296  if (_ls_psize == 0) { \
297  _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
298  _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
299  if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
300  } else if (_ls_qsize == 0 || !_ls_q) { \
301  _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
302  _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
303  if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
304  } else if (cmp(_ls_p,_ls_q) <= 0) { \
305  _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
306  _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
307  if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
308  } else { \
309  _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
310  _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
311  if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
312  } \
313  if (_ls_tail) { \
314  _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
315  } else { \
316  _CASTASGN(list,_ls_e); \
317  } \
318  _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
319  _ls_tail = _ls_e; \
320  } \
321  _ls_p = _ls_q; \
322  } \
323  _CASTASGN(list->prev,_ls_tail); \
324  _CASTASGN(_tmp,list); \
325  _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
326  if (_ls_nmerges <= 1) { \
327  _ls_looping=0; \
328  } \
329  _ls_insize *= 2; \
330  } \
331  } \
332 } while (0)
340 #define LL_PREPEND(head,add) \
341  LL_PREPEND2(head,add,next)
342 
344 #define LL_PREPEND2(head,add,next) \
345 do { \
346  (add)->next = head; \
347  head = add; \
348 } while (0)
349 
351 #define LL_CONCAT(head1,head2) \
352  LL_CONCAT2(head1,head2,next)
353 
355 #define LL_CONCAT2(head1,head2,next) \
356 do { \
357  LDECLTYPE(head1) _tmp; \
358  if (head1) { \
359  _tmp = head1; \
360  while (_tmp->next) { _tmp = _tmp->next; } \
361  _tmp->next=(head2); \
362  } else { \
363  (head1)=(head2); \
364  } \
365 } while (0)
366 
368 #define LL_APPEND(head,add) \
369  LL_APPEND2(head,add,next)
370 
372 #define LL_APPEND2(head,add,next) \
373 do { \
374  LDECLTYPE(head) _tmp; \
375  (add)->next=NULL; \
376  if (head) { \
377  _tmp = head; \
378  while (_tmp->next) { _tmp = _tmp->next; } \
379  _tmp->next=(add); \
380  } else { \
381  (head)=(add); \
382  } \
383 } while (0)
384 
386 #define LL_DELETE(head,del) \
387  LL_DELETE2(head,del,next)
388 
390 #define LL_DELETE2(head,del,next) \
391 do { \
392  LDECLTYPE(head) _tmp; \
393  if ((head) == (del)) { \
394  (head)=(head)->next; \
395  } else { \
396  _tmp = head; \
397  while (_tmp->next && (_tmp->next != (del))) { \
398  _tmp = _tmp->next; \
399  } \
400  if (_tmp->next) { \
401  _tmp->next = ((del)->next); \
402  } \
403  } \
404 } while (0)
405 
406 /* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
407 #define LL_APPEND_VS2008(head,add) \
408  LL_APPEND2_VS2008(head,add,next)
409 
410 #define LL_APPEND2_VS2008(head,add,next) \
411 do { \
412  if (head) { \
413  (add)->next = head; /* use add->next as a temp variable */ \
414  while ((add)->next->next) { (add)->next = (add)->next->next; } \
415  (add)->next->next=(add); \
416  } else { \
417  (head)=(add); \
418  } \
419  (add)->next=NULL; \
420 } while (0)
421 
422 #define LL_DELETE_VS2008(head,del) \
423  LL_DELETE2_VS2008(head,del,next)
424 
425 #define LL_DELETE2_VS2008(head,del,next) \
426 do { \
427  if ((head) == (del)) { \
428  (head)=(head)->next; \
429  } else { \
430  char *_tmp = (char*)(head); \
431  while ((head)->next && ((head)->next != (del))) { \
432  head = (head)->next; \
433  } \
434  if ((head)->next) { \
435  (head)->next = ((del)->next); \
436  } \
437  { \
438  char **_head_alias = (char**)&(head); \
439  *_head_alias = _tmp; \
440  } \
441  } \
442 } while (0)
443 #ifdef NO_DECLTYPE
444 #undef LL_APPEND
445 #define LL_APPEND LL_APPEND_VS2008
446 #undef LL_DELETE
447 #define LL_DELETE LL_DELETE_VS2008
448 #undef LL_DELETE2
449 #define LL_DELETE2 LL_DELETE2_VS2008
450 #undef LL_APPEND2
451 #define LL_APPEND2 LL_APPEND2_VS2008
452 #undef LL_CONCAT /* no LL_CONCAT_VS2008 */
453 #undef DL_CONCAT /* no DL_CONCAT_VS2008 */
454 #endif
455 /* end VS2008 replacements */
456 
458 #define LL_COUNT(head,el,counter) \
459  LL_COUNT2(head,el,counter,next) \
460 
462 #define LL_COUNT2(head,el,counter,next) \
463 { \
464  counter = 0; \
465  LL_FOREACH2(head,el,next){ ++counter; } \
466 }
467 
469 #define LL_FOREACH(head,el) \
470  LL_FOREACH2(head,el,next)
471 
473 #define LL_FOREACH2(head,el,next) \
474  for(el=head;el;el=(el)->next)
475 
480 #define LL_FOREACH_SAFE(head,el,tmp) \
481  LL_FOREACH_SAFE2(head,el,tmp,next)
482 
484 #define LL_FOREACH_SAFE2(head,el,tmp,next) \
485  for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
486 
488 #define LL_SEARCH_SCALAR(head,out,field,val) \
489  LL_SEARCH_SCALAR2(head,out,field,val,next)
490 
492 #define LL_SEARCH_SCALAR2(head,out,field,val,next) \
493 do { \
494  LL_FOREACH2(head,out,next) { \
495  if ((out)->field == (val)) break; \
496  } \
497 } while(0)
498 
500 #define LL_SEARCH(head,out,elt,cmp) \
501  LL_SEARCH2(head,out,elt,cmp,next)
502 
504 #define LL_SEARCH2(head,out,elt,cmp,next) \
505 do { \
506  LL_FOREACH2(head,out,next) { \
507  if ((cmp(out,elt))==0) break; \
508  } \
509 } while(0)
510 
512 #define LL_REPLACE_ELEM(head, el, add) \
513 do { \
514  LDECLTYPE(head) _tmp; \
515  assert(head != NULL); \
516  assert(el != NULL); \
517  assert(add != NULL); \
518  (add)->next = (el)->next; \
519  if ((head) == (el)) { \
520  (head) = (add); \
521  } else { \
522  _tmp = head; \
523  while (_tmp->next && (_tmp->next != (el))) { \
524  _tmp = _tmp->next; \
525  } \
526  if (_tmp->next) { \
527  _tmp->next = (add); \
528  } \
529  } \
530 } while (0)
531 
533 #define LL_PREPEND_ELEM(head, el, add) \
534 do { \
535  LDECLTYPE(head) _tmp; \
536  assert(head != NULL); \
537  assert(el != NULL); \
538  assert(add != NULL); \
539  (add)->next = (el); \
540  if ((head) == (el)) { \
541  (head) = (add); \
542  } else { \
543  _tmp = head; \
544  while (_tmp->next && (_tmp->next != (el))) { \
545  _tmp = _tmp->next; \
546  } \
547  if (_tmp->next) { \
548  _tmp->next = (add); \
549  } \
550  } \
551 } while (0)
559 #define DL_PREPEND(head,add) \
560  DL_PREPEND2(head,add,prev,next)
561 
563 #define DL_PREPEND2(head,add,prev,next) \
564 do { \
565  (add)->next = head; \
566  if (head) { \
567  (add)->prev = (head)->prev; \
568  (head)->prev = (add); \
569  } else { \
570  (add)->prev = (add); \
571  } \
572  (head) = (add); \
573 } while (0)
574 
576 #define DL_APPEND(head,add) \
577  DL_APPEND2(head,add,prev,next)
578 
580 #define DL_APPEND2(head,add,prev,next) \
581 do { \
582  if (head) { \
583  (add)->prev = (head)->prev; \
584  (head)->prev->next = (add); \
585  (head)->prev = (add); \
586  (add)->next = NULL; \
587  } else { \
588  (head)=(add); \
589  (head)->prev = (head); \
590  (head)->next = NULL; \
591  } \
592 } while (0)
593 
595 #define DL_CONCAT(head1,head2) \
596  DL_CONCAT2(head1,head2,prev,next)
597 
599 #define DL_CONCAT2(head1,head2,prev,next) \
600 do { \
601  LDECLTYPE(head1) _tmp; \
602  if (head2) { \
603  if (head1) { \
604  _tmp = (head2)->prev; \
605  (head2)->prev = (head1)->prev; \
606  (head1)->prev->next = (head2); \
607  (head1)->prev = _tmp; \
608  } else { \
609  (head1)=(head2); \
610  } \
611  } \
612 } while (0)
613 
615 #define DL_DELETE(head,del) \
616  DL_DELETE2(head,del,prev,next)
617 
619 #define DL_DELETE2(head,del,prev,next) \
620 do { \
621  assert((del)->prev != NULL); \
622  if ((del)->prev == (del)) { \
623  (head)=NULL; \
624  } else if ((del)==(head)) { \
625  (del)->next->prev = (del)->prev; \
626  (head) = (del)->next; \
627  } else { \
628  (del)->prev->next = (del)->next; \
629  if ((del)->next) { \
630  (del)->next->prev = (del)->prev; \
631  } else { \
632  (head)->prev = (del)->prev; \
633  } \
634  } \
635 } while (0)
636 
638 #define DL_COUNT(head,el,counter) \
639  DL_COUNT2(head,el,counter,next) \
640 
642 #define DL_COUNT2(head,el,counter,next) \
643 { \
644  counter = 0; \
645  DL_FOREACH2(head,el,next){ ++counter; } \
646 }
647 
649 #define DL_FOREACH(head,el) \
650  DL_FOREACH2(head,el,next)
651 
653 #define DL_FOREACH2(head,el,next) \
654  for(el=head;el;el=(el)->next)
655 
660 #define DL_FOREACH_SAFE(head,el,tmp) \
661  DL_FOREACH_SAFE2(head,el,tmp,next)
662 
664 #define DL_FOREACH_SAFE2(head,el,tmp,next) \
665  for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
666 
671 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
672 
677 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
678 
683 #define DL_SEARCH LL_SEARCH
684 
689 #define DL_SEARCH2 LL_SEARCH2
690 
692 #define DL_REPLACE_ELEM(head, el, add) \
693 do { \
694  assert(head != NULL); \
695  assert(el != NULL); \
696  assert(add != NULL); \
697  if ((head) == (el)) { \
698  (head) = (add); \
699  (add)->next = (el)->next; \
700  if ((el)->next == NULL) { \
701  (add)->prev = (add); \
702  } else { \
703  (add)->prev = (el)->prev; \
704  (add)->next->prev = (add); \
705  } \
706  } else { \
707  (add)->next = (el)->next; \
708  (add)->prev = (el)->prev; \
709  (add)->prev->next = (add); \
710  if ((el)->next == NULL) { \
711  (head)->prev = (add); \
712  } else { \
713  (add)->next->prev = (add); \
714  } \
715  } \
716 } while (0)
717 
719 #define DL_PREPEND_ELEM(head, el, add) \
720 do { \
721  assert(head != NULL); \
722  assert(el != NULL); \
723  assert(add != NULL); \
724  (add)->next = (el); \
725  (add)->prev = (el)->prev; \
726  (el)->prev = (add); \
727  if ((head) == (el)) { \
728  (head) = (add); \
729  } else { \
730  (add)->prev->next = (add); \
731  } \
732 } while (0)
740 #define CDL_PREPEND(head,add) \
741  CDL_PREPEND2(head,add,prev,next)
742 
744 #define CDL_PREPEND2(head,add,prev,next) \
745 do { \
746  if (head) { \
747  (add)->prev = (head)->prev; \
748  (add)->next = (head); \
749  (head)->prev = (add); \
750  (add)->prev->next = (add); \
751  } else { \
752  (add)->prev = (add); \
753  (add)->next = (add); \
754  } \
755 (head)=(add); \
756 } while (0)
757 
759 #define CDL_DELETE(head,del) \
760  CDL_DELETE2(head,del,prev,next)
761 
763 #define CDL_DELETE2(head,del,prev,next) \
764 do { \
765  if ( ((head)==(del)) && ((head)->next == (head))) { \
766  (head) = 0L; \
767  } else { \
768  (del)->next->prev = (del)->prev; \
769  (del)->prev->next = (del)->next; \
770  if ((del) == (head)) (head)=(del)->next; \
771  } \
772 } while (0)
773 
775 #define CDL_COUNT(head,el,counter) \
776  CDL_COUNT2(head,el,counter,next) \
777 
779 #define CDL_COUNT2(head, el, counter,next) \
780 { \
781  counter = 0; \
782  CDL_FOREACH2(head,el,next){ ++counter; } \
783 }
784 
786 #define CDL_FOREACH(head,el) \
787  CDL_FOREACH2(head,el,next)
788 
790 #define CDL_FOREACH2(head,el,next) \
791  for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
792 
797 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
798  CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
799 
801 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
802  for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
803  (el) && ((tmp2)=(el)->next, 1); \
804  ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
805 
807 #define CDL_SEARCH_SCALAR(head,out,field,val) \
808  CDL_SEARCH_SCALAR2(head,out,field,val,next)
809 
811 #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
812 do { \
813  CDL_FOREACH2(head,out,next) { \
814  if ((out)->field == (val)) break; \
815  } \
816 } while(0)
817 
819 #define CDL_SEARCH(head,out,elt,cmp) \
820  CDL_SEARCH2(head,out,elt,cmp,next)
821 
823 #define CDL_SEARCH2(head,out,elt,cmp,next) \
824 do { \
825  CDL_FOREACH2(head,out,next) { \
826  if ((cmp(out,elt))==0) break; \
827  } \
828 } while(0)
829 
831 #define CDL_REPLACE_ELEM(head, el, add) \
832 do { \
833  assert(head != NULL); \
834  assert(el != NULL); \
835  assert(add != NULL); \
836  if ((el)->next == (el)) { \
837  (add)->next = (add); \
838  (add)->prev = (add); \
839  (head) = (add); \
840  } else { \
841  (add)->next = (el)->next; \
842  (add)->prev = (el)->prev; \
843  (add)->next->prev = (add); \
844  (add)->prev->next = (add); \
845  if ((head) == (el)) { \
846  (head) = (add); \
847  } \
848  } \
849 } while (0)
850 
852 #define CDL_PREPEND_ELEM(head, el, add) \
853 do { \
854  assert(head != NULL); \
855  assert(el != NULL); \
856  assert(add != NULL); \
857  (add)->next = (el); \
858  (add)->prev = (el)->prev; \
859  (el)->prev = (add); \
860  (add)->prev->next = (add); \
861  if ((head) == (el)) { \
862  (head) = (add); \
863  } \
864 } while (0)
867 #ifdef __cplusplus
868 }
869 #endif
870 
871 #endif /* UTLIST_H */
POSIX.1-2008 compliant version of the assert macro.