ll.h

Go to the documentation of this file.
00001 #ifndef LL_H
00002 #define LL_H
00003 
00092 /* If assert hasn't been included, skip extra sanity checks */
00093 #ifndef assert
00094 #define assert(v)
00095 #endif
00096 
00097 /* Get preprocessor macros this needs */
00098 #ifndef PP_H
00099 #include "pp.h"
00100 #endif
00101 
00132 #define sll_decllink(type,mlabel)\
00133     type*   mlabel
00134 
00142 #define sll_initlink(type,mlabel, self)\
00143     (self)->mlabel = NULL
00144 
00152 #define sll_decllist(type,mlabel, ilabel)\
00153     type*   ilabel
00154 
00163 #define sll_autolist(type,mlabel, ilabel)\
00164     type*   ilabel = NULL
00165 
00174 #define sll_autolist_static(type,mlabel, ilabel)\
00175     static type*    ilabel = NULL
00176 
00184 #define sll_externlist(type,mlabel, ilabel)\
00185     extern type*    ilabel
00186 
00195 #define sll_initlist(type,mlabel, ilabel ) \
00196     (ilabel) = NULL
00197 
00207 #define sll_initarray(type,mlabel, ilabel, array,count) \
00208     {\
00209         type* ppScr2(sllInit,array) = (array);\
00210         type* ppScr2(sllInit,last) = ppScr2(sllInit,array) + (count) - 1;\
00211         type* ppScr2(sllInit,curr) = ppScr2(sllInit,last);\
00212         ppScr2(sllInit,last)->mlabel = NULL;\
00213         while( ppScr2(sllInit,curr)-- > ppScr2(sllInit,array) )\
00214             ppScr2(sllInit,curr)->mlabel = ppScr2(sllInit,last)--;\
00215         (ilabel) = ppScr2(sllInit,array);\
00216     }
00217 
00225 #define sll_empty(type,mlabel, ilabel ) ( NULL == (ilabel) )
00226 
00234 #define sll_reset(type,mlabel, ilabel) \
00235     {\
00236         type* __ll_curr = (array);\
00237         type* __ll_next;\
00238         while( __ll_curr ) \
00239         {\
00240             __ll_next = __ll_curr->mlabel;\
00241             __ll_curr->mlabel = NULL;\
00242             __ll_curr = __ll_next;\
00243         }\
00244         (ilabel) = NULL;\
00245     }
00246 
00255 #define sll_next(type,mlabel, ilabel, curr ) \
00256     ((curr) = (curr) ? ((curr)->mlabel) : NULL)
00257 
00269 #define sll_foreach_const(type,mlabel, ilabel, iterator ) \
00270     const type* iterator = (ilabel); \
00271     for ( ; iterator; iterator = iterator->mlabel )
00272 
00284 #define sll_foreach(type,mlabel, ilabel, iterator ) \
00285     type* iterator = (ilabel); \
00286     for ( ; iterator; iterator = iterator->mlabel )
00287 
00298 #define sll_foreach_deletable(type,mlabel, ilabel, iterator ) \
00299     type* ppConcat3(__ll_,iterator,_prev) = NULL; \
00300     type* iterator = (ilabel);\
00301     type* ppConcat3(__ll_,iterator,_next) = iterator?iterator->mlabel:NULL; \
00302     for ( ; iterator; ppConcat3(__ll_,iterator,_prev) = iterator, iterator = ppConcat3(__ll_,iterator,_next), sll_next(type,mlabel, ilabel, ppConcat3(__ll_,iterator,_next) )  )
00303 
00314 #define sll_foreach_deletable_reverse(type,mlabel, ilabel, iterator ) \
00315     type* ppConcat3(__ll_,iterator,_prev) = NULL; \
00316     type* iterator = (ilabel);\
00317     type* ppConcat3(__ll_,iterator,_next) = iterator?iterator->mlabel:NULL; \
00318     for ( ; iterator; iterator->mlabel = ppConcat3(__ll_,iterator,_prev), ppConcat3(__ll_,iterator,_prev) = (ilabel) = iterator, iterator = ppConcat3(__ll_,iterator,_next), sll_next(type,mlabel, ilabel, ppConcat3(__ll_,iterator,_next) )  )
00319 
00328 #define sll_foreach_deletecurr(type,mlabel, ilabel, iterator ) \
00329     if( iterator )\
00330     {\
00331         if ( ppConcat3(__ll_,iterator,_prev) )\
00332         {\
00333             ppConcat3(__ll_,iterator,_prev)->mlabel = ppConcat3(__ll_,iterator,_next);\
00334         }\
00335         else\
00336         {\
00337             ilabel = ppConcat3(__ll_,iterator,_next);\
00338         }\
00339         iterator->mlabel = NULL;\
00340     }
00341 
00351 #define sll_push_front(type,mlabel, ilabel, item ) \
00352     {\
00353         (item)->mlabel = (ilabel);\
00354         (ilabel) = (item);\
00355     }
00356 
00366 #define sll_push_back(type,mlabel, ilabel, item ) \
00367     {\
00368         type* __ll_iterate_add;\
00369         sll_back(type,mlabel, ilabel, __ll_iterate_add );\
00370         if( __ll_iterate_add ) \
00371         { \
00372             __ll_iterate_add->mlabel = (item);\
00373         } \
00374         else \
00375         { \
00376             (ilabel) = (item);\
00377         } \
00378         (item)->mlabel = NULL;\
00379     }
00380 
00389 #define sll_front(type,mlabel, ilabel, get ) \
00390     {(get) = (ilabel);}
00391 
00400 #define sll_back(type,mlabel, ilabel, get ) \
00401     {\
00402         type* __ll_iterate = (ilabel);\
00403         if( __ll_iterate ) \
00404             while( __ll_iterate->mlabel )\
00405                 __ll_iterate = __ll_iterate->mlabel;\
00406         (get) = __ll_iterate;\
00407     }
00408 
00417 #define sll_pop_front(type,mlabel, ilabel, get ) \
00418     {\
00419         (get) = (ilabel);\
00420         (ilabel) = (get)->mlabel;\
00421         (get)->mlabel = NULL;\
00422     }
00423 
00432 #define sll_pop_back(type,mlabel, ilabel, get ) \
00433     {\
00434         type* __ll_iterate = (ilabel);\
00435         type* __ll_iterate_prev = NULL;\
00436         if( __ll_iterate ) \
00437         {\
00438             while( __ll_iterate->mlabel )\
00439             {\
00440                 __ll_iterate_prev = __ll_iterate->mlabel;\
00441                 __ll_iterate = __ll_iterate->mlabel;\
00442             }\
00443             if( __ll_iterate_prev )\
00444             {\
00445                 __ll_iterate_prev = NULL;\
00446             }\
00447             else\
00448             {\
00449                 (ilabel) = NULL;\
00450             }\
00451         }\
00452         (get) = __ll_iterate;\
00453     }
00454 
00464 #define sll_erase(type,mlabel, ilabel, item ) \
00465     {\
00466         type* ppConcat(__ll_iterate_remove,_prev) = NULL; \
00467         type* __ll_iterate_remove = (ilabel); \
00468         while( __ll_iterate_remove )\
00469         {\
00470             if ( __ll_iterate_remove == (item) )\
00471             {\
00472                 if ( ppConcat(__ll_iterate_remove,_prev) )\
00473                 {\
00474                     ppConcat(__ll_iterate_remove,_prev)->mlabel = __ll_iterate_remove->mlabel;\
00475                 }\
00476                 else\
00477                 {\
00478                     ilabel = __ll_iterate_remove->mlabel;\
00479                 }\
00480                 break;\
00481             }\
00482             ppConcat(__ll_iterate_remove,_prev) = __ll_iterate_remove;\
00483             __ll_iterate_remove = __ll_iterate_remove->mlabel;\
00484         }\
00485     }
00486 
00498 #define sll_remove_filter(type,mlabel, ilabel, criteria ) \
00499     {\
00500         sll_foreach_deletable(type,mlabel, ilabel, __ll_iterate_delete )\
00501         {\
00502             if ( criteria(__ll_iterate_delete) ) \
00503                 sll_foreach_deletecurr(type,mlabel, ilabel, __ll_iterate_delete ); \
00504         }\
00505     }
00506 
00516 #define sll_move_filter(type,mlabel, ilabel, criteria, target ) \
00517     {\
00518         sll_foreach_deletable(type,mlabel, ilabel, __ll_iterate_move )\
00519         {\
00520             if ( criteria(__ll_iterate_move) ) \
00521             {\
00522                 sll_foreach_deletecurr(type,mlabel, ilabel, __ll_iterate_move ); \
00523                 sll_push_front(type,mlabel, target, __ll_iterate_move );\
00524             }\
00525         }\
00526     }
00527 
00536 #define sll_size(type,mlabel, ilabel, count) \
00537     {\
00538         size_t ppScr2(__sll_size_,tally) = 0;\
00539         type* ppScr2(__sll_size_,iterator);\
00540         for ( ppScr2(__sll_size_,iterator) = (ilabel); ppScr2(__sll_size_,iterator); ppScr2(__sll_size_,iterator) = ppScr2(__sll_size_,iterator)->mlabel, ppScr2(__sll_size_,tally)++ )\
00541             ;\
00542         (count) = ppScr2(__sll_size_,tally);\
00543     }
00544 
00553 #ifndef NDEBUG
00554 #define sll_assert_size(type,mlabel, ilabel, count) \
00555     {\
00556         size_t ppScr2(__sll_assert_size,tally) = 0;\
00557         sll_size(type,mlabel, ilabel, ppScr2(__sll_assert_size,tally));\
00558         assert( ppScr2(__sll_assert_size,tally) == (count) );\
00559     }
00560 #else
00561 #define sll_assert_size(type,mlabel, ilabel, count)
00562 #endif
00563 
00571 #define sll_splice(type,mlabel, toFirst, fromFirst) \
00572     {\
00573         if( toFirst ) \
00574         {\
00575             type* sllTail;\
00576             sll_back(type,mlabel, toFirst, sllTail );\
00577             sllTail->mlabel = (fromFirst);\
00578         }\
00579         else\
00580         {\
00581             (toFirst) = (fromFirst);\
00582         }\
00583         (fromFirst) = NULL;\
00584     }
00585 
00602 #define sll_bsort(type,mlabel, ilabel, compare ) \
00603 {\
00604     if( (ilabel) && (ilabel)->mlabel )\
00605     {\
00606         type* first = ilabel;\
00607         type* sortBefore, *sortPrev, *sortNext;\
00608         int sorted;\
00609         do\
00610         {\
00611             sorted = 0;\
00612             sortBefore = NULL;\
00613             sortPrev = first;\
00614             sortNext = sortPrev->mlabel;\
00615             while( sortNext )\
00616             {\
00617                 if( compare( sortPrev, sortNext ) > 0 )\
00618                 {\
00619                     if( sortBefore )\
00620                     {\
00621                         sortBefore->mlabel = sortNext;\
00622                     }\
00623                     else\
00624                     {\
00625                         first = sortNext;\
00626                     }\
00627                     sortPrev->mlabel = sortNext->mlabel;\
00628                     sortNext->mlabel = sortPrev;\
00629                     sorted++;\
00630                 }\
00631                 sortBefore = sortPrev;\
00632                 sortPrev = sortNext;\
00633                 sortNext = sortNext->mlabel;\
00634             }\
00635         }\
00636         while( sorted );\
00637         ilabel = first;\
00638     }\
00639 }
00640 
00650 #define sll_decl_qsort(type,mlabel, ilabel, name ) \
00651     void name( type** front, type** back, int (*compare)(const void* p1, const void* p2) )
00652 
00662 #define sll_qsort(type,mlabel, ilabel, name, compare ) \
00663         name( &(ilabel), NULL, (int (*)(const void*, const void*))(compare) );\
00664 
00665 
00687 #define sll_mfg_qsort(type,mlabel, ilabel, deref, name ) \
00688 sll_decl_qsort(type,mlabel, ilabel, name )\
00689 {\
00690     if( *front && (*front)->mlabel )\
00691     {\
00692         type* lesser = NULL;\
00693         type* tlesser = NULL;\
00694         type* greater = NULL;\
00695         type* tgreater = NULL;\
00696         type* equal = *front;\
00697         type* tequal = equal;\
00698         type* curr = equal->mlabel;\
00699         while( curr )\
00700         {\
00701             type* next = curr->mlabel;\
00702             int val = compare(deref(equal),deref(curr));\
00703             if( val > 0 )\
00704             {\
00705                 if( tlesser )\
00706                 {\
00707                     tlesser->mlabel = curr;\
00708                     tlesser = curr;\
00709                 }\
00710                 else\
00711                 {\
00712                     tlesser = lesser = curr;\
00713                 }\
00714             }\
00715             else if( val < 0 )\
00716             {\
00717                 if( tgreater )\
00718                 {\
00719                     tgreater->mlabel = curr;\
00720                     tgreater = curr;\
00721                 }\
00722                 else\
00723                 {\
00724                     tgreater = greater = curr;\
00725                 }\
00726             }\
00727             else /* val==0 */\
00728             {\
00729                 assert(val==0);\
00730                 tequal->mlabel = curr;\
00731                 tequal = curr;\
00732             }\
00733             curr = next;\
00734         }\
00735         /* Terminate lists */\
00736         if( lesser )\
00737         {\
00738             tlesser->mlabel = NULL;\
00739             if( lesser != tlesser )\
00740             {\
00741                 tlesser->mlabel = NULL;\
00742                 name( &lesser, &tlesser, compare );\
00743             }\
00744         }\
00745         /* equal are all the same value... */\
00746         if( greater )\
00747         {\
00748             tgreater->mlabel = NULL;\
00749             if( greater != tgreater )\
00750             {\
00751                 name( &greater, &tgreater, compare );\
00752             }\
00753         }\
00754         /* Splice lists together again */\
00755         if( tlesser )\
00756         {\
00757             *front = lesser;\
00758             tlesser->mlabel = equal;\
00759         }\
00760         else\
00761         {\
00762             *front = equal;\
00763         }\
00764         tequal->mlabel = greater;\
00765         if( back )\
00766             *back = tgreater ? tgreater : tequal;\
00767     }\
00768 }
00769 
00770 
00771 /* 
00772  * \defgroup Doubly Doubly Linked Lists
00773  * \ingroup Containers
00774  * 
00775  * last->next and first->prev members of doubly linked list are NULL
00776  * The stl version ends with a loop back to first.  
00777  * That's a bit more complicated to iterate, and we iterate more than we delete.
00778  * For one thing, we can iterate without constantly referring back to the list.
00779 **/
00781 #define _dllnext(mlabel)    ppConcat(mlabel,_next)  
00782 
00783 #define _dllprev(mlabel)    ppConcat(mlabel,_prev)  
00784 
00785 #define _dllfront(ilabel)   ppConcat(ilabel,_front) 
00786 
00787 #define _dllback(ilabel)    ppConcat(ilabel,_back)  
00788 
00795 #define dll_decllink(type,mlabel)\
00796     type*   _dllprev(mlabel);\
00797     type*   _dllnext(mlabel)
00798 
00806 #define dll_initlink(type,mlabel, curr)\
00807     (curr)->_dllprev(mlabel) = (curr)->_dllnext(mlabel) = NULL
00808 
00816 #define dll_decllist(type,mlabel, ilabel)\
00817     type*   _dllfront(ilabel);\
00818     type*   _dllback(ilabel)
00819 
00828 #define dll_islinked(type,mlabel, ilabel, curr)\
00829     ( (curr)->_dllprev(mlabel) || (curr)->_dllnext(mlabel) || (_dllfront(ilabel)==(curr) && _dllback(ilabel)==(curr)) )
00830 
00838 #define dll_initlist(type,mlabel, ilabel)\
00839     _dllfront(ilabel) = _dllback(ilabel) = NULL
00840 
00848 #define dll_autolist(type,mlabel, ilabel)\
00849     type* _dllfront(ilabel) = NULL;\
00850     type* _dllback(ilabel) = NULL
00851 
00859 #define dll_autolist_static(type,mlabel, ilabel)\
00860     static type* _dllfront(ilabel) = NULL;\
00861     static type* _dllback(ilabel) = NULL
00862 
00870 #define dll_externlist(type,mlabel, ilabel)\
00871     extern type* _dllfront(ilabel);\
00872     extern type* _dllback(ilabel)
00873 
00883 #define dll_initarray(type,mlabel, ilabel, array,count) \
00884     {\
00885         size_t __ll_remain = (size_t)(count)-1;\
00886         type* __ll_fromHead = (array);\
00887         type* __ll_fromTail = (array)+__ll_remain;\
00888         (_dllfront(ilabel)) = __ll_fromHead;\
00889         (_dllback(ilabel)) = __ll_fromTail;\
00890         while( __ll_remain-- )\
00891         {\
00892             __ll_fromHead->_dllnext(mlabel) = __ll_fromHead+1;\
00893             __ll_fromTail->_dllprev(mlabel) = __ll_fromTail-1;\
00894             __ll_fromHead++;\
00895             __ll_fromTail--;\
00896         }\
00897         (_dllfront(ilabel))->_dllprev(mlabel) = NULL;\
00898         (_dllback(ilabel))->_dllnext(mlabel) = NULL;\
00899     }
00900 
00901 
00909 #define dll_empty(type,mlabel, ilabel ) ( NULL == _dllfront(ilabel) )
00910 
00919 #define dll_check_link(type,mlabel, ilabel, item ) \
00920     ( \
00921         (item) && \
00922         ( (item)->_dllprev(mlabel) ? ((item)->_dllprev(mlabel)->_dllnext(mlabel) == (item)) : (item) == (_dllfront(ilabel)) ) &&\
00923         ( (item)->_dllnext(mlabel) ? ((item)->_dllnext(mlabel)->_dllprev(mlabel) == (item)) : (item) == (_dllback(ilabel)) )\
00924     )
00925 
00933 #define dll_check(type,mlabel, ilabel ) \
00934     (\
00935         ( !_dllback(ilabel) && !_dllfront(ilabel) ) ||\
00936         (\
00937             ( _dllback(ilabel) && _dllfront(ilabel) && !_dllfront(ilabel)->_dllprev(mlabel) && !_dllback(ilabel)->_dllnext(mlabel) ) &&\
00938             (\
00939                 ( _dllback(ilabel) == _dllfront(ilabel) ) ||\
00940                 ( _dllfront(ilabel)->_dllnext(mlabel)->_dllprev(mlabel) == _dllfront(ilabel) && _dllback(ilabel)->_dllprev(mlabel)->_dllnext(mlabel) == _dllback(ilabel) )\
00941             )\
00942         )\
00943     )
00944 
00945 
00956 #define dll_check_thorough(type,mlabel, ilabel, onfailure ) \
00957     {\
00958         if( dll_check(type,mlabel, ilabel ) )\
00959         {\
00960             const type* fromBack = _dllback(ilabel);\
00961             const type* fromFront = _dllfront(ilabel);\
00962             while( fromBack && fromFront )\
00963             {\
00964                 if( !dll_check_link(type,mlabel, ilabel, fromBack ) )\
00965                 {\
00966                     onfailure("List prev link bad", _dllfront(ilabel),_dllback(ilabel), fromBack);\
00967                     fromBack = fromFront = NULL; /* So we don't get two failures */\
00968                     break;\
00969                 }\
00970                 if( !dll_check_link(type,mlabel, ilabel, fromFront ) )\
00971                 {\
00972                     onfailure("List next link bad", _dllfront(ilabel),_dllback(ilabel), fromFront);\
00973                     fromBack = fromFront = NULL; /* So we don't get two failures */\
00974                     break;\
00975                 }\
00976                 fromBack = fromBack->_dllprev(mlabel);\
00977                 fromFront = fromFront->_dllnext(mlabel);\
00978             }\
00979             if( fromBack )\
00980                 onfailure("List prev count higher than next count.", _dllfront(ilabel),_dllback(ilabel), fromBack);\
00981             if( fromFront )\
00982                 onfailure("List next count higher than prev count.", _dllfront(ilabel),_dllback(ilabel), fromFront);\
00983         }\
00984         else\
00985         {\
00986             onfailure("List front/back links bad", _dllfront(ilabel),_dllback(ilabel),NULL);\
00987         }\
00988     }
00989 
00997 #define dll_reset(type,mlabel, ilabel) \
00998     {\
00999         type* __dllCurr = (_dllfront(ilabel));\
01000         (_dllfront(ilabel)) = (_dllback(ilabel)) = NULL;\
01001         while( _dllCurr )\
01002         {\
01003             type* __dllNext = __dllCurr->_dllnext(mlabel);\
01004             __dllCurr->_dllnext(mlabel) = __dllCurr->_dllprev(mlabel) = NULL;\
01005             __dllCurr = __dllNext;\
01006         }\
01007     }
01008 
01017 #define dll_next(type,mlabel, ilabel, curr ) \
01018     ((curr) = (curr) ? ((curr)->_dllnext(mlabel)) : NULL)
01019 
01028 #define dll_prev(type,mlabel, ilabel, curr ) \
01029     ((curr) = (curr) ? ((curr)->_dllprev(mlabel)) : NULL)
01030 
01042 #define dll_foreach_const(type,mlabel, ilabel, iterator ) \
01043     const type* iterator = (_dllfront(ilabel)); \
01044     for ( ; iterator; iterator = iterator->_dllnext(mlabel) )
01045 
01057 #define dll_foreach_reverse_const(type,mlabel, ilabel, iterator ) \
01058     const type* iterator = (_dllback(ilabel)); \
01059     for( ; iterator; iterator = iterator->_dllprev(mlabel) )
01060 
01072 #define dll_foreach(type,mlabel, ilabel, iterator ) \
01073     type* iterator = (_dllfront(ilabel)); \
01074     for ( ; iterator; iterator = iterator->_dllnext(mlabel) )
01075 
01087 #define dll_foreach_reverse(type,mlabel, ilabel, iterator ) \
01088     type* iterator = (_dllback(ilabel)); \
01089     for( ; iterator; iterator = iterator->_dllprev(mlabel) )
01090 
01101 #define dll_foreach_deletable(type,mlabel, ilabel, iterator ) \
01102     type* iterator = (_dllfront(ilabel));\
01103     type* ppConcat3(__ll_,iterator,_next) = iterator?iterator->_dllnext(mlabel):NULL; \
01104     for ( ; iterator; iterator = ppConcat3(__ll_,iterator,_next), dll_next(type,mlabel, ilabel, ppConcat3(__ll_,iterator,_next) ) )
01105 
01116 #define dll_foreach_deletable_reverse(type,mlabel, ilabel, iterator ) \
01117     type* iterator = (_dllback(ilabel));\
01118     type* ppConcat3(__ll_,iterator,_next) = iterator?iterator->_dllprev(mlabel):NULL; \
01119     for ( ; iterator; iterator = ppConcat3(__ll_,iterator,_next), dll_prev(type,mlabel, ilabel, ppConcat3(__ll_,iterator,_next) ) )
01120 
01131 #define dll_push_front(type,mlabel, ilabel, item ) \
01132     {\
01133         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01134         (item)->_dllnext(mlabel) = (_dllfront(ilabel));\
01135         (item)->_dllprev(mlabel) = NULL;\
01136         if( (_dllfront(ilabel)) )\
01137         {\
01138             (_dllfront(ilabel))->_dllprev(mlabel) = (item);\
01139         }\
01140         else\
01141         {\
01142             (_dllback(ilabel)) = (item);\
01143         }\
01144         (_dllfront(ilabel)) = (item);\
01145     }
01146 
01157 #define dll_push_back(type,mlabel, ilabel, item ) \
01158     {\
01159         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01160         (item)->_dllnext(mlabel) = NULL;\
01161         (item)->_dllprev(mlabel) = (_dllback(ilabel));\
01162         if( _dllback(ilabel) )\
01163         {\
01164             (_dllback(ilabel))->_dllnext(mlabel) = (item);\
01165         }\
01166         else\
01167         {\
01168             (_dllfront(ilabel)) = (item);\
01169         }\
01170         (_dllback(ilabel)) = (item);\
01171     }
01172 
01184 #define dll_insert(type,mlabel, ilabel, after, item ) \
01185     {\
01186         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01187         if( after )\
01188         {   /* Insert link after 'after' */ \
01189             (item)->_dllnext(mlabel) = (after)->_dllnext(mlabel);\
01190             (item)->_dllprev(mlabel) = (after);\
01191             (after)->_dllnext(mlabel) = (item);\
01192             if( (item)->_dllnext(mlabel) )\
01193                 (item)->_dllnext(mlabel)->_dllprev(mlabel) = (item);\
01194             else\
01195                 (_dllback(ilabel)) = (item);\
01196         }\
01197         else\
01198         {   /* Push front */\
01199             (item)->_dllnext(mlabel) = (_dllfront(ilabel));\
01200             (item)->_dllprev(mlabel) = NULL;\
01201             if( (_dllfront(ilabel)) )\
01202                 (_dllfront(ilabel))->_dllprev(mlabel) = (item);\
01203             else\
01204                 (_dllback(ilabel)) = (item);\
01205             (_dllfront(ilabel)) = (item);\
01206         }\
01207     }
01208 
01220 #define dll_insert_before(type,mlabel, ilabel, before, item ) \
01221     {\
01222         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01223         if( before )\
01224         {   /* Insert link before 'before' */ \
01225             (item)->_dllprev(mlabel) = (before)->_dllnext(mlabel);\
01226             (item)->_dllnext(mlabel) = (before);\
01227             (before)->_dllprev(mlabel) = (item);\
01228             if( (item)->_dllprev(mlabel) )\
01229                 (item)->_dllprev(mlabel)->_dllnext(mlabel) = (item);\
01230             else\
01231                 (_dllfront(ilabel)) = (item);\
01232         }\
01233         else\
01234         {   /* push_back */\
01235             (item)->_dllnext(mlabel) = NULL;\
01236             (item)->_dllprev(mlabel) = (_dllback(ilabel));\
01237             if( _dllback(ilabel) )\
01238                 (_dllback(ilabel))->_dllnext(mlabel) = (item);\
01239             else\
01240                 (_dllfront(ilabel)) = (item);\
01241             (_dllback(ilabel)) = (item);\
01242         }\
01243     }
01244 
01253 #define dll_front(type,mlabel, ilabel, get ) \
01254     {(get) = (_dllfront(ilabel));}
01255 
01264 #define dll_back(type,mlabel, ilabel, get ) \
01265     {(get) = (_dllback(ilabel));}
01266 
01275 #define dll_pop_front(type,mlabel, ilabel, get ) \
01276     {\
01277         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01278         (get) = (_dllfront(ilabel));\
01279         if( (get) && (get)->_dllnext(mlabel) )\
01280         {\
01281             (_dllfront(ilabel)) = (get)->_dllnext(mlabel);\
01282             (get)->_dllnext(mlabel)->_dllprev(mlabel) = NULL;\
01283         }\
01284         else\
01285         {\
01286             (_dllfront(ilabel)) = (_dllback(ilabel)) = NULL;\
01287         }\
01288     }
01289 
01298 #define dll_pop_back(type,mlabel, ilabel, get ) \
01299     {\
01300         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01301         (get) = (_dllback(ilabel));\
01302         if( (get) && (get)->_dllprev(mlabel) )\
01303         {\
01304             (_dllback(ilabel)) = (get)->_dllprev(mlabel);\
01305             (get)->_dllprev(mlabel)->_dllnext(mlabel) = NULL;\
01306         }\
01307         else\
01308         {\
01309             (_dllfront(ilabel)) = (_dllback(ilabel)) = NULL;\
01310         }\
01311     }
01312 
01323 #define dll_erase(type,mlabel, ilabel, item ) \
01324     {\
01325         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01326         assert( dll_check_link(type,mlabel, ilabel, item ) ); /* Link sanity */\
01327         if( (item)->_dllprev(mlabel) )\
01328         {\
01329             (item)->_dllprev(mlabel)->_dllnext(mlabel) = (item)->_dllnext(mlabel);\
01330         }\
01331         else\
01332         {\
01333             (_dllfront(ilabel)) = (item)->_dllnext(mlabel);\
01334         }\
01335         if( (item)->_dllnext(mlabel) )\
01336         {\
01337             (item)->_dllnext(mlabel)->_dllprev(mlabel) = (item)->_dllprev(mlabel);\
01338         }\
01339         else\
01340         {\
01341             (_dllback(ilabel)) = (item)->_dllprev(mlabel);\
01342         }\
01343         dll_initlink(type,mlabel, item );\
01344     }
01345 
01354 #define dll_remove_filter(type,mlabel, ilabel, criteria ) \
01355     {\
01356         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01357         {\
01358             dll_foreach_deletable(type,mlabel, ilabel, __ll_iterate_delete )\
01359             {\
01360                 if ( criteria(__ll_iterate_delete) ) \
01361                     dll_erase(type,mlabel, ilabel, __ll_iterate_delete );\
01362             }\
01363         }\
01364     }
01365 
01375 #define dll_move_filter(type,mlabel, ilabel, criteria, target ) \
01376     {\
01377         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01378         {\
01379             dll_foreach_deletable(type,mlabel, _dllfront(ilabel), __ll_iterate_move )\
01380             {\
01381                 if ( criteria(__ll_iterate_delete) ) \
01382                 {\
01383                     dll_erase(type,mlabel, ilabel, __ll_iterate_delete );\
01384                     dll_push_back(type,mlabel, target, __ll_iterate_move );\
01385                 }\
01386             }\
01387         }\
01388     }
01389 
01398 #define dll_size(type,mlabel, ilabel, count)            sll_size( type,_dllnext(mlabel), _dllfront(ilabel), count )
01399 
01408 #define dll_assert_size(type,mlabel, ilabel, count)     sll_assert_size( type,_dllnext(mlabel), _dllfront(ilabel), count )
01409 
01418 #define dll_splice(type,mlabel, ilabelto, ilabelfrom ) \
01419     {\
01420         assert( dll_check(type,mlabel, ilabelto ) ); /* List sanity */\
01421         assert( dll_check(type,mlabel, ilabelfrom ) ); /* List sanity */\
01422         if( _dllback(ilabelto) )\
01423         {\
01424             if( _dllfront(ilabelfrom) )\
01425             {\
01426                 (_dllfront(ilabelfrom))->_dllprev(mlabel) = (_dllback(ilabelto));\
01427                 (_dllback(ilabelto))->_dllnext(mlabel) = (_dllfront(ilabelfrom));\
01428                 (_dllback(ilabelto)) = (_dllback(ilabelfrom));\
01429             }\
01430         }\
01431         else\
01432         {\
01433             (_dllfront(ilabelto)) = (_dllfront(ilabelfrom));\
01434             (_dllback(ilabelto)) = (_dllback(ilabelfrom));\
01435         }\
01436         _dllfront(ilabelfrom) = _dllback(ilabelfrom) = NULL;\
01437     }
01438 
01439 
01447 #define dll_rebuild_back(type,mlabel, ilabel ) \
01448     {\
01449         /* Now that we've sorted the _dllnext(mlabel) links, fixup the _dllprev(mlabel) links */\
01450         type* __ll_iterator_prev = NULL; \
01451         type* iterator = (_dllfront(ilabel));\
01452         type* __ll_iterator_next = iterator?iterator->_dllnext(mlabel):NULL; \
01453         for ( ; iterator; __ll_iterator_prev = iterator, iterator = __ll_iterator_next, sll_next(type,_dllnext(mlabel), _dllfront(ilabel), __ll_iterator_next ) )\
01454         {\
01455             iterator->_dllprev(mlabel) = __ll_iterator_prev;\
01456         }\
01457         (_dllback(ilabel)) = __ll_iterator_prev;\
01458     }\
01459 
01460 
01467 #define dll_rebuild_front(type,mlabel, ilabel ) \
01468     {\
01469         /* Now that we've sorted the _dllnext(mlabel) links, fixup the _dllprev(mlabel) links */\
01470         type* __ll_iterator_next = NULL; \
01471         type* iterator = (_dllback(ilabel));\
01472         type* __ll_iterator_prev = iterator?iterator->_dllprev(mlabel):NULL; \
01473         for ( ; iterator; __ll_iterator_next = iterator, iterator = __ll_iterator_prev, sll_next(type,_dllprev(mlabel), _dllback(ilabel), __ll_iterator_prev ) )\
01474         {\
01475             iterator->_dllnext(mlabel) = __ll_iterator_next;\
01476         }\
01477         (_dllfront(ilabel)) = __ll_iterator_next;\
01478     }\
01479 
01480 
01488 #define dll_bsort(type,mlabel, ilabel, compare ) \
01489     {\
01490         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01491         sll_bsort(type,_dllnext(mlabel), _dllfront(ilabel), compare );\
01492         dll_rebuild_back(type,mlabel, ilabel );\
01493     }
01494 
01503 #define dll_decl_qsort(type,mlabel, ilabel, name ) \
01504     sll_decl_qsort(type,_dllnext(mlabel), _dllfront(ilabel), name )
01505 
01515 #define dll_mfg_qsort(type,mlabel, ilabel, deref, name ) \
01516     sll_mfg_qsort(type,_dllnext(mlabel), _dllfront(ilabel), deref, name )
01517 
01527 #define dll_qsort(type,mlabel, ilabel, name, compare ) \
01528     {\
01529         assert( dll_check(type,mlabel, ilabel ) ); /* List sanity */\
01530         name( &_dllfront(ilabel), &_dllback(ilabel), (int (*)(const void*, const void*))(compare) );\
01531         dll_rebuild_back(type,mlabel, ilabel );\
01532     }
01533 
01534 
01535 #endif /* LL_H */
01536 

Generated on Fri Jan 2 15:28:34 2009 for Squat by  doxygen 1.5.6