summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
author Vas Crabb <cuavas@users.noreply.github.com>2022-03-17 16:47:19 +1100
committer GitHub <noreply@github.com>2022-03-17 16:47:19 +1100
commitdd1e5b1d7a75e777bd307f8b0702c818fb463e65 (patch)
tree1347e4bc13373b09d581b6d0a7b2d397511adc41 /src/frontend
parent0074d3ad941011f8ea059ce1cc15f66bb517d957 (diff)
Lua engine: Enable checks for debug builds, kill sol::buffer. (#9419)
Diffstat (limited to 'src/frontend')
-rw-r--r--src/frontend/mame/luaengine.cpp38
-rw-r--r--src/frontend/mame/luaengine.h5
-rw-r--r--src/frontend/mame/luaengine.ipp135
3 files changed, 115 insertions, 63 deletions
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index b6fc0014a4c..6981ebfe41b 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -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))
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index b070969f424..6c5f572885d 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -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;
diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp
index 10d1f55f33f..0dd6d3d8d90 100644
--- a/src/frontend/mame/luaengine.ipp
+++ b/src/frontend/mame/luaengine.ipp
@@ -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 { };