vector.h

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

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