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
00018
00019 typedef void (*DeleteFPtr)(void*) ;
00020
00021
00022 struct SimplePtrInit{ static void* init() { return 0 ; } } ;
00023
00024
00025 struct NoDelete{ static void clean(void *v) { } } ;
00026
00027
00028 template <class T>
00029 struct CreationPtrInit{ static void* init() { return new T ; } } ;
00030
00031
00032 template <class T>
00033 struct DeletePtr{ static void clean(void *v) { delete (T*) v ; } } ;
00034
00035
00036
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
00050
00051 typedef std::map< unsigned , void * > PtrMap ;
00052
00053
00054 typedef std::vector< DeleteFPtr > DPtrVec ;
00055
00056
00057
00058
00059
00060
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
00079
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
00092
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
00109
00110 template <class U, class T>
00111 struct RelationOneSide :
00112 public LCBaseLinkTraits<U,T,SimplePtrInit,NoDelete,false> {};
00113
00114
00115
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
00122
00123 template <class U> struct FromRelation{} ;
00124
00125
00126 template <class U> struct ToRelation{} ;
00127
00128
00129
00130 template <class From, class To>
00131 struct BiDirectional{
00132 typedef From from ;
00133 typedef To to ;
00134 } ;
00135
00136
00137
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
00149
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 s) { t = 0 ; }
00158 };
00159
00160
00161
00162
00163 }
00164
00165 namespace lcrtrel{
00166
00167 using namespace lcrtrel_helper ;
00168
00169
00170
00171
00172
00173 template <class U, typename T>
00174 struct LCExtension : public LCBaseLinkTraits< U, T > {};
00175
00176
00177
00178
00179
00180
00181 template <class U, typename T>
00182 class LCOwnedExtension : public LCBaseLinkTraits< U, T , SimplePtrInit , DeletePtr<T> > {};
00183
00184
00185
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
00193
00194
00195
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
00203
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
00210
00211
00212
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
00220
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
00228
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
00235
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
00243
00244 template <class U >
00245 struct LCIntExtension{
00246
00247 typedef int ptr ;
00248
00249 typedef U tag ;
00250
00251 static const int allowed_to_call_ext = 1 ;
00252
00253 static void clean(void *v) { }
00254
00255 static ptr init() {
00256 return 0 ;
00257 }
00258 static DeleteFPtr deletePtr() { return &clean ; } ;
00259
00260 typedef int& ext_type ;
00261 };
00262
00263
00264
00265 template <class U >
00266
00267 struct LCFloatExtension{
00268
00269 typedef float ptr ;
00270 typedef U tag ;
00271 typedef float& ext_type ;
00272
00273 static const int allowed_to_call_ext = 1 ;
00274 static void clean(void *v) { }
00275 static ptr init() { return 0 ; }
00276 static DeleteFPtr deletePtr() { return &clean ; } ;
00277 };
00278
00279
00280
00281
00282
00283
00284 class LCRTRelations ;
00285
00286
00287
00288 template <class R>
00289 void set_relation( typename R::from::obj_ptr f,
00290 typename R::to::obj_ptr t) ;
00291
00292
00293 template <class R>
00294 void unset_relation(typename R::from::obj_ptr f );
00295
00296
00297
00298 template <class R>
00299 void add_relation( typename R::from::obj_ptr f,
00300 typename R::to::obj_ptr t) ;
00301
00302
00303
00304 template <class R>
00305 void remove_relation( typename R::from::obj_ptr f,
00306 typename R::to::obj_ptr t) ;
00307
00308
00309
00310 template <class R>
00311 void remove_relations(typename R::from::obj_ptr f );
00312
00313
00314
00315
00316
00317 template <class R>
00318 void merge_relations( typename R::from::obj_ptr f1,
00319 typename R::from::obj_ptr f2) ;
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 class LCRTRelations{
00402
00403
00404 template <class R>
00405 friend void set_relation( typename R::from::obj_ptr f,
00406 typename R::to::obj_ptr t);
00407 template <class R>
00408 friend void unset_relation(typename R::from::obj_ptr f );
00409
00410 template <class R>
00411 friend void add_relation( typename R::from::obj_ptr f,
00412 typename R::to::obj_ptr t) ;
00413 template <class R>
00414 friend void remove_relation( typename R::from::obj_ptr f,
00415 typename R::to::obj_ptr t) ;
00416 template <class R>
00417 friend void remove_relations(typename R::from::obj_ptr f );
00418
00419 template <class R>
00420 friend void merge_relations( typename R::from::obj_ptr f1,
00421 typename R::from::obj_ptr f2) ;
00422
00423 public:
00424
00425
00426
00427
00428
00429 template <class V>
00430 inline typename V::ext_type ext() {
00431
00432
00433 can_call_ext<V::allowed_to_call_ext>::check() ;
00434
00435 return ptr<V>() ;
00436 }
00437
00438
00439
00440
00441
00442
00443 template <class V>
00444 inline typename V::rel_type rel() {
00445
00446 return ptr<V>() ;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 ~LCRTRelations() {
00464 for( PtrMap::iterator it = _map.begin() ; it != _map.end() ; ++it ){
00465 cleaners()[ it->first ] ( it->second ) ;
00466 }
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 protected:
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 template <class V>
00508 typename V::ptr & ptr() {
00509
00510 typedef std::map< unsigned , typename V::ptr > MyPtrMap ;
00511
00512 MyPtrMap* map = (MyPtrMap*) &_map ;
00513
00514 typename MyPtrMap::iterator it = map->find( typeID<V>() ) ;
00515
00516 if( it == map->end() )
00517 it = map->insert( map->begin(),
00518 std::make_pair( typeID<V>() , V::init() )) ;
00519
00520 return it->second ;
00521 }
00522
00523 private:
00524
00525 static DPtrVec& cleaners(){
00526 static DPtrVec v ;
00527 return v ;
00528 }
00529
00530 inline unsigned nextID(DeleteFPtr cp){
00531 static unsigned id(0) ;
00532
00533
00534
00535
00536 cleaners().push_back( cp ) ;
00537
00538 return id++ ;
00539 }
00540
00541 template <class T>
00542 inline unsigned typeID(){
00543 static const unsigned uid = nextID( T::deletePtr() ) ;
00544
00545 return uid ;
00546 }
00547
00548
00549
00550 PtrMap _map ;
00551
00552 } ;
00553
00554
00555
00556
00557
00558 template <class R>
00559 void unset_relation(typename R::from::obj_ptr f){
00560
00561 if( f != 0 ){
00562
00563 LCRTRelations* t = f->LCRTRelations::rel<typename R::to>() ;
00564
00565 if( t != 0 )
00566 t->LCRTRelations::ptr<typename R::from>() = 0 ;
00567
00568 f->LCRTRelations::ptr<typename R::to>() = 0 ;
00569 }
00570 }
00571
00572 template <class R>
00573 void set_relation(typename R::from::obj_ptr f, typename R::to::obj_ptr t){
00574
00575
00576 unset_relation<R>( f ) ;
00577 unset_relation<R>(t->LCRTRelations::rel<typename R::from>() ) ;
00578
00579 f->LCRTRelations::ptr<typename R::to>() = t ;
00580 t->LCRTRelations::ptr<typename R::from>() = f ;
00581 }
00582
00583
00584
00585
00586 template <class R>
00587 void add_relation( typename R::from::obj_ptr f,
00588 typename R::to::obj_ptr t){
00589
00590 f->LCRTRelations::ptr<typename R::to>()->push_back( t ) ;
00591
00592
00593 objorcont<R::from::is_container>::add( t->LCRTRelations::ptr<typename R::from>() , f ) ;
00594 }
00595
00596
00597
00598
00599 template <class R>
00600 void remove_relation( typename R::from::obj_ptr f,
00601 typename R::to::obj_ptr t ) {
00602
00603 f->LCRTRelations::ptr<typename R::to>()->remove( t ) ;
00604
00605 objorcont<R::from::is_container>::remove( t->LCRTRelations::ptr<typename R::from>() , f ) ;
00606 }
00607
00608
00609 template <class R>
00610 void remove_relations( typename R::from::obj_ptr f ) {
00611
00612 typename R::to::ptr cl = f->LCRTRelations::ptr<typename R::to>() ;
00613
00614 for( typename R::to::iterator it = cl->begin(); it!=cl->end(); ++it){
00615
00616 objorcont<R::from::is_container>::remove((*it)->LCRTRelations::ptr<typename R::from>(), f ) ;
00617
00618 }
00619 cl->clear() ;
00620 }
00621
00622 template <class R>
00623 void merge_relations(typename R::from::obj_ptr f1,
00624 typename R::from::obj_ptr f2 ) {
00625
00626 typename R::to::ptr lt2 = f2->LCRTRelations::ptr<typename R::to>() ;
00627
00628 for( typename R::to::iterator it = lt2->begin() ;it != lt2->end() ; it++ ){
00629
00630 objorcont<R::from::is_container>::remove( (*it)->LCRTRelations::ptr<typename R::from>(), f2 ) ;
00631 objorcont<R::from::is_container>::add( (*it)->LCRTRelations::ptr<typename R::from>(), f1 ) ;
00632 }
00633
00634 f1->LCRTRelations::ptr<typename R::to>()->merge( *lt2 ) ;
00635 }
00636
00637
00638 }
00639
00640 #endif