00001
00006 #include <iostream>
00007
00008 #include <wibble/mixin.h>
00009 #include <wibble/cast.h>
00010 #include <wibble/maybe.h>
00011 #include <wibble/sfinae.h>
00012 #include <wibble/test.h>
00013
00014 #ifndef WIBBLE_AMORPH_H
00015 #define WIBBLE_AMORPH_H
00016
00017 namespace wibble {
00018
00019 template< typename _T >
00020 struct ReturnType {
00021 typedef _T T;
00022 };
00023
00024 template<>
00025 struct ReturnType< void > {
00026 typedef Unit T;
00027 };
00028
00029 template< typename F, typename R >
00030 struct SanitizeReturn {
00031 inline typename ReturnType< R >::T call(
00032 typename F::argument_type a )
00033 {
00034 return f( a );
00035 };
00036 };
00037
00038
00039 template< typename F >
00040 struct SanitizeReturn< F, void > {
00041 inline Unit call( typename F::argument_type a )
00042 {
00043 f( a );
00044 return Unit();
00045 }
00046 };
00047
00048 template< int A >
00049 struct IsZero {
00050 static const bool value = false;
00051 };
00052
00053 template<>
00054 struct IsZero< 0 > {
00055 static const bool value = true;
00056 };
00057
00058 template< typename T >
00059 struct IsPolymorphic {
00060 struct A : T {
00061 virtual ~A();
00062 };
00063 struct B : T {};
00064 static const bool value = IsZero< sizeof( A ) - sizeof( B ) >::value;
00065 };
00066
00067 template< typename F >
00068 struct SanitizeResultType {
00069 SanitizeResultType( F _f ) : f( _f ) {}
00070 typedef typename ReturnType< typename F::result_type >::T result_type;
00071
00072 result_type operator()( typename F::argument_type a ) {
00073 return SanitizeReturn< F, typename F::result_type >().call( a );
00074 }
00075
00076
00077 F f;
00078 };
00079
00080 #ifndef SWIG_I
00081 struct Baseless {};
00082
00083 struct VirtualBase {
00084 virtual ~VirtualBase() {}
00085 };
00086
00090 template< typename Interface >
00091 struct MorphInterface : public Interface {
00092 virtual VirtualBase *virtualBase() { return 0; }
00093 virtual MorphInterface *constructCopy( void *where = 0, unsigned int available = 0 ) const = 0;
00094 virtual void destroy( unsigned int available = 0 ) = 0;
00095 virtual ~MorphInterface() {}
00096 virtual bool leq( const MorphInterface * ) const = 0;
00097 };
00098
00100 struct MorphAllocator {
00101 void *operator new( size_t bytes, void *where, unsigned available ) {
00102 if ( bytes > available || where == 0 ) {
00103 where = ::operator new( bytes );
00104 return where;
00105 }
00106 return where;
00107 }
00108 void *operator new( size_t bytes ) {
00109 return ::operator new( bytes );
00110 }
00111 };
00112
00113 template< typename W, typename Interface >
00114 struct MorphBase : MorphInterface< Interface > {
00115 MorphBase( const W &w ) : m_wrapped( w ) {}
00116
00117 template< typename _W >
00118 typename EnableIf< IsPolymorphic< _W >, VirtualBase *>::T virtualBase() {
00119 return dynamic_cast< VirtualBase * >( &m_wrapped );
00120 }
00121
00122 template< typename _W >
00123 typename EnableIf< TNot< IsPolymorphic< _W > >, VirtualBase *>::T
00124 virtualBase() {
00125 return 0;
00126 }
00127
00128 virtual VirtualBase *virtualBase() {
00129 return virtualBase< W >();
00130 }
00131
00132 W &wrapped() {
00133 return m_wrapped;
00134 }
00135
00136 protected:
00137 W m_wrapped;
00138 };
00139
00140 template< typename Self, typename W, typename Interface >
00141 struct Morph : MorphBase< W, Interface >,
00142 mixin::Comparable< Morph< Self, W, Interface > >,
00143 MorphAllocator
00144 {
00145 typedef W Wrapped;
00146
00147 Morph( const Wrapped &w ) : MorphBase< W, Interface >( w ) {}
00148
00149 const Self &self() const { return *static_cast< const Self * >( this ); }
00150
00151 bool operator<=( const Morph &o ) const {
00152 return wrapped().operator<=( o.wrapped() );
00153 }
00154
00155
00156 virtual bool leq( const MorphInterface< Interface > *_o ) const {
00157 const Morph *o = dynamic_cast< const Morph * >( _o );
00158 if ( !o ) {
00159 if ( typeid( Morph ).before( typeid( _o ) ) )
00160 return true;
00161 else
00162 return false;
00163 }
00164 return wrapped() <= o->wrapped();
00165 }
00166
00167 virtual MorphInterface< Interface > *constructCopy(
00168 void *where, unsigned int available ) const
00169 {
00170 return new( where, available ) Self( self() );
00171 }
00172
00173 virtual void destroy( unsigned int available ) {
00174 if ( sizeof( Morph ) <= available ) {
00175 this->~Morph();
00176 } else {
00177 delete this;
00178 }
00179 }
00180
00181 const Wrapped &wrapped() const {
00182 return this->m_wrapped;
00183 }
00184
00185 Wrapped &wrapped() {
00186 return this->m_wrapped;
00187 }
00188
00189 virtual ~Morph() {}
00190 };
00191 #endif
00192
00260 #ifndef WIBBLE_AMORPH_PADDING
00261 #define WIBBLE_AMORPH_PADDING 0
00262 #endif
00263 template< typename Self, typename _Interface, int Padding = WIBBLE_AMORPH_PADDING >
00264 struct Amorph {
00265 typedef _Interface Interface;
00266
00267
00268 template <typename T> struct Convert {
00269 typedef T type;
00270 };
00271
00272
00273
00274
00275
00276 Amorph( const MorphInterface< Interface > &b ) {
00277 setMorphInterfacePointer( &b );
00278 }
00279
00280 Amorph( const Amorph &a ) {
00281 setMorphInterfacePointer( a.morphInterface() );
00282
00283 }
00284
00285 Amorph() : m_impl( 0 ) {}
00286
00287 const Self &self() const {
00288 return *static_cast< const Self * >( this );
00289 }
00290
00291 Self &self() {
00292 return *static_cast<Self *>( this );
00293 }
00294
00295 bool leq( const Self &i ) const {
00296 if ( morphInterface() )
00297 if ( i.morphInterface() )
00298 return morphInterface()->leq( i.morphInterface() );
00299 else
00300 return false;
00301 else
00302 return !i.morphInterface();
00303
00304 }
00305
00306 bool operator<=( const Self &i ) const { return leq( i ); }
00307
00308 void setInterfacePointer( const Interface *i ) {
00309 if ( !i ) {
00310 m_impl = 0;
00311 return;
00312 }
00313
00314
00315
00316
00317
00318 m_impl = dynamic_cast< const MorphInterface< Interface > * >( i )->constructCopy(
00319 &m_padding, sizeof( m_padding ) );
00320
00321
00322 }
00323
00324 void setMorphInterfacePointer( const MorphInterface< Interface > *i ) {
00325 if ( !i ) {
00326 m_impl = 0;
00327 return;
00328 }
00329 m_impl = i->constructCopy( &m_padding, sizeof( m_padding ) );
00330 }
00331
00332 Amorph &operator=( const Amorph &i ) {
00333 setInterfacePointer( i.implementation() );
00334 return *this;
00335 }
00336
00337 ~Amorph() {
00338 if ( morphInterface() )
00339 morphInterface()->destroy( sizeof( m_padding ) );
00340 }
00341
00342 template< typename F >
00343 Maybe< typename F::result_type > ifType( F func ) {
00344 typedef typename F::argument_type T;
00345 typedef Maybe< typename F::result_type > rt;
00346 T *ptr = impl<T>();
00347 if (ptr) {
00348 return rt::Just( func(*ptr) );
00349 }
00350 return rt::Nothing();
00351 }
00352
00353 const Interface *implementation() const {
00354
00355 return static_cast< const Interface * >( m_impl );
00356 }
00357
00358 Interface *implementation() {
00359
00360 return static_cast< Interface * >( m_impl );
00361 }
00362
00363 MorphInterface< Interface > *morphInterface() const {
00364 return m_impl;
00365
00366 }
00367
00368 const Interface &wrapped() const {
00369 return *implementation();
00370 }
00371
00372 Interface &wrapped() {
00373 return *implementation();
00374 }
00375
00376 template< typename T >
00377 bool is() const {
00378 return impl< T >();
00379 }
00380
00381 bool isVoid() const { return !m_impl; }
00382
00383 template< typename T >
00384 T *impl() const {
00385 T *p = dynamic_cast< T * >( m_impl );
00386 if ( !p ) {
00387 MorphBase< T, Interface > *m = dynamic_cast< MorphBase< T, Interface > * >( m_impl );
00388 if ( m ) p = &(m->wrapped());
00389 }
00390 if ( !p ) {
00391 p = dynamic_cast< T * >( morphInterface()->virtualBase() );
00392 }
00393 return p;
00394 }
00395
00396 private:
00397 unsigned int reservedSize() { return sizeof( m_padding ) + sizeof( m_impl ); }
00398 int m_padding[ Padding ];
00399 MorphInterface< Interface > *m_impl;
00400
00401 };
00402
00403 #ifndef SWIG_I
00404 template< typename T, typename X >
00405 typename X::template Convert<T>::type &downcast( const X &a )
00406 {
00407 return *a.template impl< T >();
00408 }
00409
00410 #endif
00411
00412 }
00413
00414 #endif