0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #ifndef UTLIST_INT_H
0025 #define UTLIST_INT_H
0026
0027 #define UTLIST_VERSION 1.9.1
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 #ifdef _MSC_VER
0065 #if _MSC_VER >= 1600 && defined(__cplusplus)
0066 #define LDECLTYPE(x) decltype(x)
0067 #else
0068 #define NO_DECLTYPE
0069 #define LDECLTYPE(x) char*
0070 #endif
0071 #else
0072 #define LDECLTYPE(x) __typeof(x)
0073 #endif
0074
0075
0076
0077
0078 #ifdef NO_DECLTYPE
0079 #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
0080 #define _NEXT(elt,list) ((char*)((list)->NDRX_NEXT))
0081 #define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->NDRX_NEXT); *_alias=(char*)(to); }
0082 #define _PREV(elt,list) ((char*)((list)->NDRX_PREV))
0083 #define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->NDRX_PREV); *_alias=(char*)(to); }
0084 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
0085 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
0086 #else
0087 #define _SV(elt,list)
0088 #define _NEXT(elt,list) ((elt)->NDRX_NEXT)
0089 #define _NEXTASGN(elt,list,to) ((elt)->NDRX_NEXT)=(to)
0090 #define _PREV(elt,list) ((elt)->NDRX_PREV)
0091 #define _PREVASGN(elt,list,to) ((elt)->NDRX_PREV)=(to)
0092 #define _RS(list)
0093 #define _CASTASGN(a,b) (a)=(b)
0094 #endif
0095
0096
0097
0098
0099
0100 #define LL_SORT(list, cmp) \
0101 do { \
0102 LDECLTYPE(list) _ls_p; \
0103 LDECLTYPE(list) _ls_q; \
0104 LDECLTYPE(list) _ls_e; \
0105 LDECLTYPE(list) _ls_tail; \
0106 LDECLTYPE(list) _ls_oldhead; \
0107 LDECLTYPE(list) _tmp; \
0108 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
0109 if (list) { \
0110 _ls_insize = 1; \
0111 _ls_looping = 1; \
0112 while (_ls_looping) { \
0113 _CASTASGN(_ls_p,list); \
0114 _CASTASGN(_ls_oldhead,list); \
0115 list = NULL; \
0116 _ls_tail = NULL; \
0117 _ls_nmerges = 0; \
0118 while (_ls_p) { \
0119 _ls_nmerges++; \
0120 _ls_q = _ls_p; \
0121 _ls_psize = 0; \
0122 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
0123 _ls_psize++; \
0124 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
0125 if (!_ls_q) break; \
0126 } \
0127 _ls_qsize = _ls_insize; \
0128 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
0129 if (_ls_psize == 0) { \
0130 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
0131 } else if (_ls_qsize == 0 || !_ls_q) { \
0132 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
0133 } else if (cmp(_ls_p,_ls_q) <= 0) { \
0134 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
0135 } else { \
0136 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
0137 } \
0138 if (_ls_tail) { \
0139 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
0140 } else { \
0141 _CASTASGN(list,_ls_e); \
0142 } \
0143 _ls_tail = _ls_e; \
0144 } \
0145 _ls_p = _ls_q; \
0146 } \
0147 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
0148 if (_ls_nmerges <= 1) { \
0149 _ls_looping=0; \
0150 } \
0151 _ls_insize *= 2; \
0152 } \
0153 } else _tmp=NULL; \
0154 } while (0)
0155
0156 #define DL_SORT(list, cmp) \
0157 do { \
0158 LDECLTYPE(list) _ls_p; \
0159 LDECLTYPE(list) _ls_q; \
0160 LDECLTYPE(list) _ls_e; \
0161 LDECLTYPE(list) _ls_tail; \
0162 LDECLTYPE(list) _ls_oldhead; \
0163 LDECLTYPE(list) _tmp; \
0164 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
0165 if (list) { \
0166 _ls_insize = 1; \
0167 _ls_looping = 1; \
0168 while (_ls_looping) { \
0169 _CASTASGN(_ls_p,list); \
0170 _CASTASGN(_ls_oldhead,list); \
0171 list = NULL; \
0172 _ls_tail = NULL; \
0173 _ls_nmerges = 0; \
0174 while (_ls_p) { \
0175 _ls_nmerges++; \
0176 _ls_q = _ls_p; \
0177 _ls_psize = 0; \
0178 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
0179 _ls_psize++; \
0180 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
0181 if (!_ls_q) break; \
0182 } \
0183 _ls_qsize = _ls_insize; \
0184 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
0185 if (_ls_psize == 0) { \
0186 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
0187 } else if (_ls_qsize == 0 || !_ls_q) { \
0188 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
0189 } else if (cmp(_ls_p,_ls_q) <= 0) { \
0190 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
0191 } else { \
0192 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
0193 } \
0194 if (_ls_tail) { \
0195 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
0196 } else { \
0197 _CASTASGN(list,_ls_e); \
0198 } \
0199 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
0200 _ls_tail = _ls_e; \
0201 } \
0202 _ls_p = _ls_q; \
0203 } \
0204 _CASTASGN(list->NDRX_PREV, _ls_tail); \
0205 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
0206 if (_ls_nmerges <= 1) { \
0207 _ls_looping=0; \
0208 } \
0209 _ls_insize *= 2; \
0210 } \
0211 } else _tmp=NULL; \
0212 } while (0)
0213
0214 #define CDL_SORT(list, cmp) \
0215 do { \
0216 LDECLTYPE(list) _ls_p; \
0217 LDECLTYPE(list) _ls_q; \
0218 LDECLTYPE(list) _ls_e; \
0219 LDECLTYPE(list) _ls_tail; \
0220 LDECLTYPE(list) _ls_oldhead; \
0221 LDECLTYPE(list) _tmp; \
0222 LDECLTYPE(list) _tmp2; \
0223 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
0224 if (list) { \
0225 _ls_insize = 1; \
0226 _ls_looping = 1; \
0227 while (_ls_looping) { \
0228 _CASTASGN(_ls_p,list); \
0229 _CASTASGN(_ls_oldhead,list); \
0230 list = NULL; \
0231 _ls_tail = NULL; \
0232 _ls_nmerges = 0; \
0233 while (_ls_p) { \
0234 _ls_nmerges++; \
0235 _ls_q = _ls_p; \
0236 _ls_psize = 0; \
0237 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
0238 _ls_psize++; \
0239 _SV(_ls_q,list); \
0240 if (_NEXT(_ls_q,list) == _ls_oldhead) { \
0241 _ls_q = NULL; \
0242 } else { \
0243 _ls_q = _NEXT(_ls_q,list); \
0244 } \
0245 _RS(list); \
0246 if (!_ls_q) break; \
0247 } \
0248 _ls_qsize = _ls_insize; \
0249 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
0250 if (_ls_psize == 0) { \
0251 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
0252 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
0253 } else if (_ls_qsize == 0 || !_ls_q) { \
0254 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
0255 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
0256 } else if (cmp(_ls_p,_ls_q) <= 0) { \
0257 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
0258 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
0259 } else { \
0260 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
0261 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
0262 } \
0263 if (_ls_tail) { \
0264 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
0265 } else { \
0266 _CASTASGN(list,_ls_e); \
0267 } \
0268 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
0269 _ls_tail = _ls_e; \
0270 } \
0271 _ls_p = _ls_q; \
0272 } \
0273 _CASTASGN(list->NDRX_PREV,_ls_tail); \
0274 _CASTASGN(_tmp2,list); \
0275 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
0276 if (_ls_nmerges <= 1) { \
0277 _ls_looping=0; \
0278 } \
0279 _ls_insize *= 2; \
0280 } \
0281 } else _tmp=NULL; \
0282 } while (0)
0283
0284
0285
0286
0287 #define LL_PREPEND(head,add) \
0288 do { \
0289 (add)->NDRX_NEXT = head; \
0290 head = add; \
0291 } while (0)
0292
0293 #define LL_APPEND(head,add) \
0294 do { \
0295 LDECLTYPE(head) _tmp; \
0296 (add)->NDRX_NEXT=NULL; \
0297 if (head) { \
0298 _tmp = head; \
0299 while (_tmp->NDRX_NEXT) { _tmp = _tmp->NDRX_NEXT; } \
0300 _tmp->NDRX_NEXT=(add); \
0301 } else { \
0302 (head)=(add); \
0303 } \
0304 } while (0)
0305
0306 #define LL_DELETE(head,del) \
0307 do { \
0308 LDECLTYPE(head) _tmp; \
0309 if ((head) == (del)) { \
0310 (head)=(head)->NDRX_NEXT; \
0311 } else { \
0312 _tmp = head; \
0313 while (_tmp->NDRX_NEXT && (_tmp->NDRX_NEXT != (del))) { \
0314 _tmp = _tmp->NDRX_NEXT; \
0315 } \
0316 if (_tmp->NDRX_NEXT) { \
0317 _tmp->NDRX_NEXT = ((del)->NDRX_NEXT); \
0318 } \
0319 } \
0320 } while (0)
0321
0322
0323 #define LL_APPEND_VS2008(head,add) \
0324 do { \
0325 if (head) { \
0326 (add)->NDRX_NEXT = head; \
0327 while ((add)->NDRX_NEXT->NDRX_NEXT) { (add)->NDRX_NEXT = (add)->NDRX_NEXT->NDRX_NEXT; } \
0328 (add)->NDRX_NEXT->NDRX_NEXT=(add); \
0329 } else { \
0330 (head)=(add); \
0331 } \
0332 (add)->NDRX_NEXT=NULL; \
0333 } while (0)
0334
0335 #define LL_DELETE_VS2008(head,del) \
0336 do { \
0337 if ((head) == (del)) { \
0338 (head)=(head)->NDRX_NEXT; \
0339 } else { \
0340 char *_tmp = (char*)(head); \
0341 while (head->NDRX_NEXT && (head->NDRX_NEXT != (del))) { \
0342 head = head->NDRX_NEXT; \
0343 } \
0344 if (head->NDRX_NEXT) { \
0345 head->NDRX_NEXT = ((del)->NDRX_NEXT); \
0346 } \
0347 { \
0348 char **_head_alias = (char**)&(head); \
0349 *_head_alias = _tmp; \
0350 } \
0351 } \
0352 } while (0)
0353 #ifdef NO_DECLTYPE
0354 #undef LL_APPEND
0355 #define LL_APPEND LL_APPEND_VS2008
0356 #undef LL_DELETE
0357 #define LL_DELETE LL_DELETE_VS2008
0358 #endif
0359
0360
0361 #define LL_FOREACH(head,el) \
0362 for(el=head;el;el=el->NDRX_NEXT)
0363
0364 #define LL_FOREACH_SAFE(head,el,tmp) \
0365 for((el)=(head);(el) && (tmp = (el)->NDRX_NEXT, 1); (el) = tmp)
0366
0367 #define LL_SEARCH_SCALAR(head,out,field,val) \
0368 do { \
0369 LL_FOREACH(head,out) { \
0370 if ((out)->field == (val)) break; \
0371 } \
0372 } while(0)
0373
0374 #define LL_SEARCH(head,out,elt,cmp) \
0375 do { \
0376 LL_FOREACH(head,out) { \
0377 if ((cmp(out,elt))==0) break; \
0378 } \
0379 } while(0)
0380
0381
0382
0383
0384 #define DL_PREPEND(head,add) \
0385 do { \
0386 (add)->NDRX_NEXT = head; \
0387 if (head) { \
0388 (add)->NDRX_PREV = (head)->NDRX_PREV; \
0389 (head)->NDRX_PREV = (add); \
0390 } else { \
0391 (add)->NDRX_PREV = (add); \
0392 } \
0393 (head) = (add); \
0394 } while (0)
0395
0396 #define DL_APPEND(head,add) \
0397 do { \
0398 if (head) { \
0399 (add)->NDRX_PREV = (head)->NDRX_PREV; \
0400 (head)->NDRX_PREV->NDRX_NEXT = (add); \
0401 (head)->NDRX_PREV = (add); \
0402 (add)->NDRX_NEXT = NULL; \
0403 } else { \
0404 (head)=(add); \
0405 (head)->NDRX_PREV = (head); \
0406 (head)->NDRX_NEXT = NULL; \
0407 } \
0408 } while (0);
0409
0410 #define DL_DELETE(head,del) \
0411 do { \
0412 if ((del)->NDRX_PREV == (del)) { \
0413 (head)=NULL; \
0414 } else if ((del)==(head)) { \
0415 (del)->NDRX_NEXT->NDRX_PREV = (del)->NDRX_PREV; \
0416 (head) = (del)->NDRX_NEXT; \
0417 } else { \
0418 (del)->NDRX_PREV->NDRX_NEXT = (del)->NDRX_NEXT; \
0419 if ((del)->NDRX_NEXT) { \
0420 (del)->NDRX_NEXT->NDRX_PREV = (del)->NDRX_PREV; \
0421 } else { \
0422 (head)->NDRX_PREV = (del)->NDRX_PREV; \
0423 } \
0424 } \
0425 } while (0);
0426
0427
0428 #define DL_FOREACH(head,el) \
0429 for(el=head;el;el=el->NDRX_NEXT)
0430
0431
0432 #define DL_REVFOREACH(head,el,i) \
0433 for(el=(head)->NDRX_PREV,i=1; (el) && (el->NDRX_NEXT || i); el=(el)->NDRX_PREV, i=0)
0434
0435
0436 #define DL_FOREACH_SAFE(head,el,tmp) \
0437 for((el)=(head);(el) && (tmp = (el)->NDRX_NEXT, 1); (el) = tmp)
0438
0439
0440 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
0441 #define DL_SEARCH LL_SEARCH
0442
0443
0444
0445
0446 #define CDL_PREPEND(head,add) \
0447 do { \
0448 if (head) { \
0449 (add)->NDRX_PREV = (head)->NDRX_PREV; \
0450 (add)->NDRX_NEXT = (head); \
0451 (head)->NDRX_PREV = (add); \
0452 (add)->NDRX_PREV->NDRX_NEXT = (add); \
0453 } else { \
0454 (add)->NDRX_PREV = (add); \
0455 (add)->NDRX_NEXT = (add); \
0456 } \
0457 (head)=(add); \
0458 } while (0)
0459
0460 #define CDL_APPEND(head,add) \
0461 do { \
0462 if (head) { \
0463 (add)->NDRX_PREV = (head)->NDRX_PREV; \
0464 (add)->NDRX_NEXT = (head); \
0465 (head)->NDRX_PREV = (add); \
0466 (add)->NDRX_PREV->NDRX_NEXT = (add); \
0467 } else { \
0468 (add)->NDRX_PREV = (add); \
0469 (add)->NDRX_NEXT = (add); \
0470 (head)=(add); \
0471 } \
0472 } while (0)
0473
0474 #define CDL_DELETE(head,del) \
0475 do { \
0476 if ( ((head)==(del)) && ((head)->NDRX_NEXT == (head))) { \
0477 (head) = 0L; \
0478 } else { \
0479 (del)->NDRX_NEXT->NDRX_PREV = (del)->NDRX_PREV; \
0480 (del)->NDRX_PREV->NDRX_NEXT = (del)->NDRX_NEXT; \
0481 if ((del) == (head)) (head)=(del)->NDRX_NEXT; \
0482 } \
0483 } while (0);
0484
0485 #define CDL_FOREACH(head,el) \
0486 for(el=head;el;el=(el->NDRX_NEXT==head ? 0L : el->NDRX_NEXT))
0487
0488 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
0489 for((el)=(head), ((tmp1)=(head)?((head)->NDRX_PREV):NULL); \
0490 (el) && ((tmp2)=(el)->NDRX_NEXT, 1); \
0491 ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
0492
0493 #define CDL_SEARCH_SCALAR(head,out,field,val) \
0494 do { \
0495 CDL_FOREACH(head,out) { \
0496 if ((out)->field == (val)) break; \
0497 } \
0498 } while(0)
0499
0500 #define CDL_SEARCH(head,out,elt,cmp) \
0501 do { \
0502 CDL_FOREACH(head,out) { \
0503 if ((cmp(out,elt))==0) break; \
0504 } \
0505 } while(0)
0506
0507 #endif
0508