From bd3fe0cac583739bc0d7c4b5c8f301bb350abca0 Mon Sep 17 00:00:00 2001 From: Andy Belle-Isle Date: Fri, 30 Aug 2019 00:19:31 -0400 Subject: Renamed lib to deps so github will ignore it for language stats --- lib/sol2/include/sol/stack_core.hpp | 1436 ----------------------------------- 1 file changed, 1436 deletions(-) delete mode 100644 lib/sol2/include/sol/stack_core.hpp (limited to 'lib/sol2/include/sol/stack_core.hpp') diff --git a/lib/sol2/include/sol/stack_core.hpp b/lib/sol2/include/sol/stack_core.hpp deleted file mode 100644 index 3b37210..0000000 --- a/lib/sol2/include/sol/stack_core.hpp +++ /dev/null @@ -1,1436 +0,0 @@ -// sol3 - -// The MIT License (MIT) - -// Copyright (c) 2013-2019 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 "inheritance.hpp" -#include "error_handler.hpp" -#include "reference.hpp" -#include "stack_reference.hpp" -#include "tuple.hpp" -#include "traits.hpp" -#include "tie.hpp" -#include "stack_guard.hpp" -#include "demangle.hpp" -#include "forward_detail.hpp" - -#include -#include -#include -#include -#include -#include -#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES -#include -#endif // C++17 - -namespace sol { - namespace detail { - struct with_function_tag {}; - struct as_reference_tag {}; - template - struct as_pointer_tag {}; - template - struct as_value_tag {}; - template - struct as_table_tag {}; - - using lua_reg_table = luaL_Reg[64]; - - using unique_destructor = void (*)(void*); - using unique_tag = detail::inheritance_unique_cast_function; - - inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space, std::size_t& required_space) { - // this handels arbitrary alignments... - // make this into a power-of-2-only? - // actually can't: this is a C++14-compatible framework, - // power of 2 alignment is C++17 - std::uintptr_t initial = reinterpret_cast(ptr); - std::uintptr_t offby = static_cast(initial % alignment); - std::uintptr_t padding = (alignment - offby) % alignment; - required_space += size + padding; - if (space < required_space) { - return nullptr; - } - ptr = static_cast(static_cast(ptr) + padding); - space -= padding; - return ptr; - } - - inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space) { - std::size_t required_space = 0; - return align(alignment, size, ptr, space, required_space); - } - - inline void align_one(std::size_t a, std::size_t s, void*& target_alignment) { - std::size_t space = (std::numeric_limits::max)(); - target_alignment = align(a, s, target_alignment, space); - target_alignment = static_cast(static_cast(target_alignment) + s); - } - - template - std::size_t aligned_space_for(void* alignment = nullptr) { - char* start = static_cast(alignment); - (void)detail::swallow{ int{}, (align_one(std::alignment_of_v, sizeof(Args), alignment), int{})... }; - return static_cast(alignment) - start; - } - - inline void* align_usertype_pointer(void* ptr) { - using use_align = std::integral_constant::value > 1) -#endif - >; - if (!use_align::value) { - return ptr; - } - std::size_t space = (std::numeric_limits::max)(); - return align(std::alignment_of::value, sizeof(void*), ptr, space); - } - - template - void* align_usertype_unique_destructor(void* ptr) { - using use_align = std::integral_constant::value > 1) -#endif - >; - if (!pre_aligned) { - ptr = align_usertype_pointer(ptr); - } - if (!pre_shifted) { - ptr = static_cast(static_cast(ptr) + sizeof(void*)); - } - if (!use_align::value) { - return static_cast(static_cast(ptr) + 1); - } - std::size_t space = (std::numeric_limits::max)(); - return align(std::alignment_of::value, sizeof(unique_destructor), ptr, space); - } - - template - void* align_usertype_unique_tag(void* ptr) { - using use_align = std::integral_constant::value > 1) -#endif - >; - if (!pre_aligned) { - ptr = align_usertype_unique_destructor(ptr); - } - if (!pre_shifted) { - ptr = static_cast(static_cast(ptr) + sizeof(unique_destructor)); - } - if (!use_align::value) { - return ptr; - } - std::size_t space = (std::numeric_limits::max)(); - return align(std::alignment_of::value, sizeof(unique_tag), ptr, space); - } - - template - void* align_usertype_unique(void* ptr) { - typedef std::integral_constant::value > 1) -#endif - > - use_align; - if (!pre_aligned) { - ptr = align_usertype_unique_tag(ptr); - } - if (!pre_shifted) { - ptr = static_cast(static_cast(ptr) + sizeof(unique_tag)); - } - if (!use_align::value) { - return ptr; - } - std::size_t space = (std::numeric_limits::max)(); - return align(std::alignment_of::value, sizeof(T), ptr, space); - } - - template - void* align_user(void* ptr) { - typedef std::integral_constant::value > 1) -#endif - > - use_align; - if (!use_align::value) { - return ptr; - } - std::size_t space = (std::numeric_limits::max)(); - return align(std::alignment_of::value, sizeof(T), ptr, space); - } - - template - T** usertype_allocate_pointer(lua_State* L) { - typedef std::integral_constant::value > 1) -#endif - > - use_align; - if (!use_align::value) { - T** pointerpointer = static_cast(lua_newuserdata(L, sizeof(T*))); - return pointerpointer; - } - static const std::size_t initial_size = aligned_space_for(nullptr); - static const std::size_t misaligned_size = aligned_space_for(reinterpret_cast(0x1)); - - std::size_t allocated_size = initial_size; - void* unadjusted = lua_newuserdata(L, initial_size); - void* adjusted = align(std::alignment_of::value, sizeof(T*), unadjusted, allocated_size); - if (adjusted == nullptr) { - lua_pop(L, 1); - // what kind of absolute garbage trash allocator are we dealing with? - // whatever, add some padding in the case of MAXIMAL alignment waste... - allocated_size = misaligned_size; - unadjusted = lua_newuserdata(L, allocated_size); - adjusted = align(std::alignment_of::value, sizeof(T*), unadjusted, allocated_size); - if (adjusted == nullptr) { - // trash allocator can burn in hell - lua_pop(L, 1); - // luaL_error(L, "if you are the one that wrote this allocator you should feel bad for doing a - // worse job than malloc/realloc and should go read some books, yeah?"); - luaL_error(L, "cannot properly align memory for '%s'", detail::demangle().data()); - } - } - return static_cast(adjusted); - } - - inline bool attempt_alloc(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t value_align, std::size_t value_size, - std::size_t allocated_size, void*& pointer_adjusted, void*& data_adjusted) { - void* adjusted = lua_newuserdata(L, allocated_size); - pointer_adjusted = align(ptr_align, ptr_size, adjusted, allocated_size); - if (pointer_adjusted == nullptr) { - lua_pop(L, 1); - return false; - } - // subtract size of what we're going to allocate there - allocated_size -= ptr_size; - adjusted = static_cast(static_cast(pointer_adjusted) + ptr_size); - data_adjusted = align(value_align, value_size, adjusted, allocated_size); - if (data_adjusted == nullptr) { - lua_pop(L, 1); - return false; - } - return true; - } - - inline bool attempt_alloc_unique(lua_State* L, std::size_t ptr_align, std::size_t ptr_size, std::size_t real_align, std::size_t real_size, - std::size_t allocated_size, void*& pointer_adjusted, void*& dx_adjusted, void*& id_adjusted, void*& data_adjusted) { - void* adjusted = lua_newuserdata(L, allocated_size); - pointer_adjusted = align(ptr_align, ptr_size, adjusted, allocated_size); - if (pointer_adjusted == nullptr) { - lua_pop(L, 1); - return false; - } - allocated_size -= ptr_size; - - adjusted = static_cast(static_cast(pointer_adjusted) + ptr_size); - dx_adjusted = align(std::alignment_of_v, sizeof(unique_destructor), adjusted, allocated_size); - if (dx_adjusted == nullptr) { - lua_pop(L, 1); - return false; - } - allocated_size -= sizeof(unique_destructor); - - adjusted = static_cast(static_cast(dx_adjusted) + sizeof(unique_destructor)); - - id_adjusted = align(std::alignment_of_v, sizeof(unique_tag), adjusted, allocated_size); - if (id_adjusted == nullptr) { - lua_pop(L, 1); - return false; - } - allocated_size -= sizeof(unique_tag); - - adjusted = static_cast(static_cast(id_adjusted) + sizeof(unique_tag)); - data_adjusted = align(real_align, real_size, adjusted, allocated_size); - if (data_adjusted == nullptr) { - lua_pop(L, 1); - return false; - } - return true; - } - - template - T* usertype_allocate(lua_State* L) { - typedef std::integral_constant::value > 1 || std::alignment_of::value > 1) -#endif - > - use_align; - if (!use_align::value) { - T** pointerpointer = static_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); - T*& pointerreference = *pointerpointer; - T* allocationtarget = reinterpret_cast(pointerpointer + 1); - pointerreference = allocationtarget; - return allocationtarget; - } - - /* the assumption is that `lua_newuserdata` -- unless someone - passes a specific lua_Alloc that gives us bogus, un-aligned pointers - -- uses malloc, which tends to hand out more or less aligned pointers to memory - (most of the time, anyhow) - - but it's not guaranteed, so we have to do a post-adjustment check and increase padding - - we do this preliminarily with compile-time stuff, to see - if we strike lucky with the allocator and alignment values - - otherwise, we have to re-allocate the userdata and - over-allocate some space for additional padding because - compilers are optimized for aligned reads/writes - (and clang will barf UBsan errors on us for not being aligned) - */ - static const std::size_t initial_size = aligned_space_for(nullptr); - static const std::size_t misaligned_size = aligned_space_for(reinterpret_cast(0x1)); - - void* pointer_adjusted; - void* data_adjusted; - bool result - = attempt_alloc(L, std::alignment_of_v, sizeof(T*), std::alignment_of_v, sizeof(T), initial_size, pointer_adjusted, data_adjusted); - if (!result) { - // we're likely to get something that fails to perform the proper allocation a second time, - // so we use the suggested_new_size bump to help us out here - pointer_adjusted = nullptr; - data_adjusted = nullptr; - result = attempt_alloc( - L, std::alignment_of_v, sizeof(T*), std::alignment_of_v, sizeof(T), misaligned_size, pointer_adjusted, data_adjusted); - if (!result) { - if (pointer_adjusted == nullptr) { - luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle().c_str()); - } - else { - luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle().c_str()); - } - return nullptr; - } - } - - T** pointerpointer = reinterpret_cast(pointer_adjusted); - T*& pointerreference = *pointerpointer; - T* allocationtarget = reinterpret_cast(data_adjusted); - pointerreference = allocationtarget; - return allocationtarget; - } - - template - Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx, unique_tag*& id) { - typedef std::integral_constant::value > 1 || std::alignment_of::value > 1 || std::alignment_of::value > 1 - || std::alignment_of::value > 1) -#endif - > - use_align; - if (!use_align::value) { - pref = static_cast(lua_newuserdata(L, sizeof(T*) + sizeof(detail::unique_destructor) + sizeof(unique_tag) + sizeof(Real))); - dx = static_cast(static_cast(pref + 1)); - id = static_cast(static_cast(dx + 1)); - Real* mem = static_cast(static_cast(id + 1)); - return mem; - } - - static const std::size_t initial_size = aligned_space_for(nullptr); - static const std::size_t misaligned_size = aligned_space_for(reinterpret_cast(0x1)); - - void* pointer_adjusted; - void* dx_adjusted; - void* id_adjusted; - void* data_adjusted; - bool result = attempt_alloc_unique(L, - std::alignment_of_v, - sizeof(T*), - std::alignment_of_v, - sizeof(Real), - initial_size, - pointer_adjusted, - dx_adjusted, - id_adjusted, - data_adjusted); - if (!result) { - // we're likely to get something that fails to perform the proper allocation a second time, - // so we use the suggested_new_size bump to help us out here - pointer_adjusted = nullptr; - dx_adjusted = nullptr; - id_adjusted = nullptr; - data_adjusted = nullptr; - result = attempt_alloc_unique(L, - std::alignment_of_v, - sizeof(T*), - std::alignment_of_v, - sizeof(Real), - misaligned_size, - pointer_adjusted, - dx_adjusted, - id_adjusted, - data_adjusted); - if (!result) { - if (pointer_adjusted == nullptr) { - luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle().c_str()); - } - else if (dx_adjusted == nullptr) { - luaL_error(L, "aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle().c_str()); - } - else { - luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle().c_str()); - } - return nullptr; - } - } - - pref = static_cast(pointer_adjusted); - dx = static_cast(dx_adjusted); - id = static_cast(id_adjusted); - Real* mem = static_cast(data_adjusted); - return mem; - } - - template - T* user_allocate(lua_State* L) { - typedef std::integral_constant::value > 1) -#endif - > - use_align; - if (!use_align::value) { - T* pointer = static_cast(lua_newuserdata(L, sizeof(T))); - return pointer; - } - - static const std::size_t initial_size = aligned_space_for(nullptr); - static const std::size_t misaligned_size = aligned_space_for(reinterpret_cast(0x1)); - - std::size_t allocated_size = initial_size; - void* unadjusted = lua_newuserdata(L, allocated_size); - void* adjusted = align(std::alignment_of::value, sizeof(T), unadjusted, allocated_size); - if (adjusted == nullptr) { - lua_pop(L, 1); - // try again, add extra space for alignment padding - allocated_size = misaligned_size; - unadjusted = lua_newuserdata(L, allocated_size); - adjusted = align(std::alignment_of::value, sizeof(T), unadjusted, allocated_size); - if (adjusted == nullptr) { - lua_pop(L, 1); - luaL_error(L, "cannot properly align memory for '%s'", detail::demangle().data()); - } - } - return static_cast(adjusted); - } - - template - int usertype_alloc_destruct(lua_State* L) { - void* memory = lua_touserdata(L, 1); - memory = align_usertype_pointer(memory); - T** pdata = static_cast(memory); - T* data = *pdata; - std::allocator alloc{}; - std::allocator_traits>::destroy(alloc, data); - return 0; - } - - template - int unique_destruct(lua_State* L) { - void* memory = lua_touserdata(L, 1); - memory = align_usertype_unique_destructor(memory); - unique_destructor& dx = *static_cast(memory); - memory = align_usertype_unique_tag(memory); - (dx)(memory); - return 0; - } - - template - int user_alloc_destruct(lua_State* L) { - void* memory = lua_touserdata(L, 1); - memory = align_user(memory); - T* data = static_cast(memory); - std::allocator alloc; - std::allocator_traits>::destroy(alloc, data); - return 0; - } - - template - void usertype_unique_alloc_destroy(void* memory) { - memory = align_usertype_unique(memory); - Real* target = static_cast(memory); - std::allocator alloc; - std::allocator_traits>::destroy(alloc, target); - } - - template - int cannot_destruct(lua_State* L) { - return luaL_error(L, - "cannot call the destructor for '%s': it is either hidden (protected/private) or removed with '= " - "delete' and thusly this type is being destroyed without properly destructing, invoking undefined " - "behavior: please bind a usertype and specify a custom destructor to define the behavior properly", - detail::demangle().data()); - } - - template - void reserve(T&, std::size_t) { - } - - template - void reserve(std::vector& vec, std::size_t hint) { - vec.reserve(hint); - } - - template - void reserve(std::basic_string& str, std::size_t hint) { - str.reserve(hint); - } - - inline bool property_always_true(meta_function) { - return true; - } - - struct properties_enrollment_allowed { - int& times_through; - std::bitset<64>& properties; - automagic_enrollments& enrollments; - - properties_enrollment_allowed(int& times, std::bitset<64>& props, automagic_enrollments& enroll) : times_through(times), properties(props), enrollments(enroll) { - } - - bool operator()(meta_function mf) const { - bool p = properties[static_cast(mf)]; - if (times_through > 0) { - return p; - } - switch (mf) { - case meta_function::length: - return enrollments.length_operator && !p; - case meta_function::pairs: - return enrollments.pairs_operator && !p; - case meta_function::call: - return enrollments.call_operator && !p; - case meta_function::less_than: - return enrollments.less_than_operator && !p; - case meta_function::less_than_or_equal_to: - return enrollments.less_than_or_equal_to_operator && !p; - case meta_function::equal_to: - return enrollments.equal_to_operator && !p; - default: - break; - } - return !p; - } - }; - - struct indexed_insert { - lua_reg_table& l; - int& index; - - indexed_insert(lua_reg_table& cont, int& idx) : l(cont), index(idx) { - } - void operator()(meta_function mf, lua_CFunction f) { - l[index] = luaL_Reg{ to_string(mf).c_str(), f }; - ++index; - } - }; - } // namespace detail - - namespace stack { - - template - struct field_getter; - template - struct probe_field_getter; - - template - struct field_setter; - - template - struct unqualified_getter; - template - struct qualified_getter; - - template - struct qualified_interop_getter; - template - struct unqualified_interop_getter; - - template - struct popper; - - template - struct unqualified_pusher; - - template - struct unqualified_checker; - template - struct qualified_checker; - - template - struct unqualified_check_getter; - template - struct qualified_check_getter; - - struct probe { - bool success; - int levels; - - probe(bool s, int l) : success(s), levels(l) { - } - - operator bool() const { - return success; - }; - }; - - struct record { - int last; - int used; - - record() : last(), used() { - } - void use(int count) { - last = count; - used += count; - } - }; - - } // namespace stack - - namespace meta { namespace meta_detail { - - template - using adl_sol_lua_get_test_t = decltype(sol_lua_get(types(), static_cast(nullptr), -1, std::declval())); - - template - using adl_sol_lua_interop_get_test_t - = decltype(sol_lua_interop_get(types(), static_cast(nullptr), -1, static_cast(nullptr), std::declval())); - - template - using adl_sol_lua_check_test_t = decltype(sol_lua_check(types(), static_cast(nullptr), -1, no_panic, std::declval())); - - template - using adl_sol_lua_interop_check_test_t - = decltype(sol_lua_interop_check(types(), static_cast(nullptr), -1, type::none, no_panic, std::declval())); - - template - using adl_sol_lua_check_get_test_t - = decltype(sol_lua_check_get(types(), static_cast(nullptr), -1, no_panic, std::declval())); - - template - using adl_sol_lua_push_test_t = decltype(sol_lua_push(static_cast(nullptr), std::declval()...)); - - template - using adl_sol_lua_push_exact_test_t = decltype(sol_lua_push(types(), static_cast(nullptr), std::declval()...)); - - template - inline constexpr bool is_adl_sol_lua_get_v = meta::is_detected_v; - - template - inline constexpr bool is_adl_sol_lua_interop_get_v = meta::is_detected_v; - - template - inline constexpr bool is_adl_sol_lua_check_v = meta::is_detected_v; - - template - inline constexpr bool is_adl_sol_lua_interop_check_v = meta::is_detected_v; - - template - inline constexpr bool is_adl_sol_lua_check_get_v = meta::is_detected_v; - - template - inline constexpr bool is_adl_sol_lua_push_v = meta::is_detected_v; - - template - inline constexpr bool is_adl_sol_lua_push_exact_v = meta::is_detected_v; - }} // namespace meta::meta_detail - - - namespace stack { - namespace stack_detail { - constexpr const char* not_enough_stack_space = "not enough space left on Lua stack"; - constexpr const char* not_enough_stack_space_floating = "not enough space left on Lua stack for a floating point number"; - constexpr const char* not_enough_stack_space_integral = "not enough space left on Lua stack for an integral number"; - constexpr const char* not_enough_stack_space_string = "not enough space left on Lua stack for a string"; - constexpr const char* not_enough_stack_space_meta_function_name = "not enough space left on Lua stack for the name of a meta_function"; - constexpr const char* not_enough_stack_space_userdata = "not enough space left on Lua stack to create a sol3 userdata"; - constexpr const char* not_enough_stack_space_generic = "not enough space left on Lua stack to push valuees"; - constexpr const char* not_enough_stack_space_environment = "not enough space left on Lua stack to retrieve environment"; - - template - struct strip { - typedef T type; - }; - 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; - - template - static int get_size_hint(C& c) { - return static_cast(c.size()); - } - - template - static int get_size_hint(const std::forward_list&) { - // forward_list makes me sad - return static_cast(32); - } - - template - decltype(auto) unchecked_unqualified_get(lua_State* L, int index, record& tracking) { - using Tu = meta::unqualified_t; - if constexpr (meta::meta_detail::is_adl_sol_lua_get_v) { - return sol_lua_get(types(), L, index, tracking); - } - else { - unqualified_getter g{}; - (void)g; - return g.get(L, index, tracking); - } - } - - template - decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { - if constexpr (meta::meta_detail::is_adl_sol_lua_get_v) { - return sol_lua_get(types(), L, index, tracking); - } - else { - qualified_getter g{}; - (void)g; - return g.get(L, index, tracking); - } - } - - template - decltype(auto) unqualified_interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) { - using Tu = meta::unqualified_t; - if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v) { - return sol_lua_interop_get(types(), L, index, unadjusted_pointer, tracking); - } - else { - (void)L; - (void)index; - (void)unadjusted_pointer; - (void)tracking; - using Ti = stack_detail::strip_t; - return std::pair{ false, nullptr }; - } - } - - template - decltype(auto) interop_get(lua_State* L, int index, void* unadjusted_pointer, record& tracking) { - if constexpr (meta::meta_detail::is_adl_sol_lua_interop_get_v) { - return sol_lua_interop_get(types(), L, index, unadjusted_pointer, tracking); - } - else { - return unqualified_interop_get(L, index, unadjusted_pointer, tracking); - } - } - - template - bool unqualified_interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { - using Tu = meta::unqualified_t; - if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v) { - return sol_lua_interop_check(types(), L, index, index_type, std::forward(handler), tracking); - } - else { - (void)L; - (void)index; - (void)index_type; - (void)handler; - (void)tracking; - return false; - } - } - - template - bool interop_check(lua_State* L, int index, type index_type, Handler&& handler, record& tracking) { - if constexpr (meta::meta_detail::is_adl_sol_lua_interop_check_v) { - return sol_lua_interop_check(types(), L, index, index_type, std::forward(handler), tracking); - } - else { - return unqualified_interop_check(L, index, index_type, std::forward(handler), tracking); - } - } - - using undefined_method_func = void (*)(stack_reference); - - struct undefined_metatable { - lua_State* L; - const char* key; - undefined_method_func on_new_table; - - undefined_metatable(lua_State* l, const char* k, undefined_method_func umf) : L(l), key(k), on_new_table(umf) { - } - - void operator()() const { - if (luaL_newmetatable(L, key) == 1) { - on_new_table(stack_reference(L, -1)); - } - lua_setmetatable(L, -2); - } - }; - } // namespace 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; - } - - inline int top(lua_State* L) { - return lua_gettop(L); - } - - inline bool is_main_thread(lua_State* L) { - int ismainthread = lua_pushthread(L); - lua_pop(L, 1); - return ismainthread == 1; - } - - inline void coroutine_create_guard(lua_State* L) { - if (is_main_thread(L)) { - return; - } - int stacksize = lua_gettop(L); - if (stacksize < 1) { - return; - } - if (type_of(L, 1) != type::function) { - return; - } - // well now we're screwed... - // we can clean the stack and pray it doesn't destroy anything? - lua_pop(L, stacksize); - } - - inline void clear(lua_State* L, int table_index) { - lua_pushnil(L); - while (lua_next(L, table_index) != 0) { - // remove value - lua_pop(L, 1); - // duplicate key to protect form rawset - lua_pushvalue(L, -1); - // push new value - lua_pushnil(L); - // table_index%[key] = nil - lua_rawset(L, table_index); - } - } - - inline void clear(reference& r) { - auto pp = push_pop(r); - int stack_index = pp.index_of(r); - clear(r.lua_state(), stack_index); - } - - inline void clear(stack_reference& r) { - clear(r.lua_state(), r.stack_index()); - } - - template - int push(lua_State* L, T&& t, Args&&... args) { - using Tu = meta::unqualified_t; - if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { - return sol_lua_push(types(), L, std::forward(t), std::forward(args)...); - } - else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { - return sol_lua_push(types(), L, std::forward(t), std::forward(args)...); - } - else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v) { - return sol_lua_push(L, std::forward(t), std::forward(args)...); - } - else { - unqualified_pusher p{}; - (void)p; - return p.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 ::value>> - int push(lua_State* L, Arg&& arg, Args&&... args) { - using Tu = meta::unqualified_t; - if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { - return sol_lua_push(types(), L, std::forward(arg), std::forward(args)...); - } - else if constexpr (meta::meta_detail::is_adl_sol_lua_push_exact_v) { - return sol_lua_push(types(), L, std::forward(arg), std::forward(args)...); - } - else if constexpr (meta::meta_detail::is_adl_sol_lua_push_v) { - return sol_lua_push(L, std::forward(arg), std::forward(args)...); - } - else { - unqualified_pusher p{}; - (void)p; - return p.push(L, std::forward(arg), std::forward(args)...); - } - } - - namespace stack_detail { - - template - int push_reference(lua_State* L, Arg&& arg, Args&&... args) { - using use_reference_tag = meta::all, - meta::neg>, - meta::neg>>, - meta::neg>>>; - using Tr = meta::conditional_t>; - return stack::push(L, std::forward(arg), std::forward(args)...); - } - - } // namespace stack_detail - - template - int push_reference(lua_State* L, T&& t, Args&&... args) { - return stack_detail::push_reference(L, std::forward(t), std::forward(args)...); - } - - template - int push_reference(lua_State* L, Arg&& arg, Args&&... args) { - return stack_detail::push_reference(L, std::forward(arg), std::forward(args)...); - } - - inline int multi_push(lua_State*) { - // do nothing - return 0; - } - - template - int multi_push(lua_State* L, T&& t, Args&&... args) { - int pushcount = push(L, std::forward(t)); - void(detail::swallow{ (pushcount += stack::push(L, std::forward(args)), 0)... }); - return pushcount; - } - - inline int multi_push_reference(lua_State*) { - // do nothing - return 0; - } - - template - int multi_push_reference(lua_State* L, T&& t, Args&&... args) { - int pushcount = push_reference(L, std::forward(t)); - void(detail::swallow{ (pushcount += stack::push_reference(L, std::forward(args)), 0)... }); - return pushcount; - } - - template - bool unqualified_check(lua_State* L, int index, Handler&& handler, record& tracking) { - using Tu = meta::unqualified_t; - if constexpr (meta::meta_detail::is_adl_sol_lua_check_v) { - return sol_lua_check(types(), L, index, std::forward(handler), tracking); - } - else { - unqualified_checker> c; - // VC++ has a bad warning here: shut it up - (void)c; - return c.check(L, index, std::forward(handler), tracking); - } - } - - template - bool unqualified_check(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return unqualified_check(L, index, std::forward(handler), tracking); - } - - template - bool unqualified_check(lua_State* L, int index = -lua_size>::value) { - auto handler = no_panic; - return unqualified_check(L, index, handler); - } - - template - bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - if constexpr (meta::meta_detail::is_adl_sol_lua_check_v) { - return sol_lua_check(types(), L, index, std::forward(handler), tracking); - } - else { - using Tu = meta::unqualified_t; - qualified_checker> c; - // VC++ has a bad warning here: shut it up - (void)c; - return c.check(L, index, std::forward(handler), tracking); - } - } - - template - bool check(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return check(L, index, std::forward(handler), tracking); - } - - template - bool check(lua_State* L, int index = -lua_size>::value) { - auto handler = no_panic; - return check(L, index, handler); - } - - template - bool check_usertype(lua_State* L, int index, type, Handler&& handler, record& tracking) { - using Tu = meta::unqualified_t; - using detail_t = meta::conditional_t, detail::as_pointer_tag, detail::as_value_tag>; - return check(L, index, std::forward(handler), tracking); - } - - template - bool check_usertype(lua_State* L, int index, Handler&& handler, record& tracking) { - using Tu = meta::unqualified_t; - using detail_t = meta::conditional_t, detail::as_pointer_tag, detail::as_value_tag>; - return check(L, index, std::forward(handler), tracking); - } - - template - bool check_usertype(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return check_usertype(L, index, std::forward(handler), tracking); - } - - template - bool check_usertype(lua_State* L, int index = -lua_size>::value) { - auto handler = no_panic; - return check_usertype(L, index, handler); - } - - template - decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler, record& tracking) { - using Tu = meta::unqualified_t; - if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v) { - return sol_lua_check_get(types(), L, index, std::forward(handler), tracking); - } - else if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v) { - return sol_lua_check_get(types(), L, index, std::forward(handler), tracking); - } - else { - unqualified_check_getter cg{}; - (void)cg; - return cg.get(L, index, std::forward(handler), tracking); - } - } - - template - decltype(auto) unqualified_check_get(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return unqualified_check_get(L, index, handler, tracking); - } - - template - decltype(auto) unqualified_check_get(lua_State* L, int index = -lua_size>::value) { - auto handler = no_panic; - return unqualified_check_get(L, index, handler); - } - - template - decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { - if constexpr (meta::meta_detail::is_adl_sol_lua_check_get_v) { - return sol_lua_check_get(types(), L, index, std::forward(handler), tracking); - } - else { - qualified_check_getter cg{}; - (void)cg; - return cg.get(L, index, std::forward(handler), tracking); - } - } - - template - decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return check_get(L, index, handler, tracking); - } - - template - decltype(auto) check_get(lua_State* L, int index = -lua_size>::value) { - auto handler = no_panic; - return check_get(L, index, handler); - } - - namespace stack_detail { - - template - bool check_types(lua_State*, int, Handler&&, record&) { - return true; - } - - template - bool check_types(lua_State* L, int firstargument, Handler&& handler, record& tracking) { - if (!stack::check(L, firstargument + tracking.used, handler, tracking)) - return false; - return check_types(L, firstargument, std::forward(handler), tracking); - } - - template - bool check_types(types, lua_State* L, int index, Handler&& handler, record& tracking) { - return check_types(L, index, std::forward(handler), tracking); - } - - } // namespace stack_detail - - template - bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { - return stack_detail::check_types(L, index, std::forward(handler), tracking); - } - - template - bool multi_check(lua_State* L, int index, Handler&& handler) { - record tracking{}; - return multi_check(L, index, std::forward(handler), tracking); - } - - template - bool multi_check(lua_State* L, int index) { - return multi_check(L, index); - } - - template - auto unqualified_get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_unqualified_get(L, index, tracking)) { -#if defined(SOL_SAFE_GETTER) && SOL_SAFE_GETTER - static constexpr bool is_op = meta::is_specialization_of_v -#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES - || meta::is_specialization_of_v -#endif - ; - if constexpr (is_op) { - return stack_detail::unchecked_unqualified_get(L, index, tracking); - } - else { - if (is_lua_reference::value) { - return stack_detail::unchecked_unqualified_get(L, index, tracking); - } - auto op = unqualified_check_get(L, index, type_panic_c_str, tracking); - return *std::move(op); - } -#else - return stack_detail::unchecked_unqualified_get(L, index, tracking); -#endif - } - - template - decltype(auto) unqualified_get(lua_State* L, int index = -lua_size>::value) { - record tracking{}; - return unqualified_get(L, index, tracking); - } - - template - auto get(lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get(L, index, tracking)) { -#if defined(SOL_SAFE_GETTER) && SOL_SAFE_GETTER - static constexpr bool is_op = meta::is_specialization_of_v -#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES - || meta::is_specialization_of_v -#endif - ; - if constexpr (is_op) { - return stack_detail::unchecked_get(L, index, tracking); - } - else { - if (is_lua_reference::value) { - return stack_detail::unchecked_get(L, index, tracking); - } - auto op = check_get(L, index, type_panic_c_str, tracking); - return *std::move(op); - } -#else - return stack_detail::unchecked_get(L, index, tracking); -#endif - } - - template - decltype(auto) get(lua_State* L, int index = -lua_size>::value) { - record tracking{}; - return get(L, index, tracking); - } - - template - decltype(auto) get_usertype(lua_State* L, int index, record& tracking) { - using UT = meta::conditional_t::value, detail::as_pointer_tag>, detail::as_value_tag>; - return get(L, index, tracking); - } - - template - decltype(auto) get_usertype(lua_State* L, int index = -lua_size>::value) { - record tracking{}; - return get_usertype(L, index, tracking); - } - - template - decltype(auto) pop(lua_State* L) { - return popper>{}.pop(L); - } - - template - void get_field(lua_State* L, Key&& key) { - field_getter, global, raw>{}.get(L, std::forward(key)); - } - - template - void get_field(lua_State* L, Key&& key, int tableindex) { - field_getter, global, raw>{}.get(L, std::forward(key), tableindex); - } - - template - void raw_get_field(lua_State* L, Key&& key) { - get_field(L, std::forward(key)); - } - - template - void raw_get_field(lua_State* L, Key&& key, int tableindex) { - get_field(L, std::forward(key), tableindex); - } - - template - probe probe_get_field(lua_State* L, Key&& key) { - return probe_field_getter, C, global, raw>{}.get(L, std::forward(key)); - } - - template - probe probe_get_field(lua_State* L, Key&& key, int tableindex) { - return probe_field_getter, C, global, raw>{}.get(L, std::forward(key), tableindex); - } - - template - probe probe_raw_get_field(lua_State* L, Key&& key) { - return probe_get_field(L, std::forward(key)); - } - - template - probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { - return probe_get_field(L, std::forward(key), tableindex); - } - - template - void set_field(lua_State* L, Key&& key, Value&& value) { - field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value)); - } - - template - void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { - field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value), tableindex); - } - - template - void raw_set_field(lua_State* L, Key&& key, Value&& value) { - set_field(L, std::forward(key), std::forward(value)); - } - - template - void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { - set_field(L, std::forward(key), std::forward(value), tableindex); - } - - template - void modify_unique_usertype_as(const stack_reference& obj, F&& f) { - using u_traits = unique_usertype_traits; - void* raw = lua_touserdata(obj.lua_state(), obj.stack_index()); - void* ptr_memory = detail::align_usertype_pointer(raw); - void* uu_memory = detail::align_usertype_unique(raw); - T& uu = *static_cast(uu_memory); - f(uu); - *static_cast(ptr_memory) = static_cast(u_traits::get(uu)); - } - - template - void modify_unique_usertype(const stack_reference& obj, F&& f) { - using bt = meta::bind_traits>; - using T = typename bt::template arg_at<0>; - using Tu = meta::unqualified_t; - modify_unique_usertype_as(obj, std::forward(f)); - } - - } // namespace stack - - namespace detail { - - template - lua_CFunction make_destructor(std::true_type) { - if constexpr (is_unique_usertype_v) { - return &unique_destruct; - } - else if constexpr (!std::is_pointer_v) { - return &usertype_alloc_destruct; - } - else { - return &cannot_destruct; - } - } - - template - lua_CFunction make_destructor(std::false_type) { - return &cannot_destruct; - } - - template - lua_CFunction make_destructor() { - return make_destructor(std::is_destructible()); - } - - struct no_comp { - template - bool operator()(A&&, B&&) const { - return false; - } - }; - - template - int is_check(lua_State* L) { - return stack::push(L, stack::check(L, 1, &no_panic)); - } - - template - int member_default_to_string(std::true_type, lua_State* L) { - decltype(auto) ts = stack::get(L, 1).to_string(); - return stack::push(L, std::forward(ts)); - } - - template - int member_default_to_string(std::false_type, lua_State* L) { - return luaL_error(L, - "cannot perform to_string on '%s': no 'to_string' overload in namespace, 'to_string' member " - "function, or operator<<(ostream&, ...) present", - detail::demangle().data()); - } - - template - int adl_default_to_string(std::true_type, lua_State* L) { - using namespace std; - decltype(auto) ts = to_string(stack::get(L, 1)); - return stack::push(L, std::forward(ts)); - } - - template - int adl_default_to_string(std::false_type, lua_State* L) { - return member_default_to_string(meta::supports_to_string_member(), L); - } - - template - int oss_default_to_string(std::true_type, lua_State* L) { - std::ostringstream oss; - oss << stack::unqualified_get(L, 1); - return stack::push(L, oss.str()); - } - - template - int oss_default_to_string(std::false_type, lua_State* L) { - return adl_default_to_string(meta::supports_adl_to_string(), L); - } - - template - int default_to_string(lua_State* L) { - return oss_default_to_string(meta::supports_ostream_op(), L); - } - - template - int default_size(lua_State* L) { - decltype(auto) self = stack::unqualified_get(L, 1); - return stack::push(L, self.size()); - } - - template - int comparsion_operator_wrap(lua_State* L) { - if constexpr (std::is_void_v) { - return stack::push(L, false); - } - else { - auto maybel = stack::unqualified_check_get(L, 1); - if (!maybel) { - return stack::push(L, false); - } - auto mayber = stack::unqualified_check_get(L, 2); - if (!mayber) { - return stack::push(L, false); - } - decltype(auto) l = *maybel; - decltype(auto) r = *mayber; - if constexpr (std::is_same_v) { - std::equal_to<> op; - return stack::push(L, op(detail::ptr(l), detail::ptr(r))); - } - else { - if constexpr (std::is_same_v, Op> // clang-format hack - || std::is_same_v, Op> // - || std::is_same_v, Op>) { // - if (detail::ptr(l) == detail::ptr(r)) { - return stack::push(L, true); - } - } - Op op; - return stack::push(L, op(detail::deref(l), detail::deref(r))); - } - } - } - - template - void insert_default_registrations(IFx&& ifx, Fx&& fx); - - template - struct get_is_primitive : is_lua_primitive {}; - - template - struct get_is_primitive - : meta::neg(), nullptr, -1, std::declval()))>> {}; - - template - struct get_is_primitive - : meta::neg>(), nullptr, -1, std::declval()))>> {}; - - template - struct get_is_primitive : get_is_primitive {}; - - } // namespace detail - - template - struct is_proxy_primitive - : detail::get_is_primitive, meta::meta_detail::is_adl_sol_lua_get_v>> {}; - -} // namespace sol - -#endif // SOL_STACK_CORE_HPP -- cgit v1.2.3