Added GPLv3 headers all over the place.
[fail.git] / src / services / lua / structboxing.h
blobc5da40c560397f90d36ec8b27fc939d7c8519263
1 /*
2 Fail game engine
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_ ) :
27 pOwner( pOwner_ ),
28 pStruct( pStruct_ )
32 GenericPointer pOwner;
33 S* pStruct;
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 >();
44 return 0;
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 );
54 pObj->~C();
55 return 0;
59 template< class C, e_CheckingPolicy Checking >
60 struct TypeConverter< StructType, C*, Checking >
62 TypeConverter( lua_State* pLS_ ) :
63 m_pLS( pLS_ ),
64 m_bByRef( true )
68 bool CheckType( int Index_ )
70 if( lua_type( m_pLS, Index_ ) != LUA_TUSERDATA )
72 // TODO: better error reporting
73 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
74 return false;
77 if( !lua_getmetatable( m_pLS, Index_ ) )
79 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
80 return false;
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 );
88 if( bRes )
90 lua_pop( m_pLS, 2 );
91 return true;
94 lua_pop( m_pLS, 1 );
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 );
101 lua_pop( m_pLS, 2 );
102 if( bRes )
104 m_bByRef = false;
105 return true;
108 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
109 return false;
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
117 pDest_ = 0;
119 if( !CheckType( Index_ ) )
120 return false;
122 if( m_bByRef )
124 StructRefWrapper< C >* pWrapper =
125 static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
126 pDest_ = pWrapper->pStruct;
128 else
129 pDest_ = static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
131 return true;
134 lua_State* m_pLS;
135 bool m_bByRef;
138 template< class C >
139 struct TypeConverter< StructType, C*, cp_NoCheck >
141 TypeConverter( lua_State* pLS_ ) :
142 m_pLS( pLS_ ),
143 m_bByRef( true )
147 bool CheckType( int Index_ )
149 return true;
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 );
161 lua_pop( m_pLS, 2 );
163 if( m_bByRef )
165 m_pWrapper = static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
166 pDest_ = m_pWrapper->pStruct;
168 else
169 pDest_ = static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
171 return true;
174 lua_State* m_pLS;
175 bool m_bByRef;
176 StructRefWrapper< C >* m_pWrapper;
179 template< class C, e_CheckingPolicy Checking >
180 struct TypeConverter< StructType, C, Checking >
182 TypeConverter( lua_State* pLS_ ) :
183 m_pLS( pLS_ ),
184 m_bByRef( true )
188 bool CheckType( int Index_ )
190 if( lua_type( m_pLS, Index_ ) != LUA_TUSERDATA )
192 // TODO: better error reporting
193 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
194 return false;
197 if( !lua_getmetatable( m_pLS, Index_ ) )
199 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
200 return false;
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 );
208 if( bRes )
210 lua_pop( m_pLS, 2 );
211 return true;
214 lua_pop( m_pLS, 1 );
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 );
221 lua_pop( m_pLS, 2 );
222 if( bRes )
224 m_bByRef = false;
225 return true;
228 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
229 return false;
232 bool ConvertFromLua( int Index_, C& Dest_ )
234 if( !CheckType( Index_ ) )
235 return false;
237 if( m_bByRef )
239 StructRefWrapper< C >* pWrapper =
240 static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
241 Dest_ = *pWrapper->pStruct;
243 else
244 Dest_ = *static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
246 return true;
249 void ConvertToLua( const C& Obj_ ) const
251 void* pData = lua_newuserdata( m_pLS, sizeof( C ) );
252 if( !pData )
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 > ) );
266 if( !pData )
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 );
277 lua_State* m_pLS;
278 bool m_bByRef;
281 template< class C >
282 struct TypeConverter< StructType, C, cp_NoCheck >
284 TypeConverter( lua_State* pLS_ ) :
285 m_pLS( pLS_ )
289 bool CheckType( int Index_ )
291 return true;
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 );
303 lua_pop( m_pLS, 2 );
305 if( bRes )
307 StructRefWrapper< C >* pWrapper =
308 static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
309 Dest_ = *pWrapper->pStruct;
311 else
312 Dest_ = *static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
314 return true;
317 lua_State* m_pLS;
321 #endif