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
namespace sol {
2014-06-07 10:54:45 +08:00
namespace stack {
2016-02-14 09:14:31 +08:00
namespace stack_detail {
2016-04-17 15:13:46 +08:00
template < typename T >
struct is_this_state_raw : std : : false_type { } ;
template < >
struct is_this_state_raw < this_state > : std : : true_type { } ;
template < typename T >
2016-05-19 14:15:42 +08:00
using is_this_state = is_this_state_raw < meta : : unqualified_t < T > > ;
2016-04-17 15:13:46 +08:00
2014-06-07 10:54:45 +08:00
template < typename T >
inline int push_as_upvalues ( lua_State * L , T & item ) {
2016-02-05 09:16:53 +08:00
typedef std : : decay_t < T > TValue ;
2013-12-12 00:18:13 +08:00
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 ;
2013-12-10 06:01:52 +08:00
2013-12-12 00:18:13 +08:00
data_t data { { } } ;
2016-02-17 10:22:07 +08:00
std : : memcpy ( & data [ 0 ] , std : : addressof ( item ) , itemsize ) ;
2015-03-02 10:14:42 +08:00
int pushcount = 0 ;
2014-08-11 08:49:34 +08:00
for ( auto & & v : data ) {
2016-03-12 00:34:44 +08:00
pushcount + = push ( L , light_userdata_value ( v ) ) ;
2014-06-07 10:54:45 +08:00
}
2015-03-02 10:14:42 +08:00
return pushcount ;
2013-12-10 06:01:52 +08:00
}
2014-06-07 10:54:45 +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 { { } } ;
2014-08-11 08:49:34 +08:00
for ( std : : size_t i = 0 , d = 0 ; d < sizeof ( T ) ; + + i , d + = sizeof ( void * ) ) {
2016-03-12 00:34:44 +08:00
voiddata [ i ] = get < light_userdata_value > ( L , up_value_index ( index + + ) ) ;
2014-06-07 10:54:45 +08:00
}
return std : : pair < T , int > ( * reinterpret_cast < T * > ( static_cast < void * > ( voiddata . data ( ) ) ) , index ) ;
}
2016-02-14 09:14:31 +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 > >
2016-04-07 17:21:49 +08:00
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
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. " ) ;
# endif // This compiler make me so fucking sad
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-02-14 09:14:31 +08:00
template < bool checkargs = default_check_arguments , std : : size_t . . . I , typename . . . Args , typename Fx , typename . . . FxArgs >
2016-02-13 01:47:05 +08:00
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
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. " ) ;
# endif // This compiler make me so fucking sad
2016-03-12 06:47:15 +08:00
check_types < checkargs > { } . check ( ta , tai , L , start , type_panic ) ;
2016-05-19 14:15:42 +08:00
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-03 03:22:51 +08:00
}
2016-02-14 09:14:31 +08:00
} // stack_detail
2013-12-03 03:22:51 +08:00
2015-10-25 19:17:48 +08:00
inline void remove ( lua_State * L , int index , int count ) {
2015-10-22 23:20:32 +08:00
if ( count < 1 )
return ;
2016-05-04 02:19:30 +08:00
int top = lua_gettop ( L ) ;
2015-10-22 23:20:32 +08:00
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 ) {
2016-05-04 02:19:30 +08:00
index = lua_gettop ( L ) + ( index + 1 ) ;
2015-10-22 23:20:32 +08:00
}
int last = index + count ;
for ( int i = index ; i < last ; + + i ) {
2016-05-04 02:19:30 +08:00
lua_remove ( L , i ) ;
2015-10-22 23:20:32 +08:00
}
}
2016-02-14 09:14:31 +08:00
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 > >
2016-04-07 17:21:49 +08:00
inline decltype ( auto ) call ( types < R > tr , types < Args . . . > ta , lua_State * L , int start , Fx & & fx , FxArgs & & . . . args ) {
2016-04-17 14:18:34 +08:00
typedef std : : make_index_sequence < sizeof . . . ( Args ) > args_indices ;
2016-02-14 09:14:31 +08:00
return stack_detail : : call < check_args > ( tr , ta , args_indices ( ) , L , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
2014-04-27 06:23:56 +08:00
}
2016-02-14 09:14:31 +08:00
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 > >
2016-04-07 17:21:49 +08:00
inline decltype ( auto ) call ( types < R > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
2016-02-22 08:26:58 +08:00
return call < check_args > ( tr , ta , L , 1 , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
2016-02-14 09:14:31 +08:00
template < bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
2016-02-13 01:47:05 +08:00
inline void call ( types < void > tr , types < Args . . . > ta , lua_State * L , int start , Fx & & fx , FxArgs & & . . . args ) {
2016-04-17 14:18:34 +08:00
typedef std : : make_index_sequence < sizeof . . . ( Args ) > args_indices ;
2016-02-14 09:14:31 +08:00
stack_detail : : call < check_args > ( tr , ta , args_indices ( ) , L , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
2013-12-03 03:22:51 +08:00
}
2016-02-14 09:14:31 +08:00
template < bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
2016-02-13 01:47:05 +08:00
inline void call ( types < void > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
2016-02-22 08:26:58 +08:00
call < check_args > ( tr , ta , L , 1 , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
2016-02-26 00:07:39 +08:00
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 > >
2016-04-07 17:21:49 +08:00
inline decltype ( auto ) call_from_top ( types < R > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
2016-02-26 00:07:39 +08:00
return call < check_args > ( tr , ta , L , static_cast < int > ( lua_gettop ( L ) - sizeof . . . ( Args ) ) , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
}
2016-02-22 08:26:58 +08:00
template < bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
2016-02-26 00:07:39 +08:00
inline void call_from_top ( types < void > tr , types < Args . . . > ta , lua_State * L , Fx & & fx , FxArgs & & . . . args ) {
2016-02-22 08:26:58 +08:00
call < check_args > ( tr , ta , L , static_cast < int > ( lua_gettop ( L ) - sizeof . . . ( Args ) ) , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( args ) . . . ) ;
2013-12-16 05:27:20 +08:00
}
2016-03-30 12:31:18 +08:00
template < int additionalpop = 0 , bool check_args = stack_detail : : default_check_arguments , typename . . . Args , typename Fx , typename . . . FxArgs >
2016-04-07 17:21:49 +08:00
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 ) . . . ) ;
2016-05-19 14:15:42 +08:00
int nargs = static_cast < int > ( sizeof . . . ( Args ) ) + additionalpop - meta : : count_for_pack < stack_detail : : is_this_state , Args . . . > : : value ;
2016-02-11 00:36:00 +08:00
lua_pop ( L , nargs ) ;
return 0 ;
}
2016-05-19 14:15:42 +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 > >
2016-04-07 17:21:49 +08:00
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 ) . . . ) ;
2016-05-19 14:15:42 +08:00
int nargs = static_cast < int > ( sizeof . . . ( Args ) ) + additionalpop - meta : : count_for_pack < stack_detail : : is_this_state , Args . . . > : : value ;
2016-02-11 00:36:00 +08:00
lua_pop ( L , nargs ) ;
2016-04-17 14:18:34 +08:00
return push_reference ( L , std : : forward < decltype ( r ) > ( r ) ) ;
2016-02-11 00:36:00 +08:00
}
2016-06-04 09:40:23 +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 ( ) , start , std : : forward < Fx > ( fx ) , std : : forward < FxArgs > ( fxargs ) . . . )
}
2016-05-04 02:19:30 +08:00
inline call_syntax get_call_syntax ( lua_State * L , const std : : string & key , int index = - 2 ) {
2016-04-17 14:18:34 +08:00
luaL_getmetatable ( L , key . c_str ( ) ) ;
2016-05-04 02:19:30 +08:00
if ( lua_compare ( L , - 1 , index , LUA_OPEQ ) = = 1 ) {
2016-02-19 11:17:52 +08:00
lua_pop ( L , 1 ) ;
return call_syntax : : colon ;
2014-04-27 06:23:56 +08:00
}
2016-02-19 11:17:52 +08:00
lua_pop ( L , 1 ) ;
2014-04-27 06:23:56 +08:00
return call_syntax : : dot ;
}
2016-02-27 15:43:53 +08:00
2016-02-27 20:56:28 +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
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
( void ) L ;
( void ) handler ;
2016-02-27 15:43:53 +08:00
# endif
}
inline void luajit_exception_off ( lua_State * L ) {
# ifdef SOL_LUAJIT
luaJIT_setmode ( L , - 1 , LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF ) ;
2016-02-27 15:59:47 +08:00
# else
( void ) L ;
2016-02-27 15:43:53 +08:00
# endif
}
2013-11-25 17:56:27 +08:00
} // stack
} // sol
2014-05-29 14:38:02 +08:00
# endif // SOL_STACK_HPP