modified: myjupyterlab.sh
[GalaxyCodeBases.git] / c_cpp / lib / uthash / src / utlist.h
blobbb097a2668d0336de2c8b734608e977f02c88fbc
1 /*
2 Copyright (c) 2007-2017, Troy D. Hanson http://troydhanson.github.com/uthash/
3 All rights reserved.
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.
24 #ifndef UTLIST_H
25 #define UTLIST_H
27 #define UTLIST_VERSION 2.0.2
29 #include <assert.h>
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 -------------------------
43 * struct item {
44 * int id;
45 * struct item *prev, *next;
46 * }
48 * struct item *list = NULL:
50 * int main() {
51 * struct item *item;
52 * ... allocate and populate item ...
53 * DL_APPEND(list, item);
54 * }
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) */
70 #define NO_DECLTYPE
71 #endif
72 #elif defined(__ICCARM__)
73 #define NO_DECLTYPE
74 #else /* GNU, Sun and other compilers */
75 #define LDECLTYPE(x) __typeof(x)
76 #endif
78 /* for VS2008 we use some workarounds to get around the lack of decltype,
79 * namely, we always reassign our tmp variable to the list head if we need
80 * to dereference its prev/next pointers, and save/restore the real head.*/
81 #ifdef NO_DECLTYPE
82 #define IF_NO_DECLTYPE(x) x
83 #define LDECLTYPE(x) char*
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); }
87 /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
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); }
91 #else
92 #define IF_NO_DECLTYPE(x)
93 #define _SV(elt,list)
94 #define _NEXT(elt,list,next) ((elt)->next)
95 #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
96 /* #define _PREV(elt,list,prev) ((elt)->prev) */
97 #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
98 #define _RS(list)
99 #define _CASTASGN(a,b) (a)=(b)
100 #endif
102 /******************************************************************************
103 * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
104 * Unwieldy variable names used here to avoid shadowing passed-in variables. *
105 *****************************************************************************/
106 #define LL_SORT(list, cmp) \
107 LL_SORT2(list, cmp, next)
109 #define LL_SORT2(list, cmp, next) \
110 do { \
111 LDECLTYPE(list) _ls_p; \
112 LDECLTYPE(list) _ls_q; \
113 LDECLTYPE(list) _ls_e; \
114 LDECLTYPE(list) _ls_tail; \
115 IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \
116 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
117 if (list) { \
118 _ls_insize = 1; \
119 _ls_looping = 1; \
120 while (_ls_looping) { \
121 _CASTASGN(_ls_p,list); \
122 (list) = NULL; \
123 _ls_tail = NULL; \
124 _ls_nmerges = 0; \
125 while (_ls_p) { \
126 _ls_nmerges++; \
127 _ls_q = _ls_p; \
128 _ls_psize = 0; \
129 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
130 _ls_psize++; \
131 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
132 if (!_ls_q) break; \
134 _ls_qsize = _ls_insize; \
135 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
136 if (_ls_psize == 0) { \
137 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
138 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
139 } else if (_ls_qsize == 0 || !_ls_q) { \
140 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
141 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
142 } else if (cmp(_ls_p,_ls_q) <= 0) { \
143 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
144 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
145 } else { \
146 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
147 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
149 if (_ls_tail) { \
150 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
151 } else { \
152 _CASTASGN(list,_ls_e); \
154 _ls_tail = _ls_e; \
156 _ls_p = _ls_q; \
158 if (_ls_tail) { \
159 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
161 if (_ls_nmerges <= 1) { \
162 _ls_looping=0; \
164 _ls_insize *= 2; \
167 } while (0)
170 #define DL_SORT(list, cmp) \
171 DL_SORT2(list, cmp, prev, next)
173 #define DL_SORT2(list, cmp, prev, next) \
174 do { \
175 LDECLTYPE(list) _ls_p; \
176 LDECLTYPE(list) _ls_q; \
177 LDECLTYPE(list) _ls_e; \
178 LDECLTYPE(list) _ls_tail; \
179 IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \
180 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
181 if (list) { \
182 _ls_insize = 1; \
183 _ls_looping = 1; \
184 while (_ls_looping) { \
185 _CASTASGN(_ls_p,list); \
186 (list) = NULL; \
187 _ls_tail = NULL; \
188 _ls_nmerges = 0; \
189 while (_ls_p) { \
190 _ls_nmerges++; \
191 _ls_q = _ls_p; \
192 _ls_psize = 0; \
193 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
194 _ls_psize++; \
195 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
196 if (!_ls_q) break; \
198 _ls_qsize = _ls_insize; \
199 while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \
200 if (_ls_psize == 0) { \
201 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
202 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
203 } else if ((_ls_qsize == 0) || (!_ls_q)) { \
204 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
205 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
206 } else if (cmp(_ls_p,_ls_q) <= 0) { \
207 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
208 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
209 } else { \
210 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
211 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
213 if (_ls_tail) { \
214 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
215 } else { \
216 _CASTASGN(list,_ls_e); \
218 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
219 _ls_tail = _ls_e; \
221 _ls_p = _ls_q; \
223 _CASTASGN((list)->prev, _ls_tail); \
224 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
225 if (_ls_nmerges <= 1) { \
226 _ls_looping=0; \
228 _ls_insize *= 2; \
231 } while (0)
233 #define CDL_SORT(list, cmp) \
234 CDL_SORT2(list, cmp, prev, next)
236 #define CDL_SORT2(list, cmp, prev, next) \
237 do { \
238 LDECLTYPE(list) _ls_p; \
239 LDECLTYPE(list) _ls_q; \
240 LDECLTYPE(list) _ls_e; \
241 LDECLTYPE(list) _ls_tail; \
242 LDECLTYPE(list) _ls_oldhead; \
243 LDECLTYPE(list) _tmp; \
244 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
245 if (list) { \
246 _ls_insize = 1; \
247 _ls_looping = 1; \
248 while (_ls_looping) { \
249 _CASTASGN(_ls_p,list); \
250 _CASTASGN(_ls_oldhead,list); \
251 (list) = NULL; \
252 _ls_tail = NULL; \
253 _ls_nmerges = 0; \
254 while (_ls_p) { \
255 _ls_nmerges++; \
256 _ls_q = _ls_p; \
257 _ls_psize = 0; \
258 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
259 _ls_psize++; \
260 _SV(_ls_q,list); \
261 if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
262 _ls_q = NULL; \
263 } else { \
264 _ls_q = _NEXT(_ls_q,list,next); \
266 _RS(list); \
267 if (!_ls_q) break; \
269 _ls_qsize = _ls_insize; \
270 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
271 if (_ls_psize == 0) { \
272 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
273 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
274 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
275 } else if (_ls_qsize == 0 || !_ls_q) { \
276 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
277 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
278 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
279 } else if (cmp(_ls_p,_ls_q) <= 0) { \
280 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
281 _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
282 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
283 } else { \
284 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
285 _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
286 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
288 if (_ls_tail) { \
289 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
290 } else { \
291 _CASTASGN(list,_ls_e); \
293 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
294 _ls_tail = _ls_e; \
296 _ls_p = _ls_q; \
298 _CASTASGN((list)->prev,_ls_tail); \
299 _CASTASGN(_tmp,list); \
300 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
301 if (_ls_nmerges <= 1) { \
302 _ls_looping=0; \
304 _ls_insize *= 2; \
307 } while (0)
309 /******************************************************************************
310 * singly linked list macros (non-circular) *
311 *****************************************************************************/
312 #define LL_PREPEND(head,add) \
313 LL_PREPEND2(head,add,next)
315 #define LL_PREPEND2(head,add,next) \
316 do { \
317 (add)->next = (head); \
318 (head) = (add); \
319 } while (0)
321 #define LL_CONCAT(head1,head2) \
322 LL_CONCAT2(head1,head2,next)
324 #define LL_CONCAT2(head1,head2,next) \
325 do { \
326 LDECLTYPE(head1) _tmp; \
327 if (head1) { \
328 _tmp = (head1); \
329 while (_tmp->next) { _tmp = _tmp->next; } \
330 _tmp->next=(head2); \
331 } else { \
332 (head1)=(head2); \
334 } while (0)
336 #define LL_APPEND(head,add) \
337 LL_APPEND2(head,add,next)
339 #define LL_APPEND2(head,add,next) \
340 do { \
341 LDECLTYPE(head) _tmp; \
342 (add)->next=NULL; \
343 if (head) { \
344 _tmp = (head); \
345 while (_tmp->next) { _tmp = _tmp->next; } \
346 _tmp->next=(add); \
347 } else { \
348 (head)=(add); \
350 } while (0)
352 #define LL_DELETE(head,del) \
353 LL_DELETE2(head,del,next)
355 #define LL_DELETE2(head,del,next) \
356 do { \
357 LDECLTYPE(head) _tmp; \
358 if ((head) == (del)) { \
359 (head)=(head)->next; \
360 } else { \
361 _tmp = (head); \
362 while (_tmp->next && (_tmp->next != (del))) { \
363 _tmp = _tmp->next; \
365 if (_tmp->next) { \
366 _tmp->next = (del)->next; \
369 } while (0)
371 #define LL_COUNT(head,el,counter) \
372 LL_COUNT2(head,el,counter,next) \
374 #define LL_COUNT2(head,el,counter,next) \
375 do { \
376 (counter) = 0; \
377 LL_FOREACH2(head,el,next) { ++(counter); } \
378 } while (0)
380 #define LL_FOREACH(head,el) \
381 LL_FOREACH2(head,el,next)
383 #define LL_FOREACH2(head,el,next) \
384 for ((el) = (head); el; (el) = (el)->next)
386 #define LL_FOREACH_SAFE(head,el,tmp) \
387 LL_FOREACH_SAFE2(head,el,tmp,next)
389 #define LL_FOREACH_SAFE2(head,el,tmp,next) \
390 for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
392 #define LL_SEARCH_SCALAR(head,out,field,val) \
393 LL_SEARCH_SCALAR2(head,out,field,val,next)
395 #define LL_SEARCH_SCALAR2(head,out,field,val,next) \
396 do { \
397 LL_FOREACH2(head,out,next) { \
398 if ((out)->field == (val)) break; \
400 } while (0)
402 #define LL_SEARCH(head,out,elt,cmp) \
403 LL_SEARCH2(head,out,elt,cmp,next)
405 #define LL_SEARCH2(head,out,elt,cmp,next) \
406 do { \
407 LL_FOREACH2(head,out,next) { \
408 if ((cmp(out,elt))==0) break; \
410 } while (0)
412 #define LL_REPLACE_ELEM2(head, el, add, next) \
413 do { \
414 LDECLTYPE(head) _tmp; \
415 assert((head) != NULL); \
416 assert((el) != NULL); \
417 assert((add) != NULL); \
418 (add)->next = (el)->next; \
419 if ((head) == (el)) { \
420 (head) = (add); \
421 } else { \
422 _tmp = (head); \
423 while (_tmp->next && (_tmp->next != (el))) { \
424 _tmp = _tmp->next; \
426 if (_tmp->next) { \
427 _tmp->next = (add); \
430 } while (0)
432 #define LL_REPLACE_ELEM(head, el, add) \
433 LL_REPLACE_ELEM2(head, el, add, next)
435 #define LL_PREPEND_ELEM2(head, el, add, next) \
436 do { \
437 if (el) { \
438 LDECLTYPE(head) _tmp; \
439 assert((head) != NULL); \
440 assert((add) != NULL); \
441 (add)->next = (el); \
442 if ((head) == (el)) { \
443 (head) = (add); \
444 } else { \
445 _tmp = (head); \
446 while (_tmp->next && (_tmp->next != (el))) { \
447 _tmp = _tmp->next; \
449 if (_tmp->next) { \
450 _tmp->next = (add); \
453 } else { \
454 LL_APPEND2(head, add, next); \
456 } while (0) \
458 #define LL_PREPEND_ELEM(head, el, add) \
459 LL_PREPEND_ELEM2(head, el, add, next)
461 #define LL_APPEND_ELEM2(head, el, add, next) \
462 do { \
463 if (el) { \
464 assert((head) != NULL); \
465 assert((add) != NULL); \
466 (add)->next = (el)->next; \
467 (el)->next = (add); \
468 } else { \
469 LL_PREPEND2(head, add, next); \
471 } while (0) \
473 #define LL_APPEND_ELEM(head, el, add) \
474 LL_APPEND_ELEM2(head, el, add, next)
476 #ifdef NO_DECLTYPE
477 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
479 #undef LL_CONCAT2
480 #define LL_CONCAT2(head1,head2,next) \
481 do { \
482 char *_tmp; \
483 if (head1) { \
484 _tmp = (char*)(head1); \
485 while ((head1)->next) { (head1) = (head1)->next; } \
486 (head1)->next = (head2); \
487 _RS(head1); \
488 } else { \
489 (head1)=(head2); \
491 } while (0)
493 #undef LL_APPEND2
494 #define LL_APPEND2(head,add,next) \
495 do { \
496 if (head) { \
497 (add)->next = head; /* use add->next as a temp variable */ \
498 while ((add)->next->next) { (add)->next = (add)->next->next; } \
499 (add)->next->next=(add); \
500 } else { \
501 (head)=(add); \
503 (add)->next=NULL; \
504 } while (0)
506 #undef LL_DELETE2
507 #define LL_DELETE2(head,del,next) \
508 do { \
509 if ((head) == (del)) { \
510 (head)=(head)->next; \
511 } else { \
512 char *_tmp = (char*)(head); \
513 while ((head)->next && ((head)->next != (del))) { \
514 (head) = (head)->next; \
516 if ((head)->next) { \
517 (head)->next = ((del)->next); \
519 _RS(head); \
521 } while (0)
523 #undef LL_REPLACE_ELEM2
524 #define LL_REPLACE_ELEM2(head, el, add, next) \
525 do { \
526 assert((head) != NULL); \
527 assert((el) != NULL); \
528 assert((add) != NULL); \
529 if ((head) == (el)) { \
530 (head) = (add); \
531 } else { \
532 (add)->next = head; \
533 while ((add)->next->next && ((add)->next->next != (el))) { \
534 (add)->next = (add)->next->next; \
536 if ((add)->next->next) { \
537 (add)->next->next = (add); \
540 (add)->next = (el)->next; \
541 } while (0)
543 #undef LL_PREPEND_ELEM2
544 #define LL_PREPEND_ELEM2(head, el, add, next) \
545 do { \
546 if (el) { \
547 assert((head) != NULL); \
548 assert((add) != NULL); \
549 if ((head) == (el)) { \
550 (head) = (add); \
551 } else { \
552 (add)->next = (head); \
553 while ((add)->next->next && ((add)->next->next != (el))) { \
554 (add)->next = (add)->next->next; \
556 if ((add)->next->next) { \
557 (add)->next->next = (add); \
560 (add)->next = (el); \
561 } else { \
562 LL_APPEND2(head, add, next); \
564 } while (0) \
566 #endif /* NO_DECLTYPE */
568 /******************************************************************************
569 * doubly linked list macros (non-circular) *
570 *****************************************************************************/
571 #define DL_PREPEND(head,add) \
572 DL_PREPEND2(head,add,prev,next)
574 #define DL_PREPEND2(head,add,prev,next) \
575 do { \
576 (add)->next = (head); \
577 if (head) { \
578 (add)->prev = (head)->prev; \
579 (head)->prev = (add); \
580 } else { \
581 (add)->prev = (add); \
583 (head) = (add); \
584 } while (0)
586 #define DL_APPEND(head,add) \
587 DL_APPEND2(head,add,prev,next)
589 #define DL_APPEND2(head,add,prev,next) \
590 do { \
591 if (head) { \
592 (add)->prev = (head)->prev; \
593 (head)->prev->next = (add); \
594 (head)->prev = (add); \
595 (add)->next = NULL; \
596 } else { \
597 (head)=(add); \
598 (head)->prev = (head); \
599 (head)->next = NULL; \
601 } while (0)
603 #define DL_CONCAT(head1,head2) \
604 DL_CONCAT2(head1,head2,prev,next)
606 #define DL_CONCAT2(head1,head2,prev,next) \
607 do { \
608 LDECLTYPE(head1) _tmp; \
609 if (head2) { \
610 if (head1) { \
611 _CASTASGN(_tmp, (head2)->prev); \
612 (head2)->prev = (head1)->prev; \
613 (head1)->prev->next = (head2); \
614 _CASTASGN((head1)->prev, _tmp); \
615 } else { \
616 (head1)=(head2); \
619 } while (0)
621 #define DL_DELETE(head,del) \
622 DL_DELETE2(head,del,prev,next)
624 #define DL_DELETE2(head,del,prev,next) \
625 do { \
626 assert((del)->prev != NULL); \
627 if ((del)->prev == (del)) { \
628 (head)=NULL; \
629 } else if ((del)==(head)) { \
630 (del)->next->prev = (del)->prev; \
631 (head) = (del)->next; \
632 } else { \
633 (del)->prev->next = (del)->next; \
634 if ((del)->next) { \
635 (del)->next->prev = (del)->prev; \
636 } else { \
637 (head)->prev = (del)->prev; \
640 } while (0)
642 #define DL_COUNT(head,el,counter) \
643 DL_COUNT2(head,el,counter,next) \
645 #define DL_COUNT2(head,el,counter,next) \
646 do { \
647 (counter) = 0; \
648 DL_FOREACH2(head,el,next) { ++(counter); } \
649 } while (0)
651 #define DL_FOREACH(head,el) \
652 DL_FOREACH2(head,el,next)
654 #define DL_FOREACH2(head,el,next) \
655 for ((el) = (head); el; (el) = (el)->next)
657 /* this version is safe for deleting the elements during iteration */
658 #define DL_FOREACH_SAFE(head,el,tmp) \
659 DL_FOREACH_SAFE2(head,el,tmp,next)
661 #define DL_FOREACH_SAFE2(head,el,tmp,next) \
662 for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
664 /* these are identical to their singly-linked list counterparts */
665 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
666 #define DL_SEARCH LL_SEARCH
667 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
668 #define DL_SEARCH2 LL_SEARCH2
670 #define DL_REPLACE_ELEM2(head, el, add, prev, next) \
671 do { \
672 assert((head) != NULL); \
673 assert((el) != NULL); \
674 assert((add) != NULL); \
675 if ((head) == (el)) { \
676 (head) = (add); \
677 (add)->next = (el)->next; \
678 if ((el)->next == NULL) { \
679 (add)->prev = (add); \
680 } else { \
681 (add)->prev = (el)->prev; \
682 (add)->next->prev = (add); \
684 } else { \
685 (add)->next = (el)->next; \
686 (add)->prev = (el)->prev; \
687 (add)->prev->next = (add); \
688 if ((el)->next == NULL) { \
689 (head)->prev = (add); \
690 } else { \
691 (add)->next->prev = (add); \
694 } while (0)
696 #define DL_REPLACE_ELEM(head, el, add) \
697 DL_REPLACE_ELEM2(head, el, add, prev, next)
699 #define DL_PREPEND_ELEM2(head, el, add, prev, next) \
700 do { \
701 if (el) { \
702 assert((head) != NULL); \
703 assert((add) != NULL); \
704 (add)->next = (el); \
705 (add)->prev = (el)->prev; \
706 (el)->prev = (add); \
707 if ((head) == (el)) { \
708 (head) = (add); \
709 } else { \
710 (add)->prev->next = (add); \
712 } else { \
713 DL_APPEND2(head, add, prev, next); \
715 } while (0) \
717 #define DL_PREPEND_ELEM(head, el, add) \
718 DL_PREPEND_ELEM2(head, el, add, prev, next)
720 #define DL_APPEND_ELEM2(head, el, add, prev, next) \
721 do { \
722 if (el) { \
723 assert((head) != NULL); \
724 assert((add) != NULL); \
725 (add)->next = (el)->next; \
726 (add)->prev = (el); \
727 (el)->next = (add); \
728 if ((add)->next) { \
729 (add)->next->prev = (add); \
730 } else { \
731 (head)->prev = (add); \
733 } else { \
734 DL_PREPEND2(head, add, prev, next); \
736 } while (0) \
738 #define DL_APPEND_ELEM(head, el, add) \
739 DL_APPEND_ELEM2(head, el, add, prev, next)
741 /******************************************************************************
742 * circular doubly linked list macros *
743 *****************************************************************************/
744 #define CDL_APPEND(head,add) \
745 CDL_APPEND2(head,add,prev,next)
747 #define CDL_APPEND2(head,add,prev,next) \
748 do { \
749 if (head) { \
750 (add)->prev = (head)->prev; \
751 (add)->next = (head); \
752 (head)->prev = (add); \
753 (add)->prev->next = (add); \
754 } else { \
755 (add)->prev = (add); \
756 (add)->next = (add); \
757 (head) = (add); \
759 } while (0)
761 #define CDL_PREPEND(head,add) \
762 CDL_PREPEND2(head,add,prev,next)
764 #define CDL_PREPEND2(head,add,prev,next) \
765 do { \
766 if (head) { \
767 (add)->prev = (head)->prev; \
768 (add)->next = (head); \
769 (head)->prev = (add); \
770 (add)->prev->next = (add); \
771 } else { \
772 (add)->prev = (add); \
773 (add)->next = (add); \
775 (head) = (add); \
776 } while (0)
778 #define CDL_DELETE(head,del) \
779 CDL_DELETE2(head,del,prev,next)
781 #define CDL_DELETE2(head,del,prev,next) \
782 do { \
783 if (((head)==(del)) && ((head)->next == (head))) { \
784 (head) = NULL; \
785 } else { \
786 (del)->next->prev = (del)->prev; \
787 (del)->prev->next = (del)->next; \
788 if ((del) == (head)) (head)=(del)->next; \
790 } while (0)
792 #define CDL_COUNT(head,el,counter) \
793 CDL_COUNT2(head,el,counter,next) \
795 #define CDL_COUNT2(head, el, counter,next) \
796 do { \
797 (counter) = 0; \
798 CDL_FOREACH2(head,el,next) { ++(counter); } \
799 } while (0)
801 #define CDL_FOREACH(head,el) \
802 CDL_FOREACH2(head,el,next)
804 #define CDL_FOREACH2(head,el,next) \
805 for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next))
807 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
808 CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
810 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
811 for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \
812 (el) && ((tmp2) = (el)->next, 1); \
813 (el) = ((el) == (tmp1) ? NULL : (tmp2)))
815 #define CDL_SEARCH_SCALAR(head,out,field,val) \
816 CDL_SEARCH_SCALAR2(head,out,field,val,next)
818 #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
819 do { \
820 CDL_FOREACH2(head,out,next) { \
821 if ((out)->field == (val)) break; \
823 } while (0)
825 #define CDL_SEARCH(head,out,elt,cmp) \
826 CDL_SEARCH2(head,out,elt,cmp,next)
828 #define CDL_SEARCH2(head,out,elt,cmp,next) \
829 do { \
830 CDL_FOREACH2(head,out,next) { \
831 if ((cmp(out,elt))==0) break; \
833 } while (0)
835 #define CDL_REPLACE_ELEM2(head, el, add, prev, next) \
836 do { \
837 assert((head) != NULL); \
838 assert((el) != NULL); \
839 assert((add) != NULL); \
840 if ((el)->next == (el)) { \
841 (add)->next = (add); \
842 (add)->prev = (add); \
843 (head) = (add); \
844 } else { \
845 (add)->next = (el)->next; \
846 (add)->prev = (el)->prev; \
847 (add)->next->prev = (add); \
848 (add)->prev->next = (add); \
849 if ((head) == (el)) { \
850 (head) = (add); \
853 } while (0)
855 #define CDL_REPLACE_ELEM(head, el, add) \
856 CDL_REPLACE_ELEM2(head, el, add, prev, next)
858 #define CDL_PREPEND_ELEM2(head, el, add, prev, next) \
859 do { \
860 if (el) { \
861 assert((head) != NULL); \
862 assert((add) != NULL); \
863 (add)->next = (el); \
864 (add)->prev = (el)->prev; \
865 (el)->prev = (add); \
866 (add)->prev->next = (add); \
867 if ((head) == (el)) { \
868 (head) = (add); \
870 } else { \
871 CDL_APPEND2(head, add, prev, next); \
873 } while (0)
875 #define CDL_PREPEND_ELEM(head, el, add) \
876 CDL_PREPEND_ELEM2(head, el, add, prev, next)
878 #define CDL_APPEND_ELEM2(head, el, add, prev, next) \
879 do { \
880 if (el) { \
881 assert((head) != NULL); \
882 assert((add) != NULL); \
883 (add)->next = (el)->next; \
884 (add)->prev = (el); \
885 (el)->next = (add); \
886 (add)->next->prev = (add); \
887 } else { \
888 CDL_PREPEND2(head, add, prev, next); \
890 } while (0)
892 #define CDL_APPEND_ELEM(head, el, add) \
893 CDL_APPEND_ELEM2(head, el, add, prev, next)
895 #endif /* UTLIST_H */