00001
00002
00003
00004 #ifndef DOBASE_HPP
00005 #define DOBASE_HPP
00006
00007 #include <string.h>
00008
00009
00010 #include "DoBaseI.h"
00011 #include "DoError.h"
00012
00013
00014 #if DO_USE_DYNSHARED==1
00015 #include "DoDynShared.hpp"
00016 #endif
00017
00018
00019
00021
00023
00024 template<bool b>
00025 struct DoErrorIfNot;
00026
00027 template<>
00028 struct DoErrorIfNot<true>{ };
00029
00030 #define DO_ASSERT(cond) sizeof(DoErrorIfNot<cond>)
00031
00033
00034 template <class T>
00035 struct DoBaseType {
00036 typedef T type;
00037 };
00038
00039 template <class T>
00040 struct DoBaseType<T*> {
00041 typedef typename DoBaseType<T>::type type;
00042 };
00043
00044 template <class T>
00045 struct DoBaseType<T&> {
00046 typedef typename DoBaseType<T>::type type;
00047 };
00048
00049 template <class T>
00050 struct DoBaseType<const T> {
00051 typedef typename DoBaseType<T>::type type;
00052 };
00053
00054
00056
00057 template <class T, class U>
00058 struct IsSameType {
00059 enum { v=false };
00060 };
00061
00062 template <class T>
00063 struct IsSameType<T,T> {
00064 enum { v=true };
00065 };
00066
00067
00069
00070 template<class T>
00071 struct IsVObjImpl {
00072 struct IA : public T {
00073 int m;
00074 };
00075 struct IB : public T {
00076 virtual void F( );
00077 int m;
00078 };
00079 enum { v = (sizeof(IA)==sizeof(IB)) };
00080 };
00081
00083
00084
00089 template<class T>
00090 struct IsVObj {
00091 typedef typename DoBaseType<T>::type type;
00092 enum { v=IsVObjImpl<type>::v || IsSameType<VObj,type>::v };
00093 };
00094
00095
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 template<>
00112 struct IsVObj<void> {
00113 enum { v = false };
00114 };
00115
00117
00118
00119
00120
00121 template <class T>
00122 struct VBaseSelect {
00123 typedef T type;
00124 };
00125
00126 template <class T, class U>
00127 struct DoIsTypeAImpl {
00128
00129 static char F( U* );
00130 static short F(...);
00131 static T* pt;
00132 enum { v=sizeof(F(pt))==sizeof(char) };
00133 };
00134
00135 template <class T, class U>
00136 struct DoIsTypeA {
00137 typedef typename DoBaseType<T>::type BT;
00138 typedef typename VBaseSelect<BT>::type VBST;
00139 enum { v=DoIsTypeAImpl<VBST,U>::v };
00140
00141 };
00142
00143
00144
00145
00146 template <class T>
00147 struct DoIsConst {
00148 enum { v=0 };
00149 };
00150
00151 template <class T>
00152 struct DoIsConst<const T> {
00153 enum { v=1 };
00154 };
00155
00156 template <class T>
00157 struct DoIsConst<const T&> {
00158 enum { v=1 };
00159 };
00160
00161 template <class T>
00162 struct DoIsConst<const T*> {
00163 enum { v=1 };
00164 };
00165
00166
00168
00169 template <class T>
00170 struct DoIsRef {
00171 enum { v=0 };
00172 };
00173
00174 template <class T>
00175 struct DoIsRef<T&> {
00176 enum { v=1 };
00177 };
00178
00179
00181
00182 template <class T>
00183 struct DoIsPointer {
00184 enum { v=0 };
00185 };
00186
00187 template <class T>
00188 struct DoIsPointer<T*> {
00189 enum { v=1 };
00190 };
00191
00192
00193
00194 template <class T, class U, bool is_t>
00195 struct DoCasterSelect;
00196
00197
00198 template<class T, class U>
00199 struct DoCasterSelect<T,U,true> {
00200 static U* Cast(T* pt,DynObjType *pdt){ return pt; }
00201 };
00202
00203
00204 template<class T, class U>
00205 struct DoCasterSelect<T,U,false> {
00206 static U* Cast(T* pt, DynObjType *pdt){
00207 return (U*)::doGetObj(pt,doTypeInfo<U>::Id(),pdt);
00208 }
00209 };
00210
00211
00212
00213 template<class U, int M, int N>
00214 struct DoCaster;
00215
00216 template<class U, int N>
00217 struct DoCaster<U,0,N> {
00218 static U Cast( const void *pv, doCastAlgo algo ){
00219 if( !pv ) return 0;
00220 return reinterpret_cast<U>(::doGetObj((void*)pv,doTypeInfo<U>::Id(),NULL,algo));
00221 }
00222 };
00223
00224 template<class U, int N>
00225 struct DoCaster<U,1,N> {
00226 static U Cast( const DynI *pdi, doCastAlgo algo ) {
00227 if( !pdi ) return 0;
00228 return reinterpret_cast<U>(::doGetObj((void*)pdi,doTypeInfo<U>::Id(),DI_GET_TYPE(pdi),algo));
00229 }
00230 };
00231
00232 #if DO_USE_DYNSHARED==1
00233 template<class U, int N>
00234 struct DoCaster<U,N,1> {
00235 static U Cast( const RTDynShared *prtds, doCastAlgo algo ) {
00236 if( !prtds ) return 0;
00237
00238 if( IsSameType<U,DynSharedI>::v ||
00239 IsSameType<U,DynI>::v ||
00240 IsSameType<U,VObj>::v ) return prtds;
00241 else
00242 return DoCaster<U,2,0>::Cast( prtds, algo );
00243 }
00244 };
00245 #else // DO_USE_DYNSHARED
00246
00247 struct RTDynShared { };
00248 #endif
00249
00250
00251
00252 template<class U, int M, int N>
00253 struct DoCasterStr;
00254
00255 template<class U, int N>
00256 struct DoCasterStr<U,0,N> {
00257 static U Cast( const void *pv, doCastAlgo algo ){
00258 if( !pv ) return 0;
00259 return reinterpret_cast<U>(::doGetObj((void*)pv,doTypeInfo<U>::Name(),NULL,algo));
00260 }
00261 };
00262
00263 template<class U, int N>
00264 struct DoCasterStr<U,1,N> {
00265 static U Cast( const DynI *pdi, doCastAlgo algo ) {
00266 if( !pdi ) return 0;
00267 return reinterpret_cast<U>(::doGetObj((void*)pdi,doTypeInfo<U>::Name(),DI_GET_TYPE(pdi),algo));
00268 }
00269 };
00270
00271 #if DO_USE_DYNSHARED==1
00272 template<class U, int N>
00273 struct DoCasterStr<U,N,1> {
00274 static U Cast( const RTDynShared *prtds, doCastAlgo algo ) {
00275 if( !prtds ) return 0;
00276
00277 if( IsSameType<U,DynSharedI>::v ||
00278 IsSameType<U,DynI>::v ||
00279 IsSameType<U,VObj>::v ) return prtds;
00280 else
00281 return DoCasterStr<U,2,0>::Cast( prtds, algo );
00282 }
00283 };
00284 #endif
00285
00286
00288
00289
00298 template<class U, class T>
00299 U do_cast( T* pt, doCastAlgo algo=doCastFull ) {
00300
00301
00302
00303
00304 DO_ASSERT( DoIsConst<U>::v || !DoIsConst<T>::v );
00305 DO_ASSERT( IsVObj<T>::v );
00306 return DoCaster< U, DoIsTypeA<T,DynI>::v,
00307 DoIsTypeA<T,RTDynShared>::v >
00308 ::Cast((typename VBaseSelect<T>::type*)pt,algo);
00309 }
00310
00319 template<class U, class T>
00320 U do_cast_ref( T& t, doCastAlgo algo=doCastFull ) {
00321
00322 DO_ASSERT( (int)DoIsConst<U>::v >= (int)DoIsConst<T>::v );
00323 DO_ASSERT( IsVObj<T>::v );
00324
00325 return *DoCaster< typename DoBaseType<U>::type*,
00326 DoIsTypeA<T,DynI>::v,
00327 DoIsTypeA<T,RTDynShared>::v >
00328 ::Cast((typename VBaseSelect<T>::type*)&t,algo);
00329 }
00330
00331
00332
00338 template<class U, class T>
00339 U do_cast_str( T* pt, doCastAlgo algo=doCastFull ) {
00340
00341 DO_ASSERT( DoIsConst<U>::v || !DoIsConst<T>::v );
00342 DO_ASSERT( IsVObj<T>::v );
00343 return DoCasterStr< U, DoIsTypeA<T,DynI>::v,
00344 DoIsTypeA<T,RTDynShared>::v >
00345 ::Cast((typename VBaseSelect<T>::type*)pt,algo);
00346 }
00347
00352 template<class U, class T>
00353 U do_cast_ref_str( T& t, doCastAlgo algo=doCastFull ) {
00354
00355 DO_ASSERT( (int)DoIsConst<U>::v >= (int)DoIsConst<T>::v );
00356 DO_ASSERT( IsVObj<T>::v );
00357 return *DoCasterStr< typename DoBaseType<U>::type*,
00358 DoIsTypeA<T,DynI>::v,
00359 DoIsTypeA<T,RTDynShared>::v >
00360 ::Cast((typename VBaseSelect<T>::type*)&t,algo);
00361 }
00362
00363
00364
00371 template<class T>
00372 VObj *to_vobj( T t ) {
00373 DO_ASSERT( IsVObj<T>::v );
00374 return reinterpret_cast<VObj*>(t);
00375 }
00376
00377 template<class T>
00378 VObj &to_vobj( T& t ) {
00379 DO_ASSERT( IsVObj<T>::v );
00380 return reinterpret_cast<VObj&>(t);
00381 }
00382
00383
00384 template<class T>
00385 struct doTypeWrapper{ };
00386
00387
00388
00390
00391
00392 #include <string.h>
00393 #include <assert.h>
00394
00395 #include "DoTypeBase.hpp"
00396
00397 #define DYNDATA_MAX_SIZE sizeof(double)
00398
00404
00405 class DynData : public DynI {
00406 public:
00407 DynObjType* docall doGetType( const DynI **pself ) const;
00408
00409 DynData( ) : m_type(0) { }
00410
00413
00415 template<class T>
00416 DynData( T t ) {
00417
00418 DO_ASSERT( sizeof(T) <= DYNDATA_MAX_SIZE );
00419
00420 m_type = DoFullType2Int<T>::Id();
00421
00422
00423 memset( m_data, ((m_type&DOT_TYPE_MASK)==DOT_SINT)?-1:0, DYNDATA_MAX_SIZE );
00424
00425 #ifdef PFM_BIG_ENDIAN
00426
00427 *(T*)(m_data+DYNDATA_MAX_SIZE-sizeof(T)) = t;
00428 #else
00429
00430 *(T*)m_data = t;
00431 #endif
00432 }
00433
00437 int GetType(){ return m_type; }
00438
00443 template<class T>
00444 bool IsA() const {
00445 int type = DoFullType2Int<T>::Id();
00446 if( type==UNKNOWN_TYPE_ID ) return false;
00447
00448 if( type==m_type ||
00449 type==(m_type|DOT_CONST) )
00450 return true;
00451
00452
00453 if( DOT_PTR_REF_LEVEL(type)!=DOT_PTR_REF_LEVEL(m_type) ) return false;
00454
00455
00456 if( !(type&DOT_CONST) && (m_type&DOT_CONST) ) return false;
00457
00458
00459 if( !(type&DOT_PRIMITIVE) ){
00460
00461 if( m_type&DOT_PRIMITIVE ) return false;
00462
00463
00464 DynObjType *dot = doFindType(m_type&TYPE_ID_MASK);
00465 if( !dot ){
00466 VObj::SetError( "DynData::IsA - Failed looking up DynObjType", m_type );
00467 return false;
00468 }
00469
00470
00471 return dot->IsA( type&TYPE_ID_MASK, NULL );
00472 }
00473
00474
00475
00476 if( !(m_type&DOT_PRIMITIVE) ) {
00477
00478 if( !(m_type&(DOT_PTR_MASK|DOT_REF)) ) return false;
00479 return type==DoType2Int<const void*>::v ||
00480 type==DoType2Int<bool>::v;
00481 }
00482
00483
00484
00485
00486 if( (type&DOT_TYPE_MASK)==(m_type&DOT_TYPE_MASK) ){
00487
00488 if( (type&DOT_SIZE_MASK)>=(m_type&DOT_TYPE_MASK) )
00489 return true;
00490
00491
00492
00493
00494 }
00495
00496 return false;
00497 }
00498
00504 template<class T>
00505 T Get() const {
00506 bool b = IsA<T>();
00507 assert( b );
00508
00509
00510 DO_ASSERT( DoIsConst<T>::v ||
00511 !(DoIsRef<T>::v && !DoIsPointer<T>::v) );
00512
00513 #ifdef PFM_BIG_ENDIAN
00514
00515 return *reinterpret_cast<const T*>(m_data+DYNDATA_MAX_SIZE-sizeof(T));
00516 #else
00517
00518 return *reinterpret_cast<const T*>(m_data);
00519 #endif
00520 }
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 protected:
00551 int m_type;
00552 union {
00553 char m_data[DYNDATA_MAX_SIZE];
00554 const char* m_str;
00555 };
00556 };
00557
00558
00565 template<class T>
00566 struct doKeepRef {
00567 doKeepRef( T& t ) : m_t(t) { }
00568 operator T& (){ return m_t; }
00569 T& m_t;
00570 };
00571
00572
00579 template<class I>
00580 void do_try( DynI *pdi, void (docall I::*func)() ){
00581 I *pi = do_cast<I*>(pdi);
00582 if( pi ) (pi->*func)();
00583 }
00586 template<class I, class RV>
00587 RV do_try( DynI *pdi, RV (docall I::*func)(), RV rv=0 ){
00588 I *pi = do_cast<I*>(pdi);
00589 if( !pi ) return rv;
00590 return (pi->*func)();
00591 }
00592
00595 template<class I, class A1, class _A1>
00596 void do_try( DynI *pdi, void (docall I::*func)(A1), _A1 a1 ){
00597 I *pi = do_cast<I*>(pdi);
00598 if( pi ) (pi->*func)(a1);
00599 }
00602 template<class I, class RV, class A1, class _A1>
00603 RV do_try( DynI *pdi, RV (docall I::*func)(A1), _A1 a1, RV rv=0 ){
00604 I *pi = do_cast<I*>(pdi);
00605 if( !pi ) return rv;
00606 return (pi->*func)(a1);
00607 }
00608
00611 template<class I, class A1, class A2,
00612 class _A1, class _A2>
00613 void do_try( DynI *pdi, void (docall I::*func)(A1,A2), _A1 a1, _A2 a2 ){
00614 I *pi = do_cast<I*>(pdi);
00615 if( pi ) (pi->*func)(a1,a2);
00616 }
00619 template<class I, class RV, class A1, class A2,
00620 class _A1, class _A2>
00621 RV do_try( DynI *pdi, RV (docall I::*func)(A1,A2), _A1 a1, _A2 a2, RV rv=0 ){
00622 I *pi = do_cast<I*>(pdi);
00623 if( !pi ) return rv;
00624 return (pi->*func)(a1,a2);
00625 }
00626
00627 template<class I, class A1, class A2, class A3,
00628 class _A1, class _A2, class _A3>
00629 void do_try( DynI *pdi, void (docall I::*func)(A1,A2,A3), _A1 a1, _A2 a2, _A3 a3 ){
00630 I *pi = do_cast<I*>(pdi);
00631 if( pi ) (pi->*func)(a1,a2,a3);
00632 }
00633
00634 template<class I, class RV, class A1, class A2, class A3,
00635 class _A1, class _A2, class _A3>
00636 RV do_try( DynI *pdi, RV (docall I::*func)(A1,A2,A3), _A1 a1, _A2 a2, _A3 a3, RV rv=0 ){
00637 I *pi = do_cast<I*>(pdi);
00638 if( !pi ) return rv;
00639 return (pi->*func)(a1,a2,a3);
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 #define doConstrGlob doConstructGlobal
00652
00656 template<class T>
00657 struct doConstructGlobal {
00659 doConstructGlobal( )
00660 : m_t() {
00661 Construct();
00662 }
00664 template<class A>
00665 doConstructGlobal( A arg )
00666 : m_t(arg) {
00667 Construct();
00668 }
00669
00670
00671 T& operator -> (){ return m_t; }
00672
00673 operator T&(){ return m_t; }
00674
00675 operator T*(){ return &m_t; }
00676
00677 protected:
00678 bool Construct( ){
00679 bool rv = true;
00680 DynI *pdi = NULL;
00681 DynObjType *pdt = m_t.doGetType((const DynI**)&pdi);
00682 DO_ASSERT_MSG(&m_t==reinterpret_cast<T*>(pdi),"Should be outermost type");
00683
00684
00685 if( !pdt )
00686 rv = false;
00687 else {
00688
00689
00690
00691 if( !pdt->_sh.IsOk() )
00692 rv = ::doConstructDelayed( &m_t, pdt );
00693 else {
00694 rv = ::doConstruct( &m_t, pdt, NULL );
00695
00696
00697 if( !rv )
00698 rv = ::doConstructDelayed( &m_t, pdt );
00699 }
00700 }
00701 return rv;
00702 }
00703
00704 T m_t;
00705 };
00706
00707
00708 #define doConstrLoc doConstructLocal
00709
00713 template<class T>
00714 struct doConstructLocal {
00716 doConstructLocal( ){
00717 m_pt = new T();
00718 Construct();
00719 }
00721 template<class A>
00722 doConstructLocal( A arg ){
00723 m_pt = new T(arg);
00724 Construct();
00725 }
00726
00727 ~doConstructLocal(){
00728 delete m_pt;
00729 }
00730
00731
00732 T* Release(){
00733 T* pt = m_pt;
00734 m_pt = NULL;
00735 return pt;
00736 }
00737
00738
00739 T& operator -> (){ return *m_pt; }
00740
00741 operator T&(){ return *m_pt; }
00742
00743 operator T*(){ return m_pt; }
00744
00745 protected:
00746 bool Construct( ){
00747 if( !m_pt ) return false;
00748 bool rv = true;
00749 DynI *pdi = NULL;
00750 DynObjType *pdt = m_pt->doGetType((const DynI**)&pdi);
00751 if( !pdt )
00752 rv=false;
00753 if( m_pt!=reinterpret_cast<T*>(pdi) )
00754 rv=false;
00755
00756
00757 void **vtbl = *(void***)m_pt;
00758 if( vtbl!=st_vtbl_last ){
00759 st_vtbl_last = vtbl;
00760 rv &= ::doConstruct( m_pt, pdt, NULL );
00761 }
00762 return rv;
00763 }
00764
00765 T *m_pt;
00766 static void** st_vtbl_last;
00767 };
00768
00769 template<class T>
00770 void** doConstructLocal<T>::st_vtbl_last;
00771
00772
00773
00774
00775 #ifdef DO_IMPLEMENT_DOBASE
00776 #define DO_IMPLEMENTING // If app has not defined it already
00777 #endif
00778 #include "dynobj/DynObj.h"
00779
00780
00781 class DynData;
00782
00783
00784 DO_DECL_TYPE_INFO(DynData,DYNDATA_TYPE_ID);
00785
00786
00787
00788
00789
00790
00791
00792 #ifdef DO_IMPLEMENT_DOBASE
00793
00794
00795 DynObjTypeI2R<DynData,DynI,false> g_do_vtype_DynData("DynData:DynI",DYNDATA_TYPE_ID,1);
00796 DynObjType* DynData::doGetType( const DynI **pself ) const {
00797 if(pself) *pself=(const DynI*)(const void*)this;
00798 return &g_do_vtype_DynData;
00799 }
00800 #endif //DO_IMPLEMENT_...
00801
00802
00803 #endif //DOBASE_HPP
00804
00805