gcc plagues me , and will continue to, for a while to come

BUT IT WOOORKS!
This commit is contained in:
ThePhD 2017-08-07 02:07:21 -04:00
parent 03c229b25b
commit ca685e01c9
18 changed files with 544 additions and 324 deletions

1
.gitignore vendored
View File

@ -79,3 +79,4 @@ lua-5.3.4/
temp.bad_runtime.lua temp.bad_runtime.lua
temp.bad_syntax.lua temp.bad_syntax.lua
temp.good.lua temp.good.lua
catch_mock.hpp

View File

@ -57,4 +57,4 @@ Finally, there is a special abstraction that provides further stack optimization
.. warning:: .. warning::
Do not use ``sol::stack_top`` with a ``sol::stack_aligned_protected_function``. The default behavior checks if the ``error_handler`` member variable is valid, and attempts to push the handler onto the stack in preparation for calling the function. This inevitably changes the stack. Only use ``sol::stack_aligned_protected_function`` if you know that the handler is not valid (``nil``), or if you use ``sol::stack_aligned_stack_handler_protected_function``, which references an existing stack index that can be before the precise placement of the function and its arguments. Do not use ``sol::stack_count`` with a ``sol::stack_aligned_protected_function``. The default behavior checks if the ``error_handler`` member variable is valid, and attempts to push the handler onto the stack in preparation for calling the function. This inevitably changes the stack. Only use ``sol::stack_aligned_protected_function`` with ``sol::stack_count`` if you know that the handler is not valid (it is ``nil`` or its ``error_handler.valid()`` function returns ``false``), or if you use ``sol::stack_aligned_stack_handler_protected_function``, which references an existing stack index that can be before the precise placement of the function and its arguments.

View File

@ -56,5 +56,7 @@ end
)" )"
); );
std::cout << std::endl;
return 0; return 0;
} }

View File

@ -81,5 +81,7 @@ int main() {
lua.script("f()", freshenv); lua.script("f()", freshenv);
lua.script("g()", freshenv); lua.script("g()", freshenv);
std::cout << std::endl;
return 0; return 0;
} }

View File

@ -34,7 +34,7 @@ obj = object.new()
obj:print() obj:print()
)"); )");
object& obj = lua["obj"]; cpp_class& obj = lua["obj"];
assert(obj.value == 1); assert(obj.value == 1);
return 0; return 0;

View File

@ -21,9 +21,9 @@ return 24
// and then rely on the `lua_atpanic` function being called // and then rely on the `lua_atpanic` function being called
// and trapping errors there before exiting the application // and trapping errors there before exiting the application
{ {
// default_on_error throws / panics when the code is bad: trap the error // script_default_on_error throws / panics when the code is bad: trap the error
try { try {
int value = lua.script(code, sol::default_on_error); int value = lua.script(code, sol::script_default_on_error);
// This will never be reached // This will never be reached
std::cout << value << std::endl; std::cout << value << std::endl;
assert(value == 24); assert(value == 24);
@ -34,12 +34,12 @@ return 24
} }
/* OPTION 2 */ /* OPTION 2 */
// Use the simple_on_error handler // Use the script_pass_on_error handler
// this simply passes through the protected_function_result, // this simply passes through the protected_function_result,
// rather than throwing it or calling panic // rather than throwing it or calling panic
// This will check code validity and also whether or not it runs well // This will check code validity and also whether or not it runs well
{ {
sol::protected_function_result result = lua.script(code, sol::simple_on_error); sol::protected_function_result result = lua.script(code, sol::script_pass_on_error);
assert(!result.valid()); assert(!result.valid());
if (!result.valid()) { if (!result.valid()) {
sol::error err = result; sol::error err = result;
@ -79,5 +79,7 @@ return 24
} }
} }
std::cout << std::endl;
return 0; return 0;
} }

View File

@ -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-08-05 23:28:30.507703 UTC // Generated 2017-08-07 06:06:53.826612 UTC
// This header was generated with sol v2.18.0 (revision ee67f88) // This header was generated with sol v2.18.0 (revision 03c229b)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -172,14 +172,14 @@ namespace sol {
using stack_environment = basic_environment<stack_reference>; using stack_environment = basic_environment<stack_reference>;
template <typename T, bool> template <typename T, bool>
class basic_function; class basic_function;
template <typename T, bool> template <typename T, bool, typename H>
class basic_protected_function; class basic_protected_function;
using unsafe_function = basic_function<reference, false>; using unsafe_function = basic_function<reference, false>;
using safe_function = basic_protected_function<reference, false>; using safe_function = basic_protected_function<reference, false, reference>;
using stack_unsafe_function = basic_function<stack_reference, false>; using stack_unsafe_function = basic_function<stack_reference, false>;
using stack_safe_function = basic_protected_function<stack_reference, false>; using stack_safe_function = basic_protected_function<stack_reference, false, reference>;
using stack_aligned_unsafe_function = basic_function<stack_reference, true>; using stack_aligned_unsafe_function = basic_function<stack_reference, true>;
using stack_aligned_safe_function = basic_protected_function<stack_reference, true>; using stack_aligned_safe_function = basic_protected_function<stack_reference, true, reference>;
using protected_function = safe_function; using protected_function = safe_function;
using stack_protected_function = stack_safe_function; using stack_protected_function = stack_safe_function;
using stack_aligned_protected_function = stack_aligned_safe_function; using stack_aligned_protected_function = stack_aligned_safe_function;
@ -192,6 +192,8 @@ namespace sol {
using stack_function = stack_unsafe_function; using stack_function = stack_unsafe_function;
using stack_aligned_function = stack_aligned_unsafe_function; using stack_aligned_function = stack_aligned_unsafe_function;
#endif #endif
using stack_aligned_stack_handler_function = basic_protected_function<stack_reference, true, stack_reference>;
struct function_result; struct function_result;
struct protected_function_result; struct protected_function_result;
using safe_function_result = protected_function_result; using safe_function_result = protected_function_result;
@ -3388,10 +3390,22 @@ namespace sol {
return 0; return 0;
} }
const char* c_str() const { const char* begin() const {
return p; return p;
} }
const char* end() const {
return p + s;
}
const char* cbegin() const {
return p;
}
const char* cend() const {
return p + s;
}
const char* data() const { const char* data() const {
return p; return p;
} }
@ -3426,6 +3440,8 @@ namespace sol {
}; };
#endif // C++17 #endif // C++17
} }
typedef string_detail::string_shim string_view;
} }
// end of sol/string_shim.hpp // end of sol/string_shim.hpp
@ -4064,7 +4080,7 @@ namespace sol {
inline int type_panic(lua_State* L, int index, type expected, type actual) noexcept(false) { inline int type_panic(lua_State* L, int index, type expected, type actual) noexcept(false) {
return luaL_error(L, "stack index %d, expected %s, received %s", index, return luaL_error(L, "stack index %d, expected %s, received %s", index,
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)), expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)),
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(actual)) actual == type::poly ? "anything" : lua_typename(L, static_cast<int>(actual))
); );
} }
@ -4266,8 +4282,8 @@ namespace sol {
template <typename Base, bool aligned> template <typename Base, bool aligned>
struct lua_type_of<basic_function<Base, aligned>> : std::integral_constant<type, type::function> {}; struct lua_type_of<basic_function<Base, aligned>> : std::integral_constant<type, type::function> {};
template <typename Base, bool aligned> template <typename Base, bool aligned, typename Handler>
struct lua_type_of<basic_protected_function<Base, aligned>> : std::integral_constant<type, type::function> {}; struct lua_type_of<basic_protected_function<Base, aligned, Handler>> : std::integral_constant<type, type::function> {};
template <> template <>
struct lua_type_of<coroutine> : std::integral_constant<type, type::function> {}; struct lua_type_of<coroutine> : std::integral_constant<type, type::function> {};
@ -4430,7 +4446,7 @@ namespace sol {
struct is_variadic_arguments : std::is_same<meta::unqualified_t<T>, variadic_args> {}; struct is_variadic_arguments : std::is_same<meta::unqualified_t<T>, variadic_args> {};
template <typename T> template <typename T>
struct is_lua_index : std::false_type {}; struct is_lua_index : std::is_integral<T> {};
template <> template <>
struct is_lua_index<raw_index> : std::true_type {}; struct is_lua_index<raw_index> : std::true_type {};
template <> template <>
@ -4461,8 +4477,8 @@ namespace sol {
struct is_function : std::false_type {}; struct is_function : std::false_type {};
template <typename T, bool aligned> template <typename T, bool aligned>
struct is_function<basic_function<T, aligned>> : std::true_type {}; struct is_function<basic_function<T, aligned>> : std::true_type {};
template <typename T, bool aligned> template <typename T, bool aligned, typename Handler>
struct is_function<basic_protected_function<T, aligned>> : std::true_type{}; struct is_function<basic_protected_function<T, aligned, Handler>> : std::true_type{};
template <typename T> template <typename T>
struct is_lightuserdata : std::false_type {}; struct is_lightuserdata : std::false_type {};
@ -4503,6 +4519,7 @@ namespace sol {
public: public:
stack_reference() noexcept = default; stack_reference() noexcept = default;
stack_reference(lua_nil_t) noexcept : stack_reference() {}; stack_reference(lua_nil_t) noexcept : stack_reference() {};
stack_reference(lua_State* L, lua_nil_t) noexcept : L(L), index(0) {}
stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {} stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {}
stack_reference(lua_State* L, absolute_index i) noexcept : L(L), index(i) {} stack_reference(lua_State* L, absolute_index i) noexcept : L(L), index(i) {}
stack_reference(lua_State* L, raw_index i) noexcept : L(L), index(i) {} stack_reference(lua_State* L, raw_index i) noexcept : L(L), index(i) {}
@ -4693,6 +4710,7 @@ namespace sol {
lua_rawgeti(L, LUA_REGISTRYINDEX, index.index); lua_rawgeti(L, LUA_REGISTRYINDEX, index.index);
ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX);
} }
reference(lua_State* L, lua_nil_t) noexcept : luastate(L) {}
~reference() noexcept { ~reference() noexcept {
deref(); deref();
@ -5052,14 +5070,16 @@ namespace sol {
} }
template <typename V, typename Al> template <typename V, typename Al>
static int get_size_hint(const std::forward_list<V, Al>& c) { static int get_size_hint(const std::forward_list<V, Al>&) {
// forward_list makes me sad // forward_list makes me sad
return static_cast<int>(32); return static_cast<int>(32);
} }
template<typename T> template<typename T>
inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) {
return getter<meta::unqualified_t<T>>{}.get(L, index, tracking); getter<meta::unqualified_t<T>> g{};
(void)g;
return g.get(L, index, tracking);
} }
template<typename T, typename Arg, typename... Args> template<typename T, typename Arg, typename... Args>
@ -6129,7 +6149,7 @@ namespace sol {
template<typename T, typename> template<typename T, typename>
struct getter { struct getter {
static T& get(lua_State* L, int index, record& tracking) { static T& get(lua_State* L, int index, record& tracking) {
return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking); return getter<detail::as_value_tag<T>>{}.get(L, index, tracking);
} }
}; };
@ -6303,7 +6323,7 @@ namespace sol {
} }
template <typename V> template <typename V>
static C get(types<V> t, lua_State* L, int relindex, record& tracking) { static C get(types<V>, lua_State* L, int relindex, record& tracking) {
tracking.use(1); tracking.use(1);
int index = lua_absindex(L, relindex); int index = lua_absindex(L, relindex);
@ -8248,9 +8268,27 @@ namespace sol {
namespace sol { namespace sol {
namespace detail { namespace detail {
inline const std::string& default_chunk_name() { inline const std::string& default_chunk_name() {
static const std::string name = "string"; static const std::string name = "script";
return name; return name;
} }
template <std::size_t N>
const char* make_chunk_name(const string_view& code, const std::string& chunkname, char (&basechunkname)[N]) {
if (chunkname.empty()) {
auto it = code.cbegin();
auto e = code.cend();
std::size_t i = 0;
static const std::size_t n = N - 1;
for (i = 0; i < n && it != e; ++i, ++it) {
basechunkname[i] = *it;
}
basechunkname[i] = '\0';
return &basechunkname[0];
}
else {
return chunkname.c_str();
}
}
} // detail } // detail
namespace stack { namespace stack {
@ -8389,8 +8427,10 @@ namespace sol {
return call_syntax::colon; return call_syntax::colon;
} }
inline void script(lua_State* L, const string_detail::string_shim& code, string_detail::string_shim name = detail::default_chunk_name(), load_mode mode = load_mode::any) { inline void script(lua_State* L, const string_detail::string_shim& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
if (luaL_loadbufferx(L, code.data(), code.size(), name.data(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { char basechunkname[17] = {};
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)) {
lua_error(L); lua_error(L);
} }
} }
@ -8481,9 +8521,7 @@ namespace sol {
// Must be manual, otherwise destructor will screw us // Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean // return count being 0 is enough to keep things clean
// but will be thorough // but will be thorough
o.L = nullptr; o.abandon();
o.index = 0;
o.returncount = 0;
} }
function_result& operator=(function_result&& o) { function_result& operator=(function_result&& o) {
L = o.L; L = o.L;
@ -8492,9 +8530,7 @@ namespace sol {
// Must be manual, otherwise destructor will screw us // Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean // return count being 0 is enough to keep things clean
// but will be thorough // but will be thorough
o.L = nullptr; o.abandon();
o.index = 0;
o.returncount = 0;
return *this; return *this;
} }
@ -8514,7 +8550,11 @@ namespace sol {
lua_State* lua_state() const { return L; }; lua_State* lua_state() const { return L; };
int stack_index() const { return index; }; int stack_index() const { return index; };
int return_count() const { return returncount; }; int return_count() const { return returncount; };
void abandon() noexcept {
L = nullptr;
index = 0;
returncount = 0;
}
~function_result() { ~function_result() {
lua_pop(L, returncount); lua_pop(L, returncount);
} }
@ -10762,11 +10802,7 @@ namespace sol {
// Must be manual, otherwise destructor will screw us // Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean // return count being 0 is enough to keep things clean
// but we will be thorough // but we will be thorough
o.L = nullptr; o.abandon();
o.index = 0;
o.returncount = 0;
o.popcount = 0;
o.err = call_status::runtime;
} }
protected_function_result& operator=(protected_function_result&& o) noexcept { protected_function_result& operator=(protected_function_result&& o) noexcept {
L = o.L; L = o.L;
@ -10777,11 +10813,7 @@ namespace sol {
// Must be manual, otherwise destructor will screw us // Must be manual, otherwise destructor will screw us
// return count being 0 is enough to keep things clean // return count being 0 is enough to keep things clean
// but we will be thorough // but we will be thorough
o.L = nullptr; o.abandon();
o.index = 0;
o.returncount = 0;
o.popcount = 0;
o.err = call_status::runtime;
return *this; return *this;
} }
@ -10802,7 +10834,13 @@ namespace sol {
int stack_index() const noexcept { return index; }; int stack_index() const noexcept { return index; };
int return_count() const noexcept { return returncount; }; int return_count() const noexcept { return returncount; };
int pop_count() const noexcept { return popcount; }; int pop_count() const noexcept { return popcount; };
void abandon() noexcept {
L = nullptr;
index = 0;
returncount = 0;
popcount = 0;
err = call_status::runtime;
}
~protected_function_result() { ~protected_function_result() {
stack::remove(L, index, popcount); stack::remove(L, index, popcount);
} }
@ -10834,63 +10872,90 @@ namespace sol {
return name; return name;
} }
template <bool b, typename target_t = reference>
struct handler { struct handler {
const reference& target; typedef std::is_base_of<stack_reference, target_t> is_stack;
const target_t& target;
int stackindex; int stackindex;
handler(const reference& target) : target(target), stackindex(0) {
if (target.valid()) { handler(std::false_type, const target_t& target) : target(target), stackindex(0) {
if (b) {
stackindex = lua_gettop(target.lua_state()) + 1; stackindex = lua_gettop(target.lua_state()) + 1;
target.push(); target.push();
} }
} }
bool valid() const { return stackindex != 0; }
handler(std::true_type, const target_t& target) : target(target), stackindex(0) {
if (b) {
stackindex = target.stack_index();
}
}
handler(const target_t& target) : handler(is_stack(), target) {}
bool valid() const noexcept { return b; }
~handler() { ~handler() {
if (valid()) { if (!is_stack::value && stackindex != 0) {
lua_remove(target.lua_state(), stackindex); lua_remove(target.lua_state(), stackindex);
} }
} }
}; };
} } // detail
template <typename base_t, bool aligned = false> template <typename base_t, bool aligned = false, typename handler_t = reference>
class basic_protected_function : public base_t { class basic_protected_function : public base_t {
public: public:
static reference get_default_handler(lua_State* L) { typedef std::is_base_of<stack_reference, handler_t> is_stack_handler;
if (L == nullptr)
return reference(lua_nil); static handler_t get_default_handler(lua_State* L) {
if (is_stack_handler::value || L == nullptr)
return handler_t(L, lua_nil);
lua_getglobal(L, detail::default_handler_name()); lua_getglobal(L, detail::default_handler_name());
auto pp = stack::pop_n(L, 1); auto pp = stack::pop_n(L, 1);
return reference(L, -1); return handler_t(L, -1);
} }
static void set_default_handler(const reference& ref) { template <typename T>
static void set_default_handler(const T& ref) {
if (ref.lua_state() == nullptr) {
return;
}
if (!ref.valid()) {
lua_pushnil(ref.lua_state());
lua_setglobal(ref.lua_state(), detail::default_handler_name());
}
else {
ref.push(); ref.push();
lua_setglobal(ref.lua_state(), detail::default_handler_name()); lua_setglobal(ref.lua_state(), detail::default_handler_name());
} }
}
private: private:
call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::handler& h) const { template <bool b>
call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::handler<b, handler_t>& h) const {
return static_cast<call_status>(lua_pcallk(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr)); return static_cast<call_status>(lua_pcallk(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr));
} }
template<std::size_t... I, typename... Ret> template<std::size_t... I, bool b, typename... Ret>
auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, detail::handler& h) const { auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, detail::handler<b, handler_t>& h) const {
luacall(n, sizeof...(Ret), h); luacall(n, sizeof...(Ret), h);
return stack::pop<std::tuple<Ret...>>(lua_state()); return stack::pop<std::tuple<Ret...>>(lua_state());
} }
template<std::size_t I, typename Ret> template<std::size_t I, bool b, typename Ret>
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler& h) const { Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler<b, handler_t>& h) const {
luacall(n, 1, h); luacall(n, 1, h);
return stack::pop<Ret>(lua_state()); return stack::pop<Ret>(lua_state());
} }
template <std::size_t I> template <std::size_t I, bool b>
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler& h) const { void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, detail::handler<b, handler_t>& h) const {
luacall(n, 0, h); luacall(n, 0, h);
} }
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::handler& h) const { template <bool b>
protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::handler<b, handler_t>& h) const {
int stacksize = lua_gettop(lua_state()); int stacksize = lua_gettop(lua_state());
int poststacksize = stacksize; int poststacksize = stacksize;
int firstreturn = 1; int firstreturn = 1;
@ -10899,7 +10964,7 @@ namespace sol {
#ifndef SOL_NO_EXCEPTIONS #ifndef SOL_NO_EXCEPTIONS
auto onexcept = [&](const char* error) { auto onexcept = [&](const char* error) {
h.stackindex = 0; h.stackindex = 0;
if (h.target.valid()) { if (b) {
h.target.push(); h.target.push();
stack::push(lua_state(), error); stack::push(lua_state(), error);
lua_call(lua_state(), 1, 1); lua_call(lua_state(), 1, 1);
@ -10939,10 +11004,15 @@ namespace sol {
public: public:
using base_t::lua_state; using base_t::lua_state;
reference error_handler; handler_t error_handler;
basic_protected_function() = default; basic_protected_function() = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<
meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>,
meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>,
meta::neg<std::is_same<base_t, stack_reference>>,
std::is_base_of<base_t, meta::unqualified_t<T>>
> = meta::enabler>
basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)) { basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
if (!is_function<meta::unqualified_t<T>>::value) { if (!is_function<meta::unqualified_t<T>>::value) {
@ -10957,40 +11027,48 @@ namespace sol {
basic_protected_function& operator=(basic_protected_function&&) = default; basic_protected_function& operator=(basic_protected_function&&) = default;
basic_protected_function(const basic_function<base_t>& b) : basic_protected_function(b, get_default_handler(b.lua_state())) {} basic_protected_function(const basic_function<base_t>& b) : basic_protected_function(b, get_default_handler(b.lua_state())) {}
basic_protected_function(basic_function<base_t>&& b) : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) {} basic_protected_function(basic_function<base_t>&& b) : basic_protected_function(std::move(b), get_default_handler(b.lua_state())) {}
basic_protected_function(const basic_function<base_t>& b, reference eh) : base_t(b), error_handler(std::move(eh)) {} basic_protected_function(const basic_function<base_t>& b, handler_t eh) : base_t(b), error_handler(std::move(eh)) {}
basic_protected_function(basic_function<base_t>&& b, reference eh) : base_t(std::move(b)), error_handler(std::move(eh)) {} basic_protected_function(basic_function<base_t>&& b, handler_t eh) : base_t(std::move(b)), error_handler(std::move(eh)) {}
basic_protected_function(const stack_reference& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {} basic_protected_function(const stack_reference& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {}
basic_protected_function(stack_reference&& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {} basic_protected_function(stack_reference&& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {}
basic_protected_function(const stack_reference& r, reference eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} basic_protected_function(const stack_reference& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {}
basic_protected_function(stack_reference&& r, reference eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} basic_protected_function(stack_reference&& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {}
template <typename Super> template <typename Super>
basic_protected_function(const proxy_base<Super>& p) : basic_protected_function(p.operator basic_function<base_t>(), get_default_handler(p.lua_state())) {} basic_protected_function(const proxy_base<Super>& p) : basic_protected_function(p, get_default_handler(p.lua_state())) {}
template <typename Super> template <typename Super>
basic_protected_function(proxy_base<Super>&& p) : basic_protected_function(p.operator basic_function<base_t>(), get_default_handler(p.lua_state())) {} basic_protected_function(proxy_base<Super>&& p) : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) {}
template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler> template <typename Proxy, typename Handler, meta::enable<
std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>,
meta::neg<is_lua_index<meta::unqualified_t<Handler>>>
> = meta::enabler>
basic_protected_function(Proxy&& p, Handler&& eh) : basic_protected_function(p.operator basic_function<base_t>(), std::forward<Handler>(eh)) {}
template <typename T, meta::enable<meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler>
basic_protected_function(lua_State* L, T&& r) : basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) {} basic_protected_function(lua_State* L, T&& r) : basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) {}
template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler> template <typename T, meta::enable<meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler>
basic_protected_function(lua_State* L, T&& r, reference eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {} basic_protected_function(lua_State* L, T&& r, handler_t eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {}
basic_protected_function(lua_State* L, int index = -1) : basic_protected_function(L, index, get_default_handler(L)) {} basic_protected_function(lua_State* L, int index = -1) : basic_protected_function(L, index, get_default_handler(L)) {}
basic_protected_function(lua_State* L, int index, reference eh) : base_t(L, index), error_handler(std::move(eh)) { basic_protected_function(lua_State* L, int index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
stack::check<basic_protected_function>(L, index, type_panic); stack::check<basic_protected_function>(L, index, type_panic);
#endif // Safety #endif // Safety
} }
basic_protected_function(lua_State* L, absolute_index index) : basic_protected_function(L, index, get_default_handler(L)) {} basic_protected_function(lua_State* L, absolute_index index) : basic_protected_function(L, index, get_default_handler(L)) {}
basic_protected_function(lua_State* L, absolute_index index, reference eh) : base_t(L, index), error_handler(std::move(eh)) { basic_protected_function(lua_State* L, absolute_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
stack::check<basic_protected_function>(L, index, type_panic); stack::check<basic_protected_function>(L, index, type_panic);
#endif // Safety #endif // Safety
} }
basic_protected_function(lua_State* L, raw_index index) : basic_protected_function(L, index, get_default_handler(L)) {} basic_protected_function(lua_State* L, raw_index index) : basic_protected_function(L, index, get_default_handler(L)) {}
basic_protected_function(lua_State* L, raw_index index, reference eh) : base_t(L, index), error_handler(std::move(eh)) { basic_protected_function(lua_State* L, raw_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
stack::check<basic_protected_function>(L, index, type_panic); stack::check<basic_protected_function>(L, index, type_panic);
#endif // Safety #endif // Safety
} }
basic_protected_function(lua_State* L, ref_index index) : basic_protected_function(L, index, get_default_handler(L)) {} basic_protected_function(lua_State* L, ref_index index) : basic_protected_function(L, index, get_default_handler(L)) {}
basic_protected_function(lua_State* L, ref_index index, reference eh) : base_t(L, index), error_handler(std::move(eh)) { basic_protected_function(lua_State* L, ref_index index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
auto pp = stack::push_pop(*this); auto pp = stack::push_pop(*this);
stack::check<basic_protected_function>(L, -1, type_panic); stack::check<basic_protected_function>(L, -1, type_panic);
@ -11009,13 +11087,46 @@ namespace sol {
template<typename... Ret, typename... Args> template<typename... Ret, typename... Args>
decltype(auto) call(Args&&... args) const { decltype(auto) call(Args&&... args) const {
detail::handler h(error_handler);
if (!aligned) { if (!aligned) {
// we do not expect the function to already be on the stack: push it
if (error_handler.valid()) {
detail::handler<true, handler_t> h(error_handler);
base_t::push(); base_t::push();
int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
}
else {
detail::handler<false, handler_t> h(error_handler);
base_t::push();
int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
}
}
else {
// the function is already on the stack at the right location
if (error_handler.valid()) {
// the handler will be pushed onto the stack manually,
// since it's not already on the stack this means we need to push our own
// function on the stack too and swap things to be in-place
if (!is_stack_handler::value) {
// so, we need to remove the function at the top and then dump the handler out ourselves
base_t::push();
}
detail::handler<true, handler_t> h(error_handler);
if (!is_stack_handler::value) {
lua_replace(lua_state(), -3);
h.stackindex = lua_absindex(lua_state(), -2);
} }
int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...); int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h); return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
} }
else {
detail::handler<false, handler_t> h(error_handler);
int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
return invoke(types<Ret...>(), std::make_index_sequence<sizeof...(Ret)>(), pushcount, h);
}
}
}
}; };
} // sol } // sol
@ -13594,7 +13705,7 @@ namespace sol {
typedef typename T::value_type value_type; typedef typename T::value_type value_type;
typedef std::conditional_t<is_associative::value, typedef std::conditional_t<is_associative::value,
value_type, value_type,
std::conditional_t<is_lookup::value, std::pair<value_type, value_type>, std::pair<std::size_t, value_type>> std::conditional_t<is_lookup::value, std::pair<value_type, value_type>, std::pair<std::ptrdiff_t, value_type>>
> KV; > KV;
typedef typename KV::first_type K; typedef typename KV::first_type K;
typedef typename KV::second_type V; typedef typename KV::second_type V;
@ -13602,7 +13713,7 @@ namespace sol {
typedef typename meta::iterator_tag<iterator>::type iterator_category; typedef typename meta::iterator_tag<iterator>::type iterator_category;
typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator; typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
typedef std::conditional_t<is_input_iterator::value, typedef std::conditional_t<is_input_iterator::value,
std::add_lvalue_reference_t<V>, V,
std::conditional_t<is_associative::value, std::add_lvalue_reference_t<V>, iterator_return> std::conditional_t<is_associative::value, std::add_lvalue_reference_t<V>, iterator_return>
> push_type; > push_type;
typedef std::is_copy_assignable<V> is_copyable; typedef std::is_copy_assignable<V> is_copyable;
@ -13635,11 +13746,11 @@ namespace sol {
static int get_associative(std::true_type, lua_State* L, iterator& it) { static int get_associative(std::true_type, lua_State* L, iterator& it) {
auto& v = *it; auto& v = *it;
return stack::push_reference(L, v.second); return stack::stack_detail::push_reference<push_type>(L, v.second);
} }
static int get_associative(std::false_type, lua_State* L, iterator& it) { static int get_associative(std::false_type, lua_State* L, iterator& it) {
return stack::push_reference(L, *it); return stack::stack_detail::push_reference<push_type>(L, *it);
} }
static int get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) { static int get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) {
@ -13662,7 +13773,7 @@ namespace sol {
} }
static int get_category(std::random_access_iterator_tag, lua_State* L, T& self, K& key) { static int get_category(std::random_access_iterator_tag, lua_State* L, T& self, K& key) {
std::size_t len = size_start(L, self); std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self));
if (key < 1 || key > len) { if (key < 1 || key > len) {
return stack::push(L, lua_nil); return stack::push(L, lua_nil);
} }
@ -13726,7 +13837,7 @@ namespace sol {
add_copyable(is_copyable(), L, self, std::move(value), meta::has_insert_after<T>::value ? backit : it); add_copyable(is_copyable(), L, self, std::move(value), meta::has_insert_after<T>::value ? backit : it);
return; return;
} }
// TODO: error here in safety mode luaL_error(L, "out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
set_writable(is_writable(), L, self, it, std::move(value)); set_writable(is_writable(), L, self, it, std::move(value));
@ -13734,18 +13845,18 @@ namespace sol {
static void set_category(std::random_access_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) { static void set_category(std::random_access_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) {
decltype(auto) key = okey.as<K>(); decltype(auto) key = okey.as<K>();
std::size_t len = size_start(L, self);
if (key < 1) { if (key < 1) {
// error here in safety mode luaL_error(L, "sol: out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
--key; --key;
std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self));
if (key == len) { if (key == len) {
add_copyable(is_copyable(), L, self, std::move(value)); add_copyable(is_copyable(), L, self, std::move(value));
return; return;
} }
else if (key > len) { else if (key > len) {
// error here in safety mode luaL_error(L, "sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
auto it = std::next(begin(L, self), key); auto it = std::next(begin(L, self), key);
@ -13865,7 +13976,7 @@ namespace sol {
luaL_error(L, "cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", sol::detail::demangle<T>().data()); luaL_error(L, "cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", sol::detail::demangle<T>().data());
} }
static void add_insert_after(std::true_type, lua_State* L, T& self, stack_object value, iterator& at) { static void add_insert_after(std::true_type, lua_State*, T& self, stack_object value, iterator& at) {
self.insert_after(at, value.as<V>()); self.insert_after(at, value.as<V>());
} }
@ -13965,7 +14076,7 @@ namespace sol {
auto e = end(L, self); auto e = end(L, self);
for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) { for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) {
if (backit == e) { if (backit == e) {
// TODO: error here in safety mode luaL_error(L, "sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
} }
@ -14027,7 +14138,7 @@ namespace sol {
auto e = end(L, self); auto e = end(L, self);
for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) { for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) {
if (backit == e) { if (backit == e) {
// TODO: error here in safety mode luaL_error(L, "sol: out of bounds for erase on '%s'", detail::demangle<T>().c_str());
return; return;
} }
} }
@ -14035,7 +14146,7 @@ namespace sol {
self.erase_after(backit); self.erase_after(backit);
} }
static void erase_after_has(std::false_type, lua_State* L, T& self, const K& key) { static void erase_after_has(std::false_type, lua_State* L, T&, const K&) {
luaL_error(L, "sol: cannot call erase on '%s'", detail::demangle<T>().c_str()); luaL_error(L, "sol: cannot call erase on '%s'", detail::demangle<T>().c_str());
} }
@ -14225,15 +14336,13 @@ namespace sol {
}; };
static auto& get_src(lua_State* L) { static auto& get_src(lua_State* L) {
#ifdef SOL_SAFE_USERTYPE
auto p = stack::check_get<T*>(L, 1); auto p = stack::check_get<T*>(L, 1);
#ifdef SOL_SAFE_USERTYPE
if (!p || p.value() == nullptr) { if (!p || p.value() == nullptr) {
luaL_error(L, "sol: 'self' argument is nil or not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str()); luaL_error(L, "sol: 'self' argument is nil or not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str());
} }
return *p.value();
#else
return stack::get<T>(L, 1);
#endif // Safe getting with error #endif // Safe getting with error
return *p.value();
} }
static int find(std::true_type, lua_State* L) { static int find(std::true_type, lua_State* L) {
@ -14287,7 +14396,7 @@ namespace sol {
static int get(lua_State* L) { static int get(lua_State* L) {
T& self = get_src(L); T& self = get_src(L);
std::size_t idx = stack::get<std::size_t>(L, 2); std::ptrdiff_t idx = stack::get<std::ptrdiff_t>(L, 2);
if (idx > std::extent<T>::value || idx < 1) { if (idx > std::extent<T>::value || idx < 1) {
return stack::push(L, lua_nil); return stack::push(L, lua_nil);
} }
@ -14301,9 +14410,12 @@ namespace sol {
static int set(lua_State* L) { static int set(lua_State* L) {
T& self = get_src(L); T& self = get_src(L);
std::size_t idx = stack::get<std::size_t>(L, 2); std::ptrdiff_t idx = stack::get<std::ptrdiff_t>(L, 2);
if (idx > std::extent<T>::value || idx < 1) { if (idx > std::extent<T>::value) {
return luaL_error(L, "sol: index out of bounds on set"); return luaL_error(L, "sol: index out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
}
if (idx < 1) {
return luaL_error(L, "sol: index out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
} }
--idx; --idx;
self[idx] = stack::get<value_type>(L, 3); self[idx] = stack::get<value_type>(L, 3);
@ -15574,7 +15686,7 @@ namespace sol {
err += " error:"; err += " error:";
if (t == type::string) { if (t == type::string) {
err += " "; err += " ";
string_detail::string_shim serr = stack::get<string_detail::string_shim>(L, pfr.stack_index()); string_view serr = stack::get<string_view>(L, pfr.stack_index());
err.append(serr.data(), serr.size()); err.append(serr.data(), serr.size());
} }
#ifdef SOL_NO_EXCEPTIONS #ifdef SOL_NO_EXCEPTIONS
@ -15763,7 +15875,7 @@ namespace sol {
return stack::pop<object>(L); return stack::pop<object>(L);
} }
object require_script(const std::string& key, const string_detail::string_shim& code, bool create_global = true, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { object require_script(const std::string& key, const string_view& code, bool create_global = true, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
return require_core(key, [this, &code, &chunkname, &mode]() {stack::script(L, code, chunkname, mode); }, create_global); return require_core(key, [this, &code, &chunkname, &mode]() {stack::script(L, code, chunkname, mode); }, create_global);
} }
@ -15772,13 +15884,14 @@ namespace sol {
} }
template <typename E> template <typename E>
protected_function_result do_string(const string_detail::string_shim& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result do_string(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunkname.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
if (x != load_status::ok) { if (x != load_status::ok) {
return protected_function_result(L, -1, 0, 1, static_cast<call_status>(x)); return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
} }
protected_function pf(L, -1); stack_aligned_protected_function pf(L, -1);
pf.pop();
set_environment(env, pf); set_environment(env, pf);
return pf(); return pf();
} }
@ -15787,36 +15900,35 @@ namespace sol {
protected_function_result do_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) { protected_function_result do_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
if (x != load_status::ok) { if (x != load_status::ok) {
return protected_function_result(L, -1, 0, 1, static_cast<call_status>(x)); return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
} }
protected_function pf(L, -1); stack_aligned_protected_function pf(L, -1);
pf.pop();
set_environment(env, pf); set_environment(env, pf);
return pf(); return pf();
} }
protected_function_result do_string(const string_detail::string_shim& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result do_string(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunkname.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
if (x != load_status::ok) { if (x != load_status::ok) {
return protected_function_result(L, -1, 0, 1, static_cast<call_status>(x)); return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
} }
protected_function pf(L, -1); stack_aligned_protected_function pf(L, -1);
pf.pop();
return pf(); return pf();
} }
protected_function_result do_file(const std::string& filename, load_mode mode = load_mode::any) { protected_function_result do_file(const std::string& filename, load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
if (x != load_status::ok) { if (x != load_status::ok) {
return protected_function_result(L, -1, 0, 1, static_cast<call_status>(x)); return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
} }
protected_function pf(L, -1); stack_aligned_protected_function pf(L, -1);
pf.pop();
return pf(); return pf();
} }
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler> template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
protected_function_result safe_script(const string_detail::string_shim& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result safe_script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
protected_function_result pfr = do_string(code, chunkname, mode); protected_function_result pfr = do_string(code, chunkname, mode);
if (!pfr.valid()) { if (!pfr.valid()) {
return on_error(L, std::move(pfr)); return on_error(L, std::move(pfr));
@ -15824,18 +15936,27 @@ namespace sol {
return pfr; return pfr;
} }
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler> template <typename Fx, typename E>
protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) { protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
protected_function_result pfr = do_file(filename, mode); protected_function_result pfr = do_string(code, env, chunkname, mode);
if (!pfr.valid()) { if (!pfr.valid()) {
return on_error(L, std::move(pfr)); return on_error(L, std::move(pfr));
} }
return pfr; return pfr;
} }
template <typename Fx, typename E> template <typename E>
protected_function_result safe_script(const string_detail::string_shim& code, const basic_environment<E>& env, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result safe_script(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
protected_function_result pfr = do_string(code, env, chunkname, mode); return safe_script(code, env, script_default_on_error, chunkname, mode);
}
protected_function_result safe_script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
return safe_script(code, script_default_on_error, chunkname, mode);
}
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
protected_function_result safe_script_file(const std::string& filename, Fx&& on_error, load_mode mode = load_mode::any) {
protected_function_result pfr = do_file(filename, mode);
if (!pfr.valid()) { if (!pfr.valid()) {
return on_error(L, std::move(pfr)); return on_error(L, std::move(pfr));
} }
@ -15851,25 +15972,50 @@ namespace sol {
return pfr; return pfr;
} }
protected_function_result safe_script(const string_detail::string_shim& code, const environment& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { template <typename E>
return safe_script(code, env, sol::script_default_on_error, chunkname, mode); protected_function_result safe_script_file(const std::string& filename, const basic_environment<E>& env, load_mode mode = load_mode::any) {
} return safe_script_file(filename, env, script_default_on_error, mode);
protected_function_result safe_script_file(const std::string& filename, const environment& env, load_mode mode = load_mode::any) {
return safe_script_file(filename, env, sol::script_default_on_error, mode);
}
protected_function_result safe_script(const string_detail::string_shim& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
return safe_script(code, sol::script_default_on_error, chunkname, mode);
} }
protected_function_result safe_script_file(const std::string& filename, load_mode mode = load_mode::any) { protected_function_result safe_script_file(const std::string& filename, load_mode mode = load_mode::any) {
return safe_script_file(filename, sol::script_default_on_error, mode); return safe_script_file(filename, script_default_on_error, mode);
} }
function_result unsafe_script(const string_detail::string_shim& code, const std::string& name = detail::default_chunk_name(), load_mode mode = load_mode::any) { template <typename E>
function_result unsafe_script(const string_view& code, const sol::basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
char basechunkname[17] = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
int index = lua_gettop(L); int index = lua_gettop(L);
stack::script(L, code, name, mode); if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())) {
lua_error(L);
}
set_environment(env, stack_reference(L, raw_index(index + 1)));
if (lua_call(L, 0, LUA_MULTRET)) {
lua_error(L);
}
int postindex = lua_gettop(L);
int returns = postindex - index;
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
}
function_result unsafe_script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
int index = lua_gettop(L);
stack::script(L, code, chunkname, mode);
int postindex = lua_gettop(L);
int returns = postindex - index;
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
}
template <typename E>
function_result unsafe_script_file(const std::string& filename, const sol::basic_environment<E>& env, load_mode mode = load_mode::any) {
int index = lua_gettop(L);
if (luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())) {
lua_error(L);
}
set_environment(env, stack_reference(L, raw_index(index + 1)));
if (lua_call(L, 0, LUA_MULTRET)) {
lua_error(L);
}
int postindex = lua_gettop(L); int postindex = lua_gettop(L);
int returns = postindex - index; int returns = postindex - index;
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
@ -15884,7 +16030,7 @@ namespace sol {
} }
template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler> template <typename Fx, meta::disable<meta::is_specialization_of<basic_environment, meta::unqualified_t<Fx>>> = meta::enabler>
protected_function_result script(const string_detail::string_shim& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result script(const string_view& code, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
return safe_script(code, std::forward<Fx>(on_error), chunkname, mode); return safe_script(code, std::forward<Fx>(on_error), chunkname, mode);
} }
@ -15894,7 +16040,7 @@ namespace sol {
} }
template <typename Fx, typename E> template <typename Fx, typename E>
protected_function_result script(const string_detail::string_shim& code, const basic_environment<E>& env, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result script(const string_view& code, const basic_environment<E>& env, Fx&& on_error, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
return safe_script(code, env, std::forward<Fx>(on_error), chunkname, mode); return safe_script(code, env, std::forward<Fx>(on_error), chunkname, mode);
} }
@ -15903,15 +16049,15 @@ namespace sol {
return safe_script_file(filename, env, std::forward<Fx>(on_error), mode); return safe_script_file(filename, env, std::forward<Fx>(on_error), mode);
} }
protected_function_result script(const string_detail::string_shim& code, const environment& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result script(const string_view& code, const environment& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
return safe_script(code, env, sol::script_default_on_error, chunkname, mode); return safe_script(code, env, script_default_on_error, chunkname, mode);
} }
protected_function_result script_file(const std::string& filename, const environment& env, load_mode mode = load_mode::any) { protected_function_result script_file(const std::string& filename, const environment& env, load_mode mode = load_mode::any) {
return safe_script_file(filename, env, sol::script_default_on_error, mode); return safe_script_file(filename, env, script_default_on_error, mode);
} }
function_result script(const string_detail::string_shim& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { function_result script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
return unsafe_script(code, chunkname, mode); return unsafe_script(code, chunkname, mode);
} }
@ -15919,19 +16065,23 @@ namespace sol {
return unsafe_script_file(filename, mode); return unsafe_script_file(filename, mode);
} }
load_result load(const string_detail::string_shim& code, const std::string& name = detail::default_chunk_name(), load_mode mode = load_mode::any) { load_result load(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), name.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
return load_result(L, lua_absindex(L, -1), 1, 1, x); const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
return load_result(L, absolute_index(L, -1), 1, 1, x);
} }
load_result load_file(const std::string& filename, load_mode mode = load_mode::any) { load_result load_file(const std::string& filename, load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
return load_result(L, lua_absindex(L, -1), 1, 1, x); return load_result(L, absolute_index(L, -1), 1, 1, x);
} }
load_result load(lua_Reader reader, void* data, const std::string& name = detail::default_chunk_name(), load_mode mode = load_mode::any) { load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(lua_load(L, reader, data, name.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
return load_result(L, lua_absindex(L, -1), 1, 1, x); const char* chunknametarget = detail::make_chunk_name("lua_reader", chunkname, basechunkname);
load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
return load_result(L, absolute_index(L, -1), 1, 1, x);
} }
iterator begin() const { iterator begin() const {
@ -15962,6 +16112,10 @@ namespace sol {
return total_memory_used(lua_state()); return total_memory_used(lua_state());
} }
int stack_top() const {
return stack::top(L);
}
void collect_garbage() { void collect_garbage() {
lua_gc(lua_state(), LUA_GCCOLLECT, 0); lua_gc(lua_state(), LUA_GCCOLLECT, 0);
} }

View File

@ -381,7 +381,7 @@ namespace sol {
typedef typename T::value_type value_type; typedef typename T::value_type value_type;
typedef std::conditional_t<is_associative::value, typedef std::conditional_t<is_associative::value,
value_type, value_type,
std::conditional_t<is_lookup::value, std::pair<value_type, value_type>, std::pair<std::size_t, value_type>> std::conditional_t<is_lookup::value, std::pair<value_type, value_type>, std::pair<std::ptrdiff_t, value_type>>
> KV; > KV;
typedef typename KV::first_type K; typedef typename KV::first_type K;
typedef typename KV::second_type V; typedef typename KV::second_type V;
@ -389,7 +389,7 @@ namespace sol {
typedef typename meta::iterator_tag<iterator>::type iterator_category; typedef typename meta::iterator_tag<iterator>::type iterator_category;
typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator; typedef std::is_same<iterator_category, std::input_iterator_tag> is_input_iterator;
typedef std::conditional_t<is_input_iterator::value, typedef std::conditional_t<is_input_iterator::value,
std::add_lvalue_reference_t<V>, V,
std::conditional_t<is_associative::value, std::add_lvalue_reference_t<V>, iterator_return> std::conditional_t<is_associative::value, std::add_lvalue_reference_t<V>, iterator_return>
> push_type; > push_type;
typedef std::is_copy_assignable<V> is_copyable; typedef std::is_copy_assignable<V> is_copyable;
@ -422,11 +422,11 @@ namespace sol {
static int get_associative(std::true_type, lua_State* L, iterator& it) { static int get_associative(std::true_type, lua_State* L, iterator& it) {
auto& v = *it; auto& v = *it;
return stack::push_reference(L, v.second); return stack::stack_detail::push_reference<push_type>(L, v.second);
} }
static int get_associative(std::false_type, lua_State* L, iterator& it) { static int get_associative(std::false_type, lua_State* L, iterator& it) {
return stack::push_reference(L, *it); return stack::stack_detail::push_reference<push_type>(L, *it);
} }
static int get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) { static int get_category(std::input_iterator_tag, lua_State* L, T& self, K& key) {
@ -449,7 +449,7 @@ namespace sol {
} }
static int get_category(std::random_access_iterator_tag, lua_State* L, T& self, K& key) { static int get_category(std::random_access_iterator_tag, lua_State* L, T& self, K& key) {
std::size_t len = size_start(L, self); std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self));
if (key < 1 || key > len) { if (key < 1 || key > len) {
return stack::push(L, lua_nil); return stack::push(L, lua_nil);
} }
@ -513,7 +513,7 @@ namespace sol {
add_copyable(is_copyable(), L, self, std::move(value), meta::has_insert_after<T>::value ? backit : it); add_copyable(is_copyable(), L, self, std::move(value), meta::has_insert_after<T>::value ? backit : it);
return; return;
} }
// TODO: error here in safety mode luaL_error(L, "out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
set_writable(is_writable(), L, self, it, std::move(value)); set_writable(is_writable(), L, self, it, std::move(value));
@ -521,18 +521,18 @@ namespace sol {
static void set_category(std::random_access_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) { static void set_category(std::random_access_iterator_tag, lua_State* L, T& self, stack_object okey, stack_object value) {
decltype(auto) key = okey.as<K>(); decltype(auto) key = okey.as<K>();
std::size_t len = size_start(L, self);
if (key < 1) { if (key < 1) {
// error here in safety mode luaL_error(L, "sol: out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
--key; --key;
std::ptrdiff_t len = static_cast<std::ptrdiff_t>(size_start(L, self));
if (key == len) { if (key == len) {
add_copyable(is_copyable(), L, self, std::move(value)); add_copyable(is_copyable(), L, self, std::move(value));
return; return;
} }
else if (key > len) { else if (key > len) {
// error here in safety mode luaL_error(L, "sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
auto it = std::next(begin(L, self), key); auto it = std::next(begin(L, self), key);
@ -652,7 +652,7 @@ namespace sol {
luaL_error(L, "cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", sol::detail::demangle<T>().data()); luaL_error(L, "cannot call 'add' on type '%s': no suitable insert/push_back C++ functions", sol::detail::demangle<T>().data());
} }
static void add_insert_after(std::true_type, lua_State* L, T& self, stack_object value, iterator& at) { static void add_insert_after(std::true_type, lua_State*, T& self, stack_object value, iterator& at) {
self.insert_after(at, value.as<V>()); self.insert_after(at, value.as<V>());
} }
@ -752,7 +752,7 @@ namespace sol {
auto e = end(L, self); auto e = end(L, self);
for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) { for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) {
if (backit == e) { if (backit == e) {
// TODO: error here in safety mode luaL_error(L, "sol: out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
return; return;
} }
} }
@ -814,7 +814,7 @@ namespace sol {
auto e = end(L, self); auto e = end(L, self);
for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) { for (auto it = begin(L, self); key > 0; ++backit, ++it, --key) {
if (backit == e) { if (backit == e) {
// TODO: error here in safety mode luaL_error(L, "sol: out of bounds for erase on '%s'", detail::demangle<T>().c_str());
return; return;
} }
} }
@ -822,7 +822,7 @@ namespace sol {
self.erase_after(backit); self.erase_after(backit);
} }
static void erase_after_has(std::false_type, lua_State* L, T& self, const K& key) { static void erase_after_has(std::false_type, lua_State* L, T&, const K&) {
luaL_error(L, "sol: cannot call erase on '%s'", detail::demangle<T>().c_str()); luaL_error(L, "sol: cannot call erase on '%s'", detail::demangle<T>().c_str());
} }
@ -1012,15 +1012,13 @@ namespace sol {
}; };
static auto& get_src(lua_State* L) { static auto& get_src(lua_State* L) {
#ifdef SOL_SAFE_USERTYPE
auto p = stack::check_get<T*>(L, 1); auto p = stack::check_get<T*>(L, 1);
#ifdef SOL_SAFE_USERTYPE
if (!p || p.value() == nullptr) { if (!p || p.value() == nullptr) {
luaL_error(L, "sol: 'self' argument is nil or not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str()); luaL_error(L, "sol: 'self' argument is nil or not of type '%s' (pass 'self' as first argument with ':' or call on proper type)", detail::demangle<T>().c_str());
} }
return *p.value();
#else
return stack::get<T>(L, 1);
#endif // Safe getting with error #endif // Safe getting with error
return *p.value();
} }
static int find(std::true_type, lua_State* L) { static int find(std::true_type, lua_State* L) {
@ -1074,7 +1072,7 @@ namespace sol {
static int get(lua_State* L) { static int get(lua_State* L) {
T& self = get_src(L); T& self = get_src(L);
std::size_t idx = stack::get<std::size_t>(L, 2); std::ptrdiff_t idx = stack::get<std::ptrdiff_t>(L, 2);
if (idx > std::extent<T>::value || idx < 1) { if (idx > std::extent<T>::value || idx < 1) {
return stack::push(L, lua_nil); return stack::push(L, lua_nil);
} }
@ -1088,9 +1086,12 @@ namespace sol {
static int set(lua_State* L) { static int set(lua_State* L) {
T& self = get_src(L); T& self = get_src(L);
std::size_t idx = stack::get<std::size_t>(L, 2); std::ptrdiff_t idx = stack::get<std::ptrdiff_t>(L, 2);
if (idx > std::extent<T>::value || idx < 1) { if (idx > std::extent<T>::value) {
return luaL_error(L, "sol: index out of bounds on set"); return luaL_error(L, "sol: index out of bounds (too big) for set on '%s'", detail::demangle<T>().c_str());
}
if (idx < 1) {
return luaL_error(L, "sol: index out of bounds (too small) for set on '%s'", detail::demangle<T>().c_str());
} }
--idx; --idx;
self[idx] = stack::get<value_type>(L, 3); self[idx] = stack::get<value_type>(L, 3);

View File

@ -60,7 +60,7 @@ namespace sol {
bool valid() const noexcept { return b; } bool valid() const noexcept { return b; }
~handler() { ~handler() {
if (b && !is_stack::value) { if (!is_stack::value && stackindex != 0) {
lua_remove(target.lua_state(), stackindex); lua_remove(target.lua_state(), stackindex);
} }
} }
@ -128,7 +128,7 @@ namespace sol {
#ifndef SOL_NO_EXCEPTIONS #ifndef SOL_NO_EXCEPTIONS
auto onexcept = [&](const char* error) { auto onexcept = [&](const char* error) {
h.stackindex = 0; h.stackindex = 0;
if (h.target.valid()) { if (b) {
h.target.push(); h.target.push();
stack::push(lua_state(), error); stack::push(lua_state(), error);
lua_call(lua_state(), 1, 1); lua_call(lua_state(), 1, 1);
@ -171,7 +171,12 @@ namespace sol {
handler_t error_handler; handler_t error_handler;
basic_protected_function() = default; basic_protected_function() = default;
template <typename T, meta::enable<meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>, meta::neg<std::is_same<base_t, stack_reference>>, std::is_base_of<base_t, meta::unqualified_t<T>>> = meta::enabler> template <typename T, meta::enable<
meta::neg<std::is_same<meta::unqualified_t<T>, basic_protected_function>>,
meta::neg<std::is_base_of<proxy_base_tag, meta::unqualified_t<T>>>,
meta::neg<std::is_same<base_t, stack_reference>>,
std::is_base_of<base_t, meta::unqualified_t<T>>
> = meta::enabler>
basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)) { basic_protected_function(T&& r) noexcept : base_t(std::forward<T>(r)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS
if (!is_function<meta::unqualified_t<T>>::value) { if (!is_function<meta::unqualified_t<T>>::value) {
@ -192,14 +197,22 @@ namespace sol {
basic_protected_function(stack_reference&& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {} basic_protected_function(stack_reference&& r) : basic_protected_function(r.lua_state(), r.stack_index(), get_default_handler(r.lua_state())) {}
basic_protected_function(const stack_reference& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} basic_protected_function(const stack_reference& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {}
basic_protected_function(stack_reference&& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} basic_protected_function(stack_reference&& r, handler_t eh) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {}
template <typename Super> template <typename Super>
basic_protected_function(const proxy_base<Super>& p) : basic_protected_function(p.operator basic_function<base_t>(), get_default_handler(p.lua_state())) {} basic_protected_function(const proxy_base<Super>& p) : basic_protected_function(p, get_default_handler(p.lua_state())) {}
template <typename Super> template <typename Super>
basic_protected_function(proxy_base<Super>&& p) : basic_protected_function(p.operator basic_function<base_t>(), get_default_handler(p.lua_state())) {} basic_protected_function(proxy_base<Super>&& p) : basic_protected_function(std::move(p), get_default_handler(p.lua_state())) {}
template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler> template <typename Proxy, typename Handler, meta::enable<
std::is_base_of<proxy_base_tag, meta::unqualified_t<Proxy>>,
meta::neg<is_lua_index<meta::unqualified_t<Handler>>>
> = meta::enabler>
basic_protected_function(Proxy&& p, Handler&& eh) : basic_protected_function(p.operator basic_function<base_t>(), std::forward<Handler>(eh)) {}
template <typename T, meta::enable<meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler>
basic_protected_function(lua_State* L, T&& r) : basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) {} basic_protected_function(lua_State* L, T&& r) : basic_protected_function(L, std::forward<T>(r), get_default_handler(L)) {}
template <typename T, meta::enable<meta::neg<std::is_integral<meta::unqualified_t<T>>>, meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler> template <typename T, meta::enable<meta::neg<is_lua_index<meta::unqualified_t<T>>>> = meta::enabler>
basic_protected_function(lua_State* L, T&& r, handler_t eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {} basic_protected_function(lua_State* L, T&& r, handler_t eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {}
basic_protected_function(lua_State* L, int index = -1) : basic_protected_function(L, index, get_default_handler(L)) {} basic_protected_function(lua_State* L, int index = -1) : basic_protected_function(L, index, get_default_handler(L)) {}
basic_protected_function(lua_State* L, int index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) { basic_protected_function(lua_State* L, int index, handler_t eh) : base_t(L, index), error_handler(std::move(eh)) {
#ifdef SOL_CHECK_ARGUMENTS #ifdef SOL_CHECK_ARGUMENTS

View File

@ -37,9 +37,27 @@
namespace sol { namespace sol {
namespace detail { namespace detail {
inline const std::string& default_chunk_name() { inline const std::string& default_chunk_name() {
static const std::string name = "string"; static const std::string name = "script";
return name; return name;
} }
template <std::size_t N>
const char* make_chunk_name(const string_view& code, const std::string& chunkname, char (&basechunkname)[N]) {
if (chunkname.empty()) {
auto it = code.cbegin();
auto e = code.cend();
std::size_t i = 0;
static const std::size_t n = N - 1;
for (i = 0; i < n && it != e; ++i, ++it) {
basechunkname[i] = *it;
}
basechunkname[i] = '\0';
return &basechunkname[0];
}
else {
return chunkname.c_str();
}
}
} // detail } // detail
namespace stack { namespace stack {
@ -178,8 +196,10 @@ namespace sol {
return call_syntax::colon; return call_syntax::colon;
} }
inline void script(lua_State* L, const string_detail::string_shim& code, string_detail::string_shim name = detail::default_chunk_name(), load_mode mode = load_mode::any) { inline void script(lua_State* L, const string_detail::string_shim& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
if (luaL_loadbufferx(L, code.data(), code.size(), name.data(), to_string(mode).c_str()) || lua_pcall(L, 0, LUA_MULTRET, 0)) { char basechunkname[17] = {};
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)) {
lua_error(L); lua_error(L);
} }
} }

View File

@ -166,14 +166,16 @@ namespace sol {
} }
template <typename V, typename Al> template <typename V, typename Al>
static int get_size_hint(const std::forward_list<V, Al>& c) { static int get_size_hint(const std::forward_list<V, Al>&) {
// forward_list makes me sad // forward_list makes me sad
return static_cast<int>(32); return static_cast<int>(32);
} }
template<typename T> template<typename T>
inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) {
return getter<meta::unqualified_t<T>>{}.get(L, index, tracking); getter<meta::unqualified_t<T>> g{};
(void)g;
return g.get(L, index, tracking);
} }
template<typename T, typename Arg, typename... Args> template<typename T, typename Arg, typename... Args>

View File

@ -46,7 +46,7 @@ namespace sol {
template<typename T, typename> template<typename T, typename>
struct getter { struct getter {
static T& get(lua_State* L, int index, record& tracking) { static T& get(lua_State* L, int index, record& tracking) {
return getter<sol::detail::as_value_tag<T>>{}.get(L, index, tracking); return getter<detail::as_value_tag<T>>{}.get(L, index, tracking);
} }
}; };
@ -220,7 +220,7 @@ namespace sol {
} }
template <typename V> template <typename V>
static C get(types<V> t, lua_State* L, int relindex, record& tracking) { static C get(types<V>, lua_State* L, int relindex, record& tracking) {
tracking.use(1); tracking.use(1);
int index = lua_absindex(L, relindex); int index = lua_absindex(L, relindex);

View File

@ -263,7 +263,9 @@ namespace sol {
template <typename E> template <typename E>
protected_function_result do_string(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result do_string(const string_view& code, const basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunkname.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
if (x != load_status::ok) { if (x != load_status::ok) {
return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
} }
@ -284,7 +286,9 @@ namespace sol {
} }
protected_function_result do_string(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) { protected_function_result do_string(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunkname.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
if (x != load_status::ok) { if (x != load_status::ok) {
return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x)); return protected_function_result(L, absolute_index(L, -1), 0, 1, static_cast<call_status>(x));
} }
@ -356,9 +360,11 @@ namespace sol {
} }
template <typename E> template <typename E>
function_result unsafe_script(const string_view& code, const sol::basic_environment<E>& env, load_mode mode = load_mode::any) { function_result unsafe_script(const string_view& code, const sol::basic_environment<E>& env, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
char basechunkname[17] = {};
const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
int index = lua_gettop(L); int index = lua_gettop(L);
if (luaL_loadbufferx(L, code.data(), code.size(), name.data(), to_string(mode).c_str())) { if (luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str())) {
lua_error(L); lua_error(L);
} }
set_environment(env, stack_reference(L, raw_index(index + 1))); set_environment(env, stack_reference(L, raw_index(index + 1)));
@ -370,9 +376,9 @@ namespace sol {
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
} }
function_result unsafe_script(const string_view& code, const std::string& name = detail::default_chunk_name(), load_mode mode = load_mode::any) { function_result unsafe_script(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
int index = lua_gettop(L); int index = lua_gettop(L);
stack::script(L, code, name, mode); stack::script(L, code, chunkname, mode);
int postindex = lua_gettop(L); int postindex = lua_gettop(L);
int returns = postindex - index; int returns = postindex - index;
return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); return function_result(L, (std::max)(postindex - (returns - 1), 1), returns);
@ -437,19 +443,23 @@ namespace sol {
return unsafe_script_file(filename, mode); return unsafe_script_file(filename, mode);
} }
load_result load(const string_view& code, const std::string& name = detail::default_chunk_name(), load_mode mode = load_mode::any) { load_result load(const string_view& code, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), name.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
return load_result(L, lua_absindex(L, -1), 1, 1, x); const char* chunknametarget = detail::make_chunk_name(code, chunkname, basechunkname);
load_status x = static_cast<load_status>(luaL_loadbufferx(L, code.data(), code.size(), chunknametarget, to_string(mode).c_str()));
return load_result(L, absolute_index(L, -1), 1, 1, x);
} }
load_result load_file(const std::string& filename, load_mode mode = load_mode::any) { load_result load_file(const std::string& filename, load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str())); load_status x = static_cast<load_status>(luaL_loadfilex(L, filename.c_str(), to_string(mode).c_str()));
return load_result(L, lua_absindex(L, -1), 1, 1, x); return load_result(L, absolute_index(L, -1), 1, 1, x);
} }
load_result load(lua_Reader reader, void* data, const std::string& name = detail::default_chunk_name(), load_mode mode = load_mode::any) { load_result load(lua_Reader reader, void* data, const std::string& chunkname = detail::default_chunk_name(), load_mode mode = load_mode::any) {
load_status x = static_cast<load_status>(lua_load(L, reader, data, name.c_str(), to_string(mode).c_str())); char basechunkname[17] = {};
return load_result(L, lua_absindex(L, -1), 1, 1, x); const char* chunknametarget = detail::make_chunk_name("lua_reader", chunkname, basechunkname);
load_status x = static_cast<load_status>(lua_load(L, reader, data, chunknametarget, to_string(mode).c_str()));
return load_result(L, absolute_index(L, -1), 1, 1, x);
} }
iterator begin() const { iterator begin() const {

View File

@ -53,10 +53,22 @@ namespace sol {
return 0; return 0;
} }
const char* c_str() const { const char* begin() const {
return p; return p;
} }
const char* end() const {
return p + s;
}
const char* cbegin() const {
return p;
}
const char* cend() const {
return p + s;
}
const char* data() const { const char* data() const {
return p; return p;
} }

View File

@ -666,7 +666,7 @@ namespace sol {
inline int type_panic(lua_State* L, int index, type expected, type actual) noexcept(false) { inline int type_panic(lua_State* L, int index, type expected, type actual) noexcept(false) {
return luaL_error(L, "stack index %d, expected %s, received %s", index, return luaL_error(L, "stack index %d, expected %s, received %s", index,
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)), expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(expected)),
expected == type::poly ? "anything" : lua_typename(L, static_cast<int>(actual)) actual == type::poly ? "anything" : lua_typename(L, static_cast<int>(actual))
); );
} }
@ -1032,7 +1032,7 @@ namespace sol {
struct is_variadic_arguments : std::is_same<meta::unqualified_t<T>, variadic_args> {}; struct is_variadic_arguments : std::is_same<meta::unqualified_t<T>, variadic_args> {};
template <typename T> template <typename T>
struct is_lua_index : std::false_type {}; struct is_lua_index : std::is_integral<T> {};
template <> template <>
struct is_lua_index<raw_index> : std::true_type {}; struct is_lua_index<raw_index> : std::true_type {};
template <> template <>

View File

@ -128,7 +128,7 @@ void ordered_container_check(sol::state& lua, T& items) {
{ {
auto r1 = lua.script(R"( auto r1 = lua.script(R"(
for i=1,#c do for i=1,#c do
v = c[i] v = c[(i + 10)]
assert(v == (i + 10)) assert(v == (i + 10))
end end
)", sol::script_pass_on_error); )", sol::script_pass_on_error);
@ -323,8 +323,8 @@ void associative_ordered_container_check(sol::state& lua, T& items) {
{ {
auto r1 = lua.script(R"( auto r1 = lua.script(R"(
for i=1,#c do for i=1,#c do
v = c[i] v = c[(i + 10)]
assert(v == (i + 10)) assert(v == (i + 20))
end end
)", sol::script_pass_on_error); )", sol::script_pass_on_error);
REQUIRE(r1.valid()); REQUIRE(r1.valid());
@ -810,3 +810,105 @@ TEST_CASE("containers/associative unordered containers", "check associative (map
associative_unordered_container_check(lua, items); associative_unordered_container_check(lua, items);
} }
} }
TEST_CASE("containers/auxiliary functions test", "make sure the manipulation functions are present and usable and working across various container types") {
sol::state lua;
lua.open_libraries();
lua.script(R"(
function g (x)
x:add(20)
end
function h (x)
x:add(20, 40)
end
function i (x)
x:clear()
end
function sf (x,v)
return x:find(v)
end
)");
// Have the function we
// just defined in Lua
sol::function g = lua["g"];
sol::function h = lua["h"];
sol::function i = lua["i"];
sol::function sf = lua["sf"];
// Set a global variable called
// "arr" to be a vector of 5 lements
lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 };
lua["map"] = std::map<int, int>{ { 1 , 2 },{ 2, 4 },{ 3, 6 },{ 4, 8 },{ 5, 10 } };
lua["set"] = std::set<int>{ 2, 4, 6, 8, 10 };
std::array<int, 5>& c_arr = lua["c_arr"];
std::vector<int>& arr = lua["arr"];
std::map<int, int>& map = lua["map"];
std::set<int>& set = lua["set"];
REQUIRE(c_arr.size() == 5);
REQUIRE(arr.size() == 5);
REQUIRE(map.size() == 5);
REQUIRE(set.size() == 5);
g(lua["set"]);
g(lua["arr"]);
h(lua["map"]);
REQUIRE(arr.size() == 6);
REQUIRE(map.size() == 6);
REQUIRE(set.size() == 6);
{
int r = sf(set, 8);
REQUIRE(r == 8);
sol::object rn = sf(set, 9);
REQUIRE(rn == sol::nil);
}
{
int r = sf(map, 3);
REQUIRE(r == 6);
sol::object rn = sf(map, 9);
REQUIRE(rn == sol::nil);
}
i(lua["arr"]);
i(lua["map"]);
i(lua["set"]);
REQUIRE(arr.empty());
REQUIRE(map.empty());
REQUIRE(set.empty());
REQUIRE_NOTHROW([&]() {
lua.script(R"(
c_arr[1] = 7
c_arr[2] = 7
c_arr[3] = 7
)");
}());
}
TEST_CASE("containers/indices test", "test indices on fixed array types") {
SECTION("zero index test") {
sol::state lua;
lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
auto result = lua.safe_script(R"(
c_arr[0] = 7
)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
SECTION("negative index test") {
sol::state lua;
lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
auto result = lua.safe_script(R"(
c_arr[-1] = 7
)", sol::script_pass_on_error);
REQUIRE_FALSE(result.valid());
}
}

View File

@ -65,8 +65,8 @@ TEST_CASE("containers/table conversion", "test table conversions with as_table a
lua.script("v1 = bark()"); lua.script("v1 = bark()");
lua.script("v2 = woof()"); lua.script("v2 = woof()");
sol::as_table_t<std::vector<std::string>> as_table_strings = lua["v"]; sol::as_table_t<std::vector<std::string>> as_table_strings = lua["v1"];
sol::nested<std::vector<std::string>> nested_strings = lua["v"]; sol::nested<std::vector<std::string>> nested_strings = lua["v2"];
std::vector<std::string> expected_values{"bark", "woof"}; std::vector<std::string> expected_values{"bark", "woof"};
REQUIRE(as_table_strings.source == expected_values); REQUIRE(as_table_strings.source == expected_values);
@ -456,106 +456,6 @@ TEST_CASE("containers/arbitrary creation", "userdata and tables should be usable
REQUIRE(d.get<int>("four") == 4); REQUIRE(d.get<int>("four") == 4);
} }
TEST_CASE("containers/extra functions", "make sure the manipulation functions are present and usable and working across various container types") {
sol::state lua;
lua.open_libraries();
lua.script(R"(
function g (x)
x:add(20)
end
function h (x)
x:add(20, 40)
end
function i (x)
x:clear()
end
function sf (x,v)
return x:find(v)
end
)");
// Have the function we
// just defined in Lua
sol::function g = lua["g"];
sol::function h = lua["h"];
sol::function i = lua["i"];
sol::function sf = lua["sf"];
// Set a global variable called
// "arr" to be a vector of 5 lements
lua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 };
lua["map"] = std::map<int, int>{ { 1 , 2 },{ 2, 4 },{ 3, 6 },{ 4, 8 },{ 5, 10 } };
lua["set"] = std::set<int>{ 2, 4, 6, 8, 10 };
std::array<int, 5>& c_arr = lua["c_arr"];
std::vector<int>& arr = lua["arr"];
std::map<int, int>& map = lua["map"];
std::set<int>& set = lua["set"];
REQUIRE(c_arr.size() == 5);
REQUIRE(arr.size() == 5);
REQUIRE(map.size() == 5);
REQUIRE(set.size() == 5);
g(lua["set"]);
g(lua["arr"]);
h(lua["map"]);
REQUIRE(arr.size() == 6);
REQUIRE(map.size() == 6);
REQUIRE(set.size() == 6);
{
int r = sf(set, 8);
REQUIRE(r == 8);
sol::object rn = sf(set, 9);
REQUIRE(rn == sol::nil);
}
{
int r = sf(map, 3);
REQUIRE(r == 6);
sol::object rn = sf(map, 9);
REQUIRE(rn == sol::nil);
}
i(lua["arr"]);
i(lua["map"]);
i(lua["set"]);
REQUIRE(arr.empty());
REQUIRE(map.empty());
REQUIRE(set.empty());
REQUIRE_NOTHROW([&]() {
lua.script(R"(
c_arr[1] = 7
c_arr[2] = 7
c_arr[3] = 7
)");
}());
SECTION("throw test") {
sol::state tlua;
tlua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
REQUIRE_THROWS([&]() {
tlua.script(R"(
c_arr[0] = 7
)");
}());
}
SECTION("throw test 2") {
sol::state tlua;
tlua["c_arr"] = std::array<int, 5>{ { 2, 4, 6, 8, 10 } };
REQUIRE_THROWS([&]() {
tlua.script(R"(
c_arr[-1] = 7
)");
}());
}
}
TEST_CASE("containers/usertype transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") { TEST_CASE("containers/usertype transparency", "Make sure containers pass their arguments through transparently and push the results as references, not new values") {
class A { class A {
public: public:
@ -919,20 +819,19 @@ TEST_CASE("containers/input iterators", "test shitty input iterators that are al
not_really_a_container c; not_really_a_container c;
lua["c"] = &c; lua["c"] = &c;
#if SOL_LUA_VERSION > 503 #if SOL_LUA_VERSION > 502
lua.script(R"lua( lua.script(R"lua(
for k, v in pairs(c) do for k, v in pairs(c) do
assert((k - 1) == v:val()) assert((k - 1) == v:val())
end end
)lua"); )lua");
#else #endif
lua.script(R"lua( lua.script(R"lua(
for k=1,#c do for k=1,#c do
v = c[k] v = c[k]
assert((k - 1) == v:val()) assert((k - 1) == v:val())
end end
)lua"); )lua");
#endif
} }
TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") { TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") {

View File

@ -5,13 +5,6 @@
#include <iostream> #include <iostream>
#include "test_stack_guard.hpp" #include "test_stack_guard.hpp"
std::function<int()> makefn() {
auto fx = []() -> int {
return 0x1456789;
};
return fx;
}
template <typename T> template <typename T>
T va_func(sol::variadic_args va, T first) { T va_func(sol::variadic_args va, T first) {
T s = 0; T s = 0;
@ -25,6 +18,13 @@ T va_func(sol::variadic_args va, T first) {
return s; return s;
} }
std::function<int()> makefn() {
auto fx = []() -> int {
return 0x1456789;
};
return fx;
}
void takefn(std::function<int()> purr) { void takefn(std::function<int()> purr) {
if (purr() != 0x1456789) if (purr() != 0x1456789)
throw 0; throw 0;