00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef UTLIST_H
00025 #define UTLIST_H
00026
00027 #define UTLIST_VERSION 1.9
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #ifndef DECLTYPE
00066 #ifdef _MSC_VER
00067 #if _MSC_VER >= 1600 && __cplusplus
00068 #define DECLTYPE(x) decltype(x)
00069 #else
00070 #define NO_DECLTYPE
00071 #define DECLTYPE(x) char*
00072 #endif
00073 #else
00074 #define DECLTYPE(x) __typeof(x)
00075 #endif
00076 #endif // DECLTYPE
00077
00078
00079
00080
00081 #ifdef NO_DECLTYPE
00082 #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
00083 #define _NEXT(elt,list) ((char*)((list)->next))
00084 #define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
00085 #define _PREV(elt,list) ((char*)((list)->prev))
00086 #define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
00087 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
00088 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
00089 #else
00090 #define _SV(elt,list)
00091 #define _NEXT(elt,list) ((elt)->next)
00092 #define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
00093 #define _PREV(elt,list) ((elt)->prev)
00094 #define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
00095 #define _RS(list)
00096 #define _CASTASGN(a,b) (a)=(b)
00097 #endif
00098
00099
00100
00101
00102
00103 #define LL_SORT(list, cmp) \
00104 do { \
00105 DECLTYPE(list) _ls_p; \
00106 DECLTYPE(list) _ls_q; \
00107 DECLTYPE(list) _ls_e; \
00108 DECLTYPE(list) _ls_tail; \
00109 DECLTYPE(list) _ls_oldhead; \
00110 DECLTYPE(list) _tmp; \
00111 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
00112 if (list) { \
00113 _ls_insize = 1; \
00114 _ls_looping = 1; \
00115 while (_ls_looping) { \
00116 _CASTASGN(_ls_p,list); \
00117 _CASTASGN(_ls_oldhead,list); \
00118 list = NULL; \
00119 _ls_tail = NULL; \
00120 _ls_nmerges = 0; \
00121 while (_ls_p) { \
00122 _ls_nmerges++; \
00123 _ls_q = _ls_p; \
00124 _ls_psize = 0; \
00125 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
00126 _ls_psize++; \
00127 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
00128 if (!_ls_q) break; \
00129 } \
00130 _ls_qsize = _ls_insize; \
00131 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
00132 if (_ls_psize == 0) { \
00133 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
00134 } else if (_ls_qsize == 0 || !_ls_q) { \
00135 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
00136 } else if (cmp(_ls_p,_ls_q) <= 0) { \
00137 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
00138 } else { \
00139 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
00140 } \
00141 if (_ls_tail) { \
00142 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
00143 } else { \
00144 _CASTASGN(list,_ls_e); \
00145 } \
00146 _ls_tail = _ls_e; \
00147 } \
00148 _ls_p = _ls_q; \
00149 } \
00150 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
00151 if (_ls_nmerges <= 1) { \
00152 _ls_looping=0; \
00153 } \
00154 _ls_insize *= 2; \
00155 } \
00156 } else _tmp=NULL; \
00157 } while (0)
00158
00159 #define DL_SORT(list, cmp) \
00160 do { \
00161 DECLTYPE(list) _ls_p; \
00162 DECLTYPE(list) _ls_q; \
00163 DECLTYPE(list) _ls_e; \
00164 DECLTYPE(list) _ls_tail; \
00165 DECLTYPE(list) _ls_oldhead; \
00166 DECLTYPE(list) _tmp; \
00167 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
00168 if (list) { \
00169 _ls_insize = 1; \
00170 _ls_looping = 1; \
00171 while (_ls_looping) { \
00172 _CASTASGN(_ls_p,list); \
00173 _CASTASGN(_ls_oldhead,list); \
00174 list = NULL; \
00175 _ls_tail = NULL; \
00176 _ls_nmerges = 0; \
00177 while (_ls_p) { \
00178 _ls_nmerges++; \
00179 _ls_q = _ls_p; \
00180 _ls_psize = 0; \
00181 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
00182 _ls_psize++; \
00183 _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
00184 if (!_ls_q) break; \
00185 } \
00186 _ls_qsize = _ls_insize; \
00187 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
00188 if (_ls_psize == 0) { \
00189 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
00190 } else if (_ls_qsize == 0 || !_ls_q) { \
00191 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
00192 } else if (cmp(_ls_p,_ls_q) <= 0) { \
00193 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
00194 } else { \
00195 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
00196 } \
00197 if (_ls_tail) { \
00198 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
00199 } else { \
00200 _CASTASGN(list,_ls_e); \
00201 } \
00202 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
00203 _ls_tail = _ls_e; \
00204 } \
00205 _ls_p = _ls_q; \
00206 } \
00207 _CASTASGN(list->prev, _ls_tail); \
00208 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
00209 if (_ls_nmerges <= 1) { \
00210 _ls_looping=0; \
00211 } \
00212 _ls_insize *= 2; \
00213 } \
00214 } else _tmp=NULL; \
00215 } while (0)
00216
00217 #define CDL_SORT(list, cmp) \
00218 do { \
00219 DECLTYPE(list) _ls_p; \
00220 DECLTYPE(list) _ls_q; \
00221 DECLTYPE(list) _ls_e; \
00222 DECLTYPE(list) _ls_tail; \
00223 DECLTYPE(list) _ls_oldhead; \
00224 DECLTYPE(list) _tmp; \
00225 DECLTYPE(list) _tmp2; \
00226 int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
00227 if (list) { \
00228 _ls_insize = 1; \
00229 _ls_looping = 1; \
00230 while (_ls_looping) { \
00231 _CASTASGN(_ls_p,list); \
00232 _CASTASGN(_ls_oldhead,list); \
00233 list = NULL; \
00234 _ls_tail = NULL; \
00235 _ls_nmerges = 0; \
00236 while (_ls_p) { \
00237 _ls_nmerges++; \
00238 _ls_q = _ls_p; \
00239 _ls_psize = 0; \
00240 for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
00241 _ls_psize++; \
00242 _SV(_ls_q,list); \
00243 if (_NEXT(_ls_q,list) == _ls_oldhead) { \
00244 _ls_q = NULL; \
00245 } else { \
00246 _ls_q = _NEXT(_ls_q,list); \
00247 } \
00248 _RS(list); \
00249 if (!_ls_q) break; \
00250 } \
00251 _ls_qsize = _ls_insize; \
00252 while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
00253 if (_ls_psize == 0) { \
00254 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
00255 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
00256 } else if (_ls_qsize == 0 || !_ls_q) { \
00257 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
00258 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
00259 } else if (cmp(_ls_p,_ls_q) <= 0) { \
00260 _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
00261 if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
00262 } else { \
00263 _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
00264 if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
00265 } \
00266 if (_ls_tail) { \
00267 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
00268 } else { \
00269 _CASTASGN(list,_ls_e); \
00270 } \
00271 _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
00272 _ls_tail = _ls_e; \
00273 } \
00274 _ls_p = _ls_q; \
00275 } \
00276 _CASTASGN(list->prev,_ls_tail); \
00277 _CASTASGN(_tmp2,list); \
00278 _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
00279 if (_ls_nmerges <= 1) { \
00280 _ls_looping=0; \
00281 } \
00282 _ls_insize *= 2; \
00283 } \
00284 } else _tmp=NULL; \
00285 } while (0)
00286
00287
00288
00289
00290 #define LL_PREPEND(head,add) \
00291 do { \
00292 (add)->next = head; \
00293 head = add; \
00294 } while (0)
00295
00296 #define LL_APPEND(head,add) \
00297 do { \
00298 DECLTYPE(head) _tmp; \
00299 (add)->next=NULL; \
00300 if (head) { \
00301 _tmp = head; \
00302 while (_tmp->next) { _tmp = _tmp->next; } \
00303 _tmp->next=(add); \
00304 } else { \
00305 (head)=(add); \
00306 } \
00307 } while (0)
00308
00309 #define LL_DELETE(head,del) \
00310 do { \
00311 DECLTYPE(head) _tmp; \
00312 if ((head) == (del)) { \
00313 (head)=(head)->next; \
00314 } else { \
00315 _tmp = head; \
00316 while (_tmp->next && (_tmp->next != (del))) { \
00317 _tmp = _tmp->next; \
00318 } \
00319 if (_tmp->next) { \
00320 _tmp->next = ((del)->next); \
00321 } \
00322 } \
00323 } while (0)
00324
00325
00326 #define LL_APPEND_VS2008(head,add) \
00327 do { \
00328 if (head) { \
00329 (add)->next = head; \
00330 while ((add)->next->next) { (add)->next = (add)->next->next; } \
00331 (add)->next->next=(add); \
00332 } else { \
00333 (head)=(add); \
00334 } \
00335 (add)->next=NULL; \
00336 } while (0)
00337
00338 #define LL_DELETE_VS2008(head,del) \
00339 do { \
00340 if ((head) == (del)) { \
00341 (head)=(head)->next; \
00342 } else { \
00343 char *_tmp = (char*)(head); \
00344 while (head->next && (head->next != (del))) { \
00345 head = head->next; \
00346 } \
00347 if (head->next) { \
00348 head->next = ((del)->next); \
00349 } \
00350 { \
00351 char **_head_alias = (char**)&(head); \
00352 *_head_alias = _tmp; \
00353 } \
00354 } \
00355 } while (0)
00356 #ifdef NO_DECLTYPE
00357 #undef LL_APPEND
00358 #define LL_APPEND LL_APPEND_VS2008
00359 #undef LL_DELETE
00360 #define LL_DELETE LL_DELETE_VS2008
00361 #endif
00362
00363
00364 #define LL_FOREACH(head,el) \
00365 for(el=head;el;el=el->next)
00366
00367 #define LL_FOREACH_SAFE(head,el,tmp) \
00368 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
00369
00370 #define LL_SEARCH_SCALAR(head,out,field,val) \
00371 do { \
00372 LL_FOREACH(head,out) { \
00373 if ((out)->field == (val)) break; \
00374 } \
00375 } while(0)
00376
00377 #define LL_SEARCH(head,out,elt,cmp) \
00378 do { \
00379 LL_FOREACH(head,out) { \
00380 if ((cmp(out,elt))==0) break; \
00381 } \
00382 } while(0)
00383
00384
00385
00386
00387 #define DL_PREPEND(head,add) \
00388 do { \
00389 (add)->next = head; \
00390 if (head) { \
00391 (add)->prev = (head)->prev; \
00392 (head)->prev = (add); \
00393 } else { \
00394 (add)->prev = (add); \
00395 } \
00396 (head) = (add); \
00397 } while (0)
00398
00399 #define DL_APPEND(head,add) \
00400 do { \
00401 if (head) { \
00402 (add)->prev = (head)->prev; \
00403 (head)->prev->next = (add); \
00404 (head)->prev = (add); \
00405 (add)->next = NULL; \
00406 } else { \
00407 (head)=(add); \
00408 (head)->prev = (head); \
00409 (head)->next = NULL; \
00410 } \
00411 } while (0);
00412
00413 #define DL_DELETE(head,del) \
00414 do { \
00415 if ((del)->prev == (del)) { \
00416 (head)=NULL; \
00417 } else if ((del)==(head)) { \
00418 (del)->next->prev = (del)->prev; \
00419 (head) = (del)->next; \
00420 } else { \
00421 (del)->prev->next = (del)->next; \
00422 if ((del)->next) { \
00423 (del)->next->prev = (del)->prev; \
00424 } else { \
00425 (head)->prev = (del)->prev; \
00426 } \
00427 } \
00428 } while (0);
00429
00430
00431 #define DL_FOREACH(head,el) \
00432 for(el=head;el;el=el->next)
00433
00434
00435 #define DL_FOREACH_SAFE(head,el,tmp) \
00436 for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
00437
00438
00439 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
00440 #define DL_SEARCH LL_SEARCH
00441
00442
00443
00444
00445 #define CDL_PREPEND(head,add) \
00446 do { \
00447 if (head) { \
00448 (add)->prev = (head)->prev; \
00449 (add)->next = (head); \
00450 (head)->prev = (add); \
00451 (add)->prev->next = (add); \
00452 } else { \
00453 (add)->prev = (add); \
00454 (add)->next = (add); \
00455 } \
00456 (head)=(add); \
00457 } while (0)
00458
00459 #define CDL_DELETE(head,del) \
00460 do { \
00461 if ( ((head)==(del)) && ((head)->next == (head))) { \
00462 (head) = 0L; \
00463 } else { \
00464 (del)->next->prev = (del)->prev; \
00465 (del)->prev->next = (del)->next; \
00466 if ((del) == (head)) (head)=(del)->next; \
00467 } \
00468 } while (0);
00469
00470 #define CDL_FOREACH(head,el) \
00471 for(el=head;el;el=(el->next==head ? 0L : el->next))
00472
00473 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
00474 for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
00475 (el) && ((tmp2)=(el)->next, 1); \
00476 ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
00477
00478 #define CDL_SEARCH_SCALAR(head,out,field,val) \
00479 do { \
00480 CDL_FOREACH(head,out) { \
00481 if ((out)->field == (val)) break; \
00482 } \
00483 } while(0)
00484
00485 #define CDL_SEARCH(head,out,elt,cmp) \
00486 do { \
00487 CDL_FOREACH(head,out) { \
00488 if ((cmp(out,elt))==0) break; \
00489 } \
00490 } while(0)
00491
00492 #endif
00493