// 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_CORE_HPP #define SOL_STACK_CORE_HPP #include "types.hpp" #include "reference.hpp" #include "stack_reference.hpp" #include "userdata.hpp" #include "tuple.hpp" #include "traits.hpp" #include "tie.hpp" namespace sol { namespace detail { struct as_reference_tag{}; using special_destruct_func = void(*)(void*); template inline void special_destruct(void* memory) { T** pointerpointer = static_cast(memory); special_destruct_func* dx = static_cast(static_cast(pointerpointer + 1)); Real* target = static_cast(static_cast(dx + 1)); target->~Real(); } template inline int unique_destruct(lua_State* L) { void* memory = lua_touserdata(L, 1); T** pointerpointer = static_cast(memory); special_destruct_func& dx = *static_cast( static_cast( pointerpointer + 1 ) ); (dx)(memory); return 0; } } // detail namespace stack { template struct field_getter; template struct probe_field_getter; template struct field_setter; template struct getter; template struct popper; template struct pusher; template::value, typename = void> struct checker; template struct check_getter; struct probe { bool success; int levels; probe(bool s, int l) : success(s), levels(l) {} operator bool() const { return success; }; }; namespace stack_detail { template struct strip { typedef T type; }; template struct strip> { typedef T& type; }; template struct strip> { typedef T type; }; template using strip_t = typename strip::type; const bool default_check_arguments = #ifdef SOL_CHECK_ARGUMENTS true; #else false; #endif template inline decltype(auto) unchecked_get(lua_State* L, int index = -1) { return getter>{}.get(L, index); } } // stack_detail inline bool maybe_indexable(lua_State* L, int index = -1) { type t = type_of(L, index); return t == type::userdata || t == type::table; } template inline int push(lua_State* L, T&& t, Args&&... args) { return pusher>{}.push(L, std::forward(t), std::forward(args)...); } // overload allows to use a pusher of a specific type, but pass in any kind of args template inline int push(lua_State* L, Arg&& arg, Args&&... args) { return pusher>{}.push(L, std::forward(arg), std::forward(args)...); } template inline int push_reference(lua_State* L, T&& t, Args&&... args) { typedef meta::all< std::is_lvalue_reference, meta::neg>, meta::neg> > use_reference_tag; return pusher>>{}.push(L, std::forward(t), std::forward(args)...); } inline int multi_push(lua_State*) { // do nothing return 0; } template inline int multi_push(lua_State* L, T&& t, Args&&... args) { int pushcount = push(L, std::forward(t)); void(sol::detail::swallow{(pushcount += sol::stack::push(L, std::forward(args)), 0)... }); return pushcount; } inline int multi_push_reference(lua_State*) { // do nothing return 0; } template inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { int pushcount = push_reference(L, std::forward(t)); void(sol::detail::swallow{(pushcount += sol::stack::push_reference(L, std::forward(args)), 0)... }); return pushcount; } template bool check(lua_State* L, int index, Handler&& handler) { typedef meta::unqualified_t Tu; checker c; // VC++ has a bad warning here: shut it up (void)c; return c.check(L, index, std::forward(handler)); } template bool check(lua_State* L, int index = -1) { auto handler = no_panic; return check(L, index, handler); } template inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { return check_getter>{}.get(L, index, std::forward(handler)); } template inline decltype(auto) check_get(lua_State* L, int index = -1) { auto handler = no_panic; return check_get(L, index, handler); } namespace stack_detail { template inline decltype(auto) tagged_get(types, lua_State* L, int index = -1) { #ifdef SOL_CHECK_ARGUMENTS auto op = check_get(L, index, type_panic); typedef typename meta::unqualified_t::value_type U; return static_cast(*op); #else return stack_detail::unchecked_get(L, index); #endif } template inline decltype(auto) tagged_get(types>, lua_State* L, int index = -1) { return stack_detail::unchecked_get>(L, index); } template inline int alloc_destroy(lua_State* L) { void* rawdata = lua_touserdata(L, up_value_index(1)); T* data = static_cast(rawdata); std::allocator alloc; alloc.destroy(data); } } // stack_detail template inline decltype(auto) get(lua_State* L, int index = -1) { return stack_detail::tagged_get(types(), L, index); } template inline decltype(auto) pop(lua_State* L) { return popper>{}.pop(L); } template void get_field(lua_State* L, Key&& key) { field_getter, global>{}.get(L, std::forward(key)); } template void get_field(lua_State* L, Key&& key, int tableindex) { field_getter, global>{}.get(L, std::forward(key), tableindex); } template probe probe_get_field(lua_State* L, Key&& key) { return probe_field_getter, global>{}.get(L, std::forward(key)); } template probe probe_get_field(lua_State* L, Key&& key, int tableindex) { return probe_field_getter, global>{}.get(L, std::forward(key), tableindex); } template void set_field(lua_State* L, Key&& key, Value&& value) { field_setter, global>{}.set(L, std::forward(key), std::forward(value)); } template void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { field_setter, global>{}.set(L, std::forward(key), std::forward(value), tableindex); } } // stack } // sol #endif // SOL_STACK_CORE_HPP