3 Copyright 2007 Antoine Chavasse <a.chavasse@gmail.com>
5 This file is part of Fail.
7 Fail is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 3
9 as published by the Free Software Foundation.
11 Fail is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef FAIL_LUA_STRUCTBOXING_H
20 #define FAIL_LUA_STRUCTBOXING_H
22 namespace fail
{ namespace LuaImpl
24 template< class S
> struct StructRefWrapper
26 StructRefWrapper( const GenericPointer
& pOwner_
, S
* pStruct_
) :
32 GenericPointer pOwner
;
36 template< class C
> struct StructRefFinalizer
38 static int Finalize( lua_State
* pLS
)
40 void* pData
= lua_touserdata( pLS
, 1 );
41 StructRefWrapper
< C
>* pWrapper
=
42 static_cast< StructRefWrapper
< C
>* >( pData
);
43 pWrapper
->~StructRefWrapper
< C
>();
48 template< class C
> struct StructValFinalizer
50 static int Finalize( lua_State
* pLS
)
52 void* pData
= lua_touserdata( pLS
, 1 );
53 C
* pObj
= static_cast< C
* >( pData
);
59 template< class C
, e_CheckingPolicy Checking
>
60 struct TypeConverter
< StructType
, C
*, Checking
>
62 TypeConverter( lua_State
* pLS_
) :
68 bool CheckType( int Index_
)
70 if( lua_type( m_pLS
, Index_
) != LUA_TUSERDATA
)
72 // TODO: better error reporting
73 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
77 if( !lua_getmetatable( m_pLS
, Index_
) )
79 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
83 // Check if it's a struct wrapped by reference
84 lua_pushlightuserdata( m_pLS
, &type_tag
< C
* >::dummy
);
85 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
87 bool bRes
= lua_rawequal( m_pLS
, -1, -2 );
96 // Check if it's a struct wrapped by value
97 lua_pushlightuserdata( m_pLS
, &type_tag
< C
& >::dummy
);
98 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
100 bRes
= lua_rawequal( m_pLS
, -1, -2 );
108 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
112 bool ConvertFromLua( int Index_
, C
*& pDest_
)
114 // Workaround for a warning occuring because the compiler apparently
115 // fails to detect that when using a typeconverter with cp_Throw,
116 // any code path not setting Dest_ throws
119 if( !CheckType( Index_
) )
124 StructRefWrapper
< C
>* pWrapper
=
125 static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
126 pDest_
= pWrapper
->pStruct
;
129 pDest_
= static_cast< C
* >( lua_touserdata( m_pLS
, Index_
) );
139 struct TypeConverter
< StructType
, C
*, cp_NoCheck
>
141 TypeConverter( lua_State
* pLS_
) :
147 bool CheckType( int Index_
)
152 bool ConvertFromLua( int Index_
, C
*& pDest_
)
154 lua_getmetatable( m_pLS
, Index_
);
156 // Check if it's a struct wrapped by reference
157 lua_pushlightuserdata( m_pLS
, &type_tag
< C
* >::dummy
);
158 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
160 m_bByRef
= lua_rawequal( m_pLS
, -1, -2 );
165 m_pWrapper
= static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
166 pDest_
= m_pWrapper
->pStruct
;
169 pDest_
= static_cast< C
* >( lua_touserdata( m_pLS
, Index_
) );
176 StructRefWrapper
< C
>* m_pWrapper
;
179 template< class C
, e_CheckingPolicy Checking
>
180 struct TypeConverter
< StructType
, C
, Checking
>
182 TypeConverter( lua_State
* pLS_
) :
188 bool CheckType( int Index_
)
190 if( lua_type( m_pLS
, Index_
) != LUA_TUSERDATA
)
192 // TODO: better error reporting
193 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
197 if( !lua_getmetatable( m_pLS
, Index_
) )
199 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
203 // Check if it's a struct wrapped by reference
204 lua_pushlightuserdata( m_pLS
, &type_tag
< C
* >::dummy
);
205 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
207 bool bRes
= lua_rawequal( m_pLS
, -1, -2 );
216 // Check if it's a struct wrapped by value
217 lua_pushlightuserdata( m_pLS
, &type_tag
< C
& >::dummy
);
218 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
220 bRes
= lua_rawequal( m_pLS
, -1, -2 );
228 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
232 bool ConvertFromLua( int Index_
, C
& Dest_
)
234 if( !CheckType( Index_
) )
239 StructRefWrapper
< C
>* pWrapper
=
240 static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
241 Dest_
= *pWrapper
->pStruct
;
244 Dest_
= *static_cast< C
* >( lua_touserdata( m_pLS
, Index_
) );
249 void ConvertToLua( const C
& Obj_
) const
251 void* pData
= lua_newuserdata( m_pLS
, sizeof( C
) );
253 throw std::bad_alloc();
255 new( pData
) C( Obj_
);
257 lua_pushlightuserdata( m_pLS
, &type_tag
< C
& >::dummy
);
258 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
260 lua_setmetatable( m_pLS
, -2 );
263 void ConvertToLuaByRef( GenericPointer pOwner_
, C
& Obj_
) const
265 void* pData
= lua_newuserdata( m_pLS
, sizeof( StructRefWrapper
< C
> ) );
267 throw std::bad_alloc();
269 new( pData
) StructRefWrapper
< C
>( pOwner_
, &Obj_
);
271 lua_pushlightuserdata( m_pLS
, &type_tag
< C
* >::dummy
);
272 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
274 lua_setmetatable( m_pLS
, -2 );
282 struct TypeConverter
< StructType
, C
, cp_NoCheck
>
284 TypeConverter( lua_State
* pLS_
) :
289 bool CheckType( int Index_
)
294 bool ConvertFromLua( int Index_
, C
& Dest_
)
296 lua_getmetatable( m_pLS
, Index_
);
298 // Check if it's a struct wrapped by reference
299 lua_pushlightuserdata( m_pLS
, &type_tag
< C
* >::dummy
);
300 lua_gettable( m_pLS
, LUA_REGISTRYINDEX
);
302 bool bRes
= lua_rawequal( m_pLS
, -1, -2 );
307 StructRefWrapper
< C
>* pWrapper
=
308 static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
309 Dest_
= *pWrapper
->pStruct
;
312 Dest_
= *static_cast< C
* >( lua_touserdata( m_pLS
, Index_
) );