map.h

00001 #ifndef DG_MAP_H
00002 #define DG_MAP_H
00003 
00009 #ifndef CTL_TREE_H
00010 #include "ctl/tree.h"
00011 #endif
00012 
00013 /****************************************************************************
00014 
00015 Declare ctl_map
00016 
00017 *****************************************************************************/
00018 
00028 #define ctl_declare_map(label,keytype,type)         ctl_declare_map_base(label,keytype,type,ctlt_unique)
00029 
00038 #define ctl_implement_map(label,keytype,type)       ctl_implement_map_base(label,keytype,type,ctlt_unique)
00039 
00048 #define ctl_map_foreach(label, instance, iterator ) \
00049     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00050     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00051     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00052     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00053 
00062 #define ctl_map_foreach_const(label, instance, iterator ) \
00063     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00064     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00065     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00066     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00067 
00076 #define ctl_map_foreach_reverse(label, instance, iterator ) \
00077     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00078     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00079     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00080     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)(ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ), iterator=ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00081 
00090 #define ctl_map_foreach_const_reverse(label, instance, iterator ) \
00091     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00092     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00093     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00094     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)(ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ), iterator=ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00095 
00096 
00105 #define ctl_map_from(label, instance, key, iterator )\
00106     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00107     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00108     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00109     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00110 
00113 #define ctl_map_from_const(label, instance, key, iterator )\
00114     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00115     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00116     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00117     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00118 
00121 #define ctl_map_from_reverse(label, instance, key, iterator )\
00122     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00123     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00124     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00125     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00126 
00129 #define ctl_map_from_const_reverse(label, instance, key, iterator )\
00130     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00131     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00132     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00133     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00134 
00146 #define ctl_map_from_to(label, instance, keyfrom, keyto, iterator )\
00147     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00148     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00149     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00150     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) < 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00151 
00154 #define ctl_map_from_to_const(label, instance, keyfrom, keyto, iterator )\
00155     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00156     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00157     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00158     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) < 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00159 
00162 #define ctl_map_from_to_reverse(label, instance, keyfrom, keyto, iterator )\
00163     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00164     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00165     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00166     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) > 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00167 
00171 #define ctl_map_from_to_const_reverse(label, instance, keyfrom, keyto, iterator )\
00172     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00173     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00174     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00175     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) > 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00176 
00177 /****************************************************************************
00178 
00179 Declare ctl_multimap
00180 
00181 *****************************************************************************/
00182 
00191 #define ctl_declare_multimap(label,keytype,type)    ctl_declare_map_base(label,keytype,type,ctlt_multiple)
00192 
00200 #define ctl_implement_multimap(label,keytype,type)  ctl_implement_map_base(label,keytype,type,ctlt_multiple)
00201 
00210 #define ctl_multimap_foreach(label, instance, iterator ) \
00211     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00212     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00213     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00214     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00215 
00224 #define ctl_multimap_foreach_const(label, instance, iterator ) \
00225     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00226     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple,iterator_begin)( &ppConcat(stack_,iterator), (instance) );\
00227     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00228     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00229 
00238 #define ctl_multimap_foreach_reverse(label, instance, iterator ) \
00239     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00240     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00241     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00242     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)(ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ), iterator=ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00243 
00252 #define ctl_multimap_foreach_const_reverse(label, instance, iterator ) \
00253     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00254     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin)( &ppConcat(stack_,iterator), (instance) );\
00255     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00256     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)(ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ), iterator=ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00257 
00258 
00267 #define ctl_multimap_from(label, instance, key, iterator )\
00268     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00269     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00270     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00271     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00272 
00275 #define ctl_multimap_from_const(label, instance, key, iterator )\
00276     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00277     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00278     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00279     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00280 
00283 #define ctl_multimap_from_reverse(label, instance, key, iterator )\
00284     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00285     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00286     ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00287     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00288 
00291 #define ctl_multimap_from_const_reverse(label, instance, key, iterator )\
00292     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00293     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (key) );\
00294     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00295     for ( ; ppConcat(iterator,_key); ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00296 
00308 #define ctl_multimap_from_to(label, instance, keyfrom, keyto, iterator )\
00309     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00310     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00311     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00312     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) < 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00313 
00316 #define ctl_multimap_from_to_const(label, instance, keyfrom, keyto, iterator )\
00317     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00318     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_begin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00319     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00320     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) < 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_next)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00321 
00324 #define ctl_multimap_from_to_reverse(label, instance, keyfrom, keyto, iterator )\
00325     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00326     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00327     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00328     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) > 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00329 
00333 #define ctl_multimap_from_to_const_reverse(label, instance, keyfrom, keyto, iterator )\
00334     ppConcat(label,_iterator) ppConcat(stack_,iterator);\
00335     const ppConcat(label,_keytype)* ppConcat(iterator,_key) = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_rbegin_from)( &ppConcat(stack_,iterator), (instance), (keyfrom) );\
00336     const ppConcat(label,_type)* iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) );\
00337     for( ; ppConcat(iterator,_key) && (instance)->compare(ppConcat(iterator,_key),(keyto)) > 0; ppConcat(iterator,_key) = (ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_multiple, iterator_prev)( &ppConcat(stack_,iterator) ), iterator = ppConcat(label,_obj_from_key)( ppConcat(iterator,_key) ) )
00338 
00339 
00340 /****************************************************************************
00341 
00342 Base map/multimap declaration
00343 
00344 *****************************************************************************/
00345 
00349 #define ctl_declare_map_base(label,keytype,type,ctlt_unique)\
00350     typedef struct ppConcat(label,_node)\
00351     {\
00352         ctlt_node_type(ctlt_after,ctlt_unique) link;\
00353         keytype key;                            /* The key value (must be first for sort functions) */ \
00354         type    obj;                            /* The actual member */ \
00355         ppDebug(struct label* container;)       /* For debug, sign nodes so membership assertions aren't so heinous */\
00356     } ppConcat(label,_node);\
00357     typedef ctl_tree(ctlt_after,ctlt_unique) label;\
00358     /* So we can monitor memory use/leaks */\
00359     extern ctl_pool(ppConcat(label,_node)) ppConcat(label,_pool);\
00360     /* A few typedefs */\
00361     typedef type ppConcat(label,_type);\
00362     typedef keytype ppConcat(label,_keytype);\
00363     typedef ctl_tree_(ctlt_after,ctlt_unique, iterator ) ppConcat(label,_iterator);\
00364     /* The standard pattern functions */\
00365     ctl_datagen_declare_functions(label);\
00366     /* 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) */\
00367     void  ppConcat(label,_sort)( label* self, int (*compare)(const keytype* p1, const keytype* p2) );\
00368     /* How many members in this container */\
00369     size_t ppConcat(label,_count)( const label* self);\
00370     /* Tell us if an object is part of this container */\
00371     bool ppConcat(label,_ismember)( const label* self, const type* mbr );\
00372     /* Get member from a key - will be BOGUS if 'key' is not from an instance of this container */\
00373     type* ppConcat(label,_obj_from_key)( const keytype* key );\
00374     /* Get key from a member - will be BOGUS if 'key' is not from an instance of this container */\
00375     keytype* ppConcat(label,_key_from_obj)( const type* mbr );\
00376     /* Destroy all members, release all memory */\
00377     void ppConcat(label,_clear)( label* self );\
00378     /* Get a pointer to the back end member of container */\
00379     type* ppConcat(label,_back)(const label* self);\
00380     /* Get a pointer to the front end member of container */\
00381     type* ppConcat(label,_front)(const label* self);\
00382     /* Remove (and destroy) last member */\
00383     void  ppConcat(label,_pop_back)(label* self);\
00384     /* Remove (and destroy) first member */\
00385     void  ppConcat(label,_pop_front)(label* self);\
00386     /* Insert a member with a key.  If member ALREADY exists, that pre-existing member is returned. */\
00387     type* ppConcat(label,_insert)( label* self, const keytype* key );\
00388     /* Find the member matching 'key'; returns NULL if it's not in here. */\
00389     type* ppConcat(label,_at)(const label* self, const keytype* key );\
00390     /* Erase (and destroy) a member by its pointer */\
00391     void  ppConcat(label,_erase)(label* self, type* mbr );\
00392     /* Erase (and destroy) a member by its key value */\
00393     void  ppConcat(label,_erase_key)(label* self, keytype* key );\
00394     /* Splice the container 'from' to this one and clear() from */\
00395     void  ppConcat(label,_splice)( label* self, label* from );\
00396 
00397 /****************************************************************************
00398 
00399 Base map/multimap Implementation
00400 
00401 *****************************************************************************/
00402 
00403 #ifndef CTL_POOL_DELTA
00404 
00410 #define CTL_POOL_DELTA  16
00411 #endif
00412 
00416 #define ctl_implement_map_base(label,keytype,type,ctlt_unique)\
00417 const bool ppConcat(label,_isscalar) = false;\
00418 ctl_pool_auto(ppConcat(label,_node),ppConcat(label,_pool),CTL_POOL_DELTA);\
00419 /* Initialize this record to a known, default state */\
00420 void ppConcat(label,_init)( label* self )\
00421 {\
00422     assertobjptr(self);\
00423     ctl_tree_init(ctlt_after,ctlt_unique, ppConcat(keytype,_compare), self );\
00424 }\
00425 /* Replicate a record, copying from 'src' to 'dst' */\
00426 void ppConcat(label,_copy)( label* dst, const label* src )\
00427 {\
00428     assertobjptr(dst);\
00429     assertobjconst(src);\
00430     ppConcat(label,_init)( dst );\
00431     dst->compare = src->compare;\
00432     {\
00433         ppConcat(label,_iterator) stack_curr;\
00434         const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, src );\
00435         while( curr_key )\
00436         {\
00437             ppConcat(type,_copy)(ppConcat(label,_insert)(dst,curr_key),ppConcat(label,_obj_from_key)( curr_key ));\
00438             curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00439         }\
00440     }\
00441 }\
00442 /* Move contents from 'src' to 'dst', leaving 'dst' uninitialized. */\
00443 void ppConcat(label,_move)( label* dst, label* src )\
00444 {\
00445     assertobjptr(dst);\
00446     assertobjptr(src);\
00447     *dst = *src;\
00448     ppConcat(label,_init)( src );\
00449     ppDebug( {\
00450         ppConcat(label,_iterator) stack_curr;\
00451         const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, dst );\
00452         while( curr_key )\
00453         {\
00454             dereference(ppConcat(label,_node),key,curr_key)->container = (struct label*)dst;\
00455             curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00456         }\
00457     } )\
00458 }\
00459 /* Swap contents of two records */\
00460 void ppConcat(label,_swap)( label* p1, label* p2 )\
00461 {\
00462     assertobjptr(p1);\
00463     assertobjptr(p2);\
00464     {\
00465         label tmp = *p1;\
00466         *p1 = *p2;\
00467         *p2 = tmp;\
00468     }\
00469     ppDebug( {\
00470         ppConcat(label,_iterator) stack_curr;\
00471         const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, p1 );\
00472         while( curr_key )\
00473         {\
00474             dereference(ppConcat(label,_node),key,curr_key)->container = (struct label*)p1;\
00475             curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00476         }\
00477     } )\
00478     ppDebug( {\
00479         ppConcat(label,_iterator) stack_curr;\
00480         const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, p2 );\
00481         while( curr_key )\
00482         {\
00483             dereference(ppConcat(label,_node),key,curr_key)->container = (struct label*)p2;\
00484             curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00485         }\
00486     } )\
00487 }\
00488 /* Destroy this record, freeing any contained data */\
00489 void ppConcat(label,_destroy)( label* self )\
00490 {\
00491     ppConcat(label,_clear)( self );\
00492 }\
00493 /* Compare this record to another record for sorting backwards */\
00494 int ppConcat(label,_rcompare)( const label* p1, const label* p2 ) { return ppConcat(label,_compare)( p2,p1 ); }\
00495 /* Compare this record to another record for sorting */\
00496 int ppConcat(label,_compare)( const label* p1, const label* p2 )\
00497 {\
00498     if( !p1 && !p2 )\
00499         return 0;\
00500     assertobjconst(p1);\
00501     assertobjconst(p2);\
00502     {\
00503         size_t compareLen = min(p1->size,p2->size);\
00504         ppConcat(label,_iterator) p1s;\
00505         ppConcat(label,_iterator) p2s;\
00506         const keytype* k1 = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &p1s, p1 );\
00507         const keytype* k2 = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &p2s, p2 );\
00508         while( compareLen-- && k1 && k2 )\
00509         {\
00510             int result = ppConcat(keytype,_compare)( k1,k2 );\
00511             if( result )\
00512                 return result;\
00513             result = ppConcat(type,_compare)( ppConcat(label,_obj_from_key)(k1),ppConcat(label,_obj_from_key)(k2) );\
00514             if( result )\
00515                 return result;\
00516             k1 = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_next)( &p1s );\
00517             k2 = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_next)( &p2s );\
00518         }\
00519         /* If we fell through to here, something's amiss with the links/count */\
00520         assert(compareLen == -1);\
00521         if( p1->size < p2->size )\
00522             return -1;\
00523         if( p1->size > p2->size )\
00524             return 1;\
00525         return 0;\
00526     }\
00527 }\
00528 /* Determine if a record is valid-looking; all validated members in expected range */\
00529 bool ppConcat(label,_valid)( const label* self )\
00530 {\
00531     if( !self )\
00532         return false;\
00533     assertobjconst(self);\
00534     return self->compare && ((self->root && self->size) || (NULL == self->root && 0 == self->size));\
00535 }\
00536 /* Determine total memory footprint of this container */\
00537 size_t ppConcat(label,_size)( const label* self )\
00538 {\
00539     assertobjconst(self);\
00540     if( ppConcat(type,_isscalar) )\
00541     {\
00542         return sizeof(*self) + (self->size * sizeof(ppConcat(label,_node)));\
00543     }\
00544     else\
00545     {\
00546         size_t ret = sizeof(*self);\
00547         ppConcat(label,_iterator) stack_curr;\
00548         const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00549         while( curr_key )\
00550         {\
00551             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,curr_key);\
00552             ret += ppConcat(keytype,_size)(&node->key) + ppConcat(type,_size)(&node->obj) + sizeof(ppConcat(label,_node))-sizeof(type)-sizeof(keytype);\
00553             curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00554         }\
00555         return ret;\
00556     }\
00557 }\
00558 /* Determine total size of this record as stingy serial data */\
00559 size_t ppConcat(label,_serial_size)( const label* self )\
00560 {\
00561     assertobjconst(self);\
00562     if( ppConcat(type,_isscalar) )\
00563     {\
00564         ppConcat(label,_node)* node = dereference(ppConcat(label,_node),link,self->root);\
00565         return ctl_serial_size_size( self->size ) + (self->size * (ppConcat(keytype,_serial_size)(&node->key) + ppConcat(type,_serial_size)(&node->obj)));\
00566     }\
00567     else\
00568     {\
00569         size_t total = ctl_serial_size_size( self->size );\
00570         ppConcat(label,_iterator) stack_curr;\
00571         const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00572         while( curr_key )\
00573         {\
00574             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,curr_key);\
00575             total += ppConcat(keytype,_serial_size)(&node->key);\
00576             total += ppConcat(type,_serial_size)(&node->obj);\
00577             curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00578         }\
00579         return total;\
00580     }\
00581 }\
00582 /* Write data to a stingy serial record */\
00583 void ppConcat(label,_serial_write)( const label* self, ctl_serial* serial )\
00584 {\
00585     assertobjconst(self);\
00586     assertobjptr(serial);\
00587     ctl_serial_writesize( self->size, serial ); \
00588     {\
00589         ppConcat(label,_iterator) stack_curr;\
00590         const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00591         while( curr_key )\
00592         {\
00593             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,curr_key);\
00594             ppConcat(keytype,_serial_write)(&node->key,serial);\
00595             ppConcat(type,_serial_write)(&node->obj,serial);\
00596             curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00597         }\
00598     }\
00599 }\
00600 /* Read data from a stingy serial record */\
00601 void ppConcat(label,_serial_read)( label* self, ctl_serial* serial )\
00602 {\
00603     assertobjptr(self);\
00604     assertobjptr(serial);\
00605     {\
00606         size_t readsize = ctl_serial_readsize( serial ); \
00607         while( readsize-- )\
00608         {\
00609             keytype key;\
00610             ppConcat(keytype,_init)(&key);\
00611             ppConcat(keytype,_serial_read)(&key,serial);\
00612             ppConcat(type,_serial_read)( ppConcat(label,_insert)(self,&key), serial );\
00613             ppConcat(keytype,_destroy)(&key);\
00614         }\
00615     }\
00616 }\
00617 /* Determine total size of this record as robust/archive serial data */\
00618 size_t ppConcat(label,_record_size)( const label* self, const char* szlabel )\
00619 {\
00620     assertobjconst(self);\
00621     assertconst(szlabel,1);\
00622     if( self->size )\
00623     {\
00624         size_t result = ctl_record_objarray_head_size( szlabel, "container", #keytype "_" #type );\
00625         if( ppConcat(type,_isscalar) )\
00626         {\
00627             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),link,self->root);\
00628             result += self->size * (ppConcat(keytype,_record_size)(&node->key,"key") + ppConcat(type,_record_size)(&node->obj,"obj"));\
00629         }\
00630         else\
00631         {\
00632             ppConcat(label,_iterator) stack_curr;\
00633             const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00634             while( curr_key )\
00635             {\
00636                 ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,curr_key);\
00637                 result += ppConcat(keytype,_record_size)(curr_key,"key"); \
00638                 result += ppConcat(type,_record_size)(&node->obj,"obj"); \
00639                 curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00640             }\
00641         }\
00642         return result;\
00643     }\
00644     return 0;\
00645 }\
00646 /* Write data to a robust binary serial record */\
00647 void ppConcat(label,_record_write)( const label* self, ctl_serial* serial, const char* szlabel )\
00648 {\
00649     assertobjconst(self);\
00650     assertobjptr(serial);\
00651     assertconst(szlabel,1);\
00652     if( self->size )\
00653     {\
00654         uint8* rectemp = ctl_record_write_container_begin( "container", #keytype "_" #type, 0,self->size, serial, szlabel );\
00655         { \
00656             ppConcat(label,_iterator) stack_curr;\
00657             const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00658             while( curr_key )\
00659             {\
00660                 ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,curr_key);\
00661                 ppConcat(keytype,_record_write)(curr_key,serial,"key"); \
00662                 ppConcat(type,_record_write)(&node->obj,serial,"obj"); \
00663                 curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00664             }\
00665         }\
00666         ctl_record_write_end( rectemp, serial );\
00667     }\
00668 }\
00669 /* Read data from a robust/archive binary serial record */\
00670 bool ppConcat(label,_record_read)( label* self, ctl_serial* serial, const char* szlabel )\
00671 {\
00672     assertobjptr(self);\
00673     assertobjptr(serial);\
00674     assertconst(szlabel,1);\
00675     {\
00676         ctl_serial pserial = *serial;\
00677         ppConcat(label,_clear)(self);\
00678         if( ctl_record_find( &pserial, szlabel ) )\
00679         {\
00680             size_t count = ctl_record_container_validatedata( &pserial, "container", #keytype "_" #type );\
00681             while( count-- )\
00682             {\
00683                 keytype key;\
00684                 ppConcat(keytype,_init)(&key);\
00685                 ppConcat(keytype,_record_read)(&key, &pserial, "key");\
00686                 ctl_record_next( &pserial );\
00687                 ppConcat(type,_record_read)( ppConcat(label,_insert)(self,&key), &pserial, "obj" );\
00688                 ctl_record_next( &pserial );\
00689                 ppConcat(keytype,_destroy)(&key);\
00690             }\
00691             if( pserial.curr != pserial.end )\
00692                 ctl_serial_except( &pserial, szconst(char,#label) szconst(char,"_record_read: Wrong data length!") );\
00693             return true;\
00694         }\
00695     }\
00696     return false;\
00697 }\
00698 /* Write data to an XML record */\
00699 void ppConcat(label,_xml_write)( const label* self, ctl_xmlwrite* xml, const char* szlabel )\
00700 {\
00701     assertobjconst(self);\
00702     assertobjptr(xml);\
00703     assertconst(szlabel,1);\
00704     if( self->size )\
00705     {\
00706         ctl_xmlwrite_containertag( xml, #keytype "_" #type, self->size, szlabel ); \
00707         ctl_xmlwrite_indent( xml );\
00708         {\
00709             ppConcat(label,_iterator) stack_curr;\
00710             const keytype* curr_key = (const keytype*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack_curr, self );\
00711             while( curr_key )\
00712             {\
00713                 ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,curr_key);\
00714                 ctl_xmlwrite_generaltag( xml, #keytype "_" #type, #keytype "_" #type);\
00715                 ctl_xmlwrite_indent( xml );\
00716                 ppConcat(keytype,_xml_write)(curr_key,xml,"key");\
00717                 ppConcat(type,_xml_write)(&node->obj,xml,"obj");\
00718                 ctl_xmlwrite_outdent( xml );\
00719                 ctl_xmlwrite_endtag( xml, #keytype "_" #type, #keytype "_" #type ); \
00720                 curr_key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack_curr );\
00721             }\
00722         }\
00723         ctl_xmlwrite_outdent( xml );\
00724         ctl_xmlwrite_endtag( xml, #type, szlabel ); \
00725     }\
00726 }\
00727 /* Read data from an XML record */\
00728 bool ppConcat(label,_xml_read)( label* self, ctl_xmlread* xml, const char* szlabel )\
00729 {\
00730     assertobjptr(self);\
00731     assertobjptr(xml);\
00732     assertconst(szlabel,1);\
00733     if( ctl_xmlread_find( xml, szlabel ) )\
00734     {\
00735         int32 count = 0;\
00736         if( ctl_xmlread_getattribute_int( xml, CTL_LABEL_COUNT, &count ) )\
00737         {\
00738             ctl_xmlread arraydata;\
00739             ctl_xmlread_recurse(&arraydata,xml);\
00740             while( count-- )\
00741             {\
00742                 ctl_xmlread keyobj;\
00743                 if( ctl_xmlread_recurse(&keyobj,&arraydata) )\
00744                 {\
00745                     keytype key;\
00746                     ppConcat(keytype,_init)(&key);\
00747                     ppConcat(keytype,_xml_read)(&key, &keyobj, "key");\
00748                     ppConcat(type,_xml_read)(ppConcat(label,_insert)(self,&key), &keyobj, "obj");\
00749                     ppConcat(keytype,_destroy)(&key);\
00750                 }\
00751                 ctl_xmlread_next(&arraydata);\
00752             }\
00753         }\
00754         else\
00755         {\
00756             xml->except( xml, szconst(char,#label) szconst(char,"_xml_read: Missing size attribute!"), xml->szpCurr, NULL );\
00757         }\
00758         return true;\
00759     }\
00760     return false;\
00761 }\
00762 /* Re-sort by qsort-like criteria */\
00763 void  ppConcat(label,_sort)( label* self, int (*compare)(const keytype* p1, const keytype* p2) )\
00764 {\
00765     assertobjptr(self);\
00766     assertcodeptr(compare);\
00767     if( self->size )\
00768     {\
00769         label tmp;\
00770         ppConcat(label,_move)( &tmp, self );\
00771         self->compare = (tree_compare)compare;\
00772         ppConcat(label,_splice)( self, &tmp );\
00773     }\
00774     else\
00775     {\
00776         self->compare = (tree_compare)compare;\
00777     }\
00778 }\
00779 /* How many members in this container */\
00780 size_t ppConcat(label,_count)( const label* self)\
00781 {\
00782     assertobjconst(self);\
00783     return self->size;\
00784 }\
00785 /* Tell us if an object is part of this container */\
00786 bool ppConcat(label,_ismember)( const label* self, const type* data )\
00787 {\
00788     assertobjconst(self);\
00789     if( !data )\
00790         return false;\
00791     assertobjconst(data);\
00792     {\
00793         ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,data);\
00794         ppDebug(return node->container == (struct label*)self; )\
00795         ppRelease (\
00796             /* In multimap case, more than one key may match, so check for other matches */\
00797             ppConcat(label,_iterator) stack;\
00798             const keytype* key = (const ppConcat(label,_keytype)*)ctl_tree_(ctlt_after,ctlt_unique,iterator_begin)( &stack, self );\
00799             while( key && !ppConcat(keytype,_compare)(key, &node->key ) )\
00800             {\
00801                 if( key == &node->key )\
00802                     return true;\
00803                 key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, iterator_next)( &stack );\
00804             }\
00805             return false;\
00806         )\
00807     }\
00808 }\
00809 /* Get member from a key - will be BOGUS if 'key' is not from an instance of this container */\
00810 type* ppConcat(label,_obj_from_key)( const keytype* key )\
00811 {\
00812     if( key )\
00813     {\
00814         ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,key);\
00815         return (type*)&node->obj;\
00816     }\
00817     return NULL;\
00818 }\
00819 /* Get key from a member - will be BOGUS if 'key' is not from an instance of this container */\
00820 keytype* ppConcat(label,_key_from_obj)( const type* mbr )\
00821 {\
00822     if( mbr )\
00823     {\
00824         ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,mbr);\
00825         return (keytype*)&node->key;\
00826     }\
00827     return NULL;\
00828 }\
00829 /* Recursive tree nuke-o-matic used by 'clear' */\
00830 void ppConcat(label,_recurse_clear)( ppConcat(label,_node)* node )\
00831 {\
00832     if( node->link.left )\
00833         ppConcat(label,_recurse_clear)( (ppConcat(label,_node)*)node->link.left );\
00834     if( node->link.right )\
00835         ppConcat(label,_recurse_clear)( (ppConcat(label,_node)*)node->link.right );\
00836     ppConcat(keytype,_destroy)(&node->key);\
00837     ppConcat(type,_destroy)(&node->obj);\
00838     ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00839 }\
00840 /* Destroy all members, release all memory */\
00841 void ppConcat(label,_clear)( label* self )\
00842 {\
00843     assertobjptr(self);\
00844     if( self->root )\
00845         ppConcat(label,_recurse_clear)( (ppConcat(label,_node)*)self->root );\
00846     self->size = 0;\
00847     self->root = NULL;\
00848 }\
00849 /* Get a pointer to the back end member of container */\
00850 type* ppConcat(label,_back)(const label* self)\
00851 {\
00852     assertobjconst(self);\
00853     {\
00854         keytype* key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, back)( self );\
00855         return ppConcat(label,_obj_from_key)( key );\
00856     }\
00857 }\
00858 /* Get a pointer to the front end member of container */\
00859 type* ppConcat(label,_front)(const label* self)\
00860 {\
00861     assertobjconst(self);\
00862     {\
00863         keytype* key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, front)( self );\
00864         return ppConcat(label,_obj_from_key)( key );\
00865     }\
00866 }\
00867 /* Remove (and destroy) last member */\
00868 void  ppConcat(label,_pop_back)(label* self)\
00869 {\
00870     assertobjptr(self);\
00871     {\
00872         keytype* key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, pop_back)( self );\
00873         if( key )\
00874         {\
00875             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,key);\
00876             ppConcat(keytype,_destroy)(&node->key);\
00877             ppConcat(type,_destroy)(&node->obj);\
00878             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00879         }\
00880     }\
00881 }\
00882 /* Remove (and destroy) first member */\
00883 void  ppConcat(label,_pop_front)(label* self)\
00884 {\
00885     assertobjptr(self);\
00886     {\
00887         keytype* key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, pop_front)( self );\
00888         if( key )\
00889         {\
00890             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,key);\
00891             ppConcat(keytype,_destroy)(&node->key);\
00892             ppConcat(type,_destroy)(&node->obj);\
00893             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00894         }\
00895     }\
00896 }\
00897 /* Insert a member with a key.  If member ALREADY exists, that pre-existing member is returned. */\
00898 type* ppConcat(label,_insert)( label* self, const keytype* key )\
00899 {\
00900     assertobjptr(self);\
00901     assertobjconst(key);\
00902     {\
00903         ppConcat(label,_node)* newnode;\
00904         ctl_pool_alloc(ppConcat(label,_node),&ppConcat(label,_pool), newnode);\
00905         ppConcat(keytype,_copy)(&newnode->key, key);\
00906         {\
00907             keytype* foundkey = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, insert)( self, &newnode->key );\
00908             if( foundkey != &newnode->key )\
00909             {\
00910                 ppConcat(keytype,_destroy)(&newnode->key);\
00911                 ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), newnode);\
00912                 return ppConcat(label,_obj_from_key)(foundkey);\
00913             }\
00914         }\
00915         ppDebug(newnode->container = (struct label*)self;)\
00916         ppConcat(type,_init)(&newnode->obj);\
00917         return &newnode->obj;\
00918     }\
00919 }\
00920 /* Find the member matching 'key; returns NULL if it's not in here. */\
00921 type* ppConcat(label,_at)(const label* self, const keytype* key )\
00922 {\
00923     assertobjconst(self);\
00924     assertobjconst(key);\
00925     return ppConcat(label,_obj_from_key)( (keytype*)ctl_tree_(ctlt_after,ctlt_unique, find)( self, key ) );\
00926 }\
00927 /* Erase (and destroy) a member by its pointer */\
00928 void  ppConcat(label,_erase)(label* self, type* mbr )\
00929 {\
00930     assertobjptr(self);\
00931     assertobjptr(mbr);\
00932     {\
00933         ppConcat(label,_node)* node = dereference(ppConcat(label,_node),obj,mbr);\
00934         assert( (label*)node->container == self );\
00935         {\
00936             keytype* key = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, unlink)( self, &node->key );\
00937             if( key )\
00938             {\
00939                 node = dereference(ppConcat(label,_node),key,key);\
00940                 ppConcat(keytype,_destroy)(&node->key);\
00941                 ppConcat(type,_destroy)(&node->obj);\
00942                 ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00943             }\
00944         }\
00945     }\
00946 }\
00947 /* Erase (and destroy) a member by an object representing it */\
00948 void  ppConcat(label,_erase_key)(label* self, keytype* key )\
00949 {\
00950     assertobjptr(self);\
00951     assertobjptr(key);\
00952     {\
00953         keytype* found = (keytype*)ctl_tree_(ctlt_after,ctlt_unique, remove)( self, key );\
00954         if( found )\
00955         {\
00956             ppConcat(label,_node)* node = dereference(ppConcat(label,_node),key,found);\
00957             ppConcat(keytype,_destroy)(&node->key);\
00958             ppConcat(type,_destroy)(&node->obj);\
00959             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00960         }\
00961     }\
00962 }\
00963 /* Splice the container 'from' to this one and clear() from */\
00964 void  ppConcat(label,_splice)( label* self, label* from )\
00965 {\
00966     assertobjptr(self);\
00967     assertobjptr(from);\
00968     while( from->root )\
00969     {\
00970         ppConcat(label,_node)* node = (ppConcat(label,_node)*)from->root;\
00971         ctl_tree_(ctlt_after,ctlt_unique, remove)( from, &node->key );\
00972         if( &node->key != ctl_tree_(ctlt_after,ctlt_unique, insert)( self, &node->key ) )\
00973         {\
00974             /* If this is a ctl_unique map, keys might match, so we chuck things we already have in 'self' */\
00975             ppConcat(keytype,_destroy)(&node->key);\
00976             ppConcat(type,_destroy)(&node->obj);\
00977             ctl_pool_free(ppConcat(label,_node),&ppConcat(label,_pool), node);\
00978         }\
00979         ppDebug(else node->container = (struct label*)self;)\
00980     }\
00981     ppConcat(label,_destroy)(from);\
00982 }\
00983 
00984 #endif /* DG_MAP_H */

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