Go to the documentation of this file.
27 #define UTLIST_VERSION 2.3.0
66 #if !defined(LDECLTYPE) && !defined(NO_DECLTYPE)
68 #if _MSC_VER >= 1600 && defined(__cplusplus)
69 #define LDECLTYPE(x) decltype(x)
73 #elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
76 #define LDECLTYPE(x) __typeof(x)
84 #define IF_NO_DECLTYPE(x) x
85 #define LDECLTYPE(x) char*
86 #define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
87 #define UTLIST_NEXT(elt,list,next) ((char*)((list)->next))
88 #define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
90 #define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
91 #define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
92 #define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
94 #define IF_NO_DECLTYPE(x)
95 #define UTLIST_SV(elt,list)
96 #define UTLIST_NEXT(elt,list,next) ((elt)->next)
97 #define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
99 #define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
100 #define UTLIST_RS(list)
101 #define UTLIST_CASTASGN(a,b) (a)=(b)
108 #define LL_SORT(list, cmp) \
109 LL_SORT2(list, cmp, next)
111 #define LL_SORT2(list, cmp, next) \
113 LDECLTYPE(list) _ls_p; \
114 LDECLTYPE(list) _ls_q; \
115 LDECLTYPE(list) _ls_e; \
116 LDECLTYPE(list) _ls_tail; \
117 IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \
118 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
122 while (_ls_looping) { \
123 UTLIST_CASTASGN(_ls_p,list); \
131 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
133 UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \
136 _ls_qsize = _ls_insize; \
137 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
138 if (_ls_psize == 0) { \
139 _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
140 UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
141 } else if (_ls_qsize == 0 || !_ls_q) { \
142 _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
143 UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
144 } else if (cmp(_ls_p,_ls_q) <= 0) { \
145 _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
146 UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
148 _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
149 UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
152 UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
154 UTLIST_CASTASGN(list,_ls_e); \
161 UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \
163 if (_ls_nmerges <= 1) { \
172 #define DL_SORT(list, cmp) \
173 DL_SORT2(list, cmp, prev, next)
175 #define DL_SORT2(list, cmp, prev, next) \
177 LDECLTYPE(list) _ls_p; \
178 LDECLTYPE(list) _ls_q; \
179 LDECLTYPE(list) _ls_e; \
180 LDECLTYPE(list) _ls_tail; \
181 IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \
182 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
186 while (_ls_looping) { \
187 UTLIST_CASTASGN(_ls_p,list); \
195 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
197 UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \
200 _ls_qsize = _ls_insize; \
201 while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \
202 if (_ls_psize == 0) { \
203 _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
204 UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
205 } else if ((_ls_qsize == 0) || (!_ls_q)) { \
206 _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
207 UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
208 } else if (cmp(_ls_p,_ls_q) <= 0) { \
209 _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
210 UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
212 _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
213 UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
216 UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
218 UTLIST_CASTASGN(list,_ls_e); \
220 UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \
225 UTLIST_CASTASGN((list)->prev, _ls_tail); \
226 UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \
227 if (_ls_nmerges <= 1) { \
235 #define CDL_SORT(list, cmp) \
236 CDL_SORT2(list, cmp, prev, next)
238 #define CDL_SORT2(list, cmp, prev, next) \
240 LDECLTYPE(list) _ls_p; \
241 LDECLTYPE(list) _ls_q; \
242 LDECLTYPE(list) _ls_e; \
243 LDECLTYPE(list) _ls_tail; \
244 LDECLTYPE(list) _ls_oldhead; \
245 LDECLTYPE(list) _tmp; \
246 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
250 while (_ls_looping) { \
251 UTLIST_CASTASGN(_ls_p,list); \
252 UTLIST_CASTASGN(_ls_oldhead,list); \
260 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
262 UTLIST_SV(_ls_q,list); \
263 if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \
266 _ls_q = UTLIST_NEXT(_ls_q,list,next); \
271 _ls_qsize = _ls_insize; \
272 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
273 if (_ls_psize == 0) { \
274 _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
275 UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
276 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
277 } else if (_ls_qsize == 0 || !_ls_q) { \
278 _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
279 UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
280 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
281 } else if (cmp(_ls_p,_ls_q) <= 0) { \
282 _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \
283 UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \
284 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
286 _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
287 UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
288 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
291 UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
293 UTLIST_CASTASGN(list,_ls_e); \
295 UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \
300 UTLIST_CASTASGN((list)->prev,_ls_tail); \
301 UTLIST_CASTASGN(_tmp,list); \
302 UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \
303 if (_ls_nmerges <= 1) { \
314 #define LL_PREPEND(head,add) \
315 LL_PREPEND2(head,add,next)
317 #define LL_PREPEND2(head,add,next) \
319 (add)->next = (head); \
323 #define LL_CONCAT(head1,head2) \
324 LL_CONCAT2(head1,head2,next)
326 #define LL_CONCAT2(head1,head2,next) \
328 LDECLTYPE(head1) _tmp; \
331 while (_tmp->next) { _tmp = _tmp->next; } \
332 _tmp->next=(head2); \
338 #define LL_APPEND(head,add) \
339 LL_APPEND2(head,add,next)
341 #define LL_APPEND2(head,add,next) \
343 LDECLTYPE(head) _tmp; \
347 while (_tmp->next) { _tmp = _tmp->next; } \
354 #define LL_INSERT_INORDER(head,add,cmp) \
355 LL_INSERT_INORDER2(head,add,cmp,next)
357 #define LL_INSERT_INORDER2(head,add,cmp,next) \
359 LDECLTYPE(head) _tmp; \
361 LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \
362 LL_APPEND_ELEM2(head, _tmp, add, next); \
365 (head)->next = NULL; \
369 #define LL_LOWER_BOUND(head,elt,like,cmp) \
370 LL_LOWER_BOUND2(head,elt,like,cmp,next)
372 #define LL_LOWER_BOUND2(head,elt,like,cmp,next) \
374 if ((head) == NULL || (cmp(head, like)) >= 0) { \
377 for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \
378 if (cmp((elt)->next, like) >= 0) { \
385 #define LL_DELETE(head,del) \
386 LL_DELETE2(head,del,next)
388 #define LL_DELETE2(head,del,next) \
390 LDECLTYPE(head) _tmp; \
391 if ((head) == (del)) { \
392 (head)=(head)->next; \
395 while (_tmp->next && (_tmp->next != (del))) { \
399 _tmp->next = (del)->next; \
404 #define LL_COUNT(head,el,counter) \
405 LL_COUNT2(head,el,counter,next) \
407 #define LL_COUNT2(head,el,counter,next) \
410 LL_FOREACH2(head,el,next) { ++(counter); } \
413 #define LL_FOREACH(head,el) \
414 LL_FOREACH2(head,el,next)
416 #define LL_FOREACH2(head,el,next) \
417 for ((el) = (head); el; (el) = (el)->next)
419 #define LL_FOREACH_SAFE(head,el,tmp) \
420 LL_FOREACH_SAFE2(head,el,tmp,next)
422 #define LL_FOREACH_SAFE2(head,el,tmp,next) \
423 for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
425 #define LL_SEARCH_SCALAR(head,out,field,val) \
426 LL_SEARCH_SCALAR2(head,out,field,val,next)
428 #define LL_SEARCH_SCALAR2(head,out,field,val,next) \
430 LL_FOREACH2(head,out,next) { \
431 if ((out)->field == (val)) break; \
435 #define LL_SEARCH(head,out,elt,cmp) \
436 LL_SEARCH2(head,out,elt,cmp,next)
438 #define LL_SEARCH2(head,out,elt,cmp,next) \
440 LL_FOREACH2(head,out,next) { \
441 if ((cmp(out,elt))==0) break; \
445 #define LL_REPLACE_ELEM2(head, el, add, next) \
447 LDECLTYPE(head) _tmp; \
448 assert((head) != NULL); \
449 assert((el) != NULL); \
450 assert((add) != NULL); \
451 (add)->next = (el)->next; \
452 if ((head) == (el)) { \
456 while (_tmp->next && (_tmp->next != (el))) { \
460 _tmp->next = (add); \
465 #define LL_REPLACE_ELEM(head, el, add) \
466 LL_REPLACE_ELEM2(head, el, add, next)
468 #define LL_PREPEND_ELEM2(head, el, add, next) \
471 LDECLTYPE(head) _tmp; \
472 assert((head) != NULL); \
473 assert((add) != NULL); \
474 (add)->next = (el); \
475 if ((head) == (el)) { \
479 while (_tmp->next && (_tmp->next != (el))) { \
483 _tmp->next = (add); \
487 LL_APPEND2(head, add, next); \
491 #define LL_PREPEND_ELEM(head, el, add) \
492 LL_PREPEND_ELEM2(head, el, add, next)
494 #define LL_APPEND_ELEM2(head, el, add, next) \
497 assert((head) != NULL); \
498 assert((add) != NULL); \
499 (add)->next = (el)->next; \
500 (el)->next = (add); \
502 LL_PREPEND2(head, add, next); \
506 #define LL_APPEND_ELEM(head, el, add) \
507 LL_APPEND_ELEM2(head, el, add, next)
513 #define LL_CONCAT2(head1,head2,next) \
517 _tmp = (char*)(head1); \
518 while ((head1)->next) { (head1) = (head1)->next; } \
519 (head1)->next = (head2); \
527 #define LL_APPEND2(head,add,next) \
530 (add)->next = head; \
531 while ((add)->next->next) { (add)->next = (add)->next->next; } \
532 (add)->next->next=(add); \
539 #undef LL_INSERT_INORDER2
540 #define LL_INSERT_INORDER2(head,add,cmp,next) \
542 if ((head) == NULL || (cmp(head, add)) >= 0) { \
543 (add)->next = (head); \
546 char *_tmp = (char*)(head); \
547 while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \
548 (head) = (head)->next; \
550 (add)->next = (head)->next; \
551 (head)->next = (add); \
557 #define LL_DELETE2(head,del,next) \
559 if ((head) == (del)) { \
560 (head)=(head)->next; \
562 char *_tmp = (char*)(head); \
563 while ((head)->next && ((head)->next != (del))) { \
564 (head) = (head)->next; \
566 if ((head)->next) { \
567 (head)->next = ((del)->next); \
573 #undef LL_REPLACE_ELEM2
574 #define LL_REPLACE_ELEM2(head, el, add, next) \
576 assert((head) != NULL); \
577 assert((el) != NULL); \
578 assert((add) != NULL); \
579 if ((head) == (el)) { \
582 (add)->next = head; \
583 while ((add)->next->next && ((add)->next->next != (el))) { \
584 (add)->next = (add)->next->next; \
586 if ((add)->next->next) { \
587 (add)->next->next = (add); \
590 (add)->next = (el)->next; \
593 #undef LL_PREPEND_ELEM2
594 #define LL_PREPEND_ELEM2(head, el, add, next) \
597 assert((head) != NULL); \
598 assert((add) != NULL); \
599 if ((head) == (el)) { \
602 (add)->next = (head); \
603 while ((add)->next->next && ((add)->next->next != (el))) { \
604 (add)->next = (add)->next->next; \
606 if ((add)->next->next) { \
607 (add)->next->next = (add); \
610 (add)->next = (el); \
612 LL_APPEND2(head, add, next); \
621 #define DL_PREPEND(head,add) \
622 DL_PREPEND2(head,add,prev,next)
624 #define DL_PREPEND2(head,add,prev,next) \
626 (add)->next = (head); \
628 (add)->prev = (head)->prev; \
629 (head)->prev = (add); \
631 (add)->prev = (add); \
636 #define DL_APPEND(head,add) \
637 DL_APPEND2(head,add,prev,next)
639 #define DL_APPEND2(head,add,prev,next) \
642 (add)->prev = (head)->prev; \
643 (head)->prev->next = (add); \
644 (head)->prev = (add); \
645 (add)->next = NULL; \
648 (head)->prev = (head); \
649 (head)->next = NULL; \
653 #define DL_INSERT_INORDER(head,add,cmp) \
654 DL_INSERT_INORDER2(head,add,cmp,prev,next)
656 #define DL_INSERT_INORDER2(head,add,cmp,prev,next) \
658 LDECLTYPE(head) _tmp; \
660 DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \
661 DL_APPEND_ELEM2(head, _tmp, add, prev, next); \
664 (head)->prev = (head); \
665 (head)->next = NULL; \
669 #define DL_LOWER_BOUND(head,elt,like,cmp) \
670 DL_LOWER_BOUND2(head,elt,like,cmp,next)
672 #define DL_LOWER_BOUND2(head,elt,like,cmp,next) \
674 if ((head) == NULL || (cmp(head, like)) >= 0) { \
677 for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \
678 if ((cmp((elt)->next, like)) >= 0) { \
685 #define DL_CONCAT(head1,head2) \
686 DL_CONCAT2(head1,head2,prev,next)
688 #define DL_CONCAT2(head1,head2,prev,next) \
690 LDECLTYPE(head1) _tmp; \
693 UTLIST_CASTASGN(_tmp, (head2)->prev); \
694 (head2)->prev = (head1)->prev; \
695 (head1)->prev->next = (head2); \
696 UTLIST_CASTASGN((head1)->prev, _tmp); \
703 #define DL_DELETE(head,del) \
704 DL_DELETE2(head,del,prev,next)
706 #define DL_DELETE2(head,del,prev,next) \
708 assert((head) != NULL); \
709 assert((del)->prev != NULL); \
710 if ((del)->prev == (del)) { \
712 } else if ((del)==(head)) { \
713 (del)->next->prev = (del)->prev; \
714 (head) = (del)->next; \
716 (del)->prev->next = (del)->next; \
718 (del)->next->prev = (del)->prev; \
720 (head)->prev = (del)->prev; \
725 #define DL_COUNT(head,el,counter) \
726 DL_COUNT2(head,el,counter,next) \
728 #define DL_COUNT2(head,el,counter,next) \
731 DL_FOREACH2(head,el,next) { ++(counter); } \
734 #define DL_FOREACH(head,el) \
735 DL_FOREACH2(head,el,next)
737 #define DL_FOREACH2(head,el,next) \
738 for ((el) = (head); el; (el) = (el)->next)
741 #define DL_FOREACH_SAFE(head,el,tmp) \
742 DL_FOREACH_SAFE2(head,el,tmp,next)
744 #define DL_FOREACH_SAFE2(head,el,tmp,next) \
745 for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
748 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
749 #define DL_SEARCH LL_SEARCH
750 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
751 #define DL_SEARCH2 LL_SEARCH2
753 #define DL_REPLACE_ELEM2(head, el, add, prev, next) \
755 assert((head) != NULL); \
756 assert((el) != NULL); \
757 assert((add) != NULL); \
758 if ((head) == (el)) { \
760 (add)->next = (el)->next; \
761 if ((el)->next == NULL) { \
762 (add)->prev = (add); \
764 (add)->prev = (el)->prev; \
765 (add)->next->prev = (add); \
768 (add)->next = (el)->next; \
769 (add)->prev = (el)->prev; \
770 (add)->prev->next = (add); \
771 if ((el)->next == NULL) { \
772 (head)->prev = (add); \
774 (add)->next->prev = (add); \
779 #define DL_REPLACE_ELEM(head, el, add) \
780 DL_REPLACE_ELEM2(head, el, add, prev, next)
782 #define DL_PREPEND_ELEM2(head, el, add, prev, next) \
785 assert((head) != NULL); \
786 assert((add) != NULL); \
787 (add)->next = (el); \
788 (add)->prev = (el)->prev; \
789 (el)->prev = (add); \
790 if ((head) == (el)) { \
793 (add)->prev->next = (add); \
796 DL_APPEND2(head, add, prev, next); \
800 #define DL_PREPEND_ELEM(head, el, add) \
801 DL_PREPEND_ELEM2(head, el, add, prev, next)
803 #define DL_APPEND_ELEM2(head, el, add, prev, next) \
806 assert((head) != NULL); \
807 assert((add) != NULL); \
808 (add)->next = (el)->next; \
809 (add)->prev = (el); \
810 (el)->next = (add); \
812 (add)->next->prev = (add); \
814 (head)->prev = (add); \
817 DL_PREPEND2(head, add, prev, next); \
821 #define DL_APPEND_ELEM(head, el, add) \
822 DL_APPEND_ELEM2(head, el, add, prev, next)
827 #undef DL_INSERT_INORDER2
828 #define DL_INSERT_INORDER2(head,add,cmp,prev,next) \
830 if ((head) == NULL) { \
831 (add)->prev = (add); \
832 (add)->next = NULL; \
834 } else if ((cmp(head, add)) >= 0) { \
835 (add)->prev = (head)->prev; \
836 (add)->next = (head); \
837 (head)->prev = (add); \
840 char *_tmp = (char*)(head); \
841 while ((head)->next && (cmp((head)->next, add)) < 0) { \
842 (head) = (head)->next; \
844 (add)->prev = (head); \
845 (add)->next = (head)->next; \
846 (head)->next = (add); \
849 (add)->next->prev = (add); \
851 (head)->prev = (add); \
860 #define CDL_APPEND(head,add) \
861 CDL_APPEND2(head,add,prev,next)
863 #define CDL_APPEND2(head,add,prev,next) \
866 (add)->prev = (head)->prev; \
867 (add)->next = (head); \
868 (head)->prev = (add); \
869 (add)->prev->next = (add); \
871 (add)->prev = (add); \
872 (add)->next = (add); \
877 #define CDL_PREPEND(head,add) \
878 CDL_PREPEND2(head,add,prev,next)
880 #define CDL_PREPEND2(head,add,prev,next) \
883 (add)->prev = (head)->prev; \
884 (add)->next = (head); \
885 (head)->prev = (add); \
886 (add)->prev->next = (add); \
888 (add)->prev = (add); \
889 (add)->next = (add); \
894 #define CDL_INSERT_INORDER(head,add,cmp) \
895 CDL_INSERT_INORDER2(head,add,cmp,prev,next)
897 #define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \
899 LDECLTYPE(head) _tmp; \
901 CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \
902 CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \
905 (head)->next = (head); \
906 (head)->prev = (head); \
910 #define CDL_LOWER_BOUND(head,elt,like,cmp) \
911 CDL_LOWER_BOUND2(head,elt,like,cmp,next)
913 #define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \
915 if ((head) == NULL || (cmp(head, like)) >= 0) { \
918 for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \
919 if ((cmp((elt)->next, like)) >= 0) { \
926 #define CDL_DELETE(head,del) \
927 CDL_DELETE2(head,del,prev,next)
929 #define CDL_DELETE2(head,del,prev,next) \
931 if (((head)==(del)) && ((head)->next == (head))) { \
934 (del)->next->prev = (del)->prev; \
935 (del)->prev->next = (del)->next; \
936 if ((del) == (head)) (head)=(del)->next; \
940 #define CDL_COUNT(head,el,counter) \
941 CDL_COUNT2(head,el,counter,next) \
943 #define CDL_COUNT2(head, el, counter,next) \
946 CDL_FOREACH2(head,el,next) { ++(counter); } \
949 #define CDL_FOREACH(head,el) \
950 CDL_FOREACH2(head,el,next)
952 #define CDL_FOREACH2(head,el,next) \
953 for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next))
955 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
956 CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
958 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
959 for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \
960 (el) && ((tmp2) = (el)->next, 1); \
961 (el) = ((el) == (tmp1) ? NULL : (tmp2)))
963 #define CDL_SEARCH_SCALAR(head,out,field,val) \
964 CDL_SEARCH_SCALAR2(head,out,field,val,next)
966 #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
968 CDL_FOREACH2(head,out,next) { \
969 if ((out)->field == (val)) break; \
973 #define CDL_SEARCH(head,out,elt,cmp) \
974 CDL_SEARCH2(head,out,elt,cmp,next)
976 #define CDL_SEARCH2(head,out,elt,cmp,next) \
978 CDL_FOREACH2(head,out,next) { \
979 if ((cmp(out,elt))==0) break; \
983 #define CDL_REPLACE_ELEM2(head, el, add, prev, next) \
985 assert((head) != NULL); \
986 assert((el) != NULL); \
987 assert((add) != NULL); \
988 if ((el)->next == (el)) { \
989 (add)->next = (add); \
990 (add)->prev = (add); \
993 (add)->next = (el)->next; \
994 (add)->prev = (el)->prev; \
995 (add)->next->prev = (add); \
996 (add)->prev->next = (add); \
997 if ((head) == (el)) { \
1003 #define CDL_REPLACE_ELEM(head, el, add) \
1004 CDL_REPLACE_ELEM2(head, el, add, prev, next)
1006 #define CDL_PREPEND_ELEM2(head, el, add, prev, next) \
1009 assert((head) != NULL); \
1010 assert((add) != NULL); \
1011 (add)->next = (el); \
1012 (add)->prev = (el)->prev; \
1013 (el)->prev = (add); \
1014 (add)->prev->next = (add); \
1015 if ((head) == (el)) { \
1019 CDL_APPEND2(head, add, prev, next); \
1023 #define CDL_PREPEND_ELEM(head, el, add) \
1024 CDL_PREPEND_ELEM2(head, el, add, prev, next)
1026 #define CDL_APPEND_ELEM2(head, el, add, prev, next) \
1029 assert((head) != NULL); \
1030 assert((add) != NULL); \
1031 (add)->next = (el)->next; \
1032 (add)->prev = (el); \
1033 (el)->next = (add); \
1034 (add)->next->prev = (add); \
1036 CDL_PREPEND2(head, add, prev, next); \
1040 #define CDL_APPEND_ELEM(head, el, add) \
1041 CDL_APPEND_ELEM2(head, el, add, prev, next)
1046 #undef CDL_INSERT_INORDER2
1047 #define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \
1049 if ((head) == NULL) { \
1050 (add)->prev = (add); \
1051 (add)->next = (add); \
1053 } else if ((cmp(head, add)) >= 0) { \
1054 (add)->prev = (head)->prev; \
1055 (add)->next = (head); \
1056 (add)->prev->next = (add); \
1057 (head)->prev = (add); \
1060 char *_tmp = (char*)(head); \
1061 while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \
1062 (head) = (head)->next; \
1064 (add)->prev = (head); \
1065 (add)->next = (head)->next; \
1066 (add)->next->prev = (add); \
1067 (head)->next = (add); \