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); \
00025 type obj; \
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 \
00034 extern ctl_pool(ppConcat(label,_node)) ppConcat(label,_pool);\
00035 \
00036 ctl_datagen_declare_functions(label);\
00037 \
00038 size_t ppConcat(label,_count)( const label* self);\
00039 \
00040 bool ppConcat(label,_ismember)( const label* self, const type* mbr );\
00041 \
00042 void ppConcat(label,_clear)( label* self );\
00043 \
00044 type* ppConcat(label,_back)(const label* self);\
00045 \
00046 type* ppConcat(label,_front)(const label* self);\
00047 \
00048 type* ppConcat(label,_prev)(const label* self, const type* curr);\
00049 \
00050 type* ppConcat(label,_next)(const label* self, const type* curr);\
00051 \
00052 type* ppConcat(label,_push_back)(label* self);\
00053 \
00054 type* ppConcat(label,_push_front)(label* self);\
00055 \
00056 type* ppConcat(label,_insert)(label* self, type* mbr );\
00057 \
00058 void ppConcat(label,_pop_back)(label* self);\
00059 \
00060 void ppConcat(label,_pop_front)(label* self);\
00061 \
00062 void ppConcat(label,_erase)(label* self, type* mbr );\
00063 \
00064 void ppConcat(label,_sort)( label* self, int (*compare)(const type* p1, const type* p2) );\
00065 \
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
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 \
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 \
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 \
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 \
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 \
00233 void ppConcat(label,_destroy)( label* self )\
00234 {\
00235 ppConcat(label,_clear)( self );\
00236 }\
00237 \
00238 int ppConcat(label,_rcompare)( const label* p1, const label* p2 ) { return ppConcat(label,_compare)( p2,p1 ); }\
00239 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
00438 size_t ppConcat(label,_count)( const label* self)\
00439 {\
00440 assertobjconst(self);\
00441 return self->count;\
00442 }\
00443 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
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 \
00611 dll_mfg_qsort(ppConcat(label,_node),link, list, ctl_deref_list_mbr, ppConcat(label,_qsort) );\
00612 \
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 \
00620 void ppConcat(label,_splice)( label* self, label* from )\
00621 {\
00622 assertobjptr(self);\
00623 assertobjptr(from);\
00624 {\
00625 \
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
00635