dg/array.h

Go to the documentation of this file.
00001 #ifndef DG_ARRAY_H
00002 #define DG_ARRAY_H
00003 
00010 #ifndef CTL_ALGORITHM_H
00011 #include "ctl/algorithm.h"
00012 #endif
00013 #ifndef CTL_ALGORITHM_TEMP_H
00014 #include "ctl/algorithm.temp.h"
00015 #endif
00016 
00025 #define ctl_declare_array(label,type,size)\
00026     typedef type ppConcat(label,_type);\
00027     typedef struct label\
00028     {\
00029         size_t  count;  /* How many members in array */\
00030         type    array[size];/* The array */\
00031     } label;\
00032     /* The standard pattern functions */\
00033     ctl_datagen_declare_functions(label);\
00034     /* How many members in this container */\
00035     size_t ppConcat(label,_count)( const label* self);\
00036     /* Tell us if an object is part of this container */\
00037     bool ppConcat(label,_ismember)( const label* self, const type* mbr );\
00038     /* Destroy all members, release all memory */\
00039     void ppConcat(label,_clear)( label* self );\
00040     /* Get a pointer to the back end member of container */\
00041     type* ppConcat(label,_back)(const label* self);\
00042     /* Get a pointer to the front end member of container */\
00043     type* ppConcat(label,_front)(const label* self);\
00044     /* Get a pointer to the member of container */\
00045     type* ppConcat(label,_prev)(const label* self, const type* curr);\
00046     /* Get a pointer to the member after 'curr' of self, or NULL if we hit end */\
00047     type* ppConcat(label,_next)(const label* self, const type* curr );\
00048     /* Get a pointer to the member before 'curr' of self, or NULL if we hit end */\
00049     type* ppConcat(label,_at)(label* self, int index);\
00050     /* Add a new member to back end of container, return a pointer to it */\
00051     type* ppConcat(label,_push_back)(label* self);\
00052     /* Add a new member to front end of container, return a pointer to it */\
00053     type* ppConcat(label,_push_front)(label* self);\
00054     /* Insert a new member at the current position, return a pointer to it */\
00055     type* ppConcat(label,_insert)(label* self, type* mbr );\
00056     /* Insert a new set of members at the position pointed to by mbr, return a pointer to the start of that array */\
00057     type* ppConcat(label,_insert_range)(label* self, type* mbr, size_t count );\
00058     /* Remove last member */\
00059     void  ppConcat(label,_pop_back)(label* self);\
00060     /* Remove first member */\
00061     void  ppConcat(label,_pop_front)(label* self);\
00062     /* Erase a member by its pointer */\
00063     void  ppConcat(label,_erase)(label* self, type* mbr );\
00064     /* Erase a range of members by their pointers */\
00065     void  ppConcat(label,_erase_range)(label* self, type* mbr, size_t count );\
00066     /* Erase a member by its pointer, and we don't care about order */\
00067     void  ppConcat(label,_bag_erase)(label* self, type* mbr );\
00068     /* Quicker-Sort by qsort-like criteria */\
00069     void  ppConcat(label,_sort)( label* self, int (*compare)(const type* p1, const type* p2) );\
00070     /* Splice the container 'from' to this one and clear() from */\
00071     void  ppConcat(label,_splice)( label* self, label* from )
00072 
00083 #define ctl_array_foreach_const( label, instance, iterator ) \
00084     const ppConcat(label,_type)* iterator = (instance)->array;\
00085     const ppConcat(label,_type)* ppConcat(end_,iterator) = iterator + (instance)->count;\
00086     for( ; iterator < ppConcat(end_,iterator); iterator++ )
00087 
00098 #define ctl_array_foreach_const_reverse( label, instance, iterator )\
00099     const ppConcat(label,_type)* ppConcat(end_,iterator) = (instance)->array;\
00100     const ppConcat(label,_type)* iterator = ppConcat(end_,iterator) + (instance)->count;\
00101     while( iterator-- > ppConcat(end_,iterator) )
00102 
00114 #define ctl_array_foreach( label, instance, iterator ) \
00115     ppConcat(label,_type)* iterator = (instance)->array;\
00116     const ppConcat(label,_type)* ppConcat(end_,iterator) = iterator + (instance)->count;\
00117     for( ; iterator < ppConcat(end_,iterator); iterator++ )
00118 
00130 #define ctl_array_foreach_reverse( label, instance, iterator )\
00131     ppConcat(label,_type)* ppConcat(end_,iterator) = (instance)->array;\
00132     const ppConcat(label,_type)* iterator = ppConcat(end_,iterator) + (instance)->count;\
00133     while( iterator-- > ppConcat(end_,iterator) )
00134 
00144 #define ctl_array_foreach_mutable( label, instance, iterator ) \
00145     ppConcat(label,_type)* iterator;\
00146     int ppConcat(index_,iterator);\
00147     label* ppConcat(instance_,iterator) = (instance);\
00148     for( ppConcat(index_,iterator) = 0; ppConcat(index_,iterator) < (int)ppConcat(instance_,iterator)->count && intentional_assignment(iterator=ppConcat(instance_,iterator)->array + ppConcat(index_,iterator)); ppConcat(index_,iterator)++ )
00149 
00159 #define ctl_array_foreach_mutable_reverse( label, instance, iterator )\
00160     ppConcat(label,_type)* iterator;\
00161     int ppConcat(index_,iterator);\
00162     label* ppConcat(instance_,iterator) = (instance);\
00163     for( ppConcat(index_,iterator) = (int)ppConcat(instance_,iterator)->count; ppConcat(index_,iterator) > 0 && intentional_assignment(iterator=ppConcat(instance_,iterator)->array + ppConcat(index_,iterator)-1); ppConcat(index_,iterator) = min(ppConcat(index_,iterator)-1,(int)ppConcat(instance_,iterator)->count) )
00164 
00170 #define ctl_cooked(text)    text
00171 
00177 #define ctl_raw(text)
00178 
00186 #define ctl_implement_array(label,type,rawcook)\
00187 const bool ppConcat(label,_isscalar) = false;\
00188 /* Initialize */\
00189 void ppConcat(label,_init)( label* self ) \
00190 {\
00191     assertobjptr(self);\
00192     self->count = 0;\
00193 }\
00194 /* Copy a array */\
00195 void ppConcat(label,_copy)( label* dst, const label* src ) \
00196 {\
00197     assertobjptr(dst);\
00198     assertobjconst(src);\
00199     ppConcat(label,_init)(dst);\
00200     {\
00201         ctl_array_foreach_const( label, src, curr )\
00202             ppConcat(type,_copy)(ppConcat(label,_push_back)(dst),curr);\
00203     }\
00204 }\
00205 /* Copy a array */\
00206 void ppConcat(label,_move)( label* dst, label* src ) \
00207 {\
00208     assertobjptr(dst);\
00209     assertobjptr(src);\
00210     ppConcat(label,_init)(dst);\
00211     {\
00212         ctl_array_foreach( label, src, curr )\
00213             ppConcat(type,_move)(ppConcat(label,_push_back)(dst),curr);\
00214     }\
00215     dst->count = src->count;\
00216     ppConcat(label,_destroy)(src);\
00217 }\
00218 /* Destroy the array */\
00219 void ppConcat(label,_destroy)( label* self ) \
00220 {\
00221     assertobjptr(self);\
00222     ppConcat(label,_clear)(self);\
00223 }\
00224 /* Swap contents between two arrays */\
00225 void ppConcat(label,_swap)( label* p1, label* p2 )\
00226 {\
00227     type *pbig, *pless;\
00228     size_t bigger, lesser;\
00229     assertobjptr(p1);\
00230     assertobjptr(p2);\
00231     if( p1->count > p2->count )\
00232     {\
00233         pbig = p1->array;\
00234         pless = p2->array;\
00235         lesser = p2->count;\
00236         bigger = p1->count - lesser;\
00237     }\
00238     else\
00239     {\
00240         pbig = p2->array;\
00241         pless = p1->array;\
00242         lesser = p1->count;\
00243         bigger = p2->count - lesser;\
00244     }\
00245     while( lesser-- )\
00246     {   /* Swap items where both arrays have them */\
00247         ppConcat(type,_swap)(pless,pbig);\
00248         pbig++;pless++;\
00249     }\
00250     while( bigger-- )\
00251     {   /* Copy items where only one array had it */\
00252         ppConcat(type,_copy)(pless,pbig);\
00253         pbig++;pless++;\
00254     }\
00255     {\
00256         size_t c1 = p1->count;\
00257         p1->count = p2->count;\
00258         p2->count = c1;\
00259     }\
00260 }\
00261 /* Compare this record to another record for sorting backwards */\
00262 int ppConcat(label,_rcompare)( const label* p1, const label* p2 ) { return ppConcat(label,_compare)( p2,p1 ); }\
00263 /* Compare this record to another record for sorting */\
00264 int ppConcat(label,_compare)( const label* p1, const label* p2 )\
00265 {\
00266     if( NULL == p1 )\
00267     {\
00268         if( NULL == p2 )\
00269             return 0;\
00270         return -1;\
00271     }\
00272     else if( NULL == p2 )\
00273         return 1;\
00274     assertobjconst(p1);\
00275     assertobjconst(p2);\
00276     {\
00277         size_t compareLen = min(p1->count,p2->count);\
00278         const type* p1curr = p1->array; \
00279         const type* p2curr = p2->array; \
00280         while( compareLen-- ) \
00281         {\
00282             int result = ppConcat(type,_compare)(p1curr++,p2curr++);\
00283             if( result )\
00284                 return result;\
00285         }\
00286         if( p1->count < p2->count )\
00287             return -1;\
00288         if( p1->count > p2->count )\
00289             return 1;\
00290         return 0;\
00291     }\
00292 }\
00293 /* See if a array looks valid */\
00294 bool ppConcat(label,_valid)( const label* self ) \
00295 {\
00296     if( !self )\
00297         return false;\
00298     assertobjconst(self);\
00299     if( self->count > countof(self->array) )\
00300         return false;\
00301     {\
00302         ctl_array_foreach_const( label, self, curr )\
00303             if( !ppConcat(type,_valid)(curr) )\
00304                 return false;\
00305     }\
00306     return true;\
00307 }\
00308 /* How much memory does this consume */\
00309 size_t ppConcat(label,_size)( const label* self )\
00310 {\
00311     if( ppConcat(type,_isscalar) )\
00312     {\
00313         return sizeof(*self);\
00314     }\
00315     else\
00316     {\
00317         size_t total = sizeof(*self);\
00318         ctl_array_foreach_const( label, self, curr )\
00319             total += ppConcat(type,_size)(curr);\
00320         return total;\
00321     }\
00322 }\
00323 /* How big will this be as serial data */\
00324 size_t ppConcat(label,_serial_size)( const label* self ) \
00325 {\
00326     size_t total;\
00327     assertobjconst(self);\
00328     total = ctl_serial_size_size( self->count );\
00329     if( ppConcat(type,_isscalar) )\
00330     {\
00331         total += (self->count * ppConcat(type,_serial_size)(ppConcat(label,_front)(self)));\
00332     }\
00333     else\
00334     {\
00335         ctl_array_foreach_const( label, self, curr )\
00336             total += ppConcat(type,_serial_size)(curr);\
00337     }\
00338     return total;\
00339 }\
00340 /* Write as serial data */\
00341 void ppConcat(label,_serial_write)( const label* self, ctl_serial* serial ) \
00342 {\
00343     assertobjconst(self);\
00344     assertobjptr(serial);\
00345     ctl_serial_writesize( self->count, serial ); \
00346     {\
00347         ctl_array_foreach_const( label, self, curr )\
00348             ppConcat(type,_serial_write)(curr,serial);\
00349     }\
00350 }\
00351 /* Read from serial data */\
00352 void ppConcat(label,_serial_read)( label* self, ctl_serial* serial ) \
00353 {\
00354     size_t readsize; \
00355     assertobjptr(self);\
00356     assertobjptr(serial);\
00357     readsize = ctl_serial_readsize( serial ); \
00358     if( countof(self->array) < readsize )\
00359         readsize = countof(self->array);\
00360     while( readsize-- )\
00361         ppConcat(type,_serial_read)( ppConcat(label,_push_back)(self), serial );\
00362 }\
00363 /* How big will a record made of this be? */\
00364 size_t ppConcat(label,_record_size)( const label* self, const char* szlabel ) \
00365 {\
00366     size_t result;\
00367     assertobjconst(self);\
00368     assertconst(szlabel,1);\
00369     result = ctl_record_objarray_head_size( szlabel, "container", #type );\
00370     if( ppConcat(type,_isscalar) )\
00371     {\
00372         result += (self->count * ppConcat(type,_record_size)(ppConcat(label,_front)(self),szlabel));\
00373     }\
00374     else\
00375     { \
00376         ctl_array_foreach_const(label,self,curr) \
00377             result += ppConcat(type,_record_size)(curr,szlabel); \
00378     }\
00379     return result;\
00380 }\
00381 /* Write a record */\
00382 void ppConcat(label,_record_write)( const label* self, ctl_serial* serial, const char* szlabel ) \
00383 {\
00384     uint8* rectemp;\
00385     assertobjconst(self);\
00386     assertobjptr(serial);\
00387     assertconst(szlabel,1);\
00388     rectemp = ctl_record_write_container_begin( "container", #type, 0,self->count, serial, szlabel );\
00389     { \
00390         ctl_array_foreach_const(label,self,curr) \
00391             ppConcat(type,_record_write)(curr,serial,szlabel); \
00392     }\
00393     ctl_record_write_end( rectemp, serial );\
00394 }\
00395 /* Read a record */\
00396 bool ppConcat(label,_record_read)( label* self, ctl_serial* serial, const char* szlabel ) \
00397 {\
00398     ctl_serial pserial;\
00399     assertobjptr(self);\
00400     assertobjptr(serial);\
00401     assertconst(szlabel,1);\
00402     pserial = *serial;\
00403     if( ctl_record_find( &pserial, szlabel ) )\
00404     {\
00405         size_t count = ctl_record_container_validatedata( &pserial, "container", szconst(char,#type) );\
00406         if( countof(self->array) < count )\
00407             count = countof(self->array);\
00408         while( count-- && pserial.curr < pserial.end )\
00409         {\
00410             ppConcat(type,_record_read)( ppConcat(label,_push_back)(self), &pserial, szlabel );\
00411             ctl_record_next( &pserial );\
00412         }\
00413         if( pserial.curr != pserial.end )\
00414             ctl_serial_except( &pserial, szconst(char,#label) szconst(char,"_record_read: Wrong data length!") );\
00415         return true;\
00416     }\
00417     return false;\
00418 }\
00419 /* Write XML record */\
00420 void ppConcat(label,_xml_write)( const label* self, ctl_xmlwrite* xml, const char* szlabel ) \
00421 {\
00422     assertobjconst(self);\
00423     assertobjptr(xml);\
00424     assertconst(szlabel,1);\
00425     ctl_xmlwrite_containertag( xml, #type, self->count, szlabel ); \
00426     ctl_xmlwrite_indent( xml );\
00427     {\
00428         ctl_array_foreach_const(label,self, curr ) \
00429             ppConcat(type,_xml_write)(curr,xml,NULL);\
00430     } \
00431     ctl_xmlwrite_outdent( xml );\
00432     ctl_xmlwrite_endtag( xml, #type, szlabel ); \
00433 }\
00434 /* Read XML record */\
00435 bool ppConcat(label,_xml_read)( label* self, struct ctl_xmlread* xml, const char* szlabel ) \
00436 {\
00437     assertobjptr(self);\
00438     assertobjptr(xml);\
00439     assertconst(szlabel,1);\
00440     if( ctl_xmlread_find( xml, szlabel ) )\
00441     {\
00442         int32 count = 0;\
00443         if( ctl_xmlread_getattribute_int( xml, CTL_LABEL_COUNT, &count ) )\
00444         {\
00445             ctl_xmlread arraydata;\
00446             ctl_xmlread_recurse(&arraydata,xml);\
00447             if( countof(self->array) < count )\
00448                 count = countof(self->array);\
00449             while( count-- && ppConcat(type,_xml_read)( ppConcat(label,_push_back)(self), &arraydata, NULL ) )\
00450                 ctl_xmlread_next(&arraydata);\
00451         }\
00452         else\
00453         {\
00454             xml->except( xml, szconst(char,#label) szconst(char,"_xml_read: Missing size attribute!"), xml->szpCurr, NULL );\
00455         }\
00456         return true;\
00457     }\
00458     return false;\
00459 }\
00460 /* How many members in this container */\
00461 size_t ppConcat(label,_count)( const label* self)\
00462 {\
00463     assertobjconst(self);\
00464     return self->count;\
00465 }\
00466 /* Tell us if an object is part of this container */\
00467 bool ppConcat(label,_ismember)( const label* self, const type* mbr )\
00468 {\
00469     assertobjconst(self);\
00470     return mbr >= self->array && mbr < self->array + self->count;\
00471 }\
00472 /* Destroy all members, release all memory */\
00473 void ppConcat(label,_clear)( label* self )\
00474 {\
00475     assertobjptr(self);\
00476     rawcook( { ctl_array_foreach( label, self, curr ) ppConcat( type,_destroy )(curr); } )\
00477     self->count = 0;\
00478 }\
00479 /* Add a new member to back end of container, return a pointer to it */\
00480 type* ppConcat(label,_push_back)(label* self)\
00481 {\
00482     assertobjptr(self);\
00483     if(self->count+1 <= countof(self->array) )\
00484     {\
00485         type* ret = self->array+self->count++;\
00486         rawcook( ppConcat( type,_init )(ret); )\
00487         return ret;\
00488     }\
00489     throwassert("Out of bounds");\
00490     return NULL;\
00491 }\
00492 /* Add a new member to front end of container, return a pointer to it */\
00493 type* ppConcat(label,_push_front)(label* self)\
00494 {\
00495     assertobjptr(self);\
00496     if(self->count+1 <= countof(self->array) )\
00497     {\
00498         type* curr = self->array + self->count++;\
00499         while( curr-- > self->array )\
00500             ppConcat(type,_move)( curr+1,curr );\
00501         rawcook( ppConcat( type,_init )(self->array); )\
00502         return self->array;\
00503     }\
00504     throwassert("Out of bounds");\
00505     return NULL;\
00506 }\
00507 /* Get a pointer to the back end member of container */\
00508 type* ppConcat(label,_back)(const label* self)\
00509 {\
00510     assertobjconst(self);\
00511     if( self->count > 0 )\
00512         return (type*)(self->array + (self->count-1));\
00513     return (type*)self->array;\
00514 }\
00515 /* Get a pointer to the front end member of container */\
00516 type* ppConcat(label,_front)(const label* self)\
00517 {\
00518     assertobjconst(self);\
00519     return (type*)self->array;\
00520 }\
00521 /* Get a pointer to the member before 'curr' of list self, or NULL if we hit end */\
00522 type* ppConcat(label,_prev)(const label* self, const type* curr)\
00523 {\
00524     assertobjconst(self);\
00525     if( curr )\
00526     {\
00527         assert( ppConcat(label,_ismember)(self,curr) );\
00528         if( --curr >= self->array )\
00529             return (type*)curr;\
00530     }\
00531     return NULL;\
00532 }\
00533 /* Get a pointer to the member after 'curr' of list self, or NULL if we hit end */\
00534 type* ppConcat(label,_next)(const label* self, const type* curr )\
00535 {\
00536     assertobjconst(self);\
00537     if( curr )\
00538     {\
00539         assert( ppConcat(label,_ismember)(self,curr) );\
00540         if( ++curr < self->array + self->count )\
00541             return (type*)curr;\
00542     }\
00543     return NULL;\
00544 }\
00545 /* Remove last member */\
00546 void  ppConcat(label,_pop_back)(label* self)\
00547 {\
00548     assertobjptr(self);\
00549     assert(self->count > 0 );\
00550     if( self->count > 0 )\
00551     {\
00552         --self->count;\
00553         ctl_cooked( ppConcat( type,_destroy )( self->array + self->count); )\
00554     }\
00555 }\
00556 /* Remove first member */\
00557 void  ppConcat(label,_pop_front)(label* self)\
00558 {\
00559     assert(self->count > 0 );\
00560     if(self->count > 0 )\
00561     {\
00562         type* curr = self->array;\
00563         type* end = self->array + self->count;\
00564         rawcook(ppConcat( type,_destroy )(curr++);)\
00565         while( curr < end )\
00566         {\
00567             ppConcat(type,_move)( curr,curr+1 );\
00568             curr++;\
00569         }\
00570     }\
00571 }\
00572 /* Look up a member by its index in the array */\
00573 type* ppConcat(label,_at)(label* self, int index)\
00574 {\
00575     assertobjptr(self);\
00576     if( index < 0 || index >= countof(self->array) )\
00577     {\
00578         throwassert("Out of bounds");\
00579         return NULL;\
00580     }\
00581     if( index >= (int)self->count )\
00582     {\
00583         rawcook( type* end = self->array + index + 1; )\
00584         rawcook( type* curr = self->array + self->count; )\
00585         rawcook( while( curr < end ) { ppConcat( type,_init )(curr); curr++; }  )\
00586         self->count = 1+index;\
00587     }\
00588     return (type*)self->array + index;\
00589 }\
00590 /* Insert a new member at the current position, return a pointer to it */\
00591 type* ppConcat(label,_insert)(label* self, type* mbr )\
00592 {\
00593     assertobjptr(self);\
00594     if( ppConcat(label,_ismember)( self, mbr ) )\
00595     {\
00596         size_t ombr = indexof(self->array,mbr);\
00597         if(self->count+1 <= countof(self->array) )\
00598         {\
00599             mbr = self->array + ombr;\
00600             {\
00601                 type* curr = self->array + self->count++;\
00602                 while( curr-- > mbr )\
00603                     ppConcat(type,_move)( curr+1,curr );\
00604             }\
00605             rawcook(ppConcat( type,_init )(mbr));\
00606             return mbr;\
00607         }\
00608     }\
00609     throwassert("Out of bounds");\
00610     return NULL;\
00611 }\
00612 /* Insert a new set of members at the position pointed to by mbr, return a pointer to the start of that array */\
00613 type* ppConcat(label,_insert_range)(label* self, type* mbr, size_t count )\
00614 {\
00615     assertobjptr(self);\
00616     assertconst(mbr,count*sizeof(type));\
00617     if( ppConcat(label,_ismember)( self, mbr ) )\
00618     {\
00619         size_t ombr = indexof(self->array,mbr);\
00620         if(self->count+count <= countof(self->array) )\
00621         {\
00622             mbr = self->array + ombr;\
00623             {\
00624                 type* dst = self->array + self->count + count;\
00625                 type* src = self->array + self->count;\
00626                 while( src > mbr )\
00627                     ppConcat(type,_move)( --dst,--src );\
00628                 self->count += count;\
00629                 rawcook( dst = mbr; )\
00630                 rawcook( while( count-- ) ppConcat( type,_init )(dst++); )\
00631             }\
00632             return mbr;\
00633         }\
00634     }\
00635     throwassert("Out of bounds");\
00636     return NULL;\
00637 }\
00638 /* Erase a member by its pointer */\
00639 void  ppConcat(label,_erase)(label* self, type* mbr )\
00640 {\
00641     assertobjptr(self);\
00642     if( ppConcat(label,_ismember)( self, mbr ) )\
00643     {\
00644         type* curr = mbr;\
00645         type* end = self->array + self->count;\
00646         ppConcat( type,_destroy )(curr++);\
00647         while( curr < end )\
00648         {\
00649             ppConcat(type,_move)( curr,curr+1 );\
00650             curr++;\
00651         }\
00652         rawcook( ppConcat( type,_destroy )(curr); )\
00653         self->count--;\
00654     }\
00655 }\
00656 /* Erase a range of members by their pointers */\
00657 void  ppConcat(label,_erase_range)(label* self, type* mbr, size_t count )\
00658 {\
00659     assertobjptr(self);\
00660     if( ppConcat(label,_ismember)( self, mbr ) && (mbr+count <= self->array+self->count) )\
00661     {\
00662         type* dst = mbr;\
00663         type* src = mbr + count;\
00664         type* end = self->array + self->count;\
00665         rawcook( \
00666             while( dst < src )\
00667             {\
00668                 ppConcat(type,_destroy)( dst );\
00669                 dst++;\
00670             }\
00671             dst = mbr;\
00672         )\
00673         while( src < end )\
00674             ppConcat(type,_move)( dst++,src++ );\
00675         self->count -= count;\
00676     }\
00677 }\
00678 /* Erase a member by its pointer, and we don't care about order */\
00679 void  ppConcat(label,_bag_erase)(label* self, type* mbr )\
00680 {\
00681     assertobjptr(self);\
00682     if( ppConcat(label,_ismember)( self, mbr ) )\
00683     {\
00684         type* end = self->array + self->count - 1;\
00685         if( end != mbr )\
00686         {\
00687             rawcook( ppConcat( type,_destroy )(mbr); )\
00688             ppConcat( type,_move )(mbr,end);\
00689         }\
00690     }\
00691 }\
00692 /* Erase a member by its pointer, and we don't care about order */\
00693 void  ppConcat(label,_bag_erase_range)(label* self, type* mbr, size_t count )\
00694 {\
00695     assertobjptr(self);\
00696     if( ppConcat(label,_ismember)( self, mbr ) && (mbr+count <= self->array+self->count) )\
00697     {\
00698         type* dst = mbr;\
00699         type* end = self->array + self->count;\
00700         type* src = end - count;\
00701         while( src < end )\
00702         {\
00703             rawcook( ppConcat( type,_destroy )(dst); )\
00704             ppConcat( type,_move )(dst++,src++);\
00705         }\
00706     }\
00707 }\
00708 /* Sort by qsort-like criteria */\
00709 void  ppConcat(label,_sort)( label* self, int (*compare)(const type* p1, const type* p2) )\
00710 {\
00711     assertobjptr(self);\
00712     assertcodeptr(compare);\
00713     ppConcat(type,_array_qsort)( self->array, self->array + self->count - 1, compare );\
00714 }\
00715 /* Do bsearch - in sorted array, finds unique member matching 'key' */\
00716 type* ppConcat(label,_bsearch)( const label* self, const type* key, int (*compare)(const type* p1, const type* p2) )\
00717 {\
00718     assertobjconst(self);\
00719     assertconst(key,sizeof(*key));\
00720     assertcodeptr(compare);\
00721     return (type*)bsearch( &key, self->array, self->count, sizeof(type), (int (*)(const void*,const void*))compare );\
00722 }\
00723 /* Do bsearch - in sorted array, finds unique member matching 'key' */\
00724 type* ppConcat(label,_lsearch)( const label* self, const type* key, int (*compare)(const type* p1, const type* p2) )\
00725 {\
00726     assertobjconst(self);\
00727     assertconst(key,sizeof(*key));\
00728     assertcodeptr(compare);\
00729     {\
00730         ctl_array_foreach_const( label, self, curr )\
00731             if( !compare(curr,key) )\
00732                 return (type*)curr;\
00733     }\
00734     return NULL;\
00735 }\
00736 /* Splice the container 'from' to this one and clear() from */\
00737 void  ppConcat(label,_splice)( label* self, label* from )\
00738 {\
00739     assertobjptr(self);\
00740     assertobjptr(from);\
00741     if(self->count+from->count <= countof(self->array) )\
00742     {\
00743         ctl_array_foreach( label, from, curr )\
00744             ppConcat(type,_move)( ppConcat(label,_push_back)(self), curr );\
00745     }\
00746     from->count = 0;\
00747     ppConcat(label,_clear)(from);\
00748 }\
00749 
00750 #endif /* ARRAY_H */

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