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"
|
|
|
|
#include "stack_proxy.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 {
|
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-02-13 01:47:05 +08:00
|
|
|
inline R call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
2016-03-12 06:47:15 +08:00
|
|
|
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
2016-03-25 03:45:44 +08:00
|
|
|
return fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I)...);
|
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-03-12 06:47:15 +08:00
|
|
|
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
|
2016-03-25 03:45:44 +08:00
|
|
|
fx(std::forward<FxArgs>(args)..., stack_detail::unchecked_get<Args>(L, start + I)...);
|
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;
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-02-13 01:47:05 +08:00
|
|
|
inline R call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
|
|
|
|
typedef typename types<Args...>::indices 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-02-13 01:47:05 +08:00
|
|
|
inline R 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) {
|
|
|
|
typedef typename types<Args...>::indices 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>>
|
|
|
|
inline R 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)...);
|
|
|
|
}
|
|
|
|
|
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-02-26 00:07:39 +08:00
|
|
|
inline int call_into_lua(types<void> tr, types<Args...> ta, Fx&& fx, lua_State* L, int start, FxArgs&&... fxargs) {
|
2016-02-22 08:26:58 +08:00
|
|
|
call<check_args>(tr, ta, L, start, fx, std::forward<FxArgs>(fxargs)...);
|
2016-03-30 12:31:18 +08:00
|
|
|
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop;
|
2016-02-11 00:36:00 +08:00
|
|
|
lua_pop(L, nargs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-03-30 12:31:18 +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::Not<std::is_void<Ret0>>::value>>
|
2016-02-26 00:07:39 +08:00
|
|
|
inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, Fx&& fx, lua_State* L, int start, FxArgs&&... fxargs) {
|
2016-02-24 12:39:46 +08:00
|
|
|
decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, fx, std::forward<FxArgs>(fxargs)...);
|
2016-03-30 12:31:18 +08:00
|
|
|
int nargs = static_cast<int>(sizeof...(Args)) + additionalpop;
|
2016-02-11 00:36:00 +08:00
|
|
|
lua_pop(L, nargs);
|
2016-02-13 01:47:05 +08:00
|
|
|
return push(L, std::forward<decltype(r)>(r));
|
2016-02-11 00:36:00 +08:00
|
|
|
}
|
|
|
|
|
2014-04-27 06:23:56 +08:00
|
|
|
inline call_syntax get_call_syntax(lua_State* L, const std::string& meta) {
|
2016-02-19 11:17:52 +08:00
|
|
|
luaL_getmetatable(L, meta.c_str());
|
|
|
|
if (lua_compare(L, -1, -2, LUA_OPEQ) == 1) {
|
|
|
|
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
|