libcoap  4.2.1
utlist.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2007-2017, 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 
24 #ifndef UTLIST_H
25 #define UTLIST_H
26 
27 #define UTLIST_VERSION 2.0.2
28 
29 #include <assert.h>
30 
31 /*
32  * This file contains macros to manipulate singly and doubly-linked lists.
33  *
34  * 1. LL_ macros: singly-linked lists.
35  * 2. DL_ macros: doubly-linked lists.
36  * 3. CDL_ macros: circular doubly-linked lists.
37  *
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.
41  *
42  * ----------------.EXAMPLE -------------------------
43  * struct item {
44  * int id;
45  * struct item *prev, *next;
46  * }
47  *
48  * struct item *list = NULL:
49  *
50  * int main() {
51  * struct item *item;
52  * ... allocate and populate item ...
53  * DL_APPEND(list, item);
54  * }
55  * --------------------------------------------------
56  *
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.
60  */
61 
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++ source) this code uses whatever method is needed
65  or, for VS2008 where neither is available, uses casting workarounds. */
66 #if !defined(LDECLTYPE) && !defined(NO_DECLTYPE)
67 #if defined(_MSC_VER) /* MS compiler */
68 #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
69 #define LDECLTYPE(x) decltype(x)
70 #else /* VS2008 or older (or VS2010 in C mode) */
71 #define NO_DECLTYPE
72 #endif
73 #elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
74 #define NO_DECLTYPE
75 #else /* GNU, Sun and other compilers */
76 #define LDECLTYPE(x) __typeof(x)
77 #endif
78 #endif
79 
80 /* for VS2008 we use some workarounds to get around the lack of decltype,
81  * namely, we always reassign our tmp variable to the list head if we need
82  * to dereference its prev/next pointers, and save/restore the real head.*/
83 #ifdef NO_DECLTYPE
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); }
89 /* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */
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); }
93 #else
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)
98 /* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */
99 #define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
100 #define UTLIST_RS(list)
101 #define UTLIST_CASTASGN(a,b) (a)=(b)
102 #endif
103 
104 /******************************************************************************
105  * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
106  * Unwieldy variable names used here to avoid shadowing passed-in variables. *
107  *****************************************************************************/
108 #define LL_SORT(list, cmp) \
109  LL_SORT2(list, cmp, next)
110 
111 #define LL_SORT2(list, cmp, next) \
112 do { \
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; \
119  if (list) { \
120  _ls_insize = 1; \
121  _ls_looping = 1; \
122  while (_ls_looping) { \
123  UTLIST_CASTASGN(_ls_p,list); \
124  (list) = NULL; \
125  _ls_tail = NULL; \
126  _ls_nmerges = 0; \
127  while (_ls_p) { \
128  _ls_nmerges++; \
129  _ls_q = _ls_p; \
130  _ls_psize = 0; \
131  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
132  _ls_psize++; \
133  UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \
134  if (!_ls_q) break; \
135  } \
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--; \
147  } else { \
148  _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
149  UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
150  } \
151  if (_ls_tail) { \
152  UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
153  } else { \
154  UTLIST_CASTASGN(list,_ls_e); \
155  } \
156  _ls_tail = _ls_e; \
157  } \
158  _ls_p = _ls_q; \
159  } \
160  if (_ls_tail) { \
161  UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \
162  } \
163  if (_ls_nmerges <= 1) { \
164  _ls_looping=0; \
165  } \
166  _ls_insize *= 2; \
167  } \
168  } \
169 } while (0)
170 
171 
172 #define DL_SORT(list, cmp) \
173  DL_SORT2(list, cmp, prev, next)
174 
175 #define DL_SORT2(list, cmp, prev, next) \
176 do { \
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; \
183  if (list) { \
184  _ls_insize = 1; \
185  _ls_looping = 1; \
186  while (_ls_looping) { \
187  UTLIST_CASTASGN(_ls_p,list); \
188  (list) = NULL; \
189  _ls_tail = NULL; \
190  _ls_nmerges = 0; \
191  while (_ls_p) { \
192  _ls_nmerges++; \
193  _ls_q = _ls_p; \
194  _ls_psize = 0; \
195  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
196  _ls_psize++; \
197  UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \
198  if (!_ls_q) break; \
199  } \
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--; \
211  } else { \
212  _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \
213  UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \
214  } \
215  if (_ls_tail) { \
216  UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
217  } else { \
218  UTLIST_CASTASGN(list,_ls_e); \
219  } \
220  UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \
221  _ls_tail = _ls_e; \
222  } \
223  _ls_p = _ls_q; \
224  } \
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) { \
228  _ls_looping=0; \
229  } \
230  _ls_insize *= 2; \
231  } \
232  } \
233 } while (0)
234 
235 #define CDL_SORT(list, cmp) \
236  CDL_SORT2(list, cmp, prev, next)
237 
238 #define CDL_SORT2(list, cmp, prev, next) \
239 do { \
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; \
247  if (list) { \
248  _ls_insize = 1; \
249  _ls_looping = 1; \
250  while (_ls_looping) { \
251  UTLIST_CASTASGN(_ls_p,list); \
252  UTLIST_CASTASGN(_ls_oldhead,list); \
253  (list) = NULL; \
254  _ls_tail = NULL; \
255  _ls_nmerges = 0; \
256  while (_ls_p) { \
257  _ls_nmerges++; \
258  _ls_q = _ls_p; \
259  _ls_psize = 0; \
260  for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
261  _ls_psize++; \
262  UTLIST_SV(_ls_q,list); \
263  if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \
264  _ls_q = NULL; \
265  } else { \
266  _ls_q = UTLIST_NEXT(_ls_q,list,next); \
267  } \
268  UTLIST_RS(list); \
269  if (!_ls_q) break; \
270  } \
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; } \
285  } else { \
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; } \
289  } \
290  if (_ls_tail) { \
291  UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
292  } else { \
293  UTLIST_CASTASGN(list,_ls_e); \
294  } \
295  UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \
296  _ls_tail = _ls_e; \
297  } \
298  _ls_p = _ls_q; \
299  } \
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) { \
304  _ls_looping=0; \
305  } \
306  _ls_insize *= 2; \
307  } \
308  } \
309 } while (0)
310 
311 /******************************************************************************
312  * singly linked list macros (non-circular) *
313  *****************************************************************************/
314 #define LL_PREPEND(head,add) \
315  LL_PREPEND2(head,add,next)
316 
317 #define LL_PREPEND2(head,add,next) \
318 do { \
319  (add)->next = (head); \
320  (head) = (add); \
321 } while (0)
322 
323 #define LL_CONCAT(head1,head2) \
324  LL_CONCAT2(head1,head2,next)
325 
326 #define LL_CONCAT2(head1,head2,next) \
327 do { \
328  LDECLTYPE(head1) _tmp; \
329  if (head1) { \
330  _tmp = (head1); \
331  while (_tmp->next) { _tmp = _tmp->next; } \
332  _tmp->next=(head2); \
333  } else { \
334  (head1)=(head2); \
335  } \
336 } while (0)
337 
338 #define LL_APPEND(head,add) \
339  LL_APPEND2(head,add,next)
340 
341 #define LL_APPEND2(head,add,next) \
342 do { \
343  LDECLTYPE(head) _tmp; \
344  (add)->next=NULL; \
345  if (head) { \
346  _tmp = (head); \
347  while (_tmp->next) { _tmp = _tmp->next; } \
348  _tmp->next=(add); \
349  } else { \
350  (head)=(add); \
351  } \
352 } while (0)
353 
354 #define LL_INSERT_INORDER(head,add,cmp) \
355  LL_INSERT_INORDER2(head,add,cmp,next)
356 
357 #define LL_INSERT_INORDER2(head,add,cmp,next) \
358 do { \
359  LDECLTYPE(head) _tmp; \
360  if (head) { \
361  LL_LOWER_BOUND(head, _tmp, add, cmp); \
362  LL_APPEND_ELEM(head, _tmp, add); \
363  } else { \
364  (head) = (add); \
365  (head)->next = NULL; \
366  } \
367 } while (0)
368 
369 #define LL_LOWER_BOUND(head,elt,like,cmp) \
370  LL_LOWER_BOUND2(head,elt,like,cmp,next)
371 
372 #define LL_LOWER_BOUND2(head,elt,like,cmp,next) \
373  do { \
374  if ((head) == NULL || (cmp(head, like)) >= 0) { \
375  (elt) = NULL; \
376  } else { \
377  for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \
378  if (cmp((elt)->next, like) >= 0) { \
379  break; \
380  } \
381  } \
382  } \
383  } while (0)
384 
385 #define LL_DELETE(head,del) \
386  LL_DELETE2(head,del,next)
387 
388 #define LL_DELETE2(head,del,next) \
389 do { \
390  LDECLTYPE(head) _tmp; \
391  if ((head) == (del)) { \
392  (head)=(head)->next; \
393  } else { \
394  _tmp = (head); \
395  while (_tmp->next && (_tmp->next != (del))) { \
396  _tmp = _tmp->next; \
397  } \
398  if (_tmp->next) { \
399  _tmp->next = (del)->next; \
400  } \
401  } \
402 } while (0)
403 
404 #define LL_COUNT(head,el,counter) \
405  LL_COUNT2(head,el,counter,next) \
406 
407 #define LL_COUNT2(head,el,counter,next) \
408 do { \
409  (counter) = 0; \
410  LL_FOREACH2(head,el,next) { ++(counter); } \
411 } while (0)
412 
413 #define LL_FOREACH(head,el) \
414  LL_FOREACH2(head,el,next)
415 
416 #define LL_FOREACH2(head,el,next) \
417  for ((el) = (head); el; (el) = (el)->next)
418 
419 #define LL_FOREACH_SAFE(head,el,tmp) \
420  LL_FOREACH_SAFE2(head,el,tmp,next)
421 
422 #define LL_FOREACH_SAFE2(head,el,tmp,next) \
423  for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
424 
425 #define LL_SEARCH_SCALAR(head,out,field,val) \
426  LL_SEARCH_SCALAR2(head,out,field,val,next)
427 
428 #define LL_SEARCH_SCALAR2(head,out,field,val,next) \
429 do { \
430  LL_FOREACH2(head,out,next) { \
431  if ((out)->field == (val)) break; \
432  } \
433 } while (0)
434 
435 #define LL_SEARCH(head,out,elt,cmp) \
436  LL_SEARCH2(head,out,elt,cmp,next)
437 
438 #define LL_SEARCH2(head,out,elt,cmp,next) \
439 do { \
440  LL_FOREACH2(head,out,next) { \
441  if ((cmp(out,elt))==0) break; \
442  } \
443 } while (0)
444 
445 #define LL_REPLACE_ELEM2(head, el, add, next) \
446 do { \
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)) { \
453  (head) = (add); \
454  } else { \
455  _tmp = (head); \
456  while (_tmp->next && (_tmp->next != (el))) { \
457  _tmp = _tmp->next; \
458  } \
459  if (_tmp->next) { \
460  _tmp->next = (add); \
461  } \
462  } \
463 } while (0)
464 
465 #define LL_REPLACE_ELEM(head, el, add) \
466  LL_REPLACE_ELEM2(head, el, add, next)
467 
468 #define LL_PREPEND_ELEM2(head, el, add, next) \
469 do { \
470  if (el) { \
471  LDECLTYPE(head) _tmp; \
472  assert((head) != NULL); \
473  assert((add) != NULL); \
474  (add)->next = (el); \
475  if ((head) == (el)) { \
476  (head) = (add); \
477  } else { \
478  _tmp = (head); \
479  while (_tmp->next && (_tmp->next != (el))) { \
480  _tmp = _tmp->next; \
481  } \
482  if (_tmp->next) { \
483  _tmp->next = (add); \
484  } \
485  } \
486  } else { \
487  LL_APPEND2(head, add, next); \
488  } \
489 } while (0) \
490 
491 #define LL_PREPEND_ELEM(head, el, add) \
492  LL_PREPEND_ELEM2(head, el, add, next)
493 
494 #define LL_APPEND_ELEM2(head, el, add, next) \
495 do { \
496  if (el) { \
497  assert((head) != NULL); \
498  assert((add) != NULL); \
499  (add)->next = (el)->next; \
500  (el)->next = (add); \
501  } else { \
502  LL_PREPEND2(head, add, next); \
503  } \
504 } while (0) \
505 
506 #define LL_APPEND_ELEM(head, el, add) \
507  LL_APPEND_ELEM2(head, el, add, next)
508 
509 #ifdef NO_DECLTYPE
510 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
511 
512 #undef LL_CONCAT2
513 #define LL_CONCAT2(head1,head2,next) \
514 do { \
515  char *_tmp; \
516  if (head1) { \
517  _tmp = (char*)(head1); \
518  while ((head1)->next) { (head1) = (head1)->next; } \
519  (head1)->next = (head2); \
520  UTLIST_RS(head1); \
521  } else { \
522  (head1)=(head2); \
523  } \
524 } while (0)
525 
526 #undef LL_APPEND2
527 #define LL_APPEND2(head,add,next) \
528 do { \
529  if (head) { \
530  (add)->next = head; /* use add->next as a temp variable */ \
531  while ((add)->next->next) { (add)->next = (add)->next->next; } \
532  (add)->next->next=(add); \
533  } else { \
534  (head)=(add); \
535  } \
536  (add)->next=NULL; \
537 } while (0)
538 
539 #undef LL_INSERT_INORDER2
540 #define LL_INSERT_INORDER2(head,add,cmp,next) \
541 do { \
542  if ((head) == NULL || (cmp(head, add)) >= 0) { \
543  (add)->next = (head); \
544  (head) = (add); \
545  } else { \
546  char *_tmp = (char*)(head); \
547  while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \
548  (head) = (head)->next; \
549  } \
550  (add)->next = (head)->next; \
551  (head)->next = (add); \
552  UTLIST_RS(head); \
553  } \
554 } while (0)
555 
556 #undef LL_DELETE2
557 #define LL_DELETE2(head,del,next) \
558 do { \
559  if ((head) == (del)) { \
560  (head)=(head)->next; \
561  } else { \
562  char *_tmp = (char*)(head); \
563  while ((head)->next && ((head)->next != (del))) { \
564  (head) = (head)->next; \
565  } \
566  if ((head)->next) { \
567  (head)->next = ((del)->next); \
568  } \
569  UTLIST_RS(head); \
570  } \
571 } while (0)
572 
573 #undef LL_REPLACE_ELEM2
574 #define LL_REPLACE_ELEM2(head, el, add, next) \
575 do { \
576  assert((head) != NULL); \
577  assert((el) != NULL); \
578  assert((add) != NULL); \
579  if ((head) == (el)) { \
580  (head) = (add); \
581  } else { \
582  (add)->next = head; \
583  while ((add)->next->next && ((add)->next->next != (el))) { \
584  (add)->next = (add)->next->next; \
585  } \
586  if ((add)->next->next) { \
587  (add)->next->next = (add); \
588  } \
589  } \
590  (add)->next = (el)->next; \
591 } while (0)
592 
593 #undef LL_PREPEND_ELEM2
594 #define LL_PREPEND_ELEM2(head, el, add, next) \
595 do { \
596  if (el) { \
597  assert((head) != NULL); \
598  assert((add) != NULL); \
599  if ((head) == (el)) { \
600  (head) = (add); \
601  } else { \
602  (add)->next = (head); \
603  while ((add)->next->next && ((add)->next->next != (el))) { \
604  (add)->next = (add)->next->next; \
605  } \
606  if ((add)->next->next) { \
607  (add)->next->next = (add); \
608  } \
609  } \
610  (add)->next = (el); \
611  } else { \
612  LL_APPEND2(head, add, next); \
613  } \
614 } while (0) \
615 
616 #endif /* NO_DECLTYPE */
617 
618 /******************************************************************************
619  * doubly linked list macros (non-circular) *
620  *****************************************************************************/
621 #define DL_PREPEND(head,add) \
622  DL_PREPEND2(head,add,prev,next)
623 
624 #define DL_PREPEND2(head,add,prev,next) \
625 do { \
626  (add)->next = (head); \
627  if (head) { \
628  (add)->prev = (head)->prev; \
629  (head)->prev = (add); \
630  } else { \
631  (add)->prev = (add); \
632  } \
633  (head) = (add); \
634 } while (0)
635 
636 #define DL_APPEND(head,add) \
637  DL_APPEND2(head,add,prev,next)
638 
639 #define DL_APPEND2(head,add,prev,next) \
640 do { \
641  if (head) { \
642  (add)->prev = (head)->prev; \
643  (head)->prev->next = (add); \
644  (head)->prev = (add); \
645  (add)->next = NULL; \
646  } else { \
647  (head)=(add); \
648  (head)->prev = (head); \
649  (head)->next = NULL; \
650  } \
651 } while (0)
652 
653 #define DL_INSERT_INORDER(head,add,cmp) \
654  DL_INSERT_INORDER2(head,add,cmp,next)
655 
656 #define DL_INSERT_INORDER2(head,add,cmp,next) \
657 do { \
658  LDECLTYPE(head) _tmp; \
659  if (head) { \
660  DL_LOWER_BOUND(head, _tmp, add, cmp); \
661  DL_APPEND_ELEM(head, _tmp, add); \
662  } else { \
663  (head) = (add); \
664  (head)->prev = (head); \
665  (head)->next = NULL; \
666  } \
667 } while (0)
668 
669 #define DL_LOWER_BOUND(head,elt,like,cmp) \
670  DL_LOWER_BOUND2(head,elt,like,cmp,next)
671 
672 #define DL_LOWER_BOUND2(head,elt,like,cmp,next) \
673 do { \
674  if ((head) == NULL || (cmp(head, like)) >= 0) { \
675  (elt) = NULL; \
676  } else { \
677  for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \
678  if ((cmp((elt)->next, like)) >= 0) { \
679  break; \
680  } \
681  } \
682  } \
683 } while (0)
684 
685 #define DL_CONCAT(head1,head2) \
686  DL_CONCAT2(head1,head2,prev,next)
687 
688 #define DL_CONCAT2(head1,head2,prev,next) \
689 do { \
690  LDECLTYPE(head1) _tmp; \
691  if (head2) { \
692  if (head1) { \
693  UTLIST_CASTASGN(_tmp, (head2)->prev); \
694  (head2)->prev = (head1)->prev; \
695  (head1)->prev->next = (head2); \
696  UTLIST_CASTASGN((head1)->prev, _tmp); \
697  } else { \
698  (head1)=(head2); \
699  } \
700  } \
701 } while (0)
702 
703 #define DL_DELETE(head,del) \
704  DL_DELETE2(head,del,prev,next)
705 
706 #define DL_DELETE2(head,del,prev,next) \
707 do { \
708  assert((head) != NULL); \
709  assert((del)->prev != NULL); \
710  if ((del)->prev == (del)) { \
711  (head)=NULL; \
712  } else if ((del)==(head)) { \
713  (del)->next->prev = (del)->prev; \
714  (head) = (del)->next; \
715  } else { \
716  (del)->prev->next = (del)->next; \
717  if ((del)->next) { \
718  (del)->next->prev = (del)->prev; \
719  } else { \
720  (head)->prev = (del)->prev; \
721  } \
722  } \
723 } while (0)
724 
725 #define DL_COUNT(head,el,counter) \
726  DL_COUNT2(head,el,counter,next) \
727 
728 #define DL_COUNT2(head,el,counter,next) \
729 do { \
730  (counter) = 0; \
731  DL_FOREACH2(head,el,next) { ++(counter); } \
732 } while (0)
733 
734 #define DL_FOREACH(head,el) \
735  DL_FOREACH2(head,el,next)
736 
737 #define DL_FOREACH2(head,el,next) \
738  for ((el) = (head); el; (el) = (el)->next)
739 
740 /* this version is safe for deleting the elements during iteration */
741 #define DL_FOREACH_SAFE(head,el,tmp) \
742  DL_FOREACH_SAFE2(head,el,tmp,next)
743 
744 #define DL_FOREACH_SAFE2(head,el,tmp,next) \
745  for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
746 
747 /* these are identical to their singly-linked list counterparts */
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
752 
753 #define DL_REPLACE_ELEM2(head, el, add, prev, next) \
754 do { \
755  assert((head) != NULL); \
756  assert((el) != NULL); \
757  assert((add) != NULL); \
758  if ((head) == (el)) { \
759  (head) = (add); \
760  (add)->next = (el)->next; \
761  if ((el)->next == NULL) { \
762  (add)->prev = (add); \
763  } else { \
764  (add)->prev = (el)->prev; \
765  (add)->next->prev = (add); \
766  } \
767  } else { \
768  (add)->next = (el)->next; \
769  (add)->prev = (el)->prev; \
770  (add)->prev->next = (add); \
771  if ((el)->next == NULL) { \
772  (head)->prev = (add); \
773  } else { \
774  (add)->next->prev = (add); \
775  } \
776  } \
777 } while (0)
778 
779 #define DL_REPLACE_ELEM(head, el, add) \
780  DL_REPLACE_ELEM2(head, el, add, prev, next)
781 
782 #define DL_PREPEND_ELEM2(head, el, add, prev, next) \
783 do { \
784  if (el) { \
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)) { \
791  (head) = (add); \
792  } else { \
793  (add)->prev->next = (add); \
794  } \
795  } else { \
796  DL_APPEND2(head, add, prev, next); \
797  } \
798 } while (0) \
799 
800 #define DL_PREPEND_ELEM(head, el, add) \
801  DL_PREPEND_ELEM2(head, el, add, prev, next)
802 
803 #define DL_APPEND_ELEM2(head, el, add, prev, next) \
804 do { \
805  if (el) { \
806  assert((head) != NULL); \
807  assert((add) != NULL); \
808  (add)->next = (el)->next; \
809  (add)->prev = (el); \
810  (el)->next = (add); \
811  if ((add)->next) { \
812  (add)->next->prev = (add); \
813  } else { \
814  (head)->prev = (add); \
815  } \
816  } else { \
817  DL_PREPEND2(head, add, prev, next); \
818  } \
819 } while (0) \
820 
821 #define DL_APPEND_ELEM(head, el, add) \
822  DL_APPEND_ELEM2(head, el, add, prev, next)
823 
824 #ifdef NO_DECLTYPE
825 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
826 
827 #undef DL_INSERT_INORDER2
828 #define DL_INSERT_INORDER2(head,add,cmp,next) \
829 do { \
830  if ((head) == NULL) { \
831  (add)->prev = (add); \
832  (add)->next = NULL; \
833  (head) = (add); \
834  } else if ((cmp(head, add)) >= 0) { \
835  (add)->prev = (head)->prev; \
836  (add)->next = (head); \
837  (head)->prev = (add); \
838  (head) = (add); \
839  } else { \
840  char *_tmp = (char*)(head); \
841  while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \
842  (head) = (head)->next; \
843  } \
844  (add)->prev = (head); \
845  (add)->next = (head)->next; \
846  (head)->next = (add); \
847  UTLIST_RS(head); \
848  if ((add)->next) { \
849  (add)->next->prev = (add); \
850  } else { \
851  (head)->prev = (add); \
852  } \
853  } \
854 } while (0)
855 #endif /* NO_DECLTYPE */
856 
857 /******************************************************************************
858  * circular doubly linked list macros *
859  *****************************************************************************/
860 #define CDL_APPEND(head,add) \
861  CDL_APPEND2(head,add,prev,next)
862 
863 #define CDL_APPEND2(head,add,prev,next) \
864 do { \
865  if (head) { \
866  (add)->prev = (head)->prev; \
867  (add)->next = (head); \
868  (head)->prev = (add); \
869  (add)->prev->next = (add); \
870  } else { \
871  (add)->prev = (add); \
872  (add)->next = (add); \
873  (head) = (add); \
874  } \
875 } while (0)
876 
877 #define CDL_PREPEND(head,add) \
878  CDL_PREPEND2(head,add,prev,next)
879 
880 #define CDL_PREPEND2(head,add,prev,next) \
881 do { \
882  if (head) { \
883  (add)->prev = (head)->prev; \
884  (add)->next = (head); \
885  (head)->prev = (add); \
886  (add)->prev->next = (add); \
887  } else { \
888  (add)->prev = (add); \
889  (add)->next = (add); \
890  } \
891  (head) = (add); \
892 } while (0)
893 
894 #define CDL_INSERT_INORDER(head,add,cmp) \
895  CDL_INSERT_INORDER2(head,add,cmp,next)
896 
897 #define CDL_INSERT_INORDER2(head,add,cmp,next) \
898 do { \
899  LDECLTYPE(head) _tmp; \
900  if (head) { \
901  CDL_LOWER_BOUND(head, _tmp, add, cmp); \
902  CDL_APPEND_ELEM(head, _tmp, add); \
903  } else { \
904  (head) = (add); \
905  (head)->next = (head); \
906  (head)->prev = (head); \
907  } \
908 } while (0)
909 
910 #define CDL_LOWER_BOUND(head,elt,like,cmp) \
911  CDL_LOWER_BOUND2(head,elt,like,cmp,next)
912 
913 #define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \
914 do { \
915  if ((head) == NULL || (cmp(head, like)) >= 0) { \
916  (elt) = NULL; \
917  } else { \
918  for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \
919  if ((cmp((elt)->next, like)) >= 0) { \
920  break; \
921  } \
922  } \
923  } \
924 } while (0)
925 
926 #define CDL_DELETE(head,del) \
927  CDL_DELETE2(head,del,prev,next)
928 
929 #define CDL_DELETE2(head,del,prev,next) \
930 do { \
931  if (((head)==(del)) && ((head)->next == (head))) { \
932  (head) = NULL; \
933  } else { \
934  (del)->next->prev = (del)->prev; \
935  (del)->prev->next = (del)->next; \
936  if ((del) == (head)) (head)=(del)->next; \
937  } \
938 } while (0)
939 
940 #define CDL_COUNT(head,el,counter) \
941  CDL_COUNT2(head,el,counter,next) \
942 
943 #define CDL_COUNT2(head, el, counter,next) \
944 do { \
945  (counter) = 0; \
946  CDL_FOREACH2(head,el,next) { ++(counter); } \
947 } while (0)
948 
949 #define CDL_FOREACH(head,el) \
950  CDL_FOREACH2(head,el,next)
951 
952 #define CDL_FOREACH2(head,el,next) \
953  for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next))
954 
955 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
956  CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
957 
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)))
962 
963 #define CDL_SEARCH_SCALAR(head,out,field,val) \
964  CDL_SEARCH_SCALAR2(head,out,field,val,next)
965 
966 #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
967 do { \
968  CDL_FOREACH2(head,out,next) { \
969  if ((out)->field == (val)) break; \
970  } \
971 } while (0)
972 
973 #define CDL_SEARCH(head,out,elt,cmp) \
974  CDL_SEARCH2(head,out,elt,cmp,next)
975 
976 #define CDL_SEARCH2(head,out,elt,cmp,next) \
977 do { \
978  CDL_FOREACH2(head,out,next) { \
979  if ((cmp(out,elt))==0) break; \
980  } \
981 } while (0)
982 
983 #define CDL_REPLACE_ELEM2(head, el, add, prev, next) \
984 do { \
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); \
991  (head) = (add); \
992  } else { \
993  (add)->next = (el)->next; \
994  (add)->prev = (el)->prev; \
995  (add)->next->prev = (add); \
996  (add)->prev->next = (add); \
997  if ((head) == (el)) { \
998  (head) = (add); \
999  } \
1000  } \
1001 } while (0)
1002 
1003 #define CDL_REPLACE_ELEM(head, el, add) \
1004  CDL_REPLACE_ELEM2(head, el, add, prev, next)
1005 
1006 #define CDL_PREPEND_ELEM2(head, el, add, prev, next) \
1007 do { \
1008  if (el) { \
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)) { \
1016  (head) = (add); \
1017  } \
1018  } else { \
1019  CDL_APPEND2(head, add, prev, next); \
1020  } \
1021 } while (0)
1022 
1023 #define CDL_PREPEND_ELEM(head, el, add) \
1024  CDL_PREPEND_ELEM2(head, el, add, prev, next)
1025 
1026 #define CDL_APPEND_ELEM2(head, el, add, prev, next) \
1027 do { \
1028  if (el) { \
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); \
1035  } else { \
1036  CDL_PREPEND2(head, add, prev, next); \
1037  } \
1038 } while (0)
1039 
1040 #define CDL_APPEND_ELEM(head, el, add) \
1041  CDL_APPEND_ELEM2(head, el, add, prev, next)
1042 
1043 #ifdef NO_DECLTYPE
1044 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
1045 
1046 #undef CDL_INSERT_INORDER2
1047 #define CDL_INSERT_INORDER2(head,add,cmp,next) \
1048 do { \
1049  if ((head) == NULL) { \
1050  (add)->prev = (add); \
1051  (add)->next = (add); \
1052  (head) = (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); \
1058  (head) = (add); \
1059  } else { \
1060  char *_tmp = (char*)(head); \
1061  while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \
1062  (head) = (head)->next; \
1063  } \
1064  (add)->prev = (head); \
1065  (add)->next = (head)->next; \
1066  (add)->next->prev = (add); \
1067  (head)->next = (add); \
1068  UTLIST_RS(head); \
1069  } \
1070 } while (0)
1071 #endif /* NO_DECLTYPE */
1072 
1073 #endif /* UTLIST_H */