Fixed a few issues, everything now works again.
[fail.git] / src / services / lua / structboxing.h
blob21c5a144dad52c1ca0a4635f1fc44b31789cb4ca
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 shared_ptr< void >& pOwner_, S* pStruct_ ) :
27 pOwner( pOwner_ ),
28 pStruct( pStruct_ )
32 shared_ptr< void > pOwner;
33 S* pStruct;
36 template< class S > struct StructValWrapper
38 StructValWrapper( shared_ptr< S >& pStruct_ ) :
39 pStruct( pStruct_ )
43 shared_ptr< S > pStruct;
46 template< class C > struct StructMetamethods
48 static int FinalizeRef( lua_State* pLS )
50 void* pData = lua_touserdata( pLS, 1 );
51 StructRefWrapper< C >* pWrapper =
52 static_cast< StructRefWrapper< C >* >( pData );
53 pWrapper->~StructRefWrapper< C >();
54 return 0;
57 static int FinalizeVal( lua_State* pLS )
59 void* pData = lua_touserdata( pLS, 1 );
60 StructValWrapper< C >* pWrapper =
61 static_cast< StructValWrapper< C >* >( pData );
62 pWrapper->~StructValWrapper< C >();
63 return 0;
66 static int ToStringRef( lua_State* pLS )
68 void* pData = lua_touserdata( pLS, 1 );
69 StructRefWrapper< C >* pWrapper =
70 static_cast< StructRefWrapper< C >* >( pData );
71 std::stringstream sstr;
72 sstr << "[struct " << class_traits< C >::FullName() << " " << pWrapper->pStruct
73 << " (by ref, owner object: " << pWrapper->pOwner << ")]";
74 lua_pushstring( pLS, sstr.str().c_str() );
75 return 1;
78 static int ToStringVal( lua_State* pLS )
80 void* pData = lua_touserdata( pLS, 1 );
81 StructValWrapper< C >* pWrapper =
82 static_cast< StructValWrapper< C >* >( pData );
83 std::stringstream sstr;
84 sstr << "[struct " << class_traits< C >::FullName() << " " << pWrapper->pStruct
85 << " (by value)]";
86 lua_pushstring( pLS, sstr.str().c_str() );
87 return 1;
91 template< class C, e_CheckingPolicy Checking >
92 struct TypeConverter< C*, Checking, tc_ValueType >
94 TypeConverter( lua_State* pLS_ ) :
95 m_pLS( pLS_ ),
96 m_bByRef( true )
100 bool CheckType( int Index_ )
102 if( lua_type( m_pLS, Index_ ) != LUA_TUSERDATA )
104 // TODO: better error reporting
105 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
106 return false;
109 if( !lua_getmetatable( m_pLS, Index_ ) )
111 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
112 return false;
115 // Check if it's a struct wrapped by reference
116 Registry< C* >::PushMetatable( m_pLS );
117 if( lua_rawequal( m_pLS, -1, -2 ) )
119 lua_pop( m_pLS, 2 );
120 return true;
123 lua_pop( m_pLS, 1 );
125 // Check if it's a struct wrapped by value
126 Registry< C& >::PushMetatable( m_pLS );
127 bool bRes = lua_rawequal( m_pLS, -1, -2 );
128 lua_pop( m_pLS, 2 );
129 if( bRes )
131 m_bByRef = false;
132 return true;
135 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
136 return false;
139 bool ConvertFromLua( int Index_, C*& pDest_ )
141 // Workaround for a warning occuring because the compiler apparently
142 // fails to detect that when using a typeconverter with cp_Throw,
143 // any code path not setting Dest_ throws
144 pDest_ = 0;
146 if( !CheckType( Index_ ) )
147 return false;
149 if( m_bByRef )
151 StructRefWrapper< C >* pWrapper =
152 static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
153 pDest_ = pWrapper->pStruct;
155 else
157 StructValWrapper< C >* pWrapper =
158 static_cast< StructValWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
159 pDest_ = pWrapper->pStruct.get();
162 // pDest_ = static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
164 return true;
167 lua_State* m_pLS;
168 bool m_bByRef;
171 template< class C >
172 struct TypeConverter< C*, cp_NoCheck, tc_ValueType >
174 TypeConverter( lua_State* pLS_ ) :
175 m_pLS( pLS_ ),
176 m_bByRef( true )
180 bool CheckType( int Index_ )
182 return true;
185 bool ConvertFromLua( int Index_, C*& pDest_ )
187 lua_getmetatable( m_pLS, Index_ );
189 // Check if it's a struct wrapped by reference
190 Registry< C* >::PushMetatable( m_pLS );
191 m_bByRef = lua_rawequal( m_pLS, -1, -2 );
192 lua_pop( m_pLS, 2 );
194 if( m_bByRef )
196 m_pRefWrapper = static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
197 pDest_ = m_pRefWrapper->pStruct;
199 else
201 m_pValWrapper = static_cast< StructValWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
202 pDest_ = m_pValWrapper->pStruct.get();
206 // pDest_ = static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
208 return true;
211 lua_State* m_pLS;
212 bool m_bByRef;
213 StructRefWrapper< C >* m_pRefWrapper;
214 StructValWrapper< C >* m_pValWrapper;
217 template< class C, e_CheckingPolicy Checking >
218 struct TypeConverter< C, Checking, tc_ValueType >
220 TypeConverter( lua_State* pLS_ ) :
221 m_pLS( pLS_ ),
222 m_bByRef( true )
226 bool CheckType( int Index_ )
228 if( lua_type( m_pLS, Index_ ) != LUA_TUSERDATA )
230 // TODO: better error reporting
231 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
232 return false;
235 if( !lua_getmetatable( m_pLS, Index_ ) )
237 TypeCheckHelpers< Checking >::ThrowTypeMismatch();
238 return false;
241 // Check if it's a struct wrapped by reference
242 Registry< C* >::PushMetatable( m_pLS );
243 if( lua_rawequal( m_pLS, -1, -2 ) )
245 lua_pop( m_pLS, 2 );
246 return true;
249 lua_pop( m_pLS, 1 );
251 // Check if it's a struct wrapped by value
252 Registry< C& >::PushMetatable( m_pLS );
253 if( lua_rawequal( m_pLS, -1, -2 ) )
255 lua_pop( m_pLS, 2 );
256 m_bByRef = false;
257 return true;
260 TypeCheckHelpers< Checking >::ThrowTypeMismatch( lua_type( m_pLS, -2 ), lua_type( m_pLS, -1 ) );
261 return false;
264 bool ConvertFromLua( int Index_, C& Dest_ )
266 if( !CheckType( Index_ ) )
267 return false;
268 if( m_bByRef )
270 StructRefWrapper< C >* pWrapper =
271 static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
272 Dest_ = *pWrapper->pStruct;
274 else
276 StructValWrapper< C >* pWrapper =
277 static_cast< StructValWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
278 Dest_ = *pWrapper->pStruct;
282 // Dest_ = *static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
284 return true;
287 void ConvertToLua( const C& Obj_ ) const
289 shared_ptr< C > pStruct( new C( Obj_ ) );
291 void* pData = lua_newuserdata( m_pLS, sizeof( StructValWrapper< C > ) );
292 if( !pData )
293 throw std::bad_alloc();
295 new( pData ) StructValWrapper< C >( pStruct );
297 Registry< C& >::PushMetatable( m_pLS );
298 lua_setmetatable( m_pLS, -2 );
301 void ConvertToLuaByRef( shared_ptr< void > pOwner_, C& Obj_ ) const
303 void* pData = lua_newuserdata( m_pLS, sizeof( StructRefWrapper< C > ) );
304 if( !pData )
305 throw std::bad_alloc();
307 new( pData ) StructRefWrapper< C >( pOwner_, &Obj_ );
309 Registry< C* >::PushMetatable( m_pLS );
311 lua_setmetatable( m_pLS, -2 );
314 lua_State* m_pLS;
315 bool m_bByRef;
318 template< class C >
319 struct TypeConverter< C, cp_NoCheck, tc_ValueType >
321 TypeConverter( lua_State* pLS_ ) :
322 m_pLS( pLS_ )
326 bool CheckType( int Index_ )
328 return true;
331 bool ConvertFromLua( int Index_, C& Dest_ )
333 lua_getmetatable( m_pLS, Index_ );
335 // Check if it's a struct wrapped by reference
336 Registry< C* >::PushMetatable( m_pLS );
338 bool bRes = lua_rawequal( m_pLS, -1, -2 );
339 lua_pop( m_pLS, 2 );
341 if( bRes )
343 StructRefWrapper< C >* pWrapper =
344 static_cast< StructRefWrapper< C >* >( lua_touserdata( m_pLS, Index_ ) );
345 Dest_ = *pWrapper->pStruct;
347 else
348 Dest_ = *static_cast< C* >( lua_touserdata( m_pLS, Index_ ) );
350 return true;
353 lua_State* m_pLS;
357 #endif