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