00001 #ifndef LCRTRelations_H
00002 #define LCRTRelations_H 1
00003
00004 #include <iostream>
00005 #include <vector>
00006 #include <list>
00007 #include <map>
00008
00009 namespace lcrtrel_helper{
00010
00011
00012
00013 template <bool B>
00014 struct can_call_ext{};
00015 template <>
00016 struct can_call_ext<true>{ static void check(){ } ; };
00017
00019 typedef void (*DeleteFPtr)(void*) ;
00020
00022 struct SimplePtrInit{ static void* init() { return 0 ; } } ;
00023
00025 struct NoDelete{ static void clean(void *) { } } ;
00026
00028 template <class T>
00029 struct CreationPtrInit{ static void* init() { return new T ; } } ;
00030
00032 template <class T>
00033 struct DeletePtr{ static void clean(void *v) { delete (T*) v ; } } ;
00034
00035
00037 template <class T>
00038 struct DeleteElements{
00039
00040 static void clean(void *v) {
00041 T* vec = static_cast<T*>(v) ;
00042 for( typename T::iterator it = vec->begin();it != vec->end(); ++it){
00043 delete *it ;
00044 }
00045 delete vec ;
00046 }
00047 };
00048
00049
00051 typedef std::map< unsigned , void * > PtrMap ;
00052
00054 typedef std::vector< DeleteFPtr > DPtrVec ;
00055
00057
00058
00059
00061 template <class U, class T , class I, class D, bool b>
00062 struct LCBaseTraits{
00063
00064 typedef T* ptr ;
00065 typedef U tag ;
00066
00067 static const int allowed_to_call_ext = b ;
00068
00069 static void clean(void *v) {
00070 D::clean( v ) ;
00071 }
00072 static ptr init() {
00073 return (ptr) I::init() ;
00074 }
00075 static DeleteFPtr deletePtr() { return &clean ; } ;
00076 };
00077
00078
00080 template <class U, class T , class I=SimplePtrInit, class D=NoDelete , bool b=1>
00081 struct LCBaseLinkTraits : public LCBaseTraits<U,T,I,D,b>{
00082
00083 typedef LCBaseTraits<U,T,I,D,b> base ;
00084
00085 typedef T*& ext_type ;
00086 typedef T* rel_type ;
00087 typedef typename base::ptr obj_ptr ;
00088
00089 static const bool is_container=false ;
00090 };
00091
00093 template <class U, class T , class I=CreationPtrInit<T>, class D=DeletePtr<T> , bool b=1>
00094 struct LCBaseLinkContainerTraits : public LCBaseTraits<U,T,I,D,b>{
00095
00096 typedef LCBaseTraits<U,T,I,D,b> base ;
00097
00098 typedef T* ext_type ;
00099 typedef const T* rel_type ;
00100 typedef typename T::value_type obj_ptr ;
00101
00102 typedef typename T::iterator iterator ;
00103 typedef typename T::const_iterator const_iterator ;
00104
00105 static const bool is_container=true ;
00106 };
00107
00108
00110 template <class U, class T>
00111 struct RelationOneSide :
00112 public LCBaseLinkTraits<U,T,SimplePtrInit,NoDelete,false> {};
00113
00114
00116 template <class U, class T>
00117 struct RelationManySide :
00118 public LCBaseLinkContainerTraits< U, std::list<T*>,
00119 CreationPtrInit< std::list<T*> > ,
00120 DeletePtr<std::list<T*> > ,false > {};
00121
00123 template <class U> struct FromRelation{} ;
00124
00126 template <class U> struct ToRelation{} ;
00127
00128
00130 template <class From, class To>
00131 struct BiDirectional{
00132 typedef From from ;
00133 typedef To to ;
00134 } ;
00135
00136
00138 template <bool is_container>
00139 struct objorcont{
00140
00141 template <class T, class S>
00142 inline static void add( T t, S s) { t->push_back( s ) ; }
00143
00144 template <class T, class S>
00145 inline static void remove( T t, S s) { t->remove( s ) ; }
00146 };
00147
00148
00150 template <>
00151 struct objorcont<false>{
00152
00153 template <class T, class S>
00154 inline static void add( T& t, S s) { t = s ; }
00155
00156 template <class T, class S>
00157 inline static void remove( T& t, S ) { t = 0 ; }
00158 };
00159
00160
00161
00162
00163 }
00164
00165 namespace lcrtrel{
00166
00167 using namespace lcrtrel_helper ;
00168
00173 template <class U, typename T>
00174 struct LCExtension : public LCBaseLinkTraits< U, T > {};
00175
00181 template <class U, typename T>
00182 class LCOwnedExtension : public LCBaseLinkTraits< U, T , SimplePtrInit , DeletePtr<T> > {};
00183
00184
00186 template <class U, class T>
00187 class LCExtensionVector :
00188 public LCBaseLinkContainerTraits< U, std::vector<T*>,
00189 CreationPtrInit< std::vector<T*> > ,
00190 DeletePtr<std::vector<T*> > > {};
00191
00192
00196 template <class U, class T>
00197 class LCOwnedExtensionVector :
00198 public LCBaseLinkContainerTraits< U, std::vector<T*>,
00199 CreationPtrInit< std::vector<T*> > ,
00200 DeleteElements< std::vector<T*> > > {};
00201
00202
00204 template <class U, class T>
00205 class LCExtensionList :
00206 public LCBaseLinkContainerTraits< U, std::list<T*>,
00207 CreationPtrInit< std::list<T*> > ,
00208 DeletePtr<std::list<T*> > > {};
00209
00213 template <class U, class T>
00214 class LCOwnedExtensionList :
00215 public LCBaseLinkContainerTraits< U, std::list<T*>,
00216 CreationPtrInit< std::list<T*> > ,
00217 DeleteElements< std::list<T*> > > {};
00218
00219
00221 template <class U, class From, class To>
00222 struct LC1To1Relation :
00223 public BiDirectional<RelationOneSide<FromRelation<U>,From>,
00224 RelationOneSide<ToRelation<U>,To> > {
00225
00226 } ;
00227
00229 template <class U, class From, class To>
00230 struct LC1ToNRelation :
00231 public BiDirectional<RelationOneSide<FromRelation<U>,From>,
00232 RelationManySide<ToRelation<U>,To> > {
00233 } ;
00234
00236 template <class U, class From, class To>
00237 struct LCNToNRelation :
00238 public BiDirectional<RelationManySide<FromRelation<U>,From>,
00239 RelationManySide<ToRelation<U>,To> > {
00240 } ;
00241
00242
00244 template <class U >
00245 struct LCIntExtension{
00246
00247 typedef long ptr ;
00248 typedef long& ext_type ;
00249
00250 typedef U tag ;
00251
00252 static const int allowed_to_call_ext = 1 ;
00253
00254 static void clean(void *) { }
00255
00256 static ptr init() {
00257 return 0 ;
00258 }
00259 static DeleteFPtr deletePtr() { return &clean ; } ;
00260
00261 };
00262
00263
00264
00265 template <class U >
00266
00267 struct LCFloatExtension{
00268
00269 #ifdef __i386__
00270 typedef float ptr ;
00271 typedef float& ext_type ;
00272
00273 #else // use double on 64bit systems
00274 typedef double ptr ;
00275 typedef double& ext_type ;
00276 #endif
00277
00278 typedef U tag ;
00279
00280 static const int allowed_to_call_ext = 1 ;
00281 static void clean(void *) { }
00282 static ptr init() { return 0 ; }
00283 static DeleteFPtr deletePtr() { return &clean ; } ;
00284 };
00285
00286
00287
00288
00289
00290
00291 class LCRTRelations ;
00292
00293
00294 #ifndef __CINT__
00295
00298 template <class R>
00299 void set_relation( typename R::from::obj_ptr f,
00300 typename R::to::obj_ptr t) ;
00301
00303 template <class R>
00304 void unset_relation(typename R::from::obj_ptr f );
00305
00306
00308 template <class R>
00309 void add_relation( typename R::from::obj_ptr f,
00310 typename R::to::obj_ptr t) ;
00311
00312
00314 template <class R>
00315 void remove_relation( typename R::from::obj_ptr f,
00316 typename R::to::obj_ptr t) ;
00317
00318
00320 template <class R>
00321 void remove_relations(typename R::from::obj_ptr f );
00322
00323
00327 template <class R>
00328 void merge_relations( typename R::from::obj_ptr f1,
00329 typename R::from::obj_ptr f2) ;
00330
00331
00332
00411 class LCRTRelations{
00412
00413
00414 template <class R>
00415 friend void set_relation( typename R::from::obj_ptr f,
00416 typename R::to::obj_ptr t);
00417 template <class R>
00418 friend void unset_relation(typename R::from::obj_ptr f );
00419
00420 template <class R>
00421 friend void add_relation( typename R::from::obj_ptr f,
00422 typename R::to::obj_ptr t) ;
00423 template <class R>
00424 friend void remove_relation( typename R::from::obj_ptr f,
00425 typename R::to::obj_ptr t) ;
00426 template <class R>
00427 friend void remove_relations(typename R::from::obj_ptr f );
00428
00429 template <class R>
00430 friend void merge_relations( typename R::from::obj_ptr f1,
00431 typename R::from::obj_ptr f2) ;
00432
00433 public:
00434
00439 template <class V>
00440 inline typename V::ext_type ext() {
00441
00442 can_call_ext<V::allowed_to_call_ext>::check() ;
00443
00444 return ptr<V>() ;
00445 }
00446
00447 template <class V>
00448 inline const typename V::ext_type ext() const {
00449
00450 can_call_ext<V::allowed_to_call_ext>::check() ;
00451
00452 return ptr<V>() ;
00453 }
00454
00459 template <class V>
00460 inline typename V::rel_type rel() {
00461
00462 return ptr<V>() ;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 virtual ~LCRTRelations() {
00480 for( PtrMap::iterator it = _map.begin() ; it != _map.end() ; ++it ){
00481 cleaners()[ it->first ] ( it->second ) ;
00482 }
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 protected:
00498
00499
00501 template <class V>
00502 typename V::ptr & ptr() const {
00503
00504
00505 typedef std::map< unsigned , typename V::ptr > MyPtrMap ;
00506
00507
00508 char* char_map = reinterpret_cast<char *> ( &_map ) ;
00509 MyPtrMap* map = reinterpret_cast<MyPtrMap*>( char_map ) ;
00510
00511 typename MyPtrMap::iterator it = map->find( typeID<V>() ) ;
00512
00513 if( it == map->end() )
00514 it = map->insert( map->begin(),
00515 std::make_pair( typeID<V>() , V::init() )) ;
00516
00517 return it->second ;
00518 }
00519
00520 private:
00521
00522 static DPtrVec& cleaners() {
00523 static DPtrVec v ;
00524 return v ;
00525 }
00526
00527 inline unsigned nextID(DeleteFPtr cp) const {
00528 static unsigned id(0) ;
00529
00530
00531
00532
00533 cleaners().push_back( cp ) ;
00534
00535 return id++ ;
00536 }
00537
00538 template <class T>
00539 inline unsigned typeID() const {
00540 static const unsigned uid = nextID( T::deletePtr() ) ;
00541
00542 return uid ;
00543 }
00544
00545
00546 mutable PtrMap _map{} ;
00547
00548 } ;
00549
00550
00551
00552
00553
00554 template <class R>
00555 void unset_relation(typename R::from::obj_ptr f){
00556
00557 if( f != 0 ){
00558
00559 LCRTRelations* t = f->LCRTRelations::template rel<typename R::to>() ;
00560
00561 if( t != 0 )
00562 t->LCRTRelations::ptr<typename R::from>() = 0 ;
00563
00564 f->LCRTRelations::template ptr<typename R::to>() = 0 ;
00565 }
00566 }
00567
00568 template <class R>
00569 void set_relation(typename R::from::obj_ptr f, typename R::to::obj_ptr t){
00570
00571
00572 unset_relation<R>( f ) ;
00573 unset_relation<R>(t->LCRTRelations::template rel<typename R::from>() ) ;
00574
00575 f->LCRTRelations::template ptr<typename R::to>() = t ;
00576 t->LCRTRelations::template ptr<typename R::from>() = f ;
00577 }
00578
00579
00580
00581
00582 template <class R>
00583 void add_relation( typename R::from::obj_ptr f,
00584 typename R::to::obj_ptr t){
00585
00586 f->LCRTRelations::template ptr<typename R::to>()->push_back( t ) ;
00587
00588
00589 objorcont<R::from::is_container>::add( t->LCRTRelations::template ptr<typename R::from>() , f ) ;
00590 }
00591
00592
00593
00594
00595 template <class R>
00596 void remove_relation( typename R::from::obj_ptr f,
00597 typename R::to::obj_ptr t ) {
00598
00599 f->LCRTRelations::template ptr<typename R::to>()->remove( t ) ;
00600
00601 objorcont<R::from::is_container>::remove( t->LCRTRelations::template ptr<typename R::from>() , f ) ;
00602 }
00603
00604
00605 template <class R>
00606 void remove_relations( typename R::from::obj_ptr f ) {
00607
00608 typename R::to::ptr cl = f->LCRTRelations::template ptr<typename R::to>() ;
00609
00610 for( typename R::to::iterator it = cl->begin(); it!=cl->end(); ++it){
00611
00612 objorcont<R::from::is_container>::remove((*it)->LCRTRelations::template ptr<typename R::from>(), f ) ;
00613
00614 }
00615 cl->clear() ;
00616 }
00617
00618 template <class R>
00619 void merge_relations(typename R::from::obj_ptr f1,
00620 typename R::from::obj_ptr f2 ) {
00621
00622 typename R::to::ptr lt2 = f2->LCRTRelations::template ptr<typename R::to>() ;
00623
00624 for( typename R::to::iterator it = lt2->begin() ;it != lt2->end() ; it++ ){
00625
00626 objorcont<R::from::is_container>::remove( (*it)->LCRTRelations::template ptr<typename R::from>(), f2 ) ;
00627 objorcont<R::from::is_container>::add( (*it)->LCRTRelations::template ptr<typename R::from>(), f1 ) ;
00628 }
00629
00630 f1->LCRTRelations::template ptr<typename R::to>()->merge( *lt2 ) ;
00631 }
00632 #endif // __CINT__
00633
00634 }
00635
00636 #endif