Lua: Implemented GenericPointer wrapping.
[fail.git] / lua / genericpointer.h
blob18ec465d1918477b25e796dc990f074f249574e8
1 #ifndef AWFUL_LUA_GENERICPOINTER_H
2 #define AWFUL_LUA_GENERICPOINTER_H
4 namespace awful { namespace LuaImpl
6 template<> struct TypeConverter< NormalType, GenericPointer >
8 class PointerConverter_i : public RefCounted
10 public:
11 virtual ~PointerConverter_i() {}
12 virtual void ConvertFromLua_nocheck( lua_State* pLS, int Index_, GenericPointer& Dest_ ) = 0;
13 virtual void ConvertToLua( lua_State* pLS, const GenericPointer& Dest_ ) = 0;
16 template< class C > class PointerConverter : public PointerConverter_i
18 public:
19 virtual void ConvertFromLua_nocheck( lua_State* pLS, int Index_, GenericPointer& Dest_ )
21 TypeConverter< NormalType, Pointer< C > > tc( pLS );
22 Pointer< C > pObj;
23 tc.ConvertFromLua_nocheck( Index_, pObj );
24 Dest_ = pObj;
27 virtual void ConvertToLua( lua_State* pLS, const GenericPointer& pObj_ )
29 TypeConverter< NormalType, Pointer< C > > tc( pLS );
30 Pointer< C > pObj = static_cast< C* >( pObj_ );
31 tc.ConvertToLua( pObj );
35 typedef std::map< TypeInfoKey, Pointer< PointerConverter_i > > converter_map;
36 static converter_map PointerConverters;
38 template< class C > static void RegisterClass()
40 PointerConverters.insert( std::make_pair(
41 TypeInfoKey( typeid( C ) ),
42 new PointerConverter< C > ) );
45 TypeConverter( lua_State* pLS_ ) :
46 m_pLS( pLS_ )
50 bool CheckType_nothrow( int Index_ )
52 // TODO: this is not very robust because it assume that any user data we get thrown
53 // at are our own wrapped pointers, whereas it could be some completely alien stuff.
54 if( lua_isnil( m_pLS, Index_ ) )
55 return true;
57 if( lua_type( m_pLS, Index_ ) != LUA_TUSERDATA )
58 return false;
60 PointerWrapper< RefCounted >* pWrapper =
61 static_cast< PointerWrapper< RefCounted >* >( lua_touserdata( m_pLS, Index_ ) );
63 converter_map::const_iterator it = PointerConverters.find( *pWrapper->pTypeInfo );
64 return it != PointerConverters.end();
67 void ConvertFromLua( int Index_, GenericPointer& Dest_ )
69 if( !CheckType_nothrow( Index_ ) )
70 throw Error::TypeMismatch( lua_type( m_pLS, Index_ ), LUA_TUSERDATA );
72 ConvertFromLua_nocheck( Index_, Dest_ );
75 void ConvertFromLua_nocheck( int Index_, GenericPointer& Dest_ )
77 if( lua_isnil( m_pLS, Index_ ) )
79 Dest_.clear();
80 return;
83 PointerWrapper< RefCounted >* pWrapper =
84 static_cast< PointerWrapper< RefCounted >* >( lua_touserdata( m_pLS, Index_ ) );
86 // TODO: This could be cached from the possible prior call to CheckType_nothrow
87 // so as to avoid to look this up twice.
88 converter_map::const_iterator it = PointerConverters.find( *pWrapper->pTypeInfo );
89 it->second->ConvertFromLua_nocheck( m_pLS, Index_, Dest_ );
92 void ConvertToLua( const GenericPointer& Ptr_ )
94 if( !Ptr_ )
95 lua_pushnil( m_pLS );
96 else
98 converter_map::const_iterator it = PointerConverters.find( *Ptr_.getDynamicType() );
100 // TODO: what if the GenericPointer somehow points to a type that is not registered
101 // in converter_map? We should throw a specific diagnostic message.
102 it->second->ConvertToLua( m_pLS, Ptr_ );
106 lua_State* m_pLS;
110 #endif