2 Copyright (c) 2007-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
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.
27 #define UTLIST_VERSION 1.9.8
32 * This file contains macros to manipulate singly and doubly-linked lists.
34 * 1. LL_ macros: singly-linked lists.
35 * 2. DL_ macros: doubly-linked lists.
36 * 3. CDL_ macros: circular doubly-linked lists.
38 * To use singly-linked lists, your structure must have a "next" pointer.
39 * To use doubly-linked lists, your structure must "prev" and "next" pointers.
40 * Either way, the pointer to the head of the list must be initialized to NULL.
42 * ----------------.EXAMPLE -------------------------
45 * struct item *prev, *next;
48 * struct item *list = NULL:
52 * ... allocate and populate item ...
53 * DL_APPEND(list, item);
55 * --------------------------------------------------
57 * For doubly-linked lists, the append and delete macros are O(1)
58 * For singly-linked lists, append and delete are O(n) but prepend is O(1)
59 * The sort macro is O(n log(n)) for all types of single/double/circular lists.
62 /* These macros use decltype or the earlier __typeof GNU extension.
63 As decltype is only available in newer compilers (VS2010 or gcc 4.3+
64 when compiling c++ code), this code uses whatever method is needed
65 or, for VS2008 where neither is available, uses casting workarounds. */
66 #ifdef _MSC_VER /* MS compiler */
67 #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
68 #define LDECLTYPE(x) decltype(x)
69 #else /* VS2008 or older (or VS2010 in C mode) */
71 #define LDECLTYPE(x) char*
73 #else /* GNU, Sun and other compilers */
74 #define LDECLTYPE(x) __typeof(x)
77 /* for VS2008 we use some workarounds to get around the lack of decltype,
78 * namely, we always reassign our tmp variable to the list head if we need
79 * to dereference its prev/next pointers, and save/restore the real head.*/
81 #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
82 #define _NEXT(elt,list,next) ((char*)((list)->next))
83 #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
84 /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
85 #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
86 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
87 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
90 #define _NEXT(elt,list,next) ((elt)->next)
91 #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
92 /* #define _PREV(elt,list,prev) ((elt)->prev) */
93 #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
95 #define _CASTASGN(a,b) (a)=(b)
98 /******************************************************************************
99 * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
100 * Unwieldy variable names used here to avoid shadowing passed-in variables. *
101 *****************************************************************************/
102 #define LL_SORT(list, cmp) \
103 LL_SORT2(list, cmp, next)
105 #define LL_SORT2(list, cmp, next) \
107 LDECLTYPE(list) _ls_p; \
108 LDECLTYPE(list) _ls_q; \
109 LDECLTYPE(list) _ls_e; \
110 LDECLTYPE(list) _ls_tail; \
111 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
115 while (_ls_looping) { \
116 _CASTASGN(_ls_p,list); \
124 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
126 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
129 _ls_qsize = _ls_insize; \
130 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
131 if (_ls_psize == 0) { \
132 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
133 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
134 } else if (_ls_qsize == 0 || !_ls_q) { \
135 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
136 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
137 } else if (cmp(_ls_p,_ls_q) <= 0) { \
138 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
139 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
141 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
142 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
145 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
147 _CASTASGN(list,_ls_e); \
154 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
156 if (_ls_nmerges <= 1) { \
165 #define DL_SORT(list, cmp) \
166 DL_SORT2(list, cmp, prev, next)
168 #define DL_SORT2(list, cmp, prev, next) \
170 LDECLTYPE(list) _ls_p; \
171 LDECLTYPE(list) _ls_q; \
172 LDECLTYPE(list) _ls_e; \
173 LDECLTYPE(list) _ls_tail; \
174 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
178 while (_ls_looping) { \
179 _CASTASGN(_ls_p,list); \
187 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
189 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
192 _ls_qsize = _ls_insize; \
193 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
194 if (_ls_psize == 0) { \
195 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
196 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
197 } else if (_ls_qsize == 0 || !_ls_q) { \
198 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
199 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
200 } else if (cmp(_ls_p,_ls_q) <= 0) { \
201 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
202 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
204 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
205 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
208 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
210 _CASTASGN(list,_ls_e); \
212 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
217 _CASTASGN(list->prev, _ls_tail); \
218 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
219 if (_ls_nmerges <= 1) { \
227 #define CDL_SORT(list, cmp) \
228 CDL_SORT2(list, cmp, prev, next)
230 #define CDL_SORT2(list, cmp, prev, next) \
232 LDECLTYPE(list) _ls_p; \
233 LDECLTYPE(list) _ls_q; \
234 LDECLTYPE(list) _ls_e; \
235 LDECLTYPE(list) _ls_tail; \
236 LDECLTYPE(list) _ls_oldhead; \
237 LDECLTYPE(list) _tmp; \
238 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
242 while (_ls_looping) { \
243 _CASTASGN(_ls_p,list); \
244 _CASTASGN(_ls_oldhead,list); \
252 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
255 if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
258 _ls_q = _NEXT(_ls_q,list,next); \
263 _ls_qsize = _ls_insize; \
264 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
265 if (_ls_psize == 0) { \
266 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
267 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
268 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
269 } else if (_ls_qsize == 0 || !_ls_q) { \
270 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
271 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
272 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
273 } else if (cmp(_ls_p,_ls_q) <= 0) { \
274 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
275 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
276 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
278 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
279 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
280 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
283 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
285 _CASTASGN(list,_ls_e); \
287 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
292 _CASTASGN(list->prev,_ls_tail); \
293 _CASTASGN(_tmp,list); \
294 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
295 if (_ls_nmerges <= 1) { \
303 /******************************************************************************
304 * singly linked list macros (non-circular) *
305 *****************************************************************************/
306 #define LL_PREPEND(head,add) \
307 LL_PREPEND2(head,add,next)
309 #define LL_PREPEND2(head,add,next) \
311 (add)->next = head; \
315 #define LL_CONCAT(head1,head2) \
316 LL_CONCAT2(head1,head2,next)
318 #define LL_CONCAT2(head1,head2,next) \
320 LDECLTYPE(head1) _tmp; \
323 while (_tmp->next) { _tmp = _tmp->next; } \
324 _tmp->next=(head2); \
330 #define LL_APPEND(head,add) \
331 LL_APPEND2(head,add,next)
333 #define LL_APPEND2(head,add,next) \
335 LDECLTYPE(head) _tmp; \
339 while (_tmp->next) { _tmp = _tmp->next; } \
346 #define LL_DELETE(head,del) \
347 LL_DELETE2(head,del,next)
349 #define LL_DELETE2(head,del,next) \
351 LDECLTYPE(head) _tmp; \
352 if ((head) == (del)) { \
353 (head)=(head)->next; \
356 while (_tmp->next && (_tmp->next != (del))) { \
360 _tmp->next = ((del)->next); \
365 /* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
366 #define LL_APPEND_VS2008(head,add) \
367 LL_APPEND2_VS2008(head,add,next)
369 #define LL_APPEND2_VS2008(head,add,next) \
372 (add)->next = head; /* use add->next as a temp variable */ \
373 while ((add)->next->next) { (add)->next = (add)->next->next; } \
374 (add)->next->next=(add); \
381 #define LL_DELETE_VS2008(head,del) \
382 LL_DELETE2_VS2008(head,del,next)
384 #define LL_DELETE2_VS2008(head,del,next) \
386 if ((head) == (del)) { \
387 (head)=(head)->next; \
389 char *_tmp = (char*)(head); \
390 while ((head)->next && ((head)->next != (del))) { \
391 head = (head)->next; \
393 if ((head)->next) { \
394 (head)->next = ((del)->next); \
397 char **_head_alias = (char**)&(head); \
398 *_head_alias = _tmp; \
404 #define LL_APPEND LL_APPEND_VS2008
406 #define LL_DELETE LL_DELETE_VS2008
408 #define LL_DELETE2_VS2008
410 #define LL_APPEND2 LL_APPEND2_VS2008
411 #undef LL_CONCAT /* no LL_CONCAT_VS2008 */
412 #undef DL_CONCAT /* no DL_CONCAT_VS2008 */
414 /* end VS2008 replacements */
416 #define LL_FOREACH(head,el) \
417 LL_FOREACH2(head,el,next)
419 #define LL_FOREACH2(head,el,next) \
420 for(el=head;el;el=(el)->next)
422 #define LL_FOREACH_SAFE(head,el,tmp) \
423 LL_FOREACH_SAFE2(head,el,tmp,next)
425 #define LL_FOREACH_SAFE2(head,el,tmp,next) \
426 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
428 #define LL_SEARCH_SCALAR(head,out,field,val) \
429 LL_SEARCH_SCALAR2(head,out,field,val,next)
431 #define LL_SEARCH_SCALAR2(head,out,field,val,next) \
433 LL_FOREACH2(head,out,next) { \
434 if ((out)->field == (val)) break; \
438 #define LL_SEARCH(head,out,elt,cmp) \
439 LL_SEARCH2(head,out,elt,cmp,next)
441 #define LL_SEARCH2(head,out,elt,cmp,next) \
443 LL_FOREACH2(head,out,next) { \
444 if ((cmp(out,elt))==0) break; \
448 #define LL_REPLACE_ELEM(head, el, add) \
450 LDECLTYPE(head) _tmp; \
451 assert(head != NULL); \
452 assert(el != NULL); \
453 assert(add != NULL); \
454 (add)->next = (el)->next; \
455 if ((head) == (el)) { \
459 while (_tmp->next && (_tmp->next != (el))) { \
463 _tmp->next = (add); \
468 #define LL_PREPEND_ELEM(head, el, add) \
470 LDECLTYPE(head) _tmp; \
471 assert(head != NULL); \
472 assert(el != NULL); \
473 assert(add != NULL); \
474 (add)->next = (el); \
475 if ((head) == (el)) { \
479 while (_tmp->next && (_tmp->next != (el))) { \
483 _tmp->next = (add); \
489 /******************************************************************************
490 * doubly linked list macros (non-circular) *
491 *****************************************************************************/
492 #define DL_PREPEND(head,add) \
493 DL_PREPEND2(head,add,prev,next)
495 #define DL_PREPEND2(head,add,prev,next) \
497 (add)->next = head; \
499 (add)->prev = (head)->prev; \
500 (head)->prev = (add); \
502 (add)->prev = (add); \
507 #define DL_APPEND(head,add) \
508 DL_APPEND2(head,add,prev,next)
510 #define DL_APPEND2(head,add,prev,next) \
513 (add)->prev = (head)->prev; \
514 (head)->prev->next = (add); \
515 (head)->prev = (add); \
516 (add)->next = NULL; \
519 (head)->prev = (head); \
520 (head)->next = NULL; \
524 #define DL_CONCAT(head1,head2) \
525 DL_CONCAT2(head1,head2,prev,next)
527 #define DL_CONCAT2(head1,head2,prev,next) \
529 LDECLTYPE(head1) _tmp; \
532 _tmp = (head2)->prev; \
533 (head2)->prev = (head1)->prev; \
534 (head1)->prev->next = (head2); \
535 (head1)->prev = _tmp; \
542 #define DL_DELETE(head,del) \
543 DL_DELETE2(head,del,prev,next)
545 #define DL_DELETE2(head,del,prev,next) \
547 assert((del)->prev != NULL); \
548 if ((del)->prev == (del)) { \
550 } else if ((del)==(head)) { \
551 (del)->next->prev = (del)->prev; \
552 (head) = (del)->next; \
554 (del)->prev->next = (del)->next; \
556 (del)->next->prev = (del)->prev; \
558 (head)->prev = (del)->prev; \
564 #define DL_FOREACH(head,el) \
565 DL_FOREACH2(head,el,next)
567 #define DL_FOREACH2(head,el,next) \
568 for(el=head;el;el=(el)->next)
570 /* this version is safe for deleting the elements during iteration */
571 #define DL_FOREACH_SAFE(head,el,tmp) \
572 DL_FOREACH_SAFE2(head,el,tmp,next)
574 #define DL_FOREACH_SAFE2(head,el,tmp,next) \
575 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
577 /* these are identical to their singly-linked list counterparts */
578 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
579 #define DL_SEARCH LL_SEARCH
580 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
581 #define DL_SEARCH2 LL_SEARCH2
583 #define DL_REPLACE_ELEM(head, el, add) \
585 assert(head != NULL); \
586 assert(el != NULL); \
587 assert(add != NULL); \
588 if ((head) == (el)) { \
590 (add)->next = (el)->next; \
591 if ((el)->next == NULL) { \
592 (add)->prev = (add); \
594 (add)->prev = (el)->prev; \
595 (add)->next->prev = (add); \
598 (add)->next = (el)->next; \
599 (add)->prev = (el)->prev; \
600 (add)->prev->next = (add); \
601 if ((el)->next == NULL) { \
602 (head)->prev = (add); \
604 (add)->next->prev = (add); \
609 #define DL_PREPEND_ELEM(head, el, add) \
611 assert(head != NULL); \
612 assert(el != NULL); \
613 assert(add != NULL); \
614 (add)->next = (el); \
615 (add)->prev = (el)->prev; \
616 (el)->prev = (add); \
617 if ((head) == (el)) { \
620 (add)->prev->next = (add); \
625 /******************************************************************************
626 * circular doubly linked list macros *
627 *****************************************************************************/
628 #define CDL_PREPEND(head,add) \
629 CDL_PREPEND2(head,add,prev,next)
631 #define CDL_PREPEND2(head,add,prev,next) \
634 (add)->prev = (head)->prev; \
635 (add)->next = (head); \
636 (head)->prev = (add); \
637 (add)->prev->next = (add); \
639 (add)->prev = (add); \
640 (add)->next = (add); \
645 #define CDL_DELETE(head,del) \
646 CDL_DELETE2(head,del,prev,next)
648 #define CDL_DELETE2(head,del,prev,next) \
650 if ( ((head)==(del)) && ((head)->next == (head))) { \
653 (del)->next->prev = (del)->prev; \
654 (del)->prev->next = (del)->next; \
655 if ((del) == (head)) (head)=(del)->next; \
659 #define CDL_FOREACH(head,el) \
660 CDL_FOREACH2(head,el,next)
662 #define CDL_FOREACH2(head,el,next) \
663 for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
665 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
666 CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
668 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
669 for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
670 (el) && ((tmp2)=(el)->next, 1); \
671 ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
673 #define CDL_SEARCH_SCALAR(head,out,field,val) \
674 CDL_SEARCH_SCALAR2(head,out,field,val,next)
676 #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
678 CDL_FOREACH2(head,out,next) { \
679 if ((out)->field == (val)) break; \
683 #define CDL_SEARCH(head,out,elt,cmp) \
684 CDL_SEARCH2(head,out,elt,cmp,next)
686 #define CDL_SEARCH2(head,out,elt,cmp,next) \
688 CDL_FOREACH2(head,out,next) { \
689 if ((cmp(out,elt))==0) break; \
693 #define CDL_REPLACE_ELEM(head, el, add) \
695 assert(head != NULL); \
696 assert(el != NULL); \
697 assert(add != NULL); \
698 if ((el)->next == (el)) { \
699 (add)->next = (add); \
700 (add)->prev = (add); \
703 (add)->next = (el)->next; \
704 (add)->prev = (el)->prev; \
705 (add)->next->prev = (add); \
706 (add)->prev->next = (add); \
707 if ((head) == (el)) { \
713 #define CDL_PREPEND_ELEM(head, el, add) \
715 assert(head != NULL); \
716 assert(el != NULL); \
717 assert(add != NULL); \
718 (add)->next = (el); \
719 (add)->prev = (el)->prev; \
720 (el)->prev = (add); \
721 (add)->prev->next = (add); \
722 if ((head) == (el)) { \
727 #endif /* UTLIST_H */