2016-03-14 21:53:24 +08:00
// The MIT License (MIT)
2013-11-25 17:56:27 +08:00
2016-02-27 15:43:53 +08:00
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
2013-11-25 17:56:27 +08:00
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# ifndef SOL_STACK_HPP
# define SOL_STACK_HPP
2016-03-25 03:45:44 +08:00
# include "stack_core.hpp"
2016-04-01 04:16:07 +08:00
# include "stack_reference.hpp"
2016-03-25 03:45:44 +08:00
# include "stack_check.hpp"
# include "stack_get.hpp"
# include "stack_check_get.hpp"
# include "stack_push.hpp"
# include "stack_pop.hpp"
# include "stack_field.hpp"
2016-03-25 17:27:19 +08:00
# include "stack_probe.hpp"
2013-12-10 06:01:52 +08:00
# include <cstring>
2016-03-25 03:45:44 +08:00
# include <array>
2013-11-25 17:56:27 +08:00
2016-06-20 05:59:40 +08:00
namespace sol {
namespace stack {
namespace stack_detail {
template < typename T >
inline int push_as_upvalues ( lua_State * L , T & item ) {
typedef std : : decay_t < T > TValue ;
const static std : : size_t itemsize = sizeof ( TValue ) ;
const static std : : size_t voidsize = sizeof ( void * ) ;
const static std : : size_t voidsizem1 = voidsize - 1 ;
const static std : : size_t data_t_count = ( sizeof ( TValue ) + voidsizem1 ) / voidsize ;
typedef std : : array < void * , data_t_count > data_t ;
data_t data { { } } ;
std : : memcpy ( & data [ 0 ] , std : : addressof ( item ) , itemsize ) ;
int pushcount = 0 ;
for ( auto & & v : data ) {
pushcount + = push ( L , lightuserdata_value ( v ) ) ;
}
return pushcount ;
2016-06-11 09:04:48 +08:00
}
2016-06-20 05:59:40 +08:00
template < typename T >
inline std : : pair < T , int > get_as_upvalues ( lua_State * L , int index = 1 ) {
const static std : : size_t data_t_count = ( sizeof ( T ) + ( sizeof ( void * ) - 1 ) ) / sizeof ( void * ) ;
typedef std : : array < void * , data_t_count > data_t ;
data_t voiddata { { } } ;
for ( std : : size_t i = 0 , d = 0 ; d < sizeof ( T ) ; + + i , d + = sizeof ( void * ) ) {
voiddata [ i ] = get < lightuserdata_value > ( L , up_value_index ( index + + ) ) ;
}
return std : : pair < T , int > ( * reinterpret_cast < T * > ( static_cast < void * > ( voiddata . data ( ) ) ) , index ) ;
2016-06-11 09:04:48 +08:00
}
2016-06-20 05:59:40 +08:00
template < bool checkargs = default_check_arguments , std : : size_t . . . I , typename R , typename . . . Args , typename Fx , typename . . . FxArgs , typename = std : : enable_if_t < ! std : : is_void < R > : : value > >
inline decltype ( auto ) call ( types < R > , types < Args . . . > ta , std : : index_sequence < I . . . > tai , lua_State * L , int start , Fx & & fx , FxArgs & & . . . args ) {
2016-05-19 14:15:42 +08:00
# ifndef _MSC_VER
2016-06-20 05:59:40 +08:00
static_assert ( meta : : all < meta : : is_not_move_only < Args > . . . > : : value , " One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention. " ) ;
2016-05-19 14:15:42 +08:00
# endif // This compiler make me so fucking sad
2016-06-20 05:59:40 +08:00
check_types < checkargs > { } . check ( ta , tai , L , start , type_panic ) ;
return fx ( std : : forward < FxArgs > ( args ) . . . , stack_detail : : unchecked_get < Args > ( L , start + I - meta : : count_for_to_pack < I , is_transparent_argument , Args . . . > : : value ) . . . ) ;
}
2013-12-16 05:27:20 +08:00
2016-06-20 05:59:40 +08:00
template < bool checkargs = default_check_arguments , std : : size_t . . . I , typename . . . Args , typename Fx , typename . . . FxArgs >
inline void call ( types < void > , types < Args . . . > ta , std : : index_sequence < I . . . > tai , lua_State * L , int start , Fx & & fx , FxArgs & & . . . args ) {
2016-05-19 14:15:42 +08:00
# ifndef _MSC_VER
2016-06-20 05:59:40 +08:00
static_assert ( meta : : all < meta : : is_not_move_only < Args > . . . > : : value , " One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention. " ) ;
2016-05-19 14:15:42 +08:00
# endif // This compiler make me so fucking sad
2016-06-20 05:59:40 +08:00
check_types < checkargs > { } . check ( ta , tai , L , start , type_panic ) ;
fx ( std : : forward < FxArgs > ( args ) . . . , stack_detail : : unchecked_get < Args > ( L , start + I - meta : : count_for_to_pack < I , is_transparent_argument , Args . . . > : : value ) . . . ) ;
}
} // stack_detail
2016-06-20 07:13:01 +08:00
template < typename T >
int set_ref ( lua_State * L , T & & arg , int tableindex = - 2 ) {
push ( L , std : : forward < T > ( arg ) ) ;
return luaL_ref ( L , tableindex ) ;
}
2016-06-20 05:59:40 +08:00
inline void remove ( lua_State * L , int index , int count ) {
if ( count < 1 )
return ;
int top = lua_gettop ( L ) ;
if ( index = = - 1 | | top = = index ) {
// Slice them right off the top
lua_pop ( L , static_cast < int > ( count ) ) ;
return ;
}
// Remove each item one at a time using stack operations
// Probably slower, maybe, haven't benchmarked,
// but necessary
if ( index < 0 ) {
index = lua_gettop ( L ) + ( index + 1 ) ;
}
int last = index + count ;
for ( int i = index ; i < last ; + + i ) {
lua_remove ( L , i ) ;
}
}
template < bool check_args = stack_detail : : default_check_arguments , typename R , typename . . . Args , typename Fx , typename . . . FxArgs , typename = std : : enable_if_t < ! std : : is_void < R > : : value > >
inline decltype ( auto ) call ( types < R > tr , types < Args . . . > ta , lua_State * L , int start , Fx & & fx , FxArgs & & . . . args ) {
typedef std : : make_index_sequence < sizeof . . . ( Args ) > args_indices ;
return stack_detail : : call < check_args > ( tr , ta , args_indices ( ) , L , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
template < bool check_args = stack_detail : : default_check_arguments , typename R , typename . . . Args , typename Fx , typename . . . FxArgs , typename = std : : enable_if_t < ! std : : is_void < R > : : value > >
inline decltype ( auto ) call ( types < R > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
return call < check_args > ( tr , ta , L , 1 , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
template < bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
inline void call ( types < void > tr , types < Args . . . > ta , lua_State * L , int start , Fx & & fx , FxArgs & & . . . args ) {
typedef std : : make_index_sequence < sizeof . . . ( Args ) > args_indices ;
stack_detail : : call < check_args > ( tr , ta , args_indices ( ) , L , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
template < bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
inline void call ( types < void > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
call < check_args > ( tr , ta , L , 1 , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
template < bool check_args = stack_detail : : default_check_arguments , typename R , typename . . . Args , typename Fx , typename . . . FxArgs , typename = std : : enable_if_t < ! std : : is_void < R > : : value > >
inline decltype ( auto ) call_from_top ( types < R > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
return call < check_args > ( tr , ta , L , static_cast < int > ( lua_gettop ( L ) - sizeof . . . ( Args ) ) , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
template < bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
inline void call_from_top ( types < void > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
call < check_args > ( tr , ta , L , static_cast < int > ( lua_gettop ( L ) - sizeof . . . ( Args ) ) , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
2016-06-11 09:04:48 +08:00
}
2016-06-20 05:59:40 +08:00
template < int additionalpop = 0 , bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
inline int call_into_lua ( types < void > tr , types < Args . . . > ta , lua_State * L , int start , Fx & & fx , FxArgs & & . . . fxargs ) {
call < check_args > ( tr , ta , L , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( fxargs ) . . . ) ;
int nargs = static_cast < int > ( sizeof . . . ( Args ) ) + additionalpop - meta : : count_for_pack < is_transparent_argument , Args . . . > : : value ;
lua_pop ( L , nargs ) ;
return 0 ;
2016-06-11 09:04:48 +08:00
}
2016-06-20 05:59:40 +08:00
template < int additionalpop = 0 , bool check_args = stack_detail : : default_check_arguments , typename Ret0 , typename . . . Ret , typename . . . Args , typename Fx , typename . . . FxArgs , typename = std : : enable_if_t < meta : : neg < std : : is_void < Ret0 > > : : value > >
inline int call_into_lua ( types < Ret0 , Ret . . . > , types < Args . . . > ta , lua_State * L , int start , Fx & & fx , FxArgs & & . . . fxargs ) {
decltype ( auto ) r = call < check_args > ( types < meta : : return_type_t < Ret0 , Ret . . . > > ( ) , ta , L , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( fxargs ) . . . ) ;
int nargs = static_cast < int > ( sizeof . . . ( Args ) ) + additionalpop - meta : : count_for_pack < is_transparent_argument , Args . . . > : : value ;
lua_pop ( L , nargs ) ;
return push_reference ( L , std : : forward < decltype ( r ) > ( r ) ) ;
2016-06-11 09:04:48 +08:00
}
2016-06-20 05:59:40 +08:00
template < int additionalpop = 0 , bool check_args = stack_detail : : default_check_arguments , typename Fx , typename . . . FxArgs >
inline int call_lua ( lua_State * L , int start , Fx & & fx , FxArgs & & . . . fxargs ) {
typedef lua_bind_traits < meta : : unqualified_t < Fx > > traits_type ;
typedef typename traits_type : : args_list args_list ;
typedef typename traits_type : : returns_list returns_list ;
return call_into_lua ( returns_list ( ) , args_list ( ) , L , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( fxargs ) . . . ) ;
2016-06-11 09:04:48 +08:00
}
2016-06-20 05:59:40 +08:00
inline call_syntax get_call_syntax ( lua_State * L , const std : : string & key , int index = - 2 ) {
luaL_getmetatable ( L , key . c_str ( ) ) ;
if ( lua_compare ( L , - 1 , index , LUA_OPEQ ) = = 1 ) {
lua_pop ( L , 1 ) ;
return call_syntax : : colon ;
}
2016-06-11 09:04:48 +08:00
lua_pop ( L , 1 ) ;
2016-06-20 05:59:40 +08:00
return call_syntax : : dot ;
2016-06-11 09:04:48 +08:00
}
2016-06-20 05:59:40 +08:00
inline void luajit_exception_handler ( lua_State * L , int ( * handler ) ( lua_State * , lua_CFunction ) = detail : : c_trampoline ) {
2016-02-27 15:43:53 +08:00
# ifdef SOL_LUAJIT
2016-06-20 05:59:40 +08:00
lua_pushlightuserdata ( L , ( void * ) handler ) ;
luaJIT_setmode ( L , - 1 , LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON ) ;
lua_pop ( L , 1 ) ;
2016-02-27 15:59:47 +08:00
# else
2016-06-20 05:59:40 +08:00
( void ) L ;
( void ) handler ;
2016-02-27 15:43:53 +08:00
# endif
2016-06-20 05:59:40 +08:00
}
2016-02-27 15:43:53 +08:00
2016-06-20 05:59:40 +08:00
inline void luajit_exception_off ( lua_State * L ) {
2016-02-27 15:43:53 +08:00
# ifdef SOL_LUAJIT
2016-06-20 05:59:40 +08:00
luaJIT_setmode ( L , - 1 , LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF ) ;
2016-02-27 15:59:47 +08:00
# else
2016-06-20 05:59:40 +08:00
( void ) L ;
2016-02-27 15:43:53 +08:00
# endif
2016-06-20 05:59:40 +08:00
}
} // stack
} // sol
2013-11-25 17:56:27 +08:00
2014-05-29 14:38:02 +08:00
# endif // SOL_STACK_HPP