mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
update single
This commit is contained in:
parent
73484bf8e9
commit
74d1ba87c9
|
@ -20,8 +20,8 @@
|
||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
// This file was generated with a script.
|
// This file was generated with a script.
|
||||||
// Generated 2017-10-01 03:03:08.024225 UTC
|
// Generated 2017-10-02 21:33:04.936340 UTC
|
||||||
// This header was generated with sol v2.18.4 (revision 228df26)
|
// This header was generated with sol v2.18.4 (revision 73484bf)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||||
|
@ -6498,28 +6498,343 @@ namespace sol {
|
||||||
|
|
||||||
using unique_destructor = void (*)(void*);
|
using unique_destructor = void (*)(void*);
|
||||||
|
|
||||||
template <typename T>
|
inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space, std::size_t& required_space) {
|
||||||
inline int unique_destruct(lua_State* L) {
|
// this handels arbitrary alignments...
|
||||||
void* memory = lua_touserdata(L, 1);
|
// make this into a power-of-2-only?
|
||||||
T** pointerpointer = static_cast<T**>(memory);
|
// actually can't: this is a C++14-compatible framework,
|
||||||
unique_destructor& dx = *static_cast<unique_destructor*>(static_cast<void*>(pointerpointer + 1));
|
// power of 2 alignment is C++17
|
||||||
(dx)(memory);
|
std::uintptr_t initial = reinterpret_cast<std::uintptr_t>(ptr);
|
||||||
return 0;
|
std::uintptr_t offby = static_cast<std::uintptr_t>(initial % alignment);
|
||||||
|
std::uintptr_t padding = (alignment - offby) % alignment;
|
||||||
|
required_space += size + padding;
|
||||||
|
if (space < required_space) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ptr = static_cast<void*>(static_cast<char*>(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
inline std::size_t aligned_space_for(void* alignment = nullptr) {
|
||||||
|
char* start = static_cast<char*>(alignment);
|
||||||
|
auto specific_align = [&alignment](std::size_t a, std::size_t s) {
|
||||||
|
std::size_t space = std::numeric_limits<std::size_t>::max();
|
||||||
|
alignment = align(a, s, alignment, space);
|
||||||
|
alignment = static_cast<void*>(static_cast<char*>(alignment) + s);
|
||||||
|
};
|
||||||
|
(void)detail::swallow{ int{}, (specific_align(std::alignment_of<Args>::value, sizeof(Args)), int{})... };
|
||||||
|
return static_cast<char*>(alignment) - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* align_usertype_pointer(void* ptr) {
|
||||||
|
typedef std::integral_constant<bool,
|
||||||
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
|
false
|
||||||
|
#else
|
||||||
|
(std::alignment_of<void*>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!use_align::value) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
std::size_t space = std::numeric_limits<std::size_t>::max();
|
||||||
|
return align(std::alignment_of<void*>::value, sizeof(void*), ptr, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* align_usertype_unique_destructor(void* ptr) {
|
||||||
|
typedef std::integral_constant<bool,
|
||||||
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
|
false
|
||||||
|
#else
|
||||||
|
(std::alignment_of<unique_destructor>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!use_align::value) {
|
||||||
|
return static_cast<void*>(static_cast<void**>(ptr) + 1);
|
||||||
|
}
|
||||||
|
ptr = align_usertype_pointer(ptr);
|
||||||
|
ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(void*));
|
||||||
|
std::size_t space = std::numeric_limits<std::size_t>::max();
|
||||||
|
return align(std::alignment_of<unique_destructor>::value, sizeof(unique_destructor), ptr, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool pre_aligned = false>
|
||||||
|
inline void* align_usertype_unique(void* ptr) {
|
||||||
|
typedef std::integral_constant<bool,
|
||||||
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
|
false
|
||||||
|
#else
|
||||||
|
(std::alignment_of<T>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!pre_aligned) {
|
||||||
|
ptr = align_usertype_unique_destructor(ptr);
|
||||||
|
ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_destructor));
|
||||||
|
}
|
||||||
|
if (!use_align::value) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
std::size_t space = std::numeric_limits<std::size_t>::max();
|
||||||
|
return align(std::alignment_of<T>::value, sizeof(T), ptr, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline int user_alloc_destruct(lua_State* L) {
|
inline void* align_user(void* ptr) {
|
||||||
void* rawdata = lua_touserdata(L, 1);
|
typedef std::integral_constant<bool,
|
||||||
T* data = static_cast<T*>(rawdata);
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
std::allocator<T> alloc;
|
false
|
||||||
alloc.destroy(data);
|
#else
|
||||||
return 0;
|
(std::alignment_of<T>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!use_align::value) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
std::size_t space = std::numeric_limits<std::size_t>::max();
|
||||||
|
return align(std::alignment_of<T>::value, sizeof(T), ptr, space);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T** usertype_allocate_pointer(lua_State* L) {
|
||||||
|
typedef std::integral_constant<bool,
|
||||||
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
|
false
|
||||||
|
#else
|
||||||
|
(std::alignment_of<T*>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!use_align::value) {
|
||||||
|
T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
||||||
|
return pointerpointer;
|
||||||
|
}
|
||||||
|
static const std::size_t initial_size = aligned_space_for<T*>(nullptr);
|
||||||
|
static const std::size_t misaligned_size = aligned_space_for<T*>(reinterpret_cast<void*>(0x1));
|
||||||
|
|
||||||
|
std::size_t allocated_size = initial_size;
|
||||||
|
void* unadjusted = lua_newuserdata(L, initial_size);
|
||||||
|
void* adjusted = align(std::alignment_of<T*>::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<T*>::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<T*>().data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return static_cast<T**>(adjusted);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T* usertype_allocate(lua_State* L) {
|
||||||
|
typedef std::integral_constant<bool,
|
||||||
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
|
false
|
||||||
|
#else
|
||||||
|
(std::alignment_of<T*>::value > 1 || std::alignment_of<T>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!use_align::value) {
|
||||||
|
T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
||||||
|
T*& pointerreference = *pointerpointer;
|
||||||
|
T* allocationtarget = reinterpret_cast<T*>(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<T*, T>(nullptr);
|
||||||
|
static const std::size_t misaligned_size = aligned_space_for<T*, T>(reinterpret_cast<void*>(0x1));
|
||||||
|
|
||||||
|
void* pointer_adjusted;
|
||||||
|
void* data_adjusted;
|
||||||
|
auto attempt_alloc = [](lua_State* L, std::size_t allocated_size, void*& pointer_adjusted, void*& data_adjusted) -> bool {
|
||||||
|
void* adjusted = lua_newuserdata(L, allocated_size);
|
||||||
|
pointer_adjusted = align(std::alignment_of<T*>::value, sizeof(T*), 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 -= sizeof(T*);
|
||||||
|
adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + sizeof(T*));
|
||||||
|
data_adjusted = align(std::alignment_of<T>::value, sizeof(T), adjusted, allocated_size);
|
||||||
|
if (data_adjusted == nullptr) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
bool result = attempt_alloc(L, 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, 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<T>().c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<T>().c_str());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T** pointerpointer = reinterpret_cast<T**>(pointer_adjusted);
|
||||||
|
T*& pointerreference = *pointerpointer;
|
||||||
|
T* allocationtarget = reinterpret_cast<T*>(data_adjusted);
|
||||||
|
pointerreference = allocationtarget;
|
||||||
|
return allocationtarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Real>
|
||||||
|
inline Real* usertype_unique_allocate(lua_State* L, T**& pref, unique_destructor*& dx) {
|
||||||
|
typedef std::integral_constant<bool,
|
||||||
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
|
false
|
||||||
|
#else
|
||||||
|
(std::alignment_of<T*>::value > 1 || std::alignment_of<unique_destructor>::value > 1 || std::alignment_of<Real>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!use_align::value) {
|
||||||
|
pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(detail::unique_destructor) + sizeof(Real)));
|
||||||
|
dx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1));
|
||||||
|
Real* mem = static_cast<Real*>(static_cast<void*>(dx + 1));
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::size_t initial_size = aligned_space_for<T*, unique_destructor, Real>(nullptr);
|
||||||
|
static const std::size_t misaligned_size = aligned_space_for<T*, unique_destructor, Real>(reinterpret_cast<void*>(0x1));
|
||||||
|
|
||||||
|
void* pointer_adjusted;
|
||||||
|
void* dx_adjusted;
|
||||||
|
void* data_adjusted;
|
||||||
|
auto attempt_alloc = [](lua_State* L, std::size_t allocated_size, void*& pointer_adjusted, void*& dx_adjusted, void*& data_adjusted) -> bool {
|
||||||
|
void* adjusted = lua_newuserdata(L, allocated_size);
|
||||||
|
pointer_adjusted = align(std::alignment_of<T*>::value, sizeof(T*), adjusted, allocated_size);
|
||||||
|
if (pointer_adjusted == nullptr) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
allocated_size -= sizeof(T*);
|
||||||
|
adjusted = static_cast<void*>(static_cast<char*>(pointer_adjusted) + sizeof(T*));
|
||||||
|
dx_adjusted = align(std::alignment_of<unique_destructor>::value, sizeof(unique_destructor), adjusted, allocated_size);
|
||||||
|
if (dx_adjusted == nullptr) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
allocated_size -= sizeof(unique_destructor);
|
||||||
|
adjusted = static_cast<void*>(static_cast<char*>(dx_adjusted) + sizeof(unique_destructor));
|
||||||
|
data_adjusted = align(std::alignment_of<Real>::value, sizeof(Real), adjusted, allocated_size);
|
||||||
|
if (data_adjusted == nullptr) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
bool result = attempt_alloc(L, initial_size, pointer_adjusted, dx_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;
|
||||||
|
data_adjusted = nullptr;
|
||||||
|
result = attempt_alloc(L, misaligned_size, pointer_adjusted, dx_adjusted, data_adjusted);
|
||||||
|
if (!result) {
|
||||||
|
if (pointer_adjusted == nullptr) {
|
||||||
|
luaL_error(L, "aligned allocation of userdata block (pointer section) for '%s' failed", detail::demangle<T>().c_str());
|
||||||
|
}
|
||||||
|
else if (dx_adjusted == nullptr) {
|
||||||
|
luaL_error(L, "aligned allocation of userdata block (deleter section) for '%s' failed", detail::demangle<Real>().c_str());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
luaL_error(L, "aligned allocation of userdata block (data section) for '%s' failed", detail::demangle<Real>().c_str());
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pref = static_cast<T**>(pointer_adjusted);
|
||||||
|
dx = static_cast<detail::unique_destructor*>(dx_adjusted);
|
||||||
|
Real* mem = static_cast<Real*>(data_adjusted);
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T* user_allocate(lua_State* L) {
|
||||||
|
typedef std::integral_constant<bool,
|
||||||
|
#ifdef SOL_NO_MEMORY_ALIGNMENT
|
||||||
|
false
|
||||||
|
#else
|
||||||
|
(std::alignment_of<T>::value > 1)
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
use_align;
|
||||||
|
if (!use_align::value) {
|
||||||
|
T* pointer = static_cast<T*>(lua_newuserdata(L, sizeof(T)));
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::size_t initial_size = aligned_space_for<T>(nullptr);
|
||||||
|
static const std::size_t misaligned_size = aligned_space_for<T>(reinterpret_cast<void*>(0x1));
|
||||||
|
|
||||||
|
std::size_t allocated_size = initial_size;
|
||||||
|
void* unadjusted = lua_newuserdata(L, allocated_size);
|
||||||
|
void* adjusted = align(std::alignment_of<T>::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<T>::value, sizeof(T), unadjusted, allocated_size);
|
||||||
|
if (adjusted == nullptr) {
|
||||||
|
lua_pop(L, 1);
|
||||||
|
luaL_error(L, "cannot properly align memory for '%s'", detail::demangle<T>().data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return static_cast<T*>(adjusted);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline int usertype_alloc_destruct(lua_State* L) {
|
inline int usertype_alloc_destruct(lua_State* L) {
|
||||||
void* rawdata = lua_touserdata(L, 1);
|
void* memory = lua_touserdata(L, 1);
|
||||||
T** pdata = static_cast<T**>(rawdata);
|
memory = align_usertype_pointer(memory);
|
||||||
|
T** pdata = static_cast<T**>(memory);
|
||||||
T* data = *pdata;
|
T* data = *pdata;
|
||||||
std::allocator<T> alloc{};
|
std::allocator<T> alloc{};
|
||||||
alloc.destroy(data);
|
alloc.destroy(data);
|
||||||
|
@ -6527,19 +6842,38 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline int cannot_destruct(lua_State* L) {
|
inline int unique_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", detail::demangle<T>().data());
|
void* memory = lua_touserdata(L, 1);
|
||||||
|
memory = align_usertype_unique_destructor(memory);
|
||||||
|
unique_destructor& dx = *static_cast<unique_destructor*>(memory);
|
||||||
|
memory = static_cast<void*>(static_cast<char*>(memory) + sizeof(unique_destructor));
|
||||||
|
(dx)(memory);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline int user_alloc_destruct(lua_State* L) {
|
||||||
|
void* memory = lua_touserdata(L, 1);
|
||||||
|
memory = align_user<T>(memory);
|
||||||
|
T* data = static_cast<T*>(memory);
|
||||||
|
std::allocator<T> alloc;
|
||||||
|
alloc.destroy(data);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename Real>
|
template <typename T, typename Real>
|
||||||
inline void usertype_unique_alloc_destroy(void* memory) {
|
inline void usertype_unique_alloc_destroy(void* memory) {
|
||||||
T** pointerpointer = static_cast<T**>(memory);
|
memory = align_usertype_unique<Real, true>(memory);
|
||||||
unique_destructor* dx = static_cast<unique_destructor*>(static_cast<void*>(pointerpointer + 1));
|
Real* target = static_cast<Real*>(memory);
|
||||||
Real* target = static_cast<Real*>(static_cast<void*>(dx + 1));
|
|
||||||
std::allocator<Real> alloc;
|
std::allocator<Real> alloc;
|
||||||
alloc.destroy(target);
|
alloc.destroy(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline 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<T>().data());
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void reserve(T&, std::size_t) {
|
void reserve(T&, std::size_t) {
|
||||||
}
|
}
|
||||||
|
@ -7526,8 +7860,8 @@ namespace stack {
|
||||||
int metatableindex = lua_gettop(L);
|
int metatableindex = lua_gettop(L);
|
||||||
if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex)) {
|
if (stack_detail::check_metatable<detail::unique_usertype<T>>(L, metatableindex)) {
|
||||||
void* memory = lua_touserdata(L, index);
|
void* memory = lua_touserdata(L, index);
|
||||||
T** pointerpointer = static_cast<T**>(memory);
|
memory = detail::align_usertype_unique_destructor(memory);
|
||||||
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(static_cast<void*>(pointerpointer + 1));
|
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
|
||||||
bool success = &detail::usertype_unique_alloc_destroy<T, X> == pdx;
|
bool success = &detail::usertype_unique_alloc_destroy<T, X> == pdx;
|
||||||
if (!success) {
|
if (!success) {
|
||||||
handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
|
handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype");
|
||||||
|
@ -8246,15 +8580,16 @@ namespace stack {
|
||||||
struct getter<detail::as_value_tag<T>> {
|
struct getter<detail::as_value_tag<T>> {
|
||||||
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
static T* get_no_lua_nil(lua_State* L, int index, record& tracking) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
void* rawdata = lua_touserdata(L, index);
|
void* memory = lua_touserdata(L, index);
|
||||||
#ifdef SOL_ENABLE_INTEROP
|
#ifdef SOL_ENABLE_INTEROP
|
||||||
userdata_getter<extensible<T>> ug;
|
userdata_getter<extensible<T>> ug;
|
||||||
(void)ug;
|
(void)ug;
|
||||||
auto ugr = ug.get(L, index, rawdata, tracking);
|
auto ugr = ug.get(L, index, memory, tracking);
|
||||||
if (ugr.first) {
|
if (ugr.first) {
|
||||||
return ugr.second;
|
return ugr.second;
|
||||||
}
|
}
|
||||||
#endif // interop extensibility
|
#endif // interop extensibility
|
||||||
|
void* rawdata = detail::align_usertype_pointer(memory);
|
||||||
void** pudata = static_cast<void**>(rawdata);
|
void** pudata = static_cast<void**>(rawdata);
|
||||||
void* udata = *pudata;
|
void* udata = *pudata;
|
||||||
return get_no_lua_nil_from(L, udata, index, tracking);
|
return get_no_lua_nil_from(L, udata, index, tracking);
|
||||||
|
@ -8339,9 +8674,9 @@ namespace stack {
|
||||||
|
|
||||||
static Real& get(lua_State* L, int index, record& tracking) {
|
static Real& get(lua_State* L, int index, record& tracking) {
|
||||||
tracking.use(1);
|
tracking.use(1);
|
||||||
P** pref = static_cast<P**>(lua_touserdata(L, index));
|
void* memory = lua_touserdata(L, index);
|
||||||
detail::unique_destructor* fx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1));
|
memory = detail::align_usertype_unique<Real>(memory);
|
||||||
Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1));
|
Real* mem = static_cast<Real*>(memory);
|
||||||
return *mem;
|
return *mem;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8601,12 +8936,9 @@ namespace stack {
|
||||||
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
// data in the first sizeof(T*) bytes, and then however many bytes it takes to
|
||||||
// do the actual object. Things that are std::ref or plain T* are stored as
|
// do the actual object. Things that are std::ref or plain T* are stored as
|
||||||
// just the sizeof(T*), and nothing else.
|
// just the sizeof(T*), and nothing else.
|
||||||
T** pointerpointer = static_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
T* obj = detail::usertype_allocate<T>(L);
|
||||||
T*& referencereference = *pointerpointer;
|
|
||||||
T* allocationtarget = reinterpret_cast<T*>(pointerpointer + 1);
|
|
||||||
referencereference = allocationtarget;
|
|
||||||
std::allocator<T> alloc{};
|
std::allocator<T> alloc{};
|
||||||
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
alloc.construct(obj, std::forward<Args>(args)...);
|
||||||
f();
|
f();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -8631,7 +8963,7 @@ namespace stack {
|
||||||
static int push_fx(lua_State* L, F&& f, T* obj) {
|
static int push_fx(lua_State* L, F&& f, T* obj) {
|
||||||
if (obj == nullptr)
|
if (obj == nullptr)
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
T** pref = static_cast<T**>(lua_newuserdata(L, sizeof(T*)));
|
T** pref = detail::usertype_allocate_pointer<T>(L);
|
||||||
*pref = obj;
|
*pref = obj;
|
||||||
f();
|
f();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -8692,9 +9024,9 @@ namespace stack {
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
static int push_deep(lua_State* L, Args&&... args) {
|
static int push_deep(lua_State* L, Args&&... args) {
|
||||||
P** pref = static_cast<P**>(lua_newuserdata(L, sizeof(P*) + sizeof(detail::unique_destructor) + sizeof(Real)));
|
P** pref = nullptr;
|
||||||
detail::unique_destructor* fx = static_cast<detail::unique_destructor*>(static_cast<void*>(pref + 1));
|
detail::unique_destructor* fx = nullptr;
|
||||||
Real* mem = static_cast<Real*>(static_cast<void*>(fx + 1));
|
Real* mem = detail::usertype_unique_allocate<P, Real>(L, pref, fx);
|
||||||
*fx = detail::usertype_unique_alloc_destroy<P, Real>;
|
*fx = detail::usertype_unique_alloc_destroy<P, Real>;
|
||||||
detail::default_construct::construct(mem, std::forward<Args>(args)...);
|
detail::default_construct::construct(mem, std::forward<Args>(args)...);
|
||||||
*pref = unique_usertype_traits<T>::get(*mem);
|
*pref = unique_usertype_traits<T>::get(*mem);
|
||||||
|
@ -8986,14 +9318,13 @@ namespace stack {
|
||||||
template <bool with_meta = true, typename Key, typename... Args>
|
template <bool with_meta = true, typename Key, typename... Args>
|
||||||
static int push_with(lua_State* L, Key&& name, Args&&... args) {
|
static int push_with(lua_State* L, Key&& name, Args&&... args) {
|
||||||
// A dumb pusher
|
// A dumb pusher
|
||||||
void* rawdata = lua_newuserdata(L, sizeof(T));
|
T* data = detail::user_allocate<T>(L);
|
||||||
T* data = static_cast<T*>(rawdata);
|
|
||||||
std::allocator<T> alloc;
|
std::allocator<T> alloc;
|
||||||
alloc.construct(data, std::forward<Args>(args)...);
|
alloc.construct(data, std::forward<Args>(args)...);
|
||||||
if (with_meta) {
|
if (with_meta) {
|
||||||
lua_CFunction cdel = detail::user_alloc_destruct<T>;
|
|
||||||
// Make sure we have a plain GC set for this data
|
// Make sure we have a plain GC set for this data
|
||||||
if (luaL_newmetatable(L, name) != 0) {
|
if (luaL_newmetatable(L, name) != 0) {
|
||||||
|
lua_CFunction cdel = detail::user_alloc_destruct<T>;
|
||||||
lua_pushcclosure(L, cdel, 0);
|
lua_pushcclosure(L, cdel, 0);
|
||||||
lua_setfield(L, -2, "__gc");
|
lua_setfield(L, -2, "__gc");
|
||||||
}
|
}
|
||||||
|
@ -9072,6 +9403,33 @@ namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct pusher<char*> {
|
||||||
|
static int push_sized(lua_State* L, const char* str, std::size_t len) {
|
||||||
|
pusher<const char*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push_sized(L, str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char* str) {
|
||||||
|
pusher<const char*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char* strb, const char* stre) {
|
||||||
|
pusher<const char*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, strb, stre);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char* str, std::size_t len) {
|
||||||
|
pusher<const char*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str, len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
struct pusher<char[N]> {
|
struct pusher<char[N]> {
|
||||||
static int push(lua_State* L, const char (&str)[N]) {
|
static int push(lua_State* L, const char (&str)[N]) {
|
||||||
|
@ -9173,6 +9531,27 @@ namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct pusher<wchar_t*> {
|
||||||
|
static int push(lua_State* L, const wchar_t* str) {
|
||||||
|
pusher<const wchar_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) {
|
||||||
|
pusher<const wchar_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, strb, stre);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const wchar_t* str, std::size_t len) {
|
||||||
|
pusher<const wchar_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str, len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct pusher<const char16_t*> {
|
struct pusher<const char16_t*> {
|
||||||
static int push(lua_State* L, const char16_t* u16str) {
|
static int push(lua_State* L, const char16_t* u16str) {
|
||||||
|
@ -9195,6 +9574,27 @@ namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct pusher<char16_t*> {
|
||||||
|
static int push(lua_State* L, const char16_t* str) {
|
||||||
|
pusher<const char16_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char16_t* strb, const char16_t* stre) {
|
||||||
|
pusher<const char16_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, strb, stre);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char16_t* str, std::size_t len) {
|
||||||
|
pusher<const char16_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str, len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct pusher<const char32_t*> {
|
struct pusher<const char32_t*> {
|
||||||
static int push(lua_State* L, const char32_t* u32str) {
|
static int push(lua_State* L, const char32_t* u32str) {
|
||||||
|
@ -9217,6 +9617,27 @@ namespace stack {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct pusher<char32_t*> {
|
||||||
|
static int push(lua_State* L, const char32_t* str) {
|
||||||
|
pusher<const char32_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char32_t* strb, const char32_t* stre) {
|
||||||
|
pusher<const char32_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, strb, stre);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, const char32_t* str, std::size_t len) {
|
||||||
|
pusher<const char32_t*> p{};
|
||||||
|
(void)p;
|
||||||
|
return p.push(L, str, len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
struct pusher<wchar_t[N]> {
|
struct pusher<wchar_t[N]> {
|
||||||
static int push(lua_State* L, const wchar_t (&str)[N]) {
|
static int push(lua_State* L, const wchar_t (&str)[N]) {
|
||||||
|
@ -10744,10 +11165,7 @@ namespace sol {
|
||||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
|
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
|
||||||
argcount -= static_cast<int>(syntax);
|
argcount -= static_cast<int>(syntax);
|
||||||
|
|
||||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
T* obj = detail::usertype_allocate<T>(L);
|
||||||
T*& referencepointer = *pointerpointer;
|
|
||||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
|
||||||
referencepointer = obj;
|
|
||||||
reference userdataref(L, -1);
|
reference userdataref(L, -1);
|
||||||
userdataref.pop();
|
userdataref.pop();
|
||||||
|
|
||||||
|
@ -11046,11 +11464,8 @@ namespace sol {
|
||||||
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
|
call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits<T>::user_metatable()[0], 1) : call_syntax::dot;
|
||||||
argcount -= static_cast<int>(syntax);
|
argcount -= static_cast<int>(syntax);
|
||||||
|
|
||||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
T* obj = detail::usertype_allocate<T>(L);
|
||||||
reference userdataref(L, -1);
|
reference userdataref(L, -1);
|
||||||
T*& referencepointer = *pointerpointer;
|
|
||||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
|
||||||
referencepointer = obj;
|
|
||||||
|
|
||||||
construct_match<T, Args...>(constructor_match<T, false, clean_stack>(obj), L, argcount, boost + 1 + static_cast<int>(syntax));
|
construct_match<T, Args...>(constructor_match<T, false, clean_stack>(obj), L, argcount, boost + 1 + static_cast<int>(syntax));
|
||||||
|
|
||||||
|
@ -11074,12 +11489,9 @@ namespace sol {
|
||||||
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
template <typename Fx, std::size_t I, typename... R, typename... Args>
|
||||||
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
|
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
|
||||||
const auto& metakey = usertype_traits<T>::metatable();
|
const auto& metakey = usertype_traits<T>::metatable();
|
||||||
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
|
T* obj = detail::usertype_allocate<T>(L);
|
||||||
reference userdataref(L, -1);
|
reference userdataref(L, -1);
|
||||||
T*& referencepointer = *pointerpointer;
|
|
||||||
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
|
|
||||||
referencepointer = obj;
|
|
||||||
|
|
||||||
auto& func = std::get<I>(f.functions);
|
auto& func = std::get<I>(f.functions);
|
||||||
stack::call_into_lua<checked, clean_stack>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj));
|
stack::call_into_lua<checked, clean_stack>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user