#include "MethodMap.hpp"
#include "Debug.hpp"
#include "LinkManager.hpp"
template< class X, class Y > MethodMap< X, Y >::MethodMap( Y *( X::*aMethod )() ) :
type( direct ),
directMethod( aMethod )
{}
template< class X, class Y > MethodMap< X, Y >::MethodMap( Y *( X::*aMethod )( Top * ),
Top *anAdditionalArgument ) :
type( partial ),
partialMethod( aMethod )
{
addArg = anAdditionalArgument;
if( addArg != nil )
{
LinkManager::reg( this, addArg );
}
}
template< class X, class Y > MethodMap< X, Y >::~MethodMap()
{
if( addArg != nil )
{
LinkManager::free( this, addArg );
}
addArg = nil;
}
template< class X, class Y > Y *MethodMap< X, Y >::typedApply( X *anArgument )
{
switch( type )
{
case direct:
return ( anArgument ->* directMethod )();
case partial:
return ( anArgument ->* partialMethod )( addArg );
default:
impossible_;
return nil;
}
impossible_;
return nil;
}
template< class X, class Y > Top *MethodMap< X, Y >::apply( Top *anArgument )
{
Top *rawResult;
preC( DCAST( anArgument, X ) != nil,
"Agrument of invalid type" );
rawResult = typedApply( DCAST( anArgument, X ) );
postC( DCAST( rawResult, Y ) != nil,
"Result of invalid type" );
return dynamic_cast< Y * >( rawResult );
}
template< class X, class Y > boolean MethodMap< X, Y >::equals( const Top *anOther ) const
{
MethodMap< X, Y > *other;
if( DCAST( anOther, MethodMap< X commaForCpp Y > ) == null )
{
return false;
}
other = DCAST( anOther, MethodMap< X commaForCpp Y > );
if( other -> type != type )
{
return false;
}
switch( type )
{
case direct:
if( directMethod != other -> directMethod )
{
return false;
}
break;
case partial:
if( partialMethod != other -> partialMethod )
{
return false;
}
else
{
if( ! ( addArg -> equals( other -> addArg ) ) )
{
return false;
}
}
break;
default:
impossible_;
return false;
}
return true;
}
template< class X, class Y > Top *MethodMap< X, Y >::clone() const
{
switch( type )
{
case direct:
#if defined(__GNUC__)
Y *( X::*fakeDirect )();
fakeDirect = directMethod;
return new MethodMap( fakeDirect,
isCallerResponsibility(),
isResultDependOnArg() );
#else
return new MethodMap( directMethod,
isCallerResponsibility(),
isResultDependOnArg() );
#endif
case partial:
#if defined(__GNUC__)
Y *( X::*fakePartial )( Top * );
fakePartial = partialMethod;
return new MethodMap( fakePartial,
addArg, false,
isCallerResponsibility(),
isResultDependOnArg() );
#else
return new MethodMap( ( Y *( X::* )( Top * ) ) partialMethod,
addArg, false,
isCallerResponsibility(),
isResultDependOnArg() );
#endif
default:
impossible_;
}
impossible_;
return nil;
}
template< class X, class Y > String MethodMap< X, Y >::getString() const
{
switch( type )
{
case direct:
return "direct method";
case partial:
return String( "partially evealuated with arg: " ) +
( ( addArg != null ) ? addArg -> getString() : String( "null" ) );
default:
impossible_;
}
impossible_;
return String();
}
template< class X, class Y > String MethodMap< X, Y >::getClassName() const
{
return "MethodMap";
}
#if defined(_INLINE)
#include "../src/Debug.ipp"
#endif