mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00
Lua engine: Enable checks for debug builds, kill sol::buffer. (#9419)
This commit is contained in:
parent
0074d3ad94
commit
dd1e5b1d7a
@ -95,18 +95,6 @@ template <> struct is_container<image_interface_formats> : std::true_type { };
|
||||
template <> struct is_container<plugin_options_plugins> : std::true_type { };
|
||||
|
||||
|
||||
sol::buffer *sol_lua_get(sol::types<buffer *>, lua_State *L, int index, sol::stack::record &tracking)
|
||||
{
|
||||
return new sol::buffer(stack::get<int>(L, index), L);
|
||||
}
|
||||
|
||||
int sol_lua_push(sol::types<buffer *>, lua_State *L, buffer *value)
|
||||
{
|
||||
delete value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct usertype_container<lua_engine::devenum<T> > : lua_engine::immutable_collection_helper<lua_engine::devenum<T>, T>
|
||||
{
|
||||
@ -834,7 +822,15 @@ void lua_engine::initialize()
|
||||
}
|
||||
new (&file) emu_file(path, flags);
|
||||
}));
|
||||
file_type.set("read", [](emu_file &file, sol::buffer *buff) { buff->set_len(file.read(buff->get_ptr(), buff->get_len())); return buff; });
|
||||
file_type.set("read",
|
||||
[] (emu_file &file, sol::this_state s, size_t len)
|
||||
{
|
||||
buffer_helper buf(s);
|
||||
auto space = buf.prepare(len);
|
||||
space.add(file.read(space.get(), len));
|
||||
buf.push();
|
||||
return sol::stack::pop<sol::object>(s);
|
||||
});
|
||||
file_type.set("write", [](emu_file &file, const std::string &data) { return file.write(data.data(), data.size()); });
|
||||
file_type.set("puts", &emu_file::puts);
|
||||
file_type.set("open", static_cast<std::error_condition (emu_file::*)(std::string_view)>(&emu_file::open));
|
||||
@ -1001,16 +997,18 @@ void lua_engine::initialize()
|
||||
}
|
||||
return sol::make_object(sol(), ret);
|
||||
});
|
||||
item_type.set("read_block", [](save_item &item, int offset, sol::buffer *buff) {
|
||||
if(!item.base || ((offset + buff->get_len()) > (item.size * item.count)))
|
||||
item_type.set("read_block", [](save_item &item, sol::this_state s, int offset, size_t len) {
|
||||
buffer_helper buf(s);
|
||||
auto space = buf.prepare(len);
|
||||
if(!item.base || ((offset + len) > (item.size * item.count)))
|
||||
{
|
||||
buff->set_len(0);
|
||||
space.add(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t blocksize = item.size * item.valcount;
|
||||
uint32_t remaining = buff->get_len();
|
||||
uint8_t *dest = reinterpret_cast<uint8_t *>(buff->get_ptr());
|
||||
size_t remaining = len;
|
||||
uint8_t *dest = reinterpret_cast<uint8_t *>(space.get());
|
||||
while(remaining)
|
||||
{
|
||||
const uint32_t blockno = offset / blocksize;
|
||||
@ -1022,8 +1020,10 @@ void lua_engine::initialize()
|
||||
remaining -= chunk;
|
||||
dest += chunk;
|
||||
}
|
||||
space.add(len);
|
||||
}
|
||||
return buff;
|
||||
buf.push();
|
||||
return sol::stack::pop<sol::object>(s);
|
||||
});
|
||||
item_type.set("write", [](save_item &item, int offset, uint64_t value) {
|
||||
if(!item.base || (offset >= item.count))
|
||||
|
@ -21,7 +21,11 @@
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
#define SOL_ALL_SAFETIES_ON 1
|
||||
#else
|
||||
#define SOL_SAFE_USERTYPE 1
|
||||
#endif
|
||||
#include "sol/sol.hpp"
|
||||
|
||||
struct lua_State;
|
||||
@ -30,6 +34,7 @@ class lua_engine
|
||||
{
|
||||
public:
|
||||
// helper structures
|
||||
class buffer_helper;
|
||||
template <typename T> struct devenum;
|
||||
template <typename T> struct simple_list_wrapper;
|
||||
template <typename T> struct tag_object_ptr_map;
|
||||
|
@ -16,10 +16,100 @@
|
||||
|
||||
#include <lua.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <system_error>
|
||||
|
||||
|
||||
|
||||
class lua_engine::buffer_helper
|
||||
{
|
||||
private:
|
||||
class proxy
|
||||
{
|
||||
private:
|
||||
buffer_helper &m_host;
|
||||
char *m_space;
|
||||
size_t const m_size;
|
||||
|
||||
public:
|
||||
proxy(proxy const &) = delete;
|
||||
proxy &operator=(proxy const &) = delete;
|
||||
|
||||
proxy(proxy &&that) : m_host(that.m_host), m_space(that.m_space), m_size(that.m_size)
|
||||
{
|
||||
that.m_space = nullptr;
|
||||
}
|
||||
|
||||
proxy(buffer_helper &host, size_t size) : m_host(host), m_space(luaL_prepbuffsize(&host.m_buffer, size)), m_size(size)
|
||||
{
|
||||
m_host.m_prepared = true;
|
||||
}
|
||||
|
||||
~proxy()
|
||||
{
|
||||
if (m_space)
|
||||
{
|
||||
assert(m_host.m_prepared);
|
||||
luaL_addsize(&m_host.m_buffer, 0U);
|
||||
m_host.m_prepared = false;
|
||||
}
|
||||
}
|
||||
|
||||
char *get()
|
||||
{
|
||||
return m_space;
|
||||
}
|
||||
|
||||
void add(size_t size)
|
||||
{
|
||||
assert(m_space);
|
||||
assert(size <= m_size);
|
||||
assert(m_host.m_prepared);
|
||||
m_space = nullptr;
|
||||
luaL_addsize(&m_host.m_buffer, size);
|
||||
m_host.m_prepared = false;
|
||||
}
|
||||
};
|
||||
|
||||
luaL_Buffer m_buffer;
|
||||
bool m_valid;
|
||||
bool m_prepared;
|
||||
|
||||
public:
|
||||
buffer_helper(buffer_helper const &) = delete;
|
||||
buffer_helper &operator=(buffer_helper const &) = delete;
|
||||
|
||||
buffer_helper(lua_State *L)
|
||||
{
|
||||
luaL_buffinit(L, &m_buffer);
|
||||
m_valid = true;
|
||||
m_prepared = false;
|
||||
}
|
||||
|
||||
~buffer_helper()
|
||||
{
|
||||
assert(!m_prepared);
|
||||
if (m_valid)
|
||||
luaL_pushresult(&m_buffer);
|
||||
}
|
||||
|
||||
void push()
|
||||
{
|
||||
assert(m_valid);
|
||||
assert(!m_prepared);
|
||||
luaL_pushresult(&m_buffer);
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
proxy prepare(size_t size)
|
||||
{
|
||||
assert(m_valid);
|
||||
assert(!m_prepared);
|
||||
return proxy(*this, size);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct lua_engine::simple_list_wrapper
|
||||
{
|
||||
@ -40,52 +130,9 @@ struct lua_engine::tag_object_ptr_map
|
||||
|
||||
namespace sol {
|
||||
|
||||
class buffer
|
||||
{
|
||||
public:
|
||||
// sol does lua_settop(0), save userdata buffer in registry if necessary
|
||||
buffer(int size, lua_State *L)
|
||||
{
|
||||
ptr = luaL_buffinitsize(L, &buff, size);
|
||||
len = size;
|
||||
if(buff.b != buff.initb)
|
||||
{
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "sol::buffer_temp");
|
||||
}
|
||||
}
|
||||
~buffer()
|
||||
{
|
||||
lua_State *L = buff.L;
|
||||
if(lua_getfield(L, LUA_REGISTRYINDEX, "sol::buffer_temp") != LUA_TNIL)
|
||||
{
|
||||
lua_pushnil(L);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "sol::buffer_temp");
|
||||
}
|
||||
else
|
||||
lua_pop(L, -1);
|
||||
|
||||
luaL_pushresultsize(&buff, len);
|
||||
}
|
||||
|
||||
void set_len(int size) { len = size; }
|
||||
int get_len() { return len; }
|
||||
char *get_ptr() { return ptr; }
|
||||
|
||||
private:
|
||||
luaL_Buffer buff;
|
||||
int len;
|
||||
char *ptr;
|
||||
};
|
||||
|
||||
|
||||
// don't convert core_optons to a table directly
|
||||
// don't convert core_options to a table directly
|
||||
template <> struct is_container<core_options> : std::false_type { };
|
||||
|
||||
// buffer customisation
|
||||
sol::buffer *sol_lua_get(sol::types<buffer *>, lua_State *L, int index, sol::stack::record &tracking);
|
||||
int sol_lua_push(sol::types<buffer *>, lua_State *L, buffer *value);
|
||||
|
||||
|
||||
// these things should be treated as containers
|
||||
template <typename T> struct is_container<lua_engine::devenum<T> > : std::true_type { };
|
||||
|
Loading…
Reference in New Issue
Block a user