// The MIT License (MIT) // Copyright (c) 2013-2016 Rapptz, ThePhD and contributors // 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 #include "stack_core.hpp" #include "stack_reference.hpp" #include "stack_proxy.hpp" #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" #include "stack_probe.hpp" #include #include namespace sol { namespace stack { namespace stack_detail { template struct is_this_state_raw : std::false_type {}; template <> struct is_this_state_raw : std::true_type {}; template using is_this_state = is_this_state_raw>; template inline int push_as_upvalues(lua_State* L, T& item) { typedef std::decay_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 data_t; data_t data{{}}; std::memcpy(&data[0], std::addressof(item), itemsize); int pushcount = 0; for(auto&& v : data) { pushcount += push(L, light_userdata_value(v)); } return pushcount; } template inline std::pair 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 data_t; data_t voiddata{ {} }; for(std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { voiddata[i] = get(L, up_value_index(index++)); } return std::pair(*reinterpret_cast(static_cast(voiddata.data())), index); } template ::value>> inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { typedef meta::index_in_pack state_pack_index; typedef std::integral_constant(state_pack_index::value)> state_idx; check_types{}.check(ta, tai, L, start, type_panic); return fx(std::forward(args)..., stack_detail::unchecked_get(L, start + (state_idx::value < I ? I - 1 : I))...); } template inline void call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { typedef meta::index_in_pack state_pack_index; typedef std::integral_constant(state_pack_index::value)> state_idx; check_types{}.check(ta, tai, L, start, type_panic); fx(std::forward(args)..., stack_detail::unchecked_get(L, start + (state_idx::value < I ? I - 1 : I))...); } } // stack_detail 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(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 ::value>> inline decltype(auto) call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { typedef std::make_index_sequence args_indices; return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); } template ::value>> inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); } template inline void call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { typedef std::make_index_sequence args_indices; stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); } template inline void call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); } template ::value>> inline decltype(auto) call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { return call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); } template inline void call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); } template inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); int nargs = static_cast(sizeof...(Args)) + additionalpop - meta::count_if_pack::value; lua_pop(L, nargs); return 0; } template>::value>> inline int call_into_lua(types, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); int nargs = static_cast(sizeof...(Args)) + additionalpop - meta::count_if_pack::value; lua_pop(L, nargs); return push_reference(L, std::forward(r)); } inline call_syntax get_call_syntax(lua_State* L, const std::string& key) { luaL_getmetatable(L, key.c_str()); if (lua_compare(L, -1, -2, LUA_OPEQ) == 1) { lua_pop(L, 1); return call_syntax::colon; } lua_pop(L, 1); return call_syntax::dot; } inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { #ifdef SOL_LUAJIT lua_pushlightuserdata(L, (void*)handler); luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); lua_pop(L, 1); #else (void)L; (void)handler; #endif } inline void luajit_exception_off(lua_State* L) { #ifdef SOL_LUAJIT luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); #else (void)L; #endif } } // stack } // sol #endif // SOL_STACK_HPP