Go to the documentation of this file.
27 #define UTLIST_VERSION 1.9.9
67 #if _MSC_VER >= 1600 && defined(__cplusplus)
68 #define LDECLTYPE(x) decltype(x)
71 #define LDECLTYPE(x) char*
73 #elif defined(__ICCARM__)
75 #define LDECLTYPE(x) char*
77 #define LDECLTYPE(x) __typeof(x)
84 #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
85 #define _NEXT(elt,list,next) ((char*)((list)->next))
86 #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
88 #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
89 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
90 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
93 #define _NEXT(elt,list,next) ((elt)->next)
94 #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
96 #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
98 #define _CASTASGN(a,b) (a)=(b)
105 #define LL_SORT(list, cmp) \
106 LL_SORT2(list, cmp, next)
108 #define LL_SORT2(list, cmp, next) \
110 LDECLTYPE(list) _ls_p; \
111 LDECLTYPE(list) _ls_q; \
112 LDECLTYPE(list) _ls_e; \
113 LDECLTYPE(list) _ls_tail; \
114 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
118 while (_ls_looping) { \
119 _CASTASGN(_ls_p,list); \
127 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
129 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
132 _ls_qsize = _ls_insize; \
133 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
134 if (_ls_psize == 0) { \
135 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
136 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
137 } else if (_ls_qsize == 0 || !_ls_q) { \
138 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
139 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
140 } else if (cmp(_ls_p,_ls_q) <= 0) { \
141 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
142 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
144 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
145 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
148 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
150 _CASTASGN(list,_ls_e); \
157 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
159 if (_ls_nmerges <= 1) { \
168 #define DL_SORT(list, cmp) \
169 DL_SORT2(list, cmp, prev, next)
171 #define DL_SORT2(list, cmp, prev, next) \
173 LDECLTYPE(list) _ls_p; \
174 LDECLTYPE(list) _ls_q; \
175 LDECLTYPE(list) _ls_e; \
176 LDECLTYPE(list) _ls_tail; \
177 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
181 while (_ls_looping) { \
182 _CASTASGN(_ls_p,list); \
190 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
192 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
195 _ls_qsize = _ls_insize; \
196 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
197 if (_ls_psize == 0) { \
198 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
199 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
200 } else if (_ls_qsize == 0 || !_ls_q) { \
201 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
202 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
203 } else if (cmp(_ls_p,_ls_q) <= 0) { \
204 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
205 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
207 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
208 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
211 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
213 _CASTASGN(list,_ls_e); \
215 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
220 _CASTASGN(list->prev, _ls_tail); \
221 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
222 if (_ls_nmerges <= 1) { \
230 #define CDL_SORT(list, cmp) \
231 CDL_SORT2(list, cmp, prev, next)
233 #define CDL_SORT2(list, cmp, prev, next) \
235 LDECLTYPE(list) _ls_p; \
236 LDECLTYPE(list) _ls_q; \
237 LDECLTYPE(list) _ls_e; \
238 LDECLTYPE(list) _ls_tail; \
239 LDECLTYPE(list) _ls_oldhead; \
240 LDECLTYPE(list) _tmp; \
241 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
245 while (_ls_looping) { \
246 _CASTASGN(_ls_p,list); \
247 _CASTASGN(_ls_oldhead,list); \
255 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
258 if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
261 _ls_q = _NEXT(_ls_q,list,next); \
266 _ls_qsize = _ls_insize; \
267 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
268 if (_ls_psize == 0) { \
269 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
270 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
271 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
272 } else if (_ls_qsize == 0 || !_ls_q) { \
273 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
274 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
275 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
276 } else if (cmp(_ls_p,_ls_q) <= 0) { \
277 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
278 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
279 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
281 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
282 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
283 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
286 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
288 _CASTASGN(list,_ls_e); \
290 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
295 _CASTASGN(list->prev,_ls_tail); \
296 _CASTASGN(_tmp,list); \
297 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
298 if (_ls_nmerges <= 1) { \
309 #define LL_PREPEND(head,add) \
310 LL_PREPEND2(head,add,next)
312 #define LL_PREPEND2(head,add,next) \
314 (add)->next = head; \
318 #define LL_CONCAT(head1,head2) \
319 LL_CONCAT2(head1,head2,next)
321 #define LL_CONCAT2(head1,head2,next) \
323 LDECLTYPE(head1) _tmp; \
326 while (_tmp->next) { _tmp = _tmp->next; } \
327 _tmp->next=(head2); \
333 #define LL_APPEND(head,add) \
334 LL_APPEND2(head,add,next)
336 #define LL_APPEND2(head,add,next) \
338 LDECLTYPE(head) _tmp; \
342 while (_tmp->next) { _tmp = _tmp->next; } \
349 #define LL_DELETE(head,del) \
350 LL_DELETE2(head,del,next)
352 #define LL_DELETE2(head,del,next) \
354 LDECLTYPE(head) _tmp; \
355 if ((head) == (del)) { \
356 (head)=(head)->next; \
359 while (_tmp->next && (_tmp->next != (del))) { \
363 _tmp->next = ((del)->next); \
369 #define LL_APPEND_VS2008(head,add) \
370 LL_APPEND2_VS2008(head,add,next)
372 #define LL_APPEND2_VS2008(head,add,next) \
375 (add)->next = head; \
376 while ((add)->next->next) { (add)->next = (add)->next->next; } \
377 (add)->next->next=(add); \
384 #define LL_DELETE_VS2008(head,del) \
385 LL_DELETE2_VS2008(head,del,next)
387 #define LL_DELETE2_VS2008(head,del,next) \
389 if ((head) == (del)) { \
390 (head)=(head)->next; \
392 char *_tmp = (char*)(head); \
393 while ((head)->next && ((head)->next != (del))) { \
394 head = (head)->next; \
396 if ((head)->next) { \
397 (head)->next = ((del)->next); \
400 char **_head_alias = (char**)&(head); \
401 *_head_alias = _tmp; \
407 #define LL_APPEND LL_APPEND_VS2008
409 #define LL_DELETE LL_DELETE_VS2008
411 #define LL_DELETE2 LL_DELETE2_VS2008
413 #define LL_APPEND2 LL_APPEND2_VS2008
419 #define LL_COUNT(head,el,counter) \
420 LL_COUNT2(head,el,counter,next) \
422 #define LL_COUNT2(head,el,counter,next) \
425 LL_FOREACH2(head,el,next){ ++counter; } \
428 #define LL_FOREACH(head,el) \
429 LL_FOREACH2(head,el,next)
431 #define LL_FOREACH2(head,el,next) \
432 for(el=head;el;el=(el)->next)
434 #define LL_FOREACH_SAFE(head,el,tmp) \
435 LL_FOREACH_SAFE2(head,el,tmp,next)
437 #define LL_FOREACH_SAFE2(head,el,tmp,next) \
438 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
440 #define LL_SEARCH_SCALAR(head,out,field,val) \
441 LL_SEARCH_SCALAR2(head,out,field,val,next)
443 #define LL_SEARCH_SCALAR2(head,out,field,val,next) \
445 LL_FOREACH2(head,out,next) { \
446 if ((out)->field == (val)) break; \
450 #define LL_SEARCH(head,out,elt,cmp) \
451 LL_SEARCH2(head,out,elt,cmp,next)
453 #define LL_SEARCH2(head,out,elt,cmp,next) \
455 LL_FOREACH2(head,out,next) { \
456 if ((cmp(out,elt))==0) break; \
460 #define LL_REPLACE_ELEM(head, el, add) \
462 LDECLTYPE(head) _tmp; \
463 assert(head != NULL); \
464 assert(el != NULL); \
465 assert(add != NULL); \
466 (add)->next = (el)->next; \
467 if ((head) == (el)) { \
471 while (_tmp->next && (_tmp->next != (el))) { \
475 _tmp->next = (add); \
480 #define LL_PREPEND_ELEM(head, el, add) \
482 LDECLTYPE(head) _tmp; \
483 assert(head != NULL); \
484 assert(el != NULL); \
485 assert(add != NULL); \
486 (add)->next = (el); \
487 if ((head) == (el)) { \
491 while (_tmp->next && (_tmp->next != (el))) { \
495 _tmp->next = (add); \
504 #define DL_PREPEND(head,add) \
505 DL_PREPEND2(head,add,prev,next)
507 #define DL_PREPEND2(head,add,prev,next) \
509 (add)->next = head; \
511 (add)->prev = (head)->prev; \
512 (head)->prev = (add); \
514 (add)->prev = (add); \
519 #define DL_APPEND(head,add) \
520 DL_APPEND2(head,add,prev,next)
522 #define DL_APPEND2(head,add,prev,next) \
525 (add)->prev = (head)->prev; \
526 (head)->prev->next = (add); \
527 (head)->prev = (add); \
528 (add)->next = NULL; \
531 (head)->prev = (head); \
532 (head)->next = NULL; \
536 #define DL_CONCAT(head1,head2) \
537 DL_CONCAT2(head1,head2,prev,next)
539 #define DL_CONCAT2(head1,head2,prev,next) \
541 LDECLTYPE(head1) _tmp; \
544 _tmp = (head2)->prev; \
545 (head2)->prev = (head1)->prev; \
546 (head1)->prev->next = (head2); \
547 (head1)->prev = _tmp; \
554 #define DL_DELETE(head,del) \
555 DL_DELETE2(head,del,prev,next)
557 #define DL_DELETE2(head,del,prev,next) \
559 assert((del)->prev != NULL); \
560 if ((del)->prev == (del)) { \
562 } else if ((del)==(head)) { \
563 (del)->next->prev = (del)->prev; \
564 (head) = (del)->next; \
566 (del)->prev->next = (del)->next; \
568 (del)->next->prev = (del)->prev; \
570 (head)->prev = (del)->prev; \
575 #define DL_COUNT(head,el,counter) \
576 DL_COUNT2(head,el,counter,next) \
578 #define DL_COUNT2(head,el,counter,next) \
581 DL_FOREACH2(head,el,next){ ++counter; } \
584 #define DL_FOREACH(head,el) \
585 DL_FOREACH2(head,el,next)
587 #define DL_FOREACH2(head,el,next) \
588 for(el=head;el;el=(el)->next)
591 #define DL_FOREACH_SAFE(head,el,tmp) \
592 DL_FOREACH_SAFE2(head,el,tmp,next)
594 #define DL_FOREACH_SAFE2(head,el,tmp,next) \
595 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
598 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
599 #define DL_SEARCH LL_SEARCH
600 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
601 #define DL_SEARCH2 LL_SEARCH2
603 #define DL_REPLACE_ELEM(head, el, add) \
605 assert(head != NULL); \
606 assert(el != NULL); \
607 assert(add != NULL); \
608 if ((head) == (el)) { \
610 (add)->next = (el)->next; \
611 if ((el)->next == NULL) { \
612 (add)->prev = (add); \
614 (add)->prev = (el)->prev; \
615 (add)->next->prev = (add); \
618 (add)->next = (el)->next; \
619 (add)->prev = (el)->prev; \
620 (add)->prev->next = (add); \
621 if ((el)->next == NULL) { \
622 (head)->prev = (add); \
624 (add)->next->prev = (add); \
629 #define DL_PREPEND_ELEM(head, el, add) \
631 assert(head != NULL); \
632 assert(el != NULL); \
633 assert(add != NULL); \
634 (add)->next = (el); \
635 (add)->prev = (el)->prev; \
636 (el)->prev = (add); \
637 if ((head) == (el)) { \
640 (add)->prev->next = (add); \
648 #define CDL_PREPEND(head,add) \
649 CDL_PREPEND2(head,add,prev,next)
651 #define CDL_PREPEND2(head,add,prev,next) \
654 (add)->prev = (head)->prev; \
655 (add)->next = (head); \
656 (head)->prev = (add); \
657 (add)->prev->next = (add); \
659 (add)->prev = (add); \
660 (add)->next = (add); \
665 #define CDL_DELETE(head,del) \
666 CDL_DELETE2(head,del,prev,next)
668 #define CDL_DELETE2(head,del,prev,next) \
670 if ( ((head)==(del)) && ((head)->next == (head))) { \
673 (del)->next->prev = (del)->prev; \
674 (del)->prev->next = (del)->next; \
675 if ((del) == (head)) (head)=(del)->next; \
679 #define CDL_COUNT(head,el,counter) \
680 CDL_COUNT2(head,el,counter,next) \
682 #define CDL_COUNT2(head, el, counter,next) \
685 CDL_FOREACH2(head,el,next){ ++counter; } \
688 #define CDL_FOREACH(head,el) \
689 CDL_FOREACH2(head,el,next)
691 #define CDL_FOREACH2(head,el,next) \
692 for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
694 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
695 CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
697 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
698 for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
699 (el) && ((tmp2)=(el)->next, 1); \
700 ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
702 #define CDL_SEARCH_SCALAR(head,out,field,val) \
703 CDL_SEARCH_SCALAR2(head,out,field,val,next)
705 #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
707 CDL_FOREACH2(head,out,next) { \
708 if ((out)->field == (val)) break; \
712 #define CDL_SEARCH(head,out,elt,cmp) \
713 CDL_SEARCH2(head,out,elt,cmp,next)
715 #define CDL_SEARCH2(head,out,elt,cmp,next) \
717 CDL_FOREACH2(head,out,next) { \
718 if ((cmp(out,elt))==0) break; \
722 #define CDL_REPLACE_ELEM(head, el, add) \
724 assert(head != NULL); \
725 assert(el != NULL); \
726 assert(add != NULL); \
727 if ((el)->next == (el)) { \
728 (add)->next = (add); \
729 (add)->prev = (add); \
732 (add)->next = (el)->next; \
733 (add)->prev = (el)->prev; \
734 (add)->next->prev = (add); \
735 (add)->prev->next = (add); \
736 if ((head) == (el)) { \
742 #define CDL_PREPEND_ELEM(head, el, add) \
744 assert(head != NULL); \
745 assert(el != NULL); \
746 assert(add != NULL); \
747 (add)->next = (el); \
748 (add)->prev = (el)->prev; \
749 (el)->prev = (add); \
750 (add)->prev->next = (add); \
751 if ((head) == (el)) { \