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_
) :
32 shared_ptr
< void > pOwner
;
36 template< class S
> struct StructValWrapper
38 StructValWrapper( shared_ptr
< S
>& 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
>();
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
>();
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() );
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
86 lua_pushstring( pLS
, sstr
.str().c_str() );
91 template< class C
, e_CheckingPolicy Checking
>
92 struct TypeConverter
< C
*, Checking
, tc_ValueType
>
94 TypeConverter( lua_State
* pLS_
) :
100 bool CheckType( int Index_
)
102 if( lua_type( m_pLS
, Index_
) != LUA_TUSERDATA
)
104 // TODO: better error reporting
105 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
109 if( !lua_getmetatable( m_pLS
, Index_
) )
111 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
115 // Check if it's a struct wrapped by reference
116 Registry
< C
* >::PushMetatable( m_pLS
);
117 if( lua_rawequal( m_pLS
, -1, -2 ) )
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 );
135 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
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
146 if( !CheckType( Index_
) )
151 StructRefWrapper
< C
>* pWrapper
=
152 static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
153 pDest_
= pWrapper
->pStruct
;
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_ ) );
172 struct TypeConverter
< C
*, cp_NoCheck
, tc_ValueType
>
174 TypeConverter( lua_State
* pLS_
) :
180 bool CheckType( int Index_
)
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 );
196 m_pRefWrapper
= static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
197 pDest_
= m_pRefWrapper
->pStruct
;
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_ ) );
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_
) :
226 bool CheckType( int Index_
)
228 if( lua_type( m_pLS
, Index_
) != LUA_TUSERDATA
)
230 // TODO: better error reporting
231 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
235 if( !lua_getmetatable( m_pLS
, Index_
) )
237 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch();
241 // Check if it's a struct wrapped by reference
242 Registry
< C
* >::PushMetatable( m_pLS
);
243 if( lua_rawequal( m_pLS
, -1, -2 ) )
251 // Check if it's a struct wrapped by value
252 Registry
< C
& >::PushMetatable( m_pLS
);
253 if( lua_rawequal( m_pLS
, -1, -2 ) )
260 TypeCheckHelpers
< Checking
>::ThrowTypeMismatch( lua_type( m_pLS
, -2 ), lua_type( m_pLS
, -1 ) );
264 bool ConvertFromLua( int Index_
, C
& Dest_
)
266 if( !CheckType( Index_
) )
270 StructRefWrapper
< C
>* pWrapper
=
271 static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
272 Dest_
= *pWrapper
->pStruct
;
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_ ) );
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
> ) );
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
> ) );
305 throw std::bad_alloc();
307 new( pData
) StructRefWrapper
< C
>( pOwner_
, &Obj_
);
309 Registry
< C
* >::PushMetatable( m_pLS
);
311 lua_setmetatable( m_pLS
, -2 );
319 struct TypeConverter
< C
, cp_NoCheck
, tc_ValueType
>
321 TypeConverter( lua_State
* pLS_
) :
326 bool CheckType( int Index_
)
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 );
343 StructRefWrapper
< C
>* pWrapper
=
344 static_cast< StructRefWrapper
< C
>* >( lua_touserdata( m_pLS
, Index_
) );
345 Dest_
= *pWrapper
->pStruct
;
348 Dest_
= *static_cast< C
* >( lua_touserdata( m_pLS
, Index_
) );