From 96a63454957ef3bc6d70a413c0793771c5568ed0 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Mon, 28 Oct 2024 17:43:20 +0100 Subject: Renamed compat.h → compat.hpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/allocator.h | 2 +- src/compat.cpp | 2 +- src/compat.h | 428 -------------------------------------------------------- src/compat.hpp | 428 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/uniquekey.h | 2 +- 5 files changed, 431 insertions(+), 431 deletions(-) delete mode 100644 src/compat.h create mode 100644 src/compat.hpp (limited to 'src') diff --git a/src/allocator.h b/src/allocator.h index 3f8ccc5..fa48c46 100644 --- a/src/allocator.h +++ b/src/allocator.h @@ -1,6 +1,6 @@ #pragma once -#include "compat.h" +#include "compat.hpp" // ################################################################################################# diff --git a/src/compat.cpp b/src/compat.cpp index 3dc7b56..c6073e3 100644 --- a/src/compat.cpp +++ b/src/compat.cpp @@ -1,5 +1,5 @@ #include "_pch.hpp" -#include "compat.h" +#include "compat.hpp" #include "macros_and_utils.h" diff --git a/src/compat.h b/src/compat.h deleted file mode 100644 index 59c8001..0000000 --- a/src/compat.h +++ /dev/null @@ -1,428 +0,0 @@ -#pragma once - -#include "debug.hpp" -#include "stackindex.hpp" - -// try to detect if we are building against LuaJIT or MoonJIT -#if defined(LUA_JITLIBNAME) -#include "luajit.h" -#if (defined(__x86_64__) || defined(_M_X64) || defined(__LP64__)) -#define LUAJIT_FLAVOR() 64 -#else // 64 bits -#define LUAJIT_FLAVOR() 32 -#endif // 64 bits -#else // LUA_JITLIBNAME -#define LUAJIT_FLAVOR() 0 -#define LUA_JITLIBNAME "jit" -#endif // LUA_JITLIBNAME - -#ifndef LUA_OK -#define LUA_OK 0 // doesn't exist in Lua 5.1 -#endif // LUA_OK - -#ifndef LUA_ERRGCMM -#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1 and Lua 5.4, we don't care about the actual value -#endif // LUA_ERRGCMM - - -#ifndef LUA_LOADED_TABLE -#define LUA_LOADED_TABLE "_LOADED" // doesn't exist before Lua 5.3 -#endif // LUA_LOADED_TABLE - -// code is now preferring Lua 5.4 API - -// ################################################################################################# - -// a strong-typed wrapper over lua types to see them easier in a debugger -enum class LuaType -{ - NONE = LUA_TNONE, - NIL = LUA_TNIL, - BOOLEAN = LUA_TBOOLEAN, - LIGHTUSERDATA = LUA_TLIGHTUSERDATA, - NUMBER = LUA_TNUMBER, - STRING = LUA_TSTRING, - TABLE = LUA_TTABLE, - FUNCTION = LUA_TFUNCTION, - USERDATA = LUA_TUSERDATA, - THREAD = LUA_TTHREAD, - CDATA = 10 // LuaJIT CDATA -}; - -// ################################################################################################# - -// add some Lua 5.3-style API when building for Lua 5.1 -#if LUA_VERSION_NUM == 501 - -inline size_t lua_rawlen(lua_State* L_, StackIndex idx_) -{ - return lua_objlen(L_, idx_); -} -void luaL_requiref(lua_State* L_, const char* modname_, lua_CFunction openf_, int glb_); // implementation copied from Lua 5.2 sources - -int luaL_getsubtable(lua_State* L_, StackIndex idx_, const char* fname_); - -#endif // LUA_VERSION_NUM == 501 - -// ################################################################################################# - -// wrap Lua 5.3 calls under Lua 5.1 API when it is simpler that way -#if LUA_VERSION_NUM == 503 - -inline int luaL_optint(lua_State* L_, int n_, lua_Integer d_) -{ - return static_cast(luaL_optinteger(L_, n_, d_)); -} - -#endif // LUA_VERSION_NUM == 503 - -// ################################################################################################# - -#if LUA_VERSION_NUM < 504 - -void* lua_newuserdatauv(lua_State* L_, size_t sz_, UserValueCount nuvalue_); -int lua_getiuservalue(lua_State* L_, StackIndex idx_, UserValueIndex n_); -int lua_setiuservalue(lua_State* L_, StackIndex idx_, UserValueIndex n_); - -#define LUA_GNAME "_G" - -#endif // LUA_VERSION_NUM < 504 - -// ################################################################################################# - -// wrap Lua 5.4 calls under Lua 5.1 API when it is simpler that way -#if LUA_VERSION_NUM == 504 - -inline int luaL_optint(lua_State* L_, StackIndex n_, lua_Integer d_) -{ - return static_cast(luaL_optinteger(L_, n_, d_)); -} - -#endif // LUA_VERSION_NUM == 504 - -// ################################################################################################# - -// a strong-typed wrapper over lua error codes to see them easier in a debugger -enum class LuaError -{ - OK = LUA_OK, - YIELD = LUA_YIELD, - ERRRUN = LUA_ERRRUN, - ERRSYNTAX = LUA_ERRSYNTAX, - ERRMEM = LUA_ERRMEM, - ERRGCMM = LUA_ERRGCMM, - ERRERR = LUA_ERRERR, - ERRFILE = LUA_ERRFILE -}; - -inline constexpr LuaError ToLuaError(int const rc_) -{ - assert(rc_ == LUA_OK || rc_ == LUA_YIELD || rc_ == LUA_ERRRUN || rc_ == LUA_ERRSYNTAX || rc_ == LUA_ERRMEM || rc_ == LUA_ERRGCMM || rc_ == LUA_ERRERR || rc_ == LUA_ERRFILE); - return static_cast(rc_); -} - -// ################################################################################################# - -// break lexical order for that one because it's needed below -inline LuaType luaG_type(lua_State* const L_, StackIndex const idx_) -{ - return static_cast(lua_type(L_, idx_)); -} - -// ################################################################################################# -// ################################################################################################# -// All the compatibility wrappers we expose start with luaG_ -// ################################################################################################# -// ################################################################################################# - -// must keep as a macro as long as we do constant string concatenations -#define STRINGVIEW_FMT "%.*s" - -// a replacement of lua_tolstring -[[nodiscard]] inline std::string_view luaG_tostring(lua_State* const L_, StackIndex const idx_) -{ - size_t _len{ 0 }; - char const* _str{ lua_tolstring(L_, idx_, &_len) }; - return _str ? std::string_view{ _str, _len } : ""; -} - -[[nodiscard]] inline std::string_view luaG_checkstring(lua_State* const L_, StackIndex const idx_) -{ - size_t _len{ 0 }; - char const* _str{ luaL_checklstring(L_, idx_, &_len) }; - return std::string_view{ _str, _len }; -} - -[[nodiscard]] inline std::string_view luaG_optstring(lua_State* const L_, StackIndex const idx_, std::string_view const& default_) -{ - if (lua_isnoneornil(L_, idx_)) { - return default_; - } - size_t _len{ 0 }; - char const* _str{ luaL_optlstring(L_, idx_, default_.data(), &_len) }; - return std::string_view{ _str, _len }; -} - -template -inline std::string_view luaG_pushstring(lua_State* const L_, std::string_view const& str_, EXTRA&&... extra_) -{ - if constexpr (sizeof...(EXTRA) == 0) { - if constexpr (LUA_VERSION_NUM == 501) { - // lua_pushlstring doesn't return a value in Lua 5.1 - lua_pushlstring(L_, str_.data(), str_.size()); - return luaG_tostring(L_, kIdxTop); - } else { - return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() }; - } - } else { - static_assert((... && std::is_trivial_v>)); - return std::string_view{ lua_pushfstring(L_, str_.data(), std::forward(extra_)...) }; - } -} - -// ################################################################################################# - -// use this in place of lua_absindex to save a function call -inline StackIndex luaG_absindex(lua_State* const L_, StackIndex const idx_) -{ - return StackIndex{ (idx_ >= 0 || idx_ <= kIdxRegistry) ? idx_ : StackIndex{ lua_gettop(L_) + idx_ + 1 } }; -} - -// ################################################################################################# - -template -concept RequiresOldLuaDump = requires(LUA_DUMP f_) { { f_(nullptr, nullptr, nullptr) } -> std::same_as; }; - -template -static inline int WrapLuaDump(LUA_DUMP f_, lua_State* const L_, lua_Writer const writer_, void* const data_, [[maybe_unused]] int const strip_) -{ - return f_(L_, writer_, data_); -} - -// ------------------------------------------------------------------------------------------------- - -template -concept RequiresNewLuaDump = requires(LUA_DUMP f_) { { f_(nullptr, nullptr, nullptr, 0) } -> std::same_as; }; - -template -static inline int WrapLuaDump(LUA_DUMP f_, lua_State* const L_, lua_Writer const writer_, void* const data_, int const strip_) -{ - return f_(L_, writer_, data_, strip_); -} - -// ------------------------------------------------------------------------------------------------- - -static inline int luaG_dump(lua_State* const L_, lua_Writer const writer_, void* const data_, int const strip_) -{ - return WrapLuaDump(lua_dump, L_, writer_, data_, strip_); -} - -// ################################################################################################# - -UserValueCount luaG_getalluservalues(lua_State* L_, StackIndex idx_); - -// ################################################################################################# - -template -concept RequiresOldLuaGetfield = requires(LUA_GETFIELD f_) -{ - { - f_(nullptr, 0, nullptr) - } -> std::same_as; -}; - -template -static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, StackIndex const idx_, std::string_view const& name_) -{ - f_(L_, idx_, name_.data()); - return lua_type(L_, -1); -} - -// ------------------------------------------------------------------------------------------------- - -template -concept RequiresNewLuaGetfield = requires(LUA_GETFIELD f_) -{ - { - f_(nullptr, 0, nullptr) - } -> std::same_as; -}; - -template -static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, StackIndex const idx_, std::string_view const& name_) -{ - return f_(L_, idx_, name_.data()); -} - -// ------------------------------------------------------------------------------------------------- - -static inline LuaType luaG_getfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) -{ - return static_cast(WrapLuaGetField(lua_getfield, L_, idx_, name_)); -} - -// ################################################################################################# - -LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_); - -// ################################################################################################# - -inline void luaG_registerlibfuncs(lua_State* L_, luaL_Reg const* funcs_) -{ - // fake externs to make clang happy... - extern void luaL_register(lua_State*, char const*, luaL_Reg const*); // Lua 5.1 - extern void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int nup_); // Lua 5.2+ - if constexpr (LUA_VERSION_NUM == 501) { - luaL_register(L_, nullptr, funcs_); - } else { - luaL_setfuncs(L_, funcs_, 0); - } -} - -// ################################################################################################# - -template -concept RequiresLuaResume51 = requires(LUA_RESUME f_) { { f_(nullptr, 0) } -> std::same_as; }; - -template -static inline int WrapLuaResume(LUA_RESUME const lua_resume_, lua_State* const L_, [[maybe_unused]] lua_State* const from_, int const nargs_, int* const nresults_) -{ - // lua_resume is supposed to be called from a "clean" stack: - // it should only contain the function and its initial arguments on first call, or the resume arguments on subsequent invocations - int const _rc{ lua_resume_(L_, nargs_) }; - // after resuming, the stack should only contain the yielded values - *nresults_ = lua_gettop(L_); - return _rc; -} - -// ------------------------------------------------------------------------------------------------- - -template -concept RequiresLuaResume52 = requires(LUA_RESUME f_) { { f_(nullptr, nullptr, 0) } -> std::same_as; }; - -template -static inline int WrapLuaResume(LUA_RESUME const lua_resume_, lua_State* const L_, lua_State* const from_, int const nargs_, [[maybe_unused]] int* const nresults_) -{ - // lua_resume is supposed to be called from a "clean" stack: - // it should only contain the function and its initial arguments on first call, or the resume arguments on subsequent invocations - int const _rc{ lua_resume_(L_, from_, nargs_) }; - // after resuming, the stack should only contain the yielded values - *nresults_ = lua_gettop(L_); - return _rc; -} - -// ------------------------------------------------------------------------------------------------- - -template -concept RequiresLuaResume54 = requires(LUA_RESUME f_) { { f_(nullptr, nullptr, 0, nullptr) } -> std::same_as; }; - -template -static inline int WrapLuaResume(LUA_RESUME const lua_resume_, lua_State* const L_, lua_State* const from_, int const nargs_, int* const nresults_) -{ - // starting with Lua 5.4, the stack can contain stuff below the actual yielded values, but lua_resume tells us the correct nresult - return lua_resume_(L_, from_, nargs_, nresults_); -} - -// ------------------------------------------------------------------------------------------------- - -static inline LuaError luaG_resume(lua_State* const L_, lua_State* const from_, int const nargs_, int* const nresults_) -{ - return ToLuaError(WrapLuaResume(lua_resume, L_, from_, nargs_, nresults_)); -} - -// ################################################################################################# - -static inline LuaType luaG_rawgetfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) -{ - auto const _absIdx{ luaG_absindex(L_, idx_) }; - luaG_pushstring(L_, name_); // L_: ... t ... name_ - lua_rawget(L_, _absIdx); // L_: ... t ... - return luaG_type(L_, kIdxTop); -} - -// ################################################################################################# - -template -static inline void luaG_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N]) -{ - lua_createtable(L_, 0, N - 1); - luaG_registerlibfuncs(L_, funcs_); -} - -// ################################################################################################# - -template -[[nodiscard]] T* luaG_newuserdatauv(lua_State* L_, UserValueCount nuvalue_) -{ - return static_cast(lua_newuserdatauv(L_, sizeof(T), nuvalue_)); -} - -// ################################################################################################# - -inline void luaG_pushglobaltable(lua_State* const L_) -{ -#ifdef LUA_GLOBALSINDEX // All flavors of Lua 5.1 - ::lua_pushvalue(L_, LUA_GLOBALSINDEX); -#else // LUA_GLOBALSINDEX - ::lua_rawgeti(L_, kIdxRegistry, LUA_RIDX_GLOBALS); -#endif // LUA_GLOBALSINDEX -} - -// ################################################################################################# - -inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, char const* k_) = delete; -inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, std::string_view const& k_) -{ - lua_setfield(L_, idx_, k_.data()); -} - -// ################################################################################################# - -inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname_) -{ - // fake externs to make clang happy... - if constexpr (LUA_VERSION_NUM > 501) { - extern void luaL_setmetatable(lua_State* const L_, char const* const tname_); // Lua 5.2+ - luaL_setmetatable(L_, tname_.data()); - } else { - luaL_getmetatable(L_, tname_.data()); - lua_setmetatable(L_, -2); - } -} - -// ################################################################################################# - -// a small helper to extract a full userdata pointer from the stack in a safe way -template -[[nodiscard]] T* luaG_tofulluserdata(lua_State* const L_, StackIndex const index_) -{ - LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA); - return static_cast(lua_touserdata(L_, index_)); -} - -// ------------------------------------------------------------------------------------------------- - -template -[[nodiscard]] auto luaG_tolightuserdata(lua_State* const L_, StackIndex const index_) -{ - LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_)); - if constexpr (std::is_pointer_v) { - return static_cast(lua_touserdata(L_, index_)); - } else { - return static_cast(lua_touserdata(L_, index_)); - } -} - -// ------------------------------------------------------------------------------------------------- - -[[nodiscard]] inline std::string_view luaG_typename(lua_State* const L_, LuaType const t_) -{ - return lua_typename(L_, static_cast(t_)); -} - -// ------------------------------------------------------------------------------------------------- - -[[nodiscard]] inline std::string_view luaG_typename(lua_State* const L_, StackIndex const idx_) -{ - return luaG_typename(L_, luaG_type(L_, idx_)); -} diff --git a/src/compat.hpp b/src/compat.hpp new file mode 100644 index 0000000..59c8001 --- /dev/null +++ b/src/compat.hpp @@ -0,0 +1,428 @@ +#pragma once + +#include "debug.hpp" +#include "stackindex.hpp" + +// try to detect if we are building against LuaJIT or MoonJIT +#if defined(LUA_JITLIBNAME) +#include "luajit.h" +#if (defined(__x86_64__) || defined(_M_X64) || defined(__LP64__)) +#define LUAJIT_FLAVOR() 64 +#else // 64 bits +#define LUAJIT_FLAVOR() 32 +#endif // 64 bits +#else // LUA_JITLIBNAME +#define LUAJIT_FLAVOR() 0 +#define LUA_JITLIBNAME "jit" +#endif // LUA_JITLIBNAME + +#ifndef LUA_OK +#define LUA_OK 0 // doesn't exist in Lua 5.1 +#endif // LUA_OK + +#ifndef LUA_ERRGCMM +#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1 and Lua 5.4, we don't care about the actual value +#endif // LUA_ERRGCMM + + +#ifndef LUA_LOADED_TABLE +#define LUA_LOADED_TABLE "_LOADED" // doesn't exist before Lua 5.3 +#endif // LUA_LOADED_TABLE + +// code is now preferring Lua 5.4 API + +// ################################################################################################# + +// a strong-typed wrapper over lua types to see them easier in a debugger +enum class LuaType +{ + NONE = LUA_TNONE, + NIL = LUA_TNIL, + BOOLEAN = LUA_TBOOLEAN, + LIGHTUSERDATA = LUA_TLIGHTUSERDATA, + NUMBER = LUA_TNUMBER, + STRING = LUA_TSTRING, + TABLE = LUA_TTABLE, + FUNCTION = LUA_TFUNCTION, + USERDATA = LUA_TUSERDATA, + THREAD = LUA_TTHREAD, + CDATA = 10 // LuaJIT CDATA +}; + +// ################################################################################################# + +// add some Lua 5.3-style API when building for Lua 5.1 +#if LUA_VERSION_NUM == 501 + +inline size_t lua_rawlen(lua_State* L_, StackIndex idx_) +{ + return lua_objlen(L_, idx_); +} +void luaL_requiref(lua_State* L_, const char* modname_, lua_CFunction openf_, int glb_); // implementation copied from Lua 5.2 sources + +int luaL_getsubtable(lua_State* L_, StackIndex idx_, const char* fname_); + +#endif // LUA_VERSION_NUM == 501 + +// ################################################################################################# + +// wrap Lua 5.3 calls under Lua 5.1 API when it is simpler that way +#if LUA_VERSION_NUM == 503 + +inline int luaL_optint(lua_State* L_, int n_, lua_Integer d_) +{ + return static_cast(luaL_optinteger(L_, n_, d_)); +} + +#endif // LUA_VERSION_NUM == 503 + +// ################################################################################################# + +#if LUA_VERSION_NUM < 504 + +void* lua_newuserdatauv(lua_State* L_, size_t sz_, UserValueCount nuvalue_); +int lua_getiuservalue(lua_State* L_, StackIndex idx_, UserValueIndex n_); +int lua_setiuservalue(lua_State* L_, StackIndex idx_, UserValueIndex n_); + +#define LUA_GNAME "_G" + +#endif // LUA_VERSION_NUM < 504 + +// ################################################################################################# + +// wrap Lua 5.4 calls under Lua 5.1 API when it is simpler that way +#if LUA_VERSION_NUM == 504 + +inline int luaL_optint(lua_State* L_, StackIndex n_, lua_Integer d_) +{ + return static_cast(luaL_optinteger(L_, n_, d_)); +} + +#endif // LUA_VERSION_NUM == 504 + +// ################################################################################################# + +// a strong-typed wrapper over lua error codes to see them easier in a debugger +enum class LuaError +{ + OK = LUA_OK, + YIELD = LUA_YIELD, + ERRRUN = LUA_ERRRUN, + ERRSYNTAX = LUA_ERRSYNTAX, + ERRMEM = LUA_ERRMEM, + ERRGCMM = LUA_ERRGCMM, + ERRERR = LUA_ERRERR, + ERRFILE = LUA_ERRFILE +}; + +inline constexpr LuaError ToLuaError(int const rc_) +{ + assert(rc_ == LUA_OK || rc_ == LUA_YIELD || rc_ == LUA_ERRRUN || rc_ == LUA_ERRSYNTAX || rc_ == LUA_ERRMEM || rc_ == LUA_ERRGCMM || rc_ == LUA_ERRERR || rc_ == LUA_ERRFILE); + return static_cast(rc_); +} + +// ################################################################################################# + +// break lexical order for that one because it's needed below +inline LuaType luaG_type(lua_State* const L_, StackIndex const idx_) +{ + return static_cast(lua_type(L_, idx_)); +} + +// ################################################################################################# +// ################################################################################################# +// All the compatibility wrappers we expose start with luaG_ +// ################################################################################################# +// ################################################################################################# + +// must keep as a macro as long as we do constant string concatenations +#define STRINGVIEW_FMT "%.*s" + +// a replacement of lua_tolstring +[[nodiscard]] inline std::string_view luaG_tostring(lua_State* const L_, StackIndex const idx_) +{ + size_t _len{ 0 }; + char const* _str{ lua_tolstring(L_, idx_, &_len) }; + return _str ? std::string_view{ _str, _len } : ""; +} + +[[nodiscard]] inline std::string_view luaG_checkstring(lua_State* const L_, StackIndex const idx_) +{ + size_t _len{ 0 }; + char const* _str{ luaL_checklstring(L_, idx_, &_len) }; + return std::string_view{ _str, _len }; +} + +[[nodiscard]] inline std::string_view luaG_optstring(lua_State* const L_, StackIndex const idx_, std::string_view const& default_) +{ + if (lua_isnoneornil(L_, idx_)) { + return default_; + } + size_t _len{ 0 }; + char const* _str{ luaL_optlstring(L_, idx_, default_.data(), &_len) }; + return std::string_view{ _str, _len }; +} + +template +inline std::string_view luaG_pushstring(lua_State* const L_, std::string_view const& str_, EXTRA&&... extra_) +{ + if constexpr (sizeof...(EXTRA) == 0) { + if constexpr (LUA_VERSION_NUM == 501) { + // lua_pushlstring doesn't return a value in Lua 5.1 + lua_pushlstring(L_, str_.data(), str_.size()); + return luaG_tostring(L_, kIdxTop); + } else { + return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() }; + } + } else { + static_assert((... && std::is_trivial_v>)); + return std::string_view{ lua_pushfstring(L_, str_.data(), std::forward(extra_)...) }; + } +} + +// ################################################################################################# + +// use this in place of lua_absindex to save a function call +inline StackIndex luaG_absindex(lua_State* const L_, StackIndex const idx_) +{ + return StackIndex{ (idx_ >= 0 || idx_ <= kIdxRegistry) ? idx_ : StackIndex{ lua_gettop(L_) + idx_ + 1 } }; +} + +// ################################################################################################# + +template +concept RequiresOldLuaDump = requires(LUA_DUMP f_) { { f_(nullptr, nullptr, nullptr) } -> std::same_as; }; + +template +static inline int WrapLuaDump(LUA_DUMP f_, lua_State* const L_, lua_Writer const writer_, void* const data_, [[maybe_unused]] int const strip_) +{ + return f_(L_, writer_, data_); +} + +// ------------------------------------------------------------------------------------------------- + +template +concept RequiresNewLuaDump = requires(LUA_DUMP f_) { { f_(nullptr, nullptr, nullptr, 0) } -> std::same_as; }; + +template +static inline int WrapLuaDump(LUA_DUMP f_, lua_State* const L_, lua_Writer const writer_, void* const data_, int const strip_) +{ + return f_(L_, writer_, data_, strip_); +} + +// ------------------------------------------------------------------------------------------------- + +static inline int luaG_dump(lua_State* const L_, lua_Writer const writer_, void* const data_, int const strip_) +{ + return WrapLuaDump(lua_dump, L_, writer_, data_, strip_); +} + +// ################################################################################################# + +UserValueCount luaG_getalluservalues(lua_State* L_, StackIndex idx_); + +// ################################################################################################# + +template +concept RequiresOldLuaGetfield = requires(LUA_GETFIELD f_) +{ + { + f_(nullptr, 0, nullptr) + } -> std::same_as; +}; + +template +static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, StackIndex const idx_, std::string_view const& name_) +{ + f_(L_, idx_, name_.data()); + return lua_type(L_, -1); +} + +// ------------------------------------------------------------------------------------------------- + +template +concept RequiresNewLuaGetfield = requires(LUA_GETFIELD f_) +{ + { + f_(nullptr, 0, nullptr) + } -> std::same_as; +}; + +template +static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, StackIndex const idx_, std::string_view const& name_) +{ + return f_(L_, idx_, name_.data()); +} + +// ------------------------------------------------------------------------------------------------- + +static inline LuaType luaG_getfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) +{ + return static_cast(WrapLuaGetField(lua_getfield, L_, idx_, name_)); +} + +// ################################################################################################# + +LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_); + +// ################################################################################################# + +inline void luaG_registerlibfuncs(lua_State* L_, luaL_Reg const* funcs_) +{ + // fake externs to make clang happy... + extern void luaL_register(lua_State*, char const*, luaL_Reg const*); // Lua 5.1 + extern void luaL_setfuncs(lua_State* const L_, luaL_Reg const funcs_[], int nup_); // Lua 5.2+ + if constexpr (LUA_VERSION_NUM == 501) { + luaL_register(L_, nullptr, funcs_); + } else { + luaL_setfuncs(L_, funcs_, 0); + } +} + +// ################################################################################################# + +template +concept RequiresLuaResume51 = requires(LUA_RESUME f_) { { f_(nullptr, 0) } -> std::same_as; }; + +template +static inline int WrapLuaResume(LUA_RESUME const lua_resume_, lua_State* const L_, [[maybe_unused]] lua_State* const from_, int const nargs_, int* const nresults_) +{ + // lua_resume is supposed to be called from a "clean" stack: + // it should only contain the function and its initial arguments on first call, or the resume arguments on subsequent invocations + int const _rc{ lua_resume_(L_, nargs_) }; + // after resuming, the stack should only contain the yielded values + *nresults_ = lua_gettop(L_); + return _rc; +} + +// ------------------------------------------------------------------------------------------------- + +template +concept RequiresLuaResume52 = requires(LUA_RESUME f_) { { f_(nullptr, nullptr, 0) } -> std::same_as; }; + +template +static inline int WrapLuaResume(LUA_RESUME const lua_resume_, lua_State* const L_, lua_State* const from_, int const nargs_, [[maybe_unused]] int* const nresults_) +{ + // lua_resume is supposed to be called from a "clean" stack: + // it should only contain the function and its initial arguments on first call, or the resume arguments on subsequent invocations + int const _rc{ lua_resume_(L_, from_, nargs_) }; + // after resuming, the stack should only contain the yielded values + *nresults_ = lua_gettop(L_); + return _rc; +} + +// ------------------------------------------------------------------------------------------------- + +template +concept RequiresLuaResume54 = requires(LUA_RESUME f_) { { f_(nullptr, nullptr, 0, nullptr) } -> std::same_as; }; + +template +static inline int WrapLuaResume(LUA_RESUME const lua_resume_, lua_State* const L_, lua_State* const from_, int const nargs_, int* const nresults_) +{ + // starting with Lua 5.4, the stack can contain stuff below the actual yielded values, but lua_resume tells us the correct nresult + return lua_resume_(L_, from_, nargs_, nresults_); +} + +// ------------------------------------------------------------------------------------------------- + +static inline LuaError luaG_resume(lua_State* const L_, lua_State* const from_, int const nargs_, int* const nresults_) +{ + return ToLuaError(WrapLuaResume(lua_resume, L_, from_, nargs_, nresults_)); +} + +// ################################################################################################# + +static inline LuaType luaG_rawgetfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) +{ + auto const _absIdx{ luaG_absindex(L_, idx_) }; + luaG_pushstring(L_, name_); // L_: ... t ... name_ + lua_rawget(L_, _absIdx); // L_: ... t ... + return luaG_type(L_, kIdxTop); +} + +// ################################################################################################# + +template +static inline void luaG_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N]) +{ + lua_createtable(L_, 0, N - 1); + luaG_registerlibfuncs(L_, funcs_); +} + +// ################################################################################################# + +template +[[nodiscard]] T* luaG_newuserdatauv(lua_State* L_, UserValueCount nuvalue_) +{ + return static_cast(lua_newuserdatauv(L_, sizeof(T), nuvalue_)); +} + +// ################################################################################################# + +inline void luaG_pushglobaltable(lua_State* const L_) +{ +#ifdef LUA_GLOBALSINDEX // All flavors of Lua 5.1 + ::lua_pushvalue(L_, LUA_GLOBALSINDEX); +#else // LUA_GLOBALSINDEX + ::lua_rawgeti(L_, kIdxRegistry, LUA_RIDX_GLOBALS); +#endif // LUA_GLOBALSINDEX +} + +// ################################################################################################# + +inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, char const* k_) = delete; +inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, std::string_view const& k_) +{ + lua_setfield(L_, idx_, k_.data()); +} + +// ################################################################################################# + +inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname_) +{ + // fake externs to make clang happy... + if constexpr (LUA_VERSION_NUM > 501) { + extern void luaL_setmetatable(lua_State* const L_, char const* const tname_); // Lua 5.2+ + luaL_setmetatable(L_, tname_.data()); + } else { + luaL_getmetatable(L_, tname_.data()); + lua_setmetatable(L_, -2); + } +} + +// ################################################################################################# + +// a small helper to extract a full userdata pointer from the stack in a safe way +template +[[nodiscard]] T* luaG_tofulluserdata(lua_State* const L_, StackIndex const index_) +{ + LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA); + return static_cast(lua_touserdata(L_, index_)); +} + +// ------------------------------------------------------------------------------------------------- + +template +[[nodiscard]] auto luaG_tolightuserdata(lua_State* const L_, StackIndex const index_) +{ + LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_)); + if constexpr (std::is_pointer_v) { + return static_cast(lua_touserdata(L_, index_)); + } else { + return static_cast(lua_touserdata(L_, index_)); + } +} + +// ------------------------------------------------------------------------------------------------- + +[[nodiscard]] inline std::string_view luaG_typename(lua_State* const L_, LuaType const t_) +{ + return lua_typename(L_, static_cast(t_)); +} + +// ------------------------------------------------------------------------------------------------- + +[[nodiscard]] inline std::string_view luaG_typename(lua_State* const L_, StackIndex const idx_) +{ + return luaG_typename(L_, luaG_type(L_, idx_)); +} diff --git a/src/uniquekey.h b/src/uniquekey.h index ddc157b..693a27a 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h @@ -1,6 +1,6 @@ #pragma once -#include "compat.h" +#include "compat.hpp" #include "macros_and_utils.h" // ################################################################################################# -- cgit v1.2.3-55-g6feb