list.h

00001 #ifndef DG_LIST_H
00002 #define DG_LIST_H
00003 
00009 #ifndef LL_H
00010 #include "ctl/ll.h"
00011 #endif
00012 
00020 #define ctl_declare_list(label,type)\
00021     typedef type ppConcat(label,_type);\
00022     typedef struct ppConcat(label,_node)\
00023     {\
00024         dll_decllink(struct ppConcat(label,_node),link); /* Invasive linked list base */ \
00025         type            obj;        /* The actual member */ \
00026         ppDebug(const struct label* container;)\
00027     } ppConcat(label,_node);\
00028     typedef struct label\
00029     {\
00030         dll_decllist(ppConcat(label,_node),link, list);\
00031         size_t count;\
00032     } label;\
00033     /* So we can monitor memory use/leaks */\
00034     extern ctl_pool(ppConcat(label,_node)) ppConcat(label,_pool);\
00035     /* The standard pattern functions */\
00036     ctl_datagen_declare_functions(label);\
00037     /* How many members in this list */\
00038     size_t ppConcat(label,_count)( const label* self);\
00039     /* Tell us if an object is part of this list */\
00040     bool ppConcat(label,_ismember)( const label* self, const type* mbr );\
00041     /* Destroy all members, release all memory */\
00042     void ppConcat(label,_clear)( label* self );\
00043     /* Get a pointer to the back end member of list */\
00044     type* ppConcat(label,_back)(const label* self);\
00045     /* Get a pointer to the front end member of list */\
00046     type* ppConcat(label,_front)(const label* self);\
00047     /* Get a pointer to the member before 'curr' of list self, or NULL if we hit end */\
00048     type* ppConcat(label,_prev)(const label* self, const type* curr);\
00049     /* Get a pointer to the member after 'curr' of list self, or NULL if we hit end */\
00050     type* ppConcat(label,_next)(const label* self, const type* curr);\
00051     /* Add a new member to back end of list, return a pointer to it */\
00052     type* ppConcat(label,_push_back)(label* self);\
00053     /* Add a new member to front end of list, return a pointer to it */\
00054     type* ppConcat(label,_push_front)(label* self);\
00055     /* Insert a new member at the current position */\
00056     type* ppConcat(label,_insert)(label* self, type* mbr );\
00057     /* Remove (and destroy) last member */\
00058     void  ppConcat(label,_pop_back)(label* self);\
00059     /* Remove (and destroy) first member */\
00060     void  ppConcat(label,_pop_front)(label* self);\
00061     /* Erase (and destroy) a member by its pointer */\
00062     void  ppConcat(label,_erase)(label* self, type* mbr );\
00063     /* Quicker-Sort by qsort-like criteria */\
00064     void  ppConcat(label,_sort)( label* self, int (*compare)(const type* p1, const type* p2) );\
00065     /* Splice the list 'from' to this one and clear() from */\
00066     void  ppConcat(label,_splice)( label* self, label* from );\
00067 
00068 
00079 #define ctl_list_foreach( label, instance, iterator ) \
00080     ppConcat(label,_type)* iterator;\
00081     ppConcat(label,_node)* ppConcat(_,iterator) = (instance)->_dllfront(list);\
00082     for( ; NULL != ppConcat(_,iterator) && intentional_assignment(iterator = &ppConcat(_,iterator)->obj); ppConcat(_,iterator) = ppConcat(_,iterator)->_dllnext(link) )
00083 
00094 #define ctl_list_foreach_reverse( label, instance, iterator )\
00095     ppConcat(label,_type)* iterator;\
00096     ppConcat(label,_node)* ppConcat(_,iterator) = (instance)->_dllback(list);\
00097     for( ; NULL != ppConcat(_,iterator) && intentional_assignment(iterator = &ppConcat(_,iterator)->obj); ppConcat(_,iterator) = ppConcat(_,iterator)->_dllprev(link) )
00098 
00109 #define ctl_list_foreach_const( label, instance, iterator ) \
00110     const ppConcat(label,_type)* iterator;\
00111     const ppConcat(label,_node)* ppConcat(_,iterator) = (instance)->_dllfront(list);\
00112     for( ; NULL != ppConcat(_,iterator) && intentional_assignment(iterator = &ppConcat(_,iterator)->obj); ppConcat(_,iterator) = ppConcat(_,iterator)->_dllnext(link) )
00113 
00124 #define ctl_list_foreach_const_reverse( label, instance, iterator )\
00125     const ppConcat(label,_type)* iterator;\
00126     const ppConcat(label,_node)* ppConcat(_,iterator) = (instance)->_dllback(list);\
00127     for( ; NULL != ppConcat(_,iterator) && intentional_assignment(iterator = &ppConcat(_,iterator)->obj); ppConcat(_,iterator) = ppConcat(_,iterator)->_dllprev(link) )
00128 
00139 #define ctl_list_foreach_mutable( label, instance, iterator )\
00140     ppConcat(label,_type)* iterator;\
00141     ppConcat(label,_node)* ppConcat(_,iterator) = (instance)->_dllback(list);\
00142     ppConcat(label,_node)* ppConcat3(_,iterator,_next) = ppConcat(_,iterator)?ppConcat(_,iterator)->_dllnext(link):NULL; \
00143     for ( ; NULL != ppConcat(_,iterator) && intentional_assignment(iterator = &ppConcat(_,iterator)->obj); (void)(intentional_assignment(ppConcat(_,iterator) = ppConcat3(_,iterator,_next) ) && intentional_assignment(ppConcat3(_,iterator,_next) = ppConcat3(_,iterator,_next)->_dllnext(link))) )
00144 
00155 #define ctl_list_foreach_mutable_reverse( label, instance, iterator )\
00156     ppConcat(label,_type)* iterator;\
00157     ppConcat(label,_node)* ppConcat(_,iterator) = (instance)->_dllfront(list);\
00158     ppConcat(label,_node)* ppConcat3(_,iterator,_prev) = ppConcat(_,iterator)?ppConcat(_,iterator)->_dllprev(link):NULL; \
00159     for ( ; NULL != ppConcat(_,iterator) && intentional_assignment(iterator = &ppConcat(_,iterator)->obj); (void)(intentional_assignment(ppConcat(_,iterator) = ppConcat3(_,iterator,_prev)) && intentional_assignment(ppConcat3(_,iterator,_prev) = ppConcat3(_,iterator,_prev)->_dllprev(link))) )
00160 
00161 
00162 #ifndef CTL_POOL_DELTA
00163 
00169 #define CTL_POOL_DELTA  16
00170 #endif
00171 /* Needed by the list qsort manufacture */
00172 #define ctl_deref_list_mbr(node)    &((node)->obj)
00173 
00180 #define ctl_implement_list(label,type)\
00181 ctl_pool_auto(ppConcat(label,_node),ppConcat(label,_pool),16);\
00182 const bool ppConcat(label,_isscalar) = false;\
00183 /* Initialize this record to a known, default state */\
00184 void ppConcat(label,_init)( label* self )\
00185 {\
00186     assertobjptr(self);\
00187     dll_initlist(ppConcat(label,_node),link, self->list);\
00188     self->count = 0;\
00189 }\
00190 /* Replicate a record, copying from 'src' to 'dst' */\
00191 void ppConcat(label,_copy)( label* dst, const label* src )\
00192 {\
00193     assertobjptr(dst);\
00194     assertobjconst(src);\
00195     ppConcat(label,_init)( dst );\
00196     {\
00197         ctl_list_foreach_const( label, src, curr )\
00198             ppConcat(type,_copy)(ppConcat(label,_push_back)(dst),curr);\
00199     }\
00200 }\
00201 /* Move contents from 'src' to 'dst', leaving 'dst' uninitialized. */\
00202 void ppConcat(label,_move)( label* dst, label* src )\
00203 {\
00204     assertobjptr(dst);\
00205     assertobjptr(src);\
00206     {\
00207         ppDebug(ppConcat(label,_node)* curr = src->_dllfront(list);)\
00208         ppDebug(while( curr ) { curr->container = dst; curr = curr->_dllnext(link); } )\
00209         _dllfront(dst->list) = _dllfront(src->list);\
00210         _dllback(dst->list) = _dllback(src->list);\
00211         dst->count = src->count;\
00212         src->count = 0;\
00213         dll_initlist(ppConcat(label,_node),link, src->list);\
00214     }\
00215 }\
00216 /* Swap contents of two records */\
00217 void ppConcat(label,_swap)( label* p1, label* p2 )\
00218 {\
00219     assertobjptr(p1);\
00220     assertobjptr(p2);\
00221     {\
00222         ppDebug(ppConcat(label,_node)* curr;)\
00223         label tmp = *p1;\
00224         *p1 = *p2;\
00225         *p2 = tmp;\
00226         ppDebug(curr = p1->_dllfront(list);)\
00227         ppDebug(while( curr ) { curr->container = p1; curr = curr->_dllnext(link); } )\
00228         ppDebug(curr = p2->_dllfront(list);)\
00229         ppDebug(while( curr ) { curr->container = p2; curr = curr->_dllnext(link); } )\
00230     }\
00231 }\
00232 /* Destroy this record, freeing any contained data */\
00233 void ppConcat(label,_destroy)( label* self )\
00234 {\
00235     ppConcat(label,_clear)( self );\
00236 }\
00237 /* Compare this record to another record for sorting */\
00238 int ppConcat(label,_rcompare)( const label* p1, const label* p2 ) { return ppConcat(label,_compare)( p2,p1 ); }\
00239 /* Compare this record to another record for sorting */\
00240 int ppConcat(label,_compare)( const label* p1, const label* p2 )\
00241 {\
00242     if( !p1 && !p2 )\
00243         return 0;\
00244     assertobjconst(p1);\
00245     assertobjconst(p2);\
00246     {\
00247         size_t compareLen = min(p1->count,p2->count);\
00248         const ppConcat(label,_node)* scan1;\
00249         const ppConcat(label,_node)* scan2;\
00250         dll_front(ppConcat(label,_node),link, p1->list, scan1 );\
00251         dll_front(ppConcat(label,_node),link, p2->list, scan2 );\
00252         while( compareLen-- && scan1 && scan2 )\
00253         {\
00254             int result = ppConcat(type,_compare)( &scan1->obj, &scan2->obj );\
00255             if( result )\
00256                 return result;\
00257             scan1 = scan1->_dllnext(link);\
00258             scan2 = scan2->_dllnext(link);\
00259         }\
00260         /* If we fell through to here, something's amiss with the links/count */\
00261         assert(compareLen == -1);\
00262         if( p1->count < p2->count )\
00263             return -1;\
00264         if( p1->count > p2->count )\
00265             return 1;\
00266         return 0;\
00267     }\
00268 }\
00269 /* Determine if a record is valid-looking; all validated members in expected range */\
00270 bool ppConcat(label,_valid)( const label* self )\
00271 {\
00272     if( !self )\
00273         return false;\
00274     assertobjconst(self);\
00275     if( !dll_check(ppConcat(label,_node),link, self->list ) ) \
00276         return false;\
00277     return true;\
00278 }\
00279 /* Determine total memory footprint of this list */\
00280 size_t ppConcat(label,_size)( const label* self )\
00281 {\
00282     assertobjconst(self);\
00283     if( ppConcat(type,_isscalar) )\
00284     {\
00285         return sizeof(*self) + (self->count * sizeof(ppConcat(label,_node)));\
00286     }\
00287     else\
00288     {\
00289         size_t ret = sizeof *self;\
00290         ctl_list_foreach_const( label, self, curr )\
00291             ret += ppConcat(type,_size)(curr) + sizeof(ppConcat(label,_node))-sizeof(type);\
00292         ret += (sizeof(ppConcat(label,_node))-sizeof(type))*self->count;\
00293         return ret;\
00294     }\
00295 }\
00296 /* Determine total size of this record as stingy serial data */\
00297 size_t ppConcat(label,_serial_size)( const label* self )\
00298 {\
00299     assertobjconst(self);\
00300     if( ppConcat(type,_isscalar) )\
00301     {\
00302         return ctl_serial_size_size( self->count ) + (self->count * ppConcat(type,_serial_size)(ppConcat(label,_front)(self)));\
00303     }\
00304     else\
00305     {\
00306         size_t total = ctl_serial_size_size( self->count );\
00307         ctl_list_foreach_const( label, self, curr )\
00308             total += ppConcat(type,_serial_size)(curr);\
00309         return total;\
00310     }\
00311 }\
00312 /* Write data to a stingy serial record */\
00313 void ppConcat(label,_serial_write)( const label* self, ctl_serial* serial )\
00314 {\
00315     assertobjconst(self);\
00316     assertobjptr(serial);\
00317     ctl_serial_writesize( self->count, serial ); \
00318     {\
00319         ctl_list_foreach_const( label, self, curr )\
00320             ppConcat(type,_serial_write)(curr,serial);\
00321     }\
00322 }\
00323 /* Read data from a stingy serial record */\
00324 void ppConcat(label,_serial_read)( label* self, ctl_serial* serial )\
00325 {\
00326     assertobjptr(self);\
00327     assertobjptr(serial);\
00328     {\
00329         size_t readsize = ctl_serial_readsize( serial ); \
00330         while( readsize-- )\
00331             ppConcat(type,_serial_read)( ppConcat(label,_push_back)(self), serial );\
00332     }\
00333 }\
00334 /* Determine total size of this record as robust/archive serial data */\
00335 size_t ppConcat(label,_record_size)( const label* self, const char* szlabel )\
00336 {\
00337     assertobjconst(self);\
00338     assertconst(szlabel,1);\
00339     if( self->count )\
00340     {\
00341         size_t result = ctl_record_objarray_head_size( szlabel, "container", #type );\
00342         if( ppConcat(type,_isscalar) )\
00343         {\
00344             result += (self->count * ppConcat(type,_record_size)(ppConcat(label,_front)(self),szlabel));\
00345         }\
00346         else\
00347         { \
00348             ctl_list_foreach_const(label,self,curr) \
00349                 result += ppConcat(type,_record_size)(curr,szlabel); \
00350         }\
00351         return result;\
00352     }\
00353     return 0;\
00354 }\
00355 /* Write data to a robust binary serial record */\
00356 void ppConcat(label,_record_write)( const label* self, ctl_serial* serial, const char* szlabel )\
00357 {\
00358     assertobjconst(self);\
00359     assertobjptr(serial);\
00360     assertconst(szlabel,1);\
00361     if( self->count )\
00362     {\
00363         uint8* rectemp = ctl_record_write_container_begin( "container", #type, 0,self->count, serial, szlabel );\
00364         { \
00365             ctl_list_foreach_const(label,self,curr) \
00366                 ppConcat(type,_record_write)(curr,serial,szlabel); \
00367         }\
00368         ctl_record_write_end( rectemp, serial );\
00369     }\
00370 }\
00371 /* Read data from a robust/archive binary serial record */\
00372 bool ppConcat(label,_record_read)( label* self, ctl_serial* serial, const char* szlabel )\
00373 {\
00374     assertobjptr(self);\
00375     assertobjptr(serial);\
00376     assertconst(szlabel,1);\
00377     {\
00378         ctl_serial pserial = *serial;\
00379         ppConcat(label,_clear)(self);\
00380         if( ctl_record_find( &pserial, szlabel ) )\
00381         {\
00382             size_t count = ctl_record_container_validatedata( &pserial, "container", szconst(char,#type) );\
00383             while( count-- )\
00384             {\
00385                 ppConcat(type,_record_read)( ppConcat(label,_push_back)(self), &pserial, szlabel );\
00386                 ctl_record_next( &pserial );\
00387             }\
00388             if( pserial.curr != pserial.end )\
00389                 ctl_serial_except( &pserial, szconst(char,#label) szconst(char,"_record_read: Wrong data length!") );\
00390             return true;\
00391         }\
00392     }\
00393     return false;\
00394 }\
00395 /* Write data to an XML record */\
00396 void ppConcat(label,_xml_write)( const label* self, ctl_xmlwrite* xml, const char* szlabel )\
00397 {\
00398     assertobjconst(self);\
00399     assertobjptr(xml);\
00400     assertconst(szlabel,1);\
00401     if( self->count )\
00402     {\
00403         ctl_xmlwrite_containertag( xml, #type, self->count, szlabel ); \
00404         ctl_xmlwrite_indent( xml );\
00405         {\
00406             ctl_list_foreach_const(label,self, curr ) \
00407                 ppConcat(type,_xml_write)(curr,xml,NULL);\
00408         } \
00409         ctl_xmlwrite_outdent( xml );\
00410         ctl_xmlwrite_endtag( xml, #type, szlabel ); \
00411     }\
00412 }\
00413 /* Read data from an XML record */\
00414 bool ppConcat(label,_xml_read)( label* self, ctl_xmlread* xml, const char* szlabel )\
00415 {\
00416     assertobjptr(self);\
00417     assertobjptr(xml);\
00418     assertconst(szlabel,1);\
00419     if( ctl_xmlread_find( xml, szlabel ) )\
00420     {\
00421         int32 count = 0;\
00422         if( ctl_xmlread_getattribute_int( xml, CTL_LABEL_COUNT, &count ) )\
00423         {\
00424             ctl_xmlread arraydata;\
00425             ctl_xmlread_recurse(&arraydata,xml);\
00426             while( count-- && ppConcat(type,_xml_read)( ppConcat(label,_push_back)(self), &arraydata, NULL ) )\
00427                 ctl_xmlread_next(&arraydata);\
00428         }\
00429         else\
00430         {\
00431             xml->except( xml, szconst(char,#label) szconst(char,"_xml_read: Missing size attribute!"), xml->szpCurr, NULL );\
00432         }\
00433         return true;\
00434     }\
00435     return false;\
00436 }\
00437 /* How many members in this list */\
00438 size_t ppConcat(label,_count)( const label* self)\
00439 {\
00440     assertobjconst(self);\
00441     return self->count;\
00442 }\
00443 /* Tell us if an object is part of this list */\
00444 bool ppConcat(label,_ismember)( const label* self, const type* data )\
00445 {\
00446     assertobjconst(self);\
00447     assertobjconst(data);\
00448     ppDebug(return dereference(ppConcat(label,_node),obj,data)->container == self;)\
00449     ppRelease({ ctl_list_foreach_const(label,self,curr) if( curr == data ) return true; })\
00450     ppRelease(return false;)\
00451 }\
00452 /* Destroy all members, release all memory */\
00453 void ppConcat(label,_clear)( label* self )\
00454 {\
00455     assertobjptr(self);\
00456     for( ;; )\
00457     {\
00458         ppConcat(label,_node)* curr;\
00459         dll_pop_back(ppConcat(label,_node),link, self->list, curr );\
00460         if( curr )\
00461         {\
00462             ppConcat(type,_destroy)(&curr->obj);\
00463             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), curr);\
00464         }\
00465         else\
00466             break;\
00467     }\
00468     self->count = 0;\
00469 }\
00470 /* Get a pointer to the back end member of list */\
00471 type* ppConcat(label,_back)(const label* self)\
00472 {\
00473     assertobjconst(self);\
00474     {\
00475         const ppConcat(label,_node)* ret;\
00476         dll_back(ppConcat(label,_node),link, self->list, ret );\
00477         return (type*)(ret?&ret->obj:NULL);\
00478     }\
00479 }\
00480 /* Get a pointer to the front end member of list */\
00481 type* ppConcat(label,_front)(const label* self)\
00482 {\
00483     assertobjconst(self);\
00484     {\
00485         const ppConcat(label,_node)* ret;\
00486         dll_front(ppConcat(label,_node),link, self->list, ret );\
00487         return (type*)(ret?&ret->obj:NULL);\
00488     }\
00489 }\
00490 /* Get a pointer to the member before 'curr' of list self, or NULL if we hit end */\
00491 type* ppConcat(label,_prev)(const label* self, const type* curr)\
00492 {\
00493     if( curr )\
00494     {\
00495         const ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj, curr);\
00496         assert( node->container == self );\
00497         node = node->_dllprev(link);\
00498         if( node )\
00499             return (type*)&node->obj;\
00500     }\
00501     return NULL;\
00502 }\
00503 /* Get a pointer to the member after 'curr' of list self, or NULL if we hit end */\
00504 type* ppConcat(label,_next)(const label* self, const type* curr)\
00505 {\
00506     if( curr )\
00507     {\
00508         const ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj, curr);\
00509         assert( node->container == self );\
00510         node = node->_dllnext(link);\
00511         if( node )\
00512             return (type*)&node->obj;\
00513     }\
00514     return NULL;\
00515 }\
00516 /* Get a pointer to the next member of list, given a current member */\
00517 type* ppConcat(label,_push_back)(label* self)\
00518 {\
00519     assertobjptr(self);\
00520     {\
00521         ppConcat(label,_node)* node;\
00522         ctl_pool_alloc(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00523         dll_push_back(ppConcat(label,_node),link, self->list, node );\
00524         ppConcat(type,_init)(&node->obj);\
00525         ppDebug(node->container = self;)\
00526         self->count++;\
00527         return &node->obj;\
00528     }\
00529 }\
00530 /* Add a new member to front end of list, return a pointer to it */\
00531 type* ppConcat(label,_push_front)(label* self)\
00532 {\
00533     assertobjptr(self);\
00534     {\
00535         ppConcat(label,_node)* node;\
00536         ctl_pool_alloc(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00537         dll_push_front(ppConcat(label,_node),link, self->list, node );\
00538         ppConcat(type,_init)(&node->obj);\
00539         ppDebug(node->container = self;)\
00540         self->count++;\
00541         return &node->obj;\
00542     }\
00543 }\
00544 /* Insert a new member at the current position */\
00545 type* ppConcat(label,_insert)(label* self, type* mbr )\
00546 {\
00547     assertobjptr(self);\
00548     assertobjptr(mbr);\
00549     {\
00550         ppConcat(label,_node)* inode = dereference(ppConcat(label,_node),obj, mbr);\
00551         assert( inode->container == self );\
00552         {\
00553             ppConcat(label,_node)* node;\
00554             ctl_pool_alloc(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00555             dll_insert_before(ppConcat(label,_node),link, self->list, inode, node );\
00556             ppConcat(type,_init)(&node->obj);\
00557             ppDebug(node->container = self;)\
00558             self->count++;\
00559             return &node->obj;\
00560         }\
00561     }\
00562 }\
00563 /* Remove (and destroy) last member */\
00564 void  ppConcat(label,_pop_back)(label* self)\
00565 {\
00566     assertobjptr(self);\
00567     {\
00568         ppConcat(label,_node)* node;\
00569         dll_pop_back(ppConcat(label,_node),link, self->list, node );\
00570         if( node )\
00571         {\
00572             ppConcat(type,_destroy)(&node->obj);\
00573             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00574             self->count--;\
00575         }\
00576     }\
00577 }\
00578 /* Remove (and destroy) first member */\
00579 void  ppConcat(label,_pop_front)(label* self)\
00580 {\
00581     assertobjptr(self);\
00582     {\
00583         ppConcat(label,_node)* node;\
00584         dll_pop_front(ppConcat(label,_node),link, self->list, node );\
00585         if( node )\
00586         {\
00587             ppConcat(type,_destroy)(&node->obj);\
00588             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00589             self->count--;\
00590         }\
00591     }\
00592 }\
00593 /* Erase (and destroy) a member by its pointer */\
00594 void  ppConcat(label,_erase)(label* self, type* mbr )\
00595 {\
00596     assertobjptr(self);\
00597     assertobjptr(mbr);\
00598     {\
00599         ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj, mbr);\
00600         assertobjptr(node);\
00601         assert( node->container == self );\
00602         {\
00603             ppConcat(type,_destroy)(&node->obj);\
00604             dll_erase(ppConcat(label,_node),link, self->list, node );\
00605             self->count--;\
00606             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00607         }\
00608     }\
00609 }\
00610 /* Quicker-Sort internals */\
00611 dll_mfg_qsort(ppConcat(label,_node),link, list, ctl_deref_list_mbr, ppConcat(label,_qsort) );\
00612 /* Quicker-Sort by qsort-like criteria */\
00613 void  ppConcat(label,_sort)( label* self, int (*compare)(const type* p1, const type* p2) )\
00614 {\
00615     assertobjptr(self);\
00616     assertcodeptr(compare);\
00617     dll_qsort(ppConcat(label,_node),link, self->list, ppConcat(label,_qsort), compare );\
00618 }\
00619 /* Splice the list 'from' to this one and clear() from */\
00620 void  ppConcat(label,_splice)( label* self, label* from )\
00621 {\
00622     assertobjptr(self);\
00623     assertobjptr(from);\
00624     {\
00625         /* For debug code, take an extra step and sign all the links */\
00626         ppDebug(ppConcat(label,_node)* curr = from->_dllfront(list);)\
00627         ppDebug(while( curr ) { curr->container = self; curr = curr->_dllnext(link); } )\
00628         dll_splice(ppConcat(label,_node),link, self->list, from->list );\
00629         self->count += from->count;\
00630         from->count = 0;\
00631     }\
00632 }\
00633 
00634 #endif /* DG_LIST_H */
00635 

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