utlist.h 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /*
  2. Copyright (c) 2007-2013, Troy D. Hanson http://troydhanson.github.com/uthash/
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  9. IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  10. TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  11. PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  12. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  13. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  14. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  15. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  16. LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  17. NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  18. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  19. */
  20. #ifndef UTLIST_H
  21. #define UTLIST_H
  22. /// @cond DO_NOT_SHOW
  23. #define UTLIST_VERSION 1.9.8
  24. #include <assert.h>
  25. /*
  26. * This file contains macros to manipulate singly and doubly-linked lists.
  27. *
  28. * 1. LL_ macros: singly-linked lists.
  29. * 2. DL_ macros: doubly-linked lists.
  30. * 3. CDL_ macros: circular doubly-linked lists.
  31. *
  32. * To use singly-linked lists, your structure must have a "next" pointer.
  33. * To use doubly-linked lists, your structure must "prev" and "next" pointers.
  34. * Either way, the pointer to the head of the list must be initialized to NULL.
  35. *
  36. * ----------------.EXAMPLE -------------------------
  37. * struct item {
  38. * int id;
  39. * struct item *prev, *next;
  40. * }
  41. *
  42. * struct item *list = NULL:
  43. *
  44. * int main() {
  45. * struct item *item;
  46. * ... allocate and populate item ...
  47. * DL_APPEND(list, item);
  48. * }
  49. * --------------------------------------------------
  50. *
  51. * For doubly-linked lists, the append and delete macros are O(1)
  52. * For singly-linked lists, append and delete are O(n) but prepend is O(1)
  53. * The sort macro is O(n log(n)) for all types of single/double/circular lists.
  54. */
  55. /* These macros use decltype or the earlier __typeof GNU extension.
  56. As decltype is only available in newer compilers (VS2010 or gcc 4.3+
  57. when compiling c++ code), this code uses whatever method is needed
  58. or, for VS2008 where neither is available, uses casting workarounds. */
  59. #ifdef _MSC_VER /* MS compiler */
  60. #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
  61. #define LDECLTYPE(x) decltype(x)
  62. #else /* VS2008 or older (or VS2010 in C mode) */
  63. #define NO_DECLTYPE
  64. #define LDECLTYPE(x) char*
  65. #endif
  66. #else /* GNU, Sun and other compilers */
  67. #define LDECLTYPE(x) __typeof(x)
  68. #endif
  69. /* for VS2008 we use some workarounds to get around the lack of decltype,
  70. * namely, we always reassign our tmp variable to the list head if we need
  71. * to dereference its prev/next pointers, and save/restore the real head.*/
  72. #ifdef NO_DECLTYPE
  73. #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
  74. #define _NEXT(elt,list,next) ((char*)((list)->next))
  75. #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
  76. /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
  77. #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
  78. #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
  79. #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
  80. #else
  81. #define _SV(elt,list)
  82. #define _NEXT(elt,list,next) ((elt)->next)
  83. #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
  84. /* #define _PREV(elt,list,prev) ((elt)->prev) */
  85. #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
  86. #define _RS(list)
  87. #define _CASTASGN(a,b) (a)=(b)
  88. #endif
  89. /******************************************************************************
  90. * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
  91. * Unwieldy variable names used here to avoid shadowing passed-in variables. *
  92. *****************************************************************************/
  93. #define LL_SORT(list, cmp) \
  94. LL_SORT2(list, cmp, next)
  95. #define LL_SORT2(list, cmp, next) \
  96. do { \
  97. LDECLTYPE(list) _ls_p; \
  98. LDECLTYPE(list) _ls_q; \
  99. LDECLTYPE(list) _ls_e; \
  100. LDECLTYPE(list) _ls_tail; \
  101. int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
  102. if (list) { \
  103. _ls_insize = 1; \
  104. _ls_looping = 1; \
  105. while (_ls_looping) { \
  106. _CASTASGN(_ls_p,list); \
  107. list = NULL; \
  108. _ls_tail = NULL; \
  109. _ls_nmerges = 0; \
  110. while (_ls_p) { \
  111. _ls_nmerges++; \
  112. _ls_q = _ls_p; \
  113. _ls_psize = 0; \
  114. for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
  115. _ls_psize++; \
  116. _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
  117. if (!_ls_q) break; \
  118. } \
  119. _ls_qsize = _ls_insize; \
  120. while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
  121. if (_ls_psize == 0) { \
  122. _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
  123. _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
  124. } else if (_ls_qsize == 0 || !_ls_q) { \
  125. _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
  126. _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
  127. } else if (cmp(_ls_p,_ls_q) <= 0) { \
  128. _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
  129. _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
  130. } else { \
  131. _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
  132. _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
  133. } \
  134. if (_ls_tail) { \
  135. _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
  136. } else { \
  137. _CASTASGN(list,_ls_e); \
  138. } \
  139. _ls_tail = _ls_e; \
  140. } \
  141. _ls_p = _ls_q; \
  142. } \
  143. if (_ls_tail) { \
  144. _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
  145. } \
  146. if (_ls_nmerges <= 1) { \
  147. _ls_looping=0; \
  148. } \
  149. _ls_insize *= 2; \
  150. } \
  151. } \
  152. } while (0)
  153. #define DL_SORT(list, cmp) \
  154. DL_SORT2(list, cmp, prev, next)
  155. #define DL_SORT2(list, cmp, prev, next) \
  156. do { \
  157. LDECLTYPE(list) _ls_p; \
  158. LDECLTYPE(list) _ls_q; \
  159. LDECLTYPE(list) _ls_e; \
  160. LDECLTYPE(list) _ls_tail; \
  161. int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
  162. if (list) { \
  163. _ls_insize = 1; \
  164. _ls_looping = 1; \
  165. while (_ls_looping) { \
  166. _CASTASGN(_ls_p,list); \
  167. list = NULL; \
  168. _ls_tail = NULL; \
  169. _ls_nmerges = 0; \
  170. while (_ls_p) { \
  171. _ls_nmerges++; \
  172. _ls_q = _ls_p; \
  173. _ls_psize = 0; \
  174. for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
  175. _ls_psize++; \
  176. _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list); \
  177. if (!_ls_q) break; \
  178. } \
  179. _ls_qsize = _ls_insize; \
  180. while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
  181. if (_ls_psize == 0) { \
  182. _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
  183. _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
  184. } else if (_ls_qsize == 0 || !_ls_q) { \
  185. _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
  186. _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
  187. } else if (cmp(_ls_p,_ls_q) <= 0) { \
  188. _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
  189. _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
  190. } else { \
  191. _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
  192. _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
  193. } \
  194. if (_ls_tail) { \
  195. _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
  196. } else { \
  197. _CASTASGN(list,_ls_e); \
  198. } \
  199. _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
  200. _ls_tail = _ls_e; \
  201. } \
  202. _ls_p = _ls_q; \
  203. } \
  204. _CASTASGN(list->prev, _ls_tail); \
  205. _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list); \
  206. if (_ls_nmerges <= 1) { \
  207. _ls_looping=0; \
  208. } \
  209. _ls_insize *= 2; \
  210. } \
  211. } \
  212. } while (0)
  213. #define CDL_SORT(list, cmp) \
  214. CDL_SORT2(list, cmp, prev, next)
  215. #define CDL_SORT2(list, cmp, prev, next) \
  216. do { \
  217. LDECLTYPE(list) _ls_p; \
  218. LDECLTYPE(list) _ls_q; \
  219. LDECLTYPE(list) _ls_e; \
  220. LDECLTYPE(list) _ls_tail; \
  221. LDECLTYPE(list) _ls_oldhead; \
  222. LDECLTYPE(list) _tmp; \
  223. int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
  224. if (list) { \
  225. _ls_insize = 1; \
  226. _ls_looping = 1; \
  227. while (_ls_looping) { \
  228. _CASTASGN(_ls_p,list); \
  229. _CASTASGN(_ls_oldhead,list); \
  230. list = NULL; \
  231. _ls_tail = NULL; \
  232. _ls_nmerges = 0; \
  233. while (_ls_p) { \
  234. _ls_nmerges++; \
  235. _ls_q = _ls_p; \
  236. _ls_psize = 0; \
  237. for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
  238. _ls_psize++; \
  239. _SV(_ls_q,list); \
  240. if (_NEXT(_ls_q,list,next) == _ls_oldhead) { \
  241. _ls_q = NULL; \
  242. } else { \
  243. _ls_q = _NEXT(_ls_q,list,next); \
  244. } \
  245. _RS(list); \
  246. if (!_ls_q) break; \
  247. } \
  248. _ls_qsize = _ls_insize; \
  249. while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
  250. if (_ls_psize == 0) { \
  251. _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
  252. _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
  253. if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
  254. } else if (_ls_qsize == 0 || !_ls_q) { \
  255. _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
  256. _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
  257. if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
  258. } else if (cmp(_ls_p,_ls_q) <= 0) { \
  259. _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = \
  260. _NEXT(_ls_p,list,next); _RS(list); _ls_psize--; \
  261. if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
  262. } else { \
  263. _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = \
  264. _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--; \
  265. if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
  266. } \
  267. if (_ls_tail) { \
  268. _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list); \
  269. } else { \
  270. _CASTASGN(list,_ls_e); \
  271. } \
  272. _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list); \
  273. _ls_tail = _ls_e; \
  274. } \
  275. _ls_p = _ls_q; \
  276. } \
  277. _CASTASGN(list->prev,_ls_tail); \
  278. _CASTASGN(_tmp,list); \
  279. _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list); \
  280. if (_ls_nmerges <= 1) { \
  281. _ls_looping=0; \
  282. } \
  283. _ls_insize *= 2; \
  284. } \
  285. } \
  286. } while (0)
  287. /******************************************************************************
  288. * singly linked list macros (non-circular) *
  289. *****************************************************************************/
  290. #define LL_PREPEND(head,add) \
  291. LL_PREPEND2(head,add,next)
  292. #define LL_PREPEND2(head,add,next) \
  293. do { \
  294. (add)->next = head; \
  295. head = add; \
  296. } while (0)
  297. #define LL_CONCAT(head1,head2) \
  298. LL_CONCAT2(head1,head2,next)
  299. #define LL_CONCAT2(head1,head2,next) \
  300. do { \
  301. LDECLTYPE(head1) _tmp; \
  302. if (head1) { \
  303. _tmp = head1; \
  304. while (_tmp->next) { _tmp = _tmp->next; } \
  305. _tmp->next=(head2); \
  306. } else { \
  307. (head1)=(head2); \
  308. } \
  309. } while (0)
  310. #define LL_APPEND(head,add) \
  311. LL_APPEND2(head,add,next)
  312. #define LL_APPEND2(head,add,next) \
  313. do { \
  314. LDECLTYPE(head) _tmp; \
  315. (add)->next=NULL; \
  316. if (head) { \
  317. _tmp = head; \
  318. while (_tmp->next) { _tmp = _tmp->next; } \
  319. _tmp->next=(add); \
  320. } else { \
  321. (head)=(add); \
  322. } \
  323. } while (0)
  324. #define LL_DELETE(head,del) \
  325. LL_DELETE2(head,del,next)
  326. #define LL_DELETE2(head,del,next) \
  327. do { \
  328. LDECLTYPE(head) _tmp; \
  329. if ((head) == (del)) { \
  330. (head)=(head)->next; \
  331. } else { \
  332. _tmp = head; \
  333. while (_tmp->next && (_tmp->next != (del))) { \
  334. _tmp = _tmp->next; \
  335. } \
  336. if (_tmp->next) { \
  337. _tmp->next = ((del)->next); \
  338. } \
  339. } \
  340. } while (0)
  341. /* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
  342. #define LL_APPEND_VS2008(head,add) \
  343. LL_APPEND2_VS2008(head,add,next)
  344. #define LL_APPEND2_VS2008(head,add,next) \
  345. do { \
  346. if (head) { \
  347. (add)->next = head; /* use add->next as a temp variable */ \
  348. while ((add)->next->next) { (add)->next = (add)->next->next; } \
  349. (add)->next->next=(add); \
  350. } else { \
  351. (head)=(add); \
  352. } \
  353. (add)->next=NULL; \
  354. } while (0)
  355. #define LL_DELETE_VS2008(head,del) \
  356. LL_DELETE2_VS2008(head,del,next)
  357. #define LL_DELETE2_VS2008(head,del,next) \
  358. do { \
  359. if ((head) == (del)) { \
  360. (head)=(head)->next; \
  361. } else { \
  362. char *_tmp = (char*)(head); \
  363. while ((head)->next && ((head)->next != (del))) { \
  364. head = (head)->next; \
  365. } \
  366. if ((head)->next) { \
  367. (head)->next = ((del)->next); \
  368. } \
  369. { \
  370. char **_head_alias = (char**)&(head); \
  371. *_head_alias = _tmp; \
  372. } \
  373. } \
  374. } while (0)
  375. #ifdef NO_DECLTYPE
  376. #undef LL_APPEND
  377. #define LL_APPEND LL_APPEND_VS2008
  378. #undef LL_DELETE
  379. #define LL_DELETE LL_DELETE_VS2008
  380. #undef LL_DELETE2
  381. #define LL_DELETE2_VS2008
  382. #undef LL_APPEND2
  383. #define LL_APPEND2 LL_APPEND2_VS2008
  384. #undef LL_CONCAT /* no LL_CONCAT_VS2008 */
  385. #undef DL_CONCAT /* no DL_CONCAT_VS2008 */
  386. #endif
  387. /* end VS2008 replacements */
  388. #define LL_FOREACH(head,el) \
  389. LL_FOREACH2(head,el,next)
  390. #define LL_FOREACH2(head,el,next) \
  391. for(el=head;el;el=(el)->next)
  392. #define LL_FOREACH_SAFE(head,el,tmp) \
  393. LL_FOREACH_SAFE2(head,el,tmp,next)
  394. #define LL_FOREACH_SAFE2(head,el,tmp,next) \
  395. for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
  396. #define LL_SEARCH_SCALAR(head,out,field,val) \
  397. LL_SEARCH_SCALAR2(head,out,field,val,next)
  398. #define LL_SEARCH_SCALAR2(head,out,field,val,next) \
  399. do { \
  400. LL_FOREACH2(head,out,next) { \
  401. if ((out)->field == (val)) break; \
  402. } \
  403. } while(0)
  404. #define LL_SEARCH(head,out,elt,cmp) \
  405. LL_SEARCH2(head,out,elt,cmp,next)
  406. #define LL_SEARCH2(head,out,elt,cmp,next) \
  407. do { \
  408. LL_FOREACH2(head,out,next) { \
  409. if ((cmp(out,elt))==0) break; \
  410. } \
  411. } while(0)
  412. #define LL_REPLACE_ELEM(head, el, add) \
  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; \
  425. } \
  426. if (_tmp->next) { \
  427. _tmp->next = (add); \
  428. } \
  429. } \
  430. } while (0)
  431. #define LL_PREPEND_ELEM(head, el, add) \
  432. do { \
  433. LDECLTYPE(head) _tmp; \
  434. assert(head != NULL); \
  435. assert(el != NULL); \
  436. assert(add != NULL); \
  437. (add)->next = (el); \
  438. if ((head) == (el)) { \
  439. (head) = (add); \
  440. } else { \
  441. _tmp = head; \
  442. while (_tmp->next && (_tmp->next != (el))) { \
  443. _tmp = _tmp->next; \
  444. } \
  445. if (_tmp->next) { \
  446. _tmp->next = (add); \
  447. } \
  448. } \
  449. } while (0) \
  450. /******************************************************************************
  451. * doubly linked list macros (non-circular) *
  452. *****************************************************************************/
  453. #define DL_PREPEND(head,add) \
  454. DL_PREPEND2(head,add,prev,next)
  455. #define DL_PREPEND2(head,add,prev,next) \
  456. do { \
  457. (add)->next = head; \
  458. if (head) { \
  459. (add)->prev = (head)->prev; \
  460. (head)->prev = (add); \
  461. } else { \
  462. (add)->prev = (add); \
  463. } \
  464. (head) = (add); \
  465. } while (0)
  466. #define DL_APPEND(head,add) \
  467. DL_APPEND2(head,add,prev,next)
  468. #define DL_APPEND2(head,add,prev,next) \
  469. do { \
  470. if (head) { \
  471. (add)->prev = (head)->prev; \
  472. (head)->prev->next = (add); \
  473. (head)->prev = (add); \
  474. (add)->next = NULL; \
  475. } else { \
  476. (head)=(add); \
  477. (head)->prev = (head); \
  478. (head)->next = NULL; \
  479. } \
  480. } while (0)
  481. #define DL_CONCAT(head1,head2) \
  482. DL_CONCAT2(head1,head2,prev,next)
  483. #define DL_CONCAT2(head1,head2,prev,next) \
  484. do { \
  485. LDECLTYPE(head1) _tmp; \
  486. if (head2) { \
  487. if (head1) { \
  488. _tmp = (head2)->prev; \
  489. (head2)->prev = (head1)->prev; \
  490. (head1)->prev->next = (head2); \
  491. (head1)->prev = _tmp; \
  492. } else { \
  493. (head1)=(head2); \
  494. } \
  495. } \
  496. } while (0)
  497. #define DL_DELETE(head,del) \
  498. DL_DELETE2(head,del,prev,next)
  499. #define DL_DELETE2(head,del,prev,next) \
  500. do { \
  501. assert((del)->prev != NULL); \
  502. if ((del)->prev == (del)) { \
  503. (head)=NULL; \
  504. } else if ((del)==(head)) { \
  505. (del)->next->prev = (del)->prev; \
  506. (head) = (del)->next; \
  507. } else { \
  508. (del)->prev->next = (del)->next; \
  509. if ((del)->next) { \
  510. (del)->next->prev = (del)->prev; \
  511. } else { \
  512. (head)->prev = (del)->prev; \
  513. } \
  514. } \
  515. } while (0)
  516. #define DL_FOREACH(head,el) \
  517. DL_FOREACH2(head,el,next)
  518. #define DL_FOREACH2(head,el,next) \
  519. for(el=head;el;el=(el)->next)
  520. /* this version is safe for deleting the elements during iteration */
  521. #define DL_FOREACH_SAFE(head,el,tmp) \
  522. DL_FOREACH_SAFE2(head,el,tmp,next)
  523. #define DL_FOREACH_SAFE2(head,el,tmp,next) \
  524. for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
  525. /* these are identical to their singly-linked list counterparts */
  526. #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
  527. #define DL_SEARCH LL_SEARCH
  528. #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
  529. #define DL_SEARCH2 LL_SEARCH2
  530. #define DL_REPLACE_ELEM(head, el, add) \
  531. do { \
  532. assert(head != NULL); \
  533. assert(el != NULL); \
  534. assert(add != NULL); \
  535. if ((head) == (el)) { \
  536. (head) = (add); \
  537. (add)->next = (el)->next; \
  538. if ((el)->next == NULL) { \
  539. (add)->prev = (add); \
  540. } else { \
  541. (add)->prev = (el)->prev; \
  542. (add)->next->prev = (add); \
  543. } \
  544. } else { \
  545. (add)->next = (el)->next; \
  546. (add)->prev = (el)->prev; \
  547. (add)->prev->next = (add); \
  548. if ((el)->next == NULL) { \
  549. (head)->prev = (add); \
  550. } else { \
  551. (add)->next->prev = (add); \
  552. } \
  553. } \
  554. } while (0)
  555. #define DL_PREPEND_ELEM(head, el, add) \
  556. do { \
  557. assert(head != NULL); \
  558. assert(el != NULL); \
  559. assert(add != NULL); \
  560. (add)->next = (el); \
  561. (add)->prev = (el)->prev; \
  562. (el)->prev = (add); \
  563. if ((head) == (el)) { \
  564. (head) = (add); \
  565. } else { \
  566. (add)->prev->next = (add); \
  567. } \
  568. } while (0) \
  569. /******************************************************************************
  570. * circular doubly linked list macros *
  571. *****************************************************************************/
  572. #define CDL_PREPEND(head,add) \
  573. CDL_PREPEND2(head,add,prev,next)
  574. #define CDL_PREPEND2(head,add,prev,next) \
  575. do { \
  576. if (head) { \
  577. (add)->prev = (head)->prev; \
  578. (add)->next = (head); \
  579. (head)->prev = (add); \
  580. (add)->prev->next = (add); \
  581. } else { \
  582. (add)->prev = (add); \
  583. (add)->next = (add); \
  584. } \
  585. (head)=(add); \
  586. } while (0)
  587. #define CDL_DELETE(head,del) \
  588. CDL_DELETE2(head,del,prev,next)
  589. #define CDL_DELETE2(head,del,prev,next) \
  590. do { \
  591. if ( ((head)==(del)) && ((head)->next == (head))) { \
  592. (head) = 0L; \
  593. } else { \
  594. (del)->next->prev = (del)->prev; \
  595. (del)->prev->next = (del)->next; \
  596. if ((del) == (head)) (head)=(del)->next; \
  597. } \
  598. } while (0)
  599. #define CDL_FOREACH(head,el) \
  600. CDL_FOREACH2(head,el,next)
  601. #define CDL_FOREACH2(head,el,next) \
  602. for(el=head;el;el=((el)->next==head ? 0L : (el)->next))
  603. #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
  604. CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
  605. #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \
  606. for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
  607. (el) && ((tmp2)=(el)->next, 1); \
  608. ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
  609. #define CDL_SEARCH_SCALAR(head,out,field,val) \
  610. CDL_SEARCH_SCALAR2(head,out,field,val,next)
  611. #define CDL_SEARCH_SCALAR2(head,out,field,val,next) \
  612. do { \
  613. CDL_FOREACH2(head,out,next) { \
  614. if ((out)->field == (val)) break; \
  615. } \
  616. } while(0)
  617. #define CDL_SEARCH(head,out,elt,cmp) \
  618. CDL_SEARCH2(head,out,elt,cmp,next)
  619. #define CDL_SEARCH2(head,out,elt,cmp,next) \
  620. do { \
  621. CDL_FOREACH2(head,out,next) { \
  622. if ((cmp(out,elt))==0) break; \
  623. } \
  624. } while(0)
  625. #define CDL_REPLACE_ELEM(head, el, add) \
  626. do { \
  627. assert(head != NULL); \
  628. assert(el != NULL); \
  629. assert(add != NULL); \
  630. if ((el)->next == (el)) { \
  631. (add)->next = (add); \
  632. (add)->prev = (add); \
  633. (head) = (add); \
  634. } else { \
  635. (add)->next = (el)->next; \
  636. (add)->prev = (el)->prev; \
  637. (add)->next->prev = (add); \
  638. (add)->prev->next = (add); \
  639. if ((head) == (el)) { \
  640. (head) = (add); \
  641. } \
  642. } \
  643. } while (0)
  644. #define CDL_PREPEND_ELEM(head, el, add) \
  645. do { \
  646. assert(head != NULL); \
  647. assert(el != NULL); \
  648. assert(add != NULL); \
  649. (add)->next = (el); \
  650. (add)->prev = (el)->prev; \
  651. (el)->prev = (add); \
  652. (add)->prev->next = (add); \
  653. if ((head) == (el)) { \
  654. (head) = (add); \
  655. } \
  656. } while (0) \
  657. /// @endcond
  658. #endif /* UTLIST_H */