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