diff --git a/docs/source/safety.rst b/docs/source/safety.rst index 20adb355..a4c744cd 100644 --- a/docs/source/safety.rst +++ b/docs/source/safety.rst @@ -97,7 +97,7 @@ Feature Config ``SOL_ENABLE_INTEROP`` triggers the following change: * Allows the use of ``extensible`` to be used with ``userdata_checker`` and ``userdata_getter`` to retrieve non-sol usertypes - Particularly enables non-sol usertypes to be used in overloads - - See the :ref:`stack dcoumentation` for details + - See the :ref:`stack documentation` for details * May come with a slight performance penalty: only recommended for those stuck with non-sol libraries that still need to leverage some of sol's power * **Not** turned on by default under any settings: *this MUST be turned on manually* @@ -107,6 +107,15 @@ Feature Config * Some automagical methods might cause huge compiler errors, and some people have code bases with different conventions. * Turned on by default. This *must be turned off manually*. +``SOL_NO_THREAD_LOCAL`` triggers the following change: + * If this is turned on, simply removes all usages of the ``thread_local`` keyword in sol2. + * This is useful for lower versions of iOS and Android, which do not have threading capabilities at all and so the use of the keyword provides no additional guarantees. + * **Not** turned on by default under any settings: *this MUST be turned on manually* + +``SOL_ID_SIZE`` triggers the following change: + * If this is defined to a numeric value, it uses that numeric value for the number of bytes of input to be put into the error message blurb in standard tracebacks and ``chunkname`` descriptions for ``.script``/``.script_file`` usage. + * Defaults to the ``LUA_ID_SIZE`` macro if defined, or some basic internal value like 2048. + .. _config-memory: Memory Config diff --git a/docs/source/threading.rst b/docs/source/threading.rst index 598d582b..dd7c7cc0 100644 --- a/docs/source/threading.rst +++ b/docs/source/threading.rst @@ -24,7 +24,7 @@ You can mitigate some of the pressure of using coroutines and threading by using .. note:: - Advanced used: Furthermore, for every single ``sol::reference`` derived type, there exists a version prefixed with the word ``main_``, such as ``sol::main_table``, ``sol::main_function``, ``sol::main_object`` and similar. These classes, on construction, assignment and other operations, forcibly obtain the ``lua_State*`` associated with the main thread, if possible. Using these classes will allow your code to be immune when a wrapped coroutine or a lua thread is set to ``nil`` and then garbage-collected. + Advanced: For every single ``sol::reference`` derived type, there exists a version prefixed with the word ``main_``, such as ``sol::main_table``, ``sol::main_function``, ``sol::main_object`` and similar. These classes, on construction, assignment and other operations, forcibly obtain the ``lua_State*`` associated with the main thread, if possible. Using these classes will allow your code to be immune when a wrapped coroutine or a lua thread is set to ``nil`` and then garbage-collected. .. note:: diff --git a/include/sol/optional.hpp b/include/sol/optional.hpp index e4097d47..018ab25f 100644 --- a/include/sol/optional.hpp +++ b/include/sol/optional.hpp @@ -51,6 +51,23 @@ namespace sol { template constexpr inline bool is_optional_v = is_optional::value; } // namespace meta + + namespace detail { + template + struct associated_nullopt { + inline static constexpr std::nullopt_t value = std::nullopt; + }; + +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST + template + struct associated_nullopt> { + inline static constexpr std::nullopt_t value = boost::nullopt; + }; +#endif // Boost nullopt + + template + inline constexpr auto associated_nullopt_v = associated_nullopt::value; + } // namespace detail } // namespace sol #endif // SOL_OPTIONAL_HPP diff --git a/include/sol/stack.hpp b/include/sol/stack.hpp index 03069057..f189ed38 100644 --- a/include/sol/stack.hpp +++ b/include/sol/stack.hpp @@ -1,4 +1,4 @@ -// sol3 +// sol3 // The MIT License (MIT) @@ -40,7 +40,8 @@ namespace sol { namespace detail { - using typical_chunk_name_t = char[32]; + using typical_chunk_name_t = char[SOL_ID_SIZE_]; + using typical_file_chunk_name_t = char[SOL_FILE_ID_SIZE_]; inline const std::string& default_chunk_name() { static const std::string name = ""; @@ -97,7 +98,7 @@ namespace sol { static const std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; typedef std::array data_t; - data_t data{ {} }; + data_t data { {} }; std::memcpy(&data[0], std::addressof(item), itemsize); int pushcount = 0; for (auto&& v : data) { @@ -110,7 +111,7 @@ namespace sol { inline std::pair get_as_upvalues(lua_State* L, int index = 2) { static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); typedef std::array data_t; - data_t voiddata{ {} }; + data_t voiddata { {} }; for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { voiddata[i] = get(L, upvalue_index(index++)); } @@ -123,18 +124,28 @@ namespace sol { } template - static decltype(auto) eval(types, std::index_sequence, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { - return eval(types(), std::index_sequence(), L, start, tracking, std::forward(fx), std::forward(fxargs)..., stack_detail::unchecked_get(L, start + tracking.used, tracking)); + static decltype(auto) eval( + types, std::index_sequence, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { + return eval(types(), + std::index_sequence(), + L, + start, + tracking, + std::forward(fx), + std::forward(fxargs)..., + stack_detail::unchecked_get(L, start + tracking.used, tracking)); } - template + template inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); + static_assert(meta::all...>::value, + "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take " + "a reference and std::move it manually if this was your intention."); if constexpr (checkargs) { - argument_handler> handler{}; + argument_handler> handler {}; multi_check(L, start, handler); } - record tracking{}; + record tracking {}; if constexpr (std::is_void_v) { eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); } @@ -163,7 +174,7 @@ namespace sol { template inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - if constexpr(std::is_void_v) { + if constexpr (std::is_void_v) { call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); } else { @@ -192,7 +203,8 @@ namespace sol { } } - template + template inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { if constexpr (std::is_void_v) { call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); @@ -203,7 +215,8 @@ namespace sol { } else { (void)tr; - decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); + decltype(auto) r + = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); using R = meta::unqualified_t; using is_stack = meta::any, std::is_same, std::is_same, std::is_same>; if constexpr (clean_stack && !is_stack::value) { @@ -233,7 +246,8 @@ namespace sol { return call_syntax::colon; } - inline void script(lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + inline void script( + lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { detail::typical_chunk_name_t basechunkname = {}; const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { @@ -241,7 +255,9 @@ namespace sol { } } - inline void script(lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + inline void script( + lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { diff --git a/include/sol/stack_check_get_unqualified.hpp b/include/sol/stack_check_get_unqualified.hpp index 51be9d2f..93bb7954 100644 --- a/include/sol/stack_check_get_unqualified.hpp +++ b/include/sol/stack_check_get_unqualified.hpp @@ -53,7 +53,7 @@ namespace sol { namespace stack { // expected type, actual type tracking.use(static_cast(success)); handler(L, index, type::poly, type_of(L, index), ""); - return std::nullopt; + return detail::associated_nullopt_v; } return stack_detail::unchecked_get(L, index, tracking); } @@ -81,7 +81,7 @@ namespace sol { namespace stack { const type t = type_of(L, index); tracking.use(static_cast(t != type::none)); handler(L, index, type::number, t, "not an integer"); - return std::nullopt; + return detail::associated_nullopt_v; } else if constexpr (std::is_floating_point_v || std::is_same_v) { int isnum = 0; @@ -90,7 +90,7 @@ namespace sol { namespace stack { type t = type_of(L, index); tracking.use(static_cast(t != type::none)); handler(L, index, type::number, t, "not a valid floating point number"); - return std::nullopt; + return detail::associated_nullopt_v; } tracking.use(1); return static_cast(value); @@ -102,7 +102,7 @@ namespace sol { namespace stack { type t = type_of(L, index); tracking.use(static_cast(t != type::none)); handler(L, index, type::number, t, "not a valid enumeration value"); - return std::nullopt; + return detail::associated_nullopt_v; } tracking.use(1); return static_cast(value); @@ -110,7 +110,7 @@ namespace sol { namespace stack { else { if (!unqualified_check(L, index, std::forward(handler))) { tracking.use(static_cast(!lua_isnone(L, index))); - return std::nullopt; + return detail::associated_nullopt_v; } return stack_detail::unchecked_unqualified_get(L, index, tracking); } @@ -118,7 +118,7 @@ namespace sol { namespace stack { else { if (!unqualified_check(L, index, std::forward(handler))) { tracking.use(static_cast(!lua_isnone(L, index))); - return std::nullopt; + return detail::associated_nullopt_v; } return stack_detail::unchecked_unqualified_get(L, index, tracking); } diff --git a/include/sol/version.hpp b/include/sol/version.hpp index 3e0d612f..a7483b69 100644 --- a/include/sol/version.hpp +++ b/include/sol/version.hpp @@ -62,6 +62,20 @@ #define SOL_STD_VARIANT_ 0 #endif // make is_automagical on/off by default +#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_ID_SIZE_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_ 512 +#endif + +#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 + #define SOL_FILE_ID_SIZE_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_ 2048 +#endif + // clang-format on diff --git a/single/include/sol/forward.hpp b/single/include/sol/forward.hpp index 15a9f471..cb023041 100644 --- a/single/include/sol/forward.hpp +++ b/single/include/sol/forward.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2020-07-04 08:02:02.982843 UTC -// This header was generated with sol v3.2.1 (revision 7d8532b) +// Generated 2020-07-15 13:23:11.320974 UTC +// This header was generated with sol v3.2.1 (revision 6869ad3) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP @@ -232,6 +232,20 @@ #define SOL_STD_VARIANT_ 0 #endif // make is_automagical on/off by default +#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_ID_SIZE_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_ 512 +#endif + +#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 + #define SOL_FILE_ID_SIZE_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_ 2048 +#endif + // end of sol/version.hpp // end of sol/feature_test.hpp diff --git a/single/include/sol/sol.hpp b/single/include/sol/sol.hpp index 6e20d2db..a1344fec 100644 --- a/single/include/sol/sol.hpp +++ b/single/include/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2020-07-04 08:02:02.484853 UTC -// This header was generated with sol v3.2.1 (revision 7d8532b) +// Generated 2020-07-15 13:23:10.917866 UTC +// This header was generated with sol v3.2.1 (revision 6869ad3) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -258,6 +258,20 @@ #define SOL_STD_VARIANT_ 0 #endif // make is_automagical on/off by default +#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_ID_SIZE_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_ 512 +#endif + +#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 + #define SOL_FILE_ID_SIZE_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_ 2048 +#endif + // end of sol/version.hpp // end of sol/feature_test.hpp @@ -5743,6 +5757,23 @@ namespace sol { template constexpr inline bool is_optional_v = is_optional::value; } // namespace meta + + namespace detail { + template + struct associated_nullopt { + inline static constexpr std::nullopt_t value = std::nullopt; + }; + +#if defined(SOL_USE_BOOST) && SOL_USE_BOOST + template + struct associated_nullopt> { + inline static constexpr std::nullopt_t value = boost::nullopt; + }; +#endif // Boost nullopt + + template + inline constexpr auto associated_nullopt_v = associated_nullopt::value; + } // namespace detail } // namespace sol // end of sol/optional.hpp @@ -12716,7 +12747,7 @@ namespace sol { namespace stack { // expected type, actual type tracking.use(static_cast(success)); handler(L, index, type::poly, type_of(L, index), ""); - return std::nullopt; + return detail::associated_nullopt_v; } return stack_detail::unchecked_get(L, index, tracking); } @@ -12744,7 +12775,7 @@ namespace sol { namespace stack { const type t = type_of(L, index); tracking.use(static_cast(t != type::none)); handler(L, index, type::number, t, "not an integer"); - return std::nullopt; + return detail::associated_nullopt_v; } else if constexpr (std::is_floating_point_v || std::is_same_v) { int isnum = 0; @@ -12753,7 +12784,7 @@ namespace sol { namespace stack { type t = type_of(L, index); tracking.use(static_cast(t != type::none)); handler(L, index, type::number, t, "not a valid floating point number"); - return std::nullopt; + return detail::associated_nullopt_v; } tracking.use(1); return static_cast(value); @@ -12765,7 +12796,7 @@ namespace sol { namespace stack { type t = type_of(L, index); tracking.use(static_cast(t != type::none)); handler(L, index, type::number, t, "not a valid enumeration value"); - return std::nullopt; + return detail::associated_nullopt_v; } tracking.use(1); return static_cast(value); @@ -12773,7 +12804,7 @@ namespace sol { namespace stack { else { if (!unqualified_check(L, index, std::forward(handler))) { tracking.use(static_cast(!lua_isnone(L, index))); - return std::nullopt; + return detail::associated_nullopt_v; } return stack_detail::unchecked_unqualified_get(L, index, tracking); } @@ -12781,7 +12812,7 @@ namespace sol { namespace stack { else { if (!unqualified_check(L, index, std::forward(handler))) { tracking.use(static_cast(!lua_isnone(L, index))); - return std::nullopt; + return detail::associated_nullopt_v; } return stack_detail::unchecked_unqualified_get(L, index, tracking); } @@ -14405,7 +14436,8 @@ namespace stack { namespace sol { namespace detail { - using typical_chunk_name_t = char[32]; + using typical_chunk_name_t = char[SOL_ID_SIZE_]; + using typical_file_chunk_name_t = char[SOL_FILE_ID_SIZE_]; inline const std::string& default_chunk_name() { static const std::string name = ""; @@ -14462,7 +14494,7 @@ namespace sol { static const std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; typedef std::array data_t; - data_t data{ {} }; + data_t data { {} }; std::memcpy(&data[0], std::addressof(item), itemsize); int pushcount = 0; for (auto&& v : data) { @@ -14475,7 +14507,7 @@ namespace sol { inline std::pair get_as_upvalues(lua_State* L, int index = 2) { static const std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); typedef std::array data_t; - data_t voiddata{ {} }; + data_t voiddata { {} }; for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { voiddata[i] = get(L, upvalue_index(index++)); } @@ -14488,18 +14520,28 @@ namespace sol { } template - static decltype(auto) eval(types, std::index_sequence, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { - return eval(types(), std::index_sequence(), L, start, tracking, std::forward(fx), std::forward(fxargs)..., stack_detail::unchecked_get(L, start + tracking.used, tracking)); + static decltype(auto) eval( + types, std::index_sequence, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { + return eval(types(), + std::index_sequence(), + L, + start, + tracking, + std::forward(fx), + std::forward(fxargs)..., + stack_detail::unchecked_get(L, start + tracking.used, tracking)); } - template + template inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { - static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); + static_assert(meta::all...>::value, + "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take " + "a reference and std::move it manually if this was your intention."); if constexpr (checkargs) { - argument_handler> handler{}; + argument_handler> handler {}; multi_check(L, start, handler); } - record tracking{}; + record tracking {}; if constexpr (std::is_void_v) { eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); } @@ -14528,7 +14570,7 @@ namespace sol { template inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { - if constexpr(std::is_void_v) { + if constexpr (std::is_void_v) { call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); } else { @@ -14557,7 +14599,8 @@ namespace sol { } } - template + template inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { if constexpr (std::is_void_v) { call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); @@ -14568,7 +14611,8 @@ namespace sol { } else { (void)tr; - decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); + decltype(auto) r + = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); using R = meta::unqualified_t; using is_stack = meta::any, std::is_same, std::is_same, std::is_same>; if constexpr (clean_stack && !is_stack::value) { @@ -14598,7 +14642,8 @@ namespace sol { return call_syntax::colon; } - inline void script(lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + inline void script( + lua_State* L, lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { detail::typical_chunk_name_t basechunkname = {}; const char* chunknametarget = detail::make_chunk_name("lua_Reader", chunkname, basechunkname); if (lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { @@ -14606,7 +14651,9 @@ namespace sol { } } - inline void script(lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + inline void script( + lua_State* L, const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { + detail::typical_chunk_name_t basechunkname = {}; const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname); if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) {