This adds the additional safety features. stack_guard should probably be migrated into the tests too, since a lesser form is already used there.

Closes #54 #55
This commit is contained in:
ThePhD 2016-04-04 02:28:39 -04:00
parent 5efbae5798
commit 204bd5d5ed
9 changed files with 128 additions and 13 deletions

View File

@ -67,7 +67,11 @@ private:
}
public:
coroutine(lua_State* L, int index = -1) noexcept : reference(L, index) {}
coroutine(lua_State* L, int index = -1) : reference(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert(L, index, type::function);
#endif // Safety
}
coroutine() noexcept = default;
coroutine(const coroutine&) noexcept = default;
coroutine& operator=(const coroutine&) noexcept = default;

View File

@ -65,7 +65,16 @@ private:
}
public:
using reference::reference;
function() = default;
function(const function&) = default;
function& operator=(const function&) = default;
function( function&& ) = default;
function& operator=( function&& ) = default;
function(lua_State* L, int index = -1): reference(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert(L, index, type::function);
#endif // Safety
}
template<typename... Args>
function_result operator()( Args&&... args ) const {

View File

@ -130,13 +130,15 @@ public:
reference error_handler;
protected_function() = default;
protected_function(lua_State* L, int index = -1): reference(L, index), error_handler(get_default_handler()) {
type_assert(L, index, type::function);
}
protected_function(const protected_function&) = default;
protected_function& operator=(const protected_function&) = default;
protected_function( protected_function&& ) = default;
protected_function& operator=( protected_function&& ) = default;
protected_function(lua_State* L, int index = -1): reference(L, index), error_handler(get_default_handler()) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert(L, index, type::function);
#endif // Safety
}
template<typename... Args>
protected_function_result operator()(Args&&... args) const {

View File

@ -148,6 +148,18 @@ struct getter<c_closure> {
}
};
template<>
struct getter<error> {
static error get(lua_State* L, int index = -1) {
size_t sz = 0;
const char* err = lua_tolstring(L, index, &sz);
if (err == nullptr) {
return error(detail::direct_error, "");
}
return error(detail::direct_error, std::string(err, sz));
}
};
template<>
struct getter<void*> {
static void* get(lua_State* L, int index = -1) {

59
sol/stack_guard.hpp Normal file
View File

@ -0,0 +1,59 @@
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef SOL_STACK_GUARD_HPP
#define SOL_STACK_GUARD_HPP
#include "compatibility/version.hpp"
#include "error.hpp"
#include <functional>
namespace sol {
namespace detail {
inline void stack_fail(int, int) {
#ifndef SOL_NO_EXCEPTIONS
throw error(detail::direct_error, "imbalanced stack after operation finish");
#else
// Lol, what do you want, an error printout? :3c
// There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so
// hopefully someone will register their own stack_fail thing here
#endif // No Exceptions
}
} // detail
struct stack_guard {
lua_State* L;
int top;
std::function<void(int, int)> fx;
stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {}
stack_guard(lua_State* L, int top, std::function<void(int, int)> fx = detail::stack_fail) : L(L), top(top), fx(std::move(fx)) {}
~stack_guard() {
int bottom = lua_gettop(L);
if (top == bottom) {
return;
}
fx(top, bottom);
}
};
} // sol
#endif // SOL_STACK_GUARD_HPP

View File

@ -152,7 +152,9 @@ public:
table_core( ) noexcept : reference( ) { }
table_core( const table_core<true>& global ) noexcept : reference( global ) { }
table_core( lua_State* L, int index = -1 ) : reference( L, index ) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert( L, index, type::table );
#endif // Safety
}
table_iterator begin () const {

View File

@ -28,7 +28,16 @@
namespace sol {
class thread : public reference {
public:
using reference::reference;
thread () noexcept = default;
thread(const thread&) = default;
thread(thread&&) = default;
thread& operator=(const thread&) = default;
thread& operator=(thread&&) = default;
thread(lua_State* L, int index = -1) : reference(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert(L, index, type::thread);
#endif // Safety
}
state_view state() const {
return state_view(this->thread_state());

View File

@ -213,7 +213,7 @@ class coroutine;
class thread;
class object;
class userdata;
class light_userdata;
class lightuserdata;
template <typename T, typename = void>
struct lua_type_of : std::integral_constant<type, type::userdata> {};
@ -264,7 +264,7 @@ template <>
struct lua_type_of<userdata_value> : std::integral_constant<type, type::userdata> {};
template <>
struct lua_type_of<light_userdata> : std::integral_constant<type, type::lightuserdata> {};
struct lua_type_of<lightuserdata> : std::integral_constant<type, type::lightuserdata> {};
template <>
struct lua_type_of<userdata> : std::integral_constant<type, type::userdata> {};

View File

@ -27,12 +27,30 @@
namespace sol {
class userdata : public reference {
public:
using reference::reference;
userdata () noexcept = default;
userdata(const userdata&) = default;
userdata(userdata&&) = default;
userdata& operator=(const userdata&) = default;
userdata& operator=(userdata&&) = default;
userdata(lua_State* L, int index = -1) : reference(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert(L, index, type::userdata);
#endif // Safety
}
};
class light_userdata : public reference {
class lightuserdata : public reference {
public:
using reference::reference;
lightuserdata () noexcept = default;
lightuserdata(const lightuserdata&) = default;
lightuserdata(lightuserdata&&) = default;
lightuserdata& operator=(const lightuserdata&) = default;
lightuserdata& operator=(lightuserdata&&) = default;
lightuserdata(lua_State* L, int index = -1) : reference(L, index) {
#ifdef SOL_CHECK_ARGUMENTS
type_assert(L, index, type::lightuserdata);
#endif // Safety
}
};
} // sol