set.h

00001 #ifndef DG_SET_H
00002 #define DG_SET_H
00003 
00009 #ifndef CTL_TREE_H
00010 #include "ctl/tree.h"
00011 #endif
00012 
00013 /****************************************************************************
00014 
00015 Declare ctl_set
00016 
00017 *****************************************************************************/
00018 
00019 
00028 #define ctl_declare_set(label,type)             ctl_declare_set_base(label,type,ctlt_unique)
00029 
00037 #define ctl_implement_set(label,type)           ctl_implement_set_base(label,type,ctlt_unique)
00038 
00047 #define ctl_declare_set(label,type)             ctl_declare_set_base(label,type,ctlt_unique)
00048 
00056 #define ctl_implement_set(label,type)           ctl_implement_set_base(label,type,ctlt_unique)
00057 
00066 #define ctl_set_foreach(label, instance, iterator ) \
00067     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00068     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00069     for ( ; iterator; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ) )
00070 
00079 #define ctl_set_foreach_const(label, instance, iterator ) \
00080     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00081     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00082     for ( ; iterator; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ) )
00083 
00092 #define ctl_set_foreach_reverse(label, instance, iterator ) \
00093     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00094     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique,iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00095     for ( ; iterator; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ) )
00096 
00105 #define ctl_set_foreach_const_reverse(label, instance, iterator ) \
00106     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00107     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique,iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00108     for ( ; iterator; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ) )
00109 
00110 
00119 #define ctl_set_from(label, instance, key, iterator )\
00120     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00121     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00122     for ( ; iterator; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ) )
00123 
00126 #define ctl_set_from_const(label, instance, key, iterator )\
00127     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00128     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00129     for ( ; iterator; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ) )
00130 
00133 #define ctl_set_from_reverse(label, instance, key, iterator )\
00134     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00135     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00136     for ( ; iterator; iterator = (ppConcat(label,_type)*)(ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ) )
00137 
00140 #define ctl_set_from_const_reverse(label, instance, key, iterator )\
00141     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00142     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00143     for ( ; iterator; iterator = (const ppConcat(label,_type)*)(ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ) )
00144 
00156 #define ctl_set_from_to(label, instance, keyfrom, keyto, iterator )\
00157     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00158     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00159     for( ; iterator && (instance)->compare(iterator,(keyto)) < 0; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ) )
00160 
00163 #define ctl_set_from_to_const(label, instance, keyfrom, keyto, iterator )\
00164     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00165     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00166     for( ; iterator && (instance)->compare(iterator,(keyto)) < 0; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ) )
00167 
00170 #define ctl_set_from_to_reverse(label, instance, keyfrom, keyto, iterator )\
00171     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00172     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00173     for( ; iterator && (instance)->compare(iterator,(keyto)) > 0; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ) )
00174 
00178 #define ctl_set_from_to_const_reverse(label, instance, keyfrom, keyto, iterator )\
00179     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00180     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00181     for( ; iterator && (instance)->compare(iterator,(keyto)) > 0; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ) )
00182 
00183 /****************************************************************************
00184 
00185 Declare ctl_multiset
00186 
00187 *****************************************************************************/
00188 
00196 #define ctl_declare_multiset(label,type)    ctl_declare_set_base(label,type,ctlt_multiple)
00197 
00204 #define ctl_implement_multiset(label,type)  ctl_implement_set_base(label,type,ctlt_multiple)
00205 
00214 #define ctl_multiset_foreach(label, instance, iterator ) \
00215     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00216     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00217     for ( ; iterator; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ) )
00218 
00227 #define ctl_multiset_foreach_const(label, instance, iterator ) \
00228     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00229     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00230     for ( ; iterator; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ) )
00231 
00240 #define ctl_multiset_foreach_reverse(label, instance, iterator ) \
00241     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00242     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple,iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00243     for ( ; iterator; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ) )
00244 
00253 #define ctl_multiset_foreach_const_reverse(label, instance, iterator ) \
00254     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00255     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple,iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00256     for ( ; iterator; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ) )
00257 
00258 
00267 #define ctl_multiset_from(label, instance, key, iterator )\
00268     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00269     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00270     for ( ; iterator; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ) )
00271 
00274 #define ctl_multiset_from_const(label, instance, key, iterator )\
00275     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00276     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00277     for ( ; iterator; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ) )
00278 
00281 #define ctl_multiset_from_reverse(label, instance, key, iterator )\
00282     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00283     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00284     for ( ; iterator; iterator = (ppConcat(label,_type)*)(ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ) )
00285 
00288 #define ctl_multiset_from_const_reverse(label, instance, key, iterator )\
00289     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00290     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00291     for ( ; iterator; iterator = (const ppConcat(label,_type)*)(ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ) )
00292 
00304 #define ctl_multiset_from_to(label, instance, keyfrom, keyto, iterator )\
00305     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00306     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00307     for( ; iterator && (instance)->compare(iterator,(keyto)) < 0; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ) )
00308 
00311 #define ctl_multiset_from_to_const(label, instance, keyfrom, keyto, iterator )\
00312     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00313     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00314     for( ; iterator && (instance)->compare(iterator,(keyto)) < 0; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ) )
00315 
00318 #define ctl_multiset_from_to_reverse(label, instance, keyfrom, keyto, iterator )\
00319     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00320     ppConcat(label,_type)* iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00321     for( ; iterator && (instance)->compare(iterator,(keyto)) > 0; iterator = (ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ) )
00322 
00326 #define ctl_multiset_from_to_const_reverse(label, instance, keyfrom, keyto, iterator )\
00327     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00328     const ppConcat(label,_type)* iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00329     for( ; iterator && (instance)->compare(iterator,(keyto)) > 0; iterator = (const ppConcat(label,_type)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ) )
00330 
00331 
00332 /****************************************************************************
00333 
00334 Base set/multiset declaration
00335 
00336 *****************************************************************************/
00337 
00341 #define ctl_declare_set_base(label,type,ctlt_unique)\
00342     typedef struct ppConcat(label,_node)\
00343     {\
00344         ctlt_node_type(ctlt_after,ctlt_unique) link;\
00345         type    obj;                            /* The actual member */ \
00346         ppDebug(struct label* container;)       /* For debug, sign nodes so membership assertions aren't so heinous */\
00347     } ppConcat(label,_node);\
00348     typedef ctl_tree(ctlt_after,ctlt_unique) label;\
00349     /* So we can monitor memory use/leaks */\
00350     extern ctl_pool(ppConcat(label,_node)) ppConcat(label,_pool);\
00351     /* A few typedefs */\
00352     typedef type ppConcat(label,_type);\
00353     typedef ctl_tree_(ctlt_after,ctlt_unique, iterator ) ppConcat(label,_iterator);\
00354     /* The standard pattern functions */\
00355     ctl_datagen_declare_functions(label);\
00356     /* Set or change the sort order of this tree (will re-sort if there are already members in it - needless to say it's expensive to do) */\
00357     void  ppConcat(label,_sort)( label* self, int (*compare)(const type* p1, const type* p2) );\
00358     /* How many members in this container */\
00359     size_t ppConcat(label,_count)( const label* self);\
00360     /* Tell us if an object is part of this container */\
00361     bool ppConcat(label,_ismember)( const label* self, const type* mbr );\
00362     /* Destroy all members, release all memory */\
00363     void ppConcat(label,_clear)( label* self );\
00364     /* Get a pointer to the back end member of container */\
00365     type* ppConcat(label,_back)(const label* self);\
00366     /* Get a pointer to the front end member of container */\
00367     type* ppConcat(label,_front)(const label* self);\
00368     /* Remove (and destroy) last member */\
00369     void  ppConcat(label,_pop_back)(label* self);\
00370     /* Remove (and destroy) first member */\
00371     void  ppConcat(label,_pop_front)(label* self);\
00372     /* Insert a member from some template */\
00373     type* ppConcat(label,_insert)( label* self, const type* key );\
00374     /* Find the member matching 'key'; returns NULL if it's not in here. */\
00375     type* ppConcat(label,_at)(const label* self, const type* key );\
00376     /* Erase (and destroy) a member by its pointer */\
00377     void  ppConcat(label,_erase)(label* self, type* mbr );\
00378     /* Erase (and destroy) a member by its key value */\
00379     void  ppConcat(label,_erase_key)(label* self, type* key );\
00380     /* Splice the container 'from' to this one and clear() from */\
00381     void  ppConcat(label,_splice)( label* self, label* from );\
00382 
00383 /****************************************************************************
00384 
00385 Base set/multiset Implementation
00386 
00387 *****************************************************************************/
00388 
00389 #ifndef CTL_POOL_DELTA
00390 
00396 #define CTL_POOL_DELTA  16
00397 #endif
00398 
00402 #define ctl_implement_set_base(label,type,ctlt_unique)\
00403 const bool ppConcat(label,_isscalar) = false;\
00404 ctl_pool_auto(ppConcat(label,_node),ppConcat(label,_pool),CTL_POOL_DELTA);\
00405 /* Initialize this record to a known, default state */\
00406 void ppConcat(label,_init)( label* self )\
00407 {\
00408     assertobjptr(self);\
00409     ctl_tree_init(ctlt_after,ctlt_unique, ppConcat(type,_compare), self );\
00410 }\
00411 /* Replicate a record, copying from 'src' to 'dst' */\
00412 void ppConcat(label,_copy)( label* dst, const label* src )\
00413 {\
00414     assertobjptr(dst);\
00415     assertobjconst(src);\
00416     assertcodeptr(src->compare);\
00417     ppConcat(label,_init)( dst );\
00418     dst->compare = src->compare;\
00419     {\
00420         ppConcat(label,_iterator) stack_curr;\
00421         const type* curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, src );\
00422         while( curr )\
00423         {\
00424             ppConcat(label,_insert)(dst,curr);\
00425             curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00426         }\
00427     }\
00428 }\
00429 /* Move contents from 'src' to 'dst', leaving 'dst' uninitialized. */\
00430 void ppConcat(label,_move)( label* dst, label* src )\
00431 {\
00432     assertobjptr(dst);\
00433     assertobjptr(src);\
00434     *dst = *src;\
00435     ppConcat(label,_init)( src );\
00436     ppDebug( {\
00437         ppConcat(label,_iterator) stack_curr;\
00438         type* curr = (type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, dst );\
00439         while( curr )\
00440         {\
00441             dereference(ppConcat(label,_node),obj,curr)->container = (struct label*)dst;\
00442             curr = (type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00443         }\
00444     } )\
00445 }\
00446 /* Swap contents of two records */\
00447 void ppConcat(label,_swap)( label* p1, label* p2 )\
00448 {\
00449     assertobjptr(p1);\
00450     assertobjptr(p2);\
00451     {\
00452         label tmp = *p1;\
00453         *p1 = *p2;\
00454         *p2 = tmp;\
00455     }\
00456     ppDebug( {\
00457         ppConcat(label,_iterator) stack_curr;\
00458         type* curr = (type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, p1 );\
00459         while( curr )\
00460         {\
00461             dereference(ppConcat(label,_node),obj,curr)->container = (struct label*)p1;\
00462             curr = (type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00463         }\
00464     } )\
00465     ppDebug( {\
00466         ppConcat(label,_iterator) stack_curr;\
00467         type* curr = (type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, p2 );\
00468         while( curr )\
00469         {\
00470             dereference(ppConcat(label,_node),obj,curr)->container = (struct label*)p2;\
00471             curr = (type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00472         }\
00473     } )\
00474 }\
00475 /* Destroy this record, freeing any contained data */\
00476 void ppConcat(label,_destroy)( label* self )\
00477 {\
00478     ppConcat(label,_clear)( self );\
00479 }\
00480 /* Compare this record to another record for sorting backwards */\
00481 int ppConcat(label,_rcompare)( const label* p1, const label* p2 ) { return ppConcat(label,_compare)( p2,p1 ); }\
00482 /* Compare this record to another record for sorting */\
00483 int ppConcat(label,_compare)( const label* p1, const label* p2 )\
00484 {\
00485     if( NULL == p1 )\
00486     {\
00487         if( NULL == p2 )\
00488             return 0;\
00489         return -1;\
00490     }\
00491     else if( NULL == p2 )\
00492         return 1;\
00493     assertobjconst(p1);\
00494     assertobjconst(p2);\
00495     {\
00496         size_t compareLen = min(p1->size,p2->size);\
00497         ppConcat(label,_iterator) p1s;\
00498         ppConcat(label,_iterator) p2s;\
00499         type* v1 = (type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &p1s, p1 );\
00500         type* v2 = (type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &p2s, p2 );\
00501         while( compareLen-- && v1 && v2 )\
00502         {\
00503             int result = ppConcat(type,_compare)( v1,v2 );\
00504             if( result )\
00505                 return result;\
00506             v1 = (type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_next)( &p1s );\
00507             v2 = (type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_next)( &p2s );\
00508         }\
00509         /* If we fell through to here, something's amiss with the links/count */\
00510         assert(compareLen == -1);\
00511         if( p1->size < p2->size )\
00512             return -1;\
00513         if( p1->size > p2->size )\
00514             return 1;\
00515         return 0;\
00516     }\
00517 }\
00518 /* Determine if a record is valid-looking; all validated members in expected range */\
00519 bool ppConcat(label,_valid)( const label* self )\
00520 {\
00521     if( !self )\
00522         return false;\
00523     assertobjconst(self);\
00524     assertcodeptr(self->compare);\
00525     return ((NULL != self->root && self->size) || (NULL == self->root && 0 == self->size));\
00526 }\
00527 /* Determine total memory footprint of this container */\
00528 size_t ppConcat(label,_size)( const label* self )\
00529 {\
00530     assertobjconst(self);\
00531     if( ppConcat(type,_isscalar) )\
00532     {\
00533         return sizeof(*self) + (self->size * sizeof(ppConcat(label,_node)));\
00534     }\
00535     else\
00536     {\
00537         size_t ret = sizeof(*self);\
00538         ppConcat(label,_iterator) stack_curr;\
00539         const type* curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00540         while( curr )\
00541         {\
00542             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,curr);\
00543             ret += ppConcat(type,_size)(&node->obj) + sizeof(ppConcat(label,_node))-sizeof(type);\
00544             curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00545         }\
00546         return ret;\
00547     }\
00548 }\
00549 /* Determine total size of this record as stingy serial data */\
00550 size_t ppConcat(label,_serial_size)( const label* self )\
00551 {\
00552     assertobjconst(self);\
00553     if( ppConcat(type,_isscalar) )\
00554     {\
00555         return ctl_serial_size_size( self->size ) + (self->size * ppConcat(type,_serial_size)(&dereference(ppConcat(label,_node),link,self->root)->obj));\
00556     }\
00557     else\
00558     {\
00559         size_t total = ctl_serial_size_size( self->size );\
00560         ppConcat(label,_iterator) stack_curr;\
00561         const type* curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00562         while( curr )\
00563         {\
00564             total += ppConcat(type,_serial_size)(curr);\
00565             curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00566         }\
00567         return total;\
00568     }\
00569 }\
00570 /* Write data to a stingy serial record */\
00571 void ppConcat(label,_serial_write)( const label* self, ctl_serial* serial )\
00572 {\
00573     assertobjconst(self);\
00574     assertobjptr(serial);\
00575     ctl_serial_writesize( self->size, serial ); \
00576     {\
00577         ppConcat(label,_iterator) stack_curr;\
00578         const type* curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00579         while( curr )\
00580         {\
00581             ppConcat(type,_serial_write)(curr,serial);\
00582             curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00583         }\
00584     }\
00585 }\
00586 /* Read data from a stingy serial record */\
00587 void ppConcat(label,_serial_read)( label* self, ctl_serial* serial )\
00588 {\
00589     assertobjptr(self);\
00590     assertobjptr(serial);\
00591     {\
00592         size_t readsize = ctl_serial_readsize( serial ); \
00593         while( readsize-- )\
00594         {\
00595             type value;\
00596             ppConcat(type,_init)(&value);\
00597             ppConcat(type,_serial_read)(&value,serial);\
00598             ppConcat(label,_insert)(self,&value);\
00599             ppConcat(type,_destroy)(&value);\
00600         }\
00601     }\
00602 }\
00603 /* Determine total size of this record as robust/archive serial data */\
00604 size_t ppConcat(label,_record_size)( const label* self, const char* szlabel )\
00605 {\
00606     assertobjconst(self);\
00607     assertconst(szlabel,1);\
00608     if( self->size )\
00609     {\
00610         size_t result = ctl_record_objarray_head_size( szlabel, "container", #type );\
00611         if( ppConcat(type,_isscalar) )\
00612         {\
00613             result += self->size * ppConcat(type,_record_size)(&dereference(ppConcat(label,_node),link,self->root)->obj,szlabel);\
00614         }\
00615         else\
00616         {\
00617             ppConcat(label,_iterator) stack_curr;\
00618             const type* curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00619             while( curr )\
00620             {\
00621                 result += ppConcat(type,_record_size)(curr,szlabel); \
00622                 curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00623             }\
00624         }\
00625         return result;\
00626     }\
00627     return 0;\
00628 }\
00629 /* Write data to a robust binary serial record */\
00630 void ppConcat(label,_record_write)( const label* self, ctl_serial* serial, const char* szlabel )\
00631 {\
00632     assertobjconst(self);\
00633     assertobjptr(serial);\
00634     assertconst(szlabel,1);\
00635     if( self->size )\
00636     {\
00637         uint8* rectemp = ctl_record_write_container_begin( "container", #type, 0,self->size, serial, szlabel );\
00638         ppConcat(label,_iterator) stack_curr;\
00639         const type* curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00640         while( curr )\
00641         {\
00642             ppConcat(type,_record_write)(curr,serial,szlabel); \
00643             curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00644         }\
00645         ctl_record_write_end( rectemp, serial );\
00646     }\
00647 }\
00648 /* Read data from a robust/archive binary serial record */\
00649 bool ppConcat(label,_record_read)( label* self, ctl_serial* serial, const char* szlabel )\
00650 {\
00651     assertobjptr(self);\
00652     assertobjptr(serial);\
00653     assertconst(szlabel,1);\
00654     {\
00655         ctl_serial pserial = *serial;\
00656         ppConcat(label,_clear)(self);\
00657         if( ctl_record_find( &pserial, szlabel ) )\
00658         {\
00659             size_t count = ctl_record_container_validatedata( &pserial, "container", #type );\
00660             while( count-- )\
00661             {\
00662                 type value;\
00663                 ppConcat(type,_init)(&value);\
00664                 ppConcat(type,_record_read)(&value, &pserial, szlabel );\
00665                 ppConcat(label,_insert)(self,&value);\
00666                 ppConcat(type,_destroy)(&value);\
00667                 ctl_record_next( &pserial );\
00668             }\
00669             if( pserial.curr != pserial.end )\
00670                 ctl_serial_except( &pserial, szconst(char,#label) szconst(char,"_record_read: Wrong data length!") );\
00671             return true;\
00672         }\
00673     }\
00674     return false;\
00675 }\
00676 /* Write data to an XML record */\
00677 void ppConcat(label,_xml_write)( const label* self, ctl_xmlwrite* xml, const char* szlabel )\
00678 {\
00679     assertobjconst(self);\
00680     assertobjptr(xml);\
00681     assertconst(szlabel,1);\
00682     if( self->size )\
00683     {\
00684         ctl_xmlwrite_containertag( xml, #type, self->size, szlabel ); \
00685         ctl_xmlwrite_indent( xml );\
00686         {\
00687             ppConcat(label,_iterator) stack_curr;\
00688             const type* curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00689             while( curr )\
00690             {\
00691                 ppConcat(type,_xml_write)(curr,xml,NULL); \
00692                 curr = (const type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00693             }\
00694         }\
00695         ctl_xmlwrite_outdent( xml );\
00696         ctl_xmlwrite_endtag( xml, #type, szlabel ); \
00697     }\
00698 }\
00699 /* Read data from an XML record */\
00700 bool ppConcat(label,_xml_read)( label* self, ctl_xmlread* xml, const char* szlabel )\
00701 {\
00702     assertobjptr(self);\
00703     assertobjptr(xml);\
00704     assertconst(szlabel,1);\
00705     if( ctl_xmlread_find( xml, szlabel ) )\
00706     {\
00707         int32 count = 0;\
00708         if( ctl_xmlread_getattribute_int( xml, CTL_LABEL_COUNT, &count ) )\
00709         {\
00710             ctl_xmlread arraydata;\
00711             ctl_xmlread_recurse(&arraydata,xml);\
00712             while( count-- )\
00713             {\
00714                 type value;\
00715                 ppConcat(type,_init)(&value);\
00716                 ppConcat(type,_xml_read)(&value, &arraydata, NULL );\
00717                 ppConcat(label,_insert)(self,&value);\
00718                 ppConcat(type,_destroy)(&value);\
00719                 ctl_xmlread_next(&arraydata);\
00720             }\
00721         }\
00722         else\
00723         {\
00724             xml->except( xml, szconst(char,#label) szconst(char,"_xml_read: Missing size attribute!"), xml->szpCurr, NULL );\
00725         }\
00726         return true;\
00727     }\
00728     return false;\
00729 }\
00730 /* Re-sort by qsort-like criteria */\
00731 void  ppConcat(label,_sort)( label* self, int (*compare)(const type* p1, const type* p2) )\
00732 {\
00733     assertobjptr(self);\
00734     assertcodeptr(compare);\
00735     if( self->size )\
00736     {\
00737         label tmp;\
00738         ppConcat(label,_move)( &tmp, self );\
00739         self->compare = (tree_compare)compare;\
00740         ppConcat(label,_splice)( self, &tmp );\
00741     }\
00742     else\
00743     {\
00744         self->compare = (tree_compare)compare;\
00745     }\
00746 }\
00747 /* How many members in this container */\
00748 size_t ppConcat(label,_count)( const label* self)\
00749 {\
00750     assertobjconst(self);\
00751     return self->size;\
00752 }\
00753 /* Tell us if an object is part of this container */\
00754 bool ppConcat(label,_ismember)( const label* self, const type* data )\
00755 {\
00756     assertobjconst(self);\
00757     if( NULL == data )\
00758         return false;\
00759     assertobjconst(data);\
00760     {\
00761         ppDebug(return dereference(ppConcat(label,_node),obj,data)->container == (struct label*)self; )\
00762         ppRelease (\
00763             /* In multiset case, more than one key may match, so check for other matches */\
00764             ppConcat(label,_iterator) stack;\
00765             const type* key = (const type*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack, self );\
00766             while( key && !ppConcat(type,_compare)(key, data ) )\
00767             {\
00768                 if( key == data )\
00769                     return true;\
00770                 key = (type*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack );\
00771             }\
00772             return false;\
00773         )\
00774     }\
00775 }\
00776 /* Recursive tree nuke-o-matic used by 'clear' */\
00777 void ppConcat(label,_recurse_clear)( ppConcat(label,_node)* node )\
00778 {\
00779     if( node->link.left )\
00780         ppConcat(label,_recurse_clear)( (ppConcat(label,_node)*)node->link.left );\
00781     if( node->link.right )\
00782         ppConcat(label,_recurse_clear)( (ppConcat(label,_node)*)node->link.right );\
00783     ppConcat(type,_destroy)(&node->obj);\
00784     ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00785 }\
00786 /* Destroy all members, release all memory */\
00787 void ppConcat(label,_clear)( label* self )\
00788 {\
00789     assertobjptr(self);\
00790     if( self->root )\
00791         ppConcat(label,_recurse_clear)( (ppConcat(label,_node)*)self->root );\
00792     self->size = 0;\
00793     self->root = NULL;\
00794 }\
00795 /* Get a pointer to the back end member of container */\
00796 type* ppConcat(label,_back)(const label* self)\
00797 {\
00798     assertobjconst(self);\
00799     return (type*)ctl_tree_(ctlt_after,ctlt_unique, back)( self );\
00800 }\
00801 /* Get a pointer to the front end member of container */\
00802 type* ppConcat(label,_front)(const label* self)\
00803 {\
00804     assertobjconst(self);\
00805     return (type*)ctl_tree_(ctlt_after,ctlt_unique, front)( self );\
00806 }\
00807 /* Remove (and destroy) last member */\
00808 void  ppConcat(label,_pop_back)(label* self)\
00809 {\
00810     assertobjptr(self);\
00811     {\
00812         type* obj = (type*)ctl_tree_(ctlt_after,ctlt_unique, pop_back)( self );\
00813         if( obj )\
00814         {\
00815             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,obj);\
00816             ppConcat(type,_destroy)(&node->obj);\
00817             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00818         }\
00819     }\
00820 }\
00821 /* Remove (and destroy) first member */\
00822 void  ppConcat(label,_pop_front)(label* self)\
00823 {\
00824     assertobjptr(self);\
00825     {\
00826         type* obj = (type*)ctl_tree_(ctlt_after,ctlt_unique, pop_front)( self );\
00827         if( obj )\
00828         {\
00829             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,obj);\
00830             ppConcat(type,_destroy)(&node->obj);\
00831             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00832         }\
00833     }\
00834 }\
00835 /* Insert a member with a key.  If member ALREADY exists, that pre-existing member is returned. */\
00836 type* ppConcat(label,_insert)( label* self, const type* key )\
00837 {\
00838     assertobjptr(self);\
00839     assertobjconst(key);\
00840     {\
00841         ppConcat(label,_node)* newnode;\
00842         ctl_pool_alloc(ppConcat(label,_node),&ppConcat(label,_pool), newnode);\
00843         ppConcat(type,_copy)(&newnode->obj, key);\
00844         {\
00845             type* foundkey = (type*)ctl_tree_(ctlt_after,ctlt_unique, insert)( self, &newnode->obj );\
00846             if( foundkey != &newnode->obj )\
00847             {\
00848                 ppConcat(type,_destroy)(&newnode->obj);\
00849                 ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), newnode);\
00850                 return foundkey;\
00851             }\
00852         }\
00853         ppDebug(newnode->container = (struct label*)self;)\
00854         return &newnode->obj;\
00855     }\
00856 }\
00857 /* Find the member matching 'key; returns NULL if it's not in here. */\
00858 type* ppConcat(label,_at)(const label* self, const type* key )\
00859 {\
00860     assertobjconst(self);\
00861     assertobjconst(key);\
00862     return (type*)ctl_tree_(ctlt_after,ctlt_unique, find)( self, key );\
00863 }\
00864 /* Erase (and destroy) a member by its pointer */\
00865 void  ppConcat(label,_erase)(label* self, type* mbr )\
00866 {\
00867     assertobjptr(self);\
00868     assertobjptr(mbr);\
00869     {\
00870         ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,mbr);\
00871         assert( (label*)node->container == self );\
00872         {\
00873             type* key = (type*)ctl_tree_(ctlt_after,ctlt_unique, unlink)( self, &node->obj );\
00874             if( key )\
00875             {\
00876                 node = dereference(ppConcat(label,_node),obj,key);\
00877                 ppConcat(type,_destroy)(&node->obj);\
00878                 ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00879             }\
00880         }\
00881     }\
00882 }\
00883 /* Erase (and destroy) a member by an object representing it */\
00884 void  ppConcat(label,_erase_key)(label* self, type* key )\
00885 {\
00886     assertobjptr(self);\
00887     assertobjptr(key);\
00888     {\
00889         type* found = (type*)ctl_tree_(ctlt_after,ctlt_unique, remove)( self, key );\
00890         if( found )\
00891         {\
00892             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,found);\
00893             ppConcat(type,_destroy)(&node->obj);\
00894             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00895         }\
00896     }\
00897 }\
00898 /* Splice the container 'from' to this one and clear() from */\
00899 void  ppConcat(label,_splice)( label* self, label* from )\
00900 {\
00901     assertobjptr(self);\
00902     assertobjptr(from);\
00903     while( from->root )\
00904     {\
00905         ppConcat(label,_node)* node = (ppConcat(label,_node)*)from->root;\
00906         ctl_tree_(ctlt_after,ctlt_unique, remove)( from, &node->obj );\
00907         if( &node->obj != ctl_tree_(ctlt_after,ctlt_unique, insert)( self, &node->obj ) )\
00908         {\
00909             /* If this is a ctl_unique set, keys might match, so we chuck things we already have in 'self' */\
00910             ppConcat(type,_destroy)(&node->obj);\
00911             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00912         }\
00913         ppDebug(else node->container = (struct label*)self;)\
00914     }\
00915     ppConcat(label,_destroy)(from);\
00916 }\
00917 
00918 #endif /* DG_SET_H */

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