Move some serialization-related code from binding-util to sandbox-serial-util

This commit is contained in:
刘皓 2025-05-29 21:06:29 -04:00
parent 28b81ca95d
commit 56c711f1c1
No known key found for this signature in database
GPG key ID: 7901753DB465B711
5 changed files with 116 additions and 120 deletions

View file

@ -21,81 +21,9 @@
#include "binding-util.h"
#include "sharedstate.h"
#include <utility>
#include <boost/type_traits/is_detected.hpp>
using namespace mkxp_sandbox;
template <typename T> static typename std::enable_if<std::is_constructible<T>::value, void *>::type construct() {
return new T;
}
template <typename T> static typename std::enable_if<!std::is_constructible<T>::value && std::is_constructible<T, Exception &>::value, void *>::type construct() {
Exception e;
T *obj = new T(e);
if (e.is_ok()) {
return obj;
} else {
delete obj;
return nullptr;
}
}
template <typename T> static void destroy(void *self) {
if (self != nullptr) {
delete (T *)self;
}
}
template <typename T> static typename std::enable_if<std::is_base_of<Disposable, T>::value>::type dispose(void *self) {
if (self != nullptr) {
((T *)self)->dispose();
}
}
template <typename T> static typename std::enable_if<!std::is_base_of<Disposable, T>::value>::type dispose(void *self) {}
template <typename T> static typename std::enable_if<std::is_base_of<Disposable, T>::value, bool>::type disposed(void *self) {
return self == nullptr || ((T *)self)->isDisposed();
}
template <typename T> static typename std::enable_if<!std::is_base_of<Disposable, T>::value, bool>::type disposed(void *self) {
return self == nullptr;
}
template <typename T> static bool serialize(const void *self, void *&data, wasm_size_t &max_size) {
return ((const T *)self)->sandbox_serialize(data, max_size);
}
template <typename T> static bool deserialize(void *self, const void *&data, wasm_size_t &max_size) {
return ((T *)self)->sandbox_deserialize(data, max_size);
}
template <typename T> using deserialize_begin_declaration_with_is_new = decltype(std::declval<T *>()->sandbox_deserialize_begin(std::declval<bool>()));
template <typename T> using deserialize_begin_declaration_without_is_new = decltype(std::declval<T *>()->sandbox_deserialize_begin());
template <typename T> static typename std::enable_if<boost::is_detected<deserialize_begin_declaration_with_is_new, T>::value>::type deserialize_begin(void *self, bool is_new) {
((T *)self)->sandbox_deserialize_begin(is_new);
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_begin_declaration_with_is_new, T>::value && boost::is_detected<deserialize_begin_declaration_without_is_new, T>::value>::type deserialize_begin(void *self, bool is_new) {
((T *)self)->sandbox_deserialize_begin();
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_begin_declaration_with_is_new, T>::value && !boost::is_detected<deserialize_begin_declaration_without_is_new, T>::value>::type deserialize_begin(void *self, bool is_new) {}
template <typename T> using deserialize_end_declaration = decltype(std::declval<T *>()->sandbox_deserialize_end());
template <typename T> static typename std::enable_if<boost::is_detected<deserialize_end_declaration, T>::value>::type deserialize_end(void *self) {
((T *)self)->sandbox_deserialize_end();
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_end_declaration, T>::value>::type deserialize_end(void *self) {}
#define _SANDBOX_DEF_TYPENUM_TABLE_ENTRY(_r, _data, T) {construct<T>, destroy<T>, dispose<T>, disposed<T>, serialize<T>, deserialize<T>, deserialize_begin<T>, deserialize_end<T>},
extern const struct typenum_table_entry mkxp_sandbox::typenum_table[SANDBOX_NUM_TYPENUMS] = {BOOST_PP_SEQ_FOR_EACH(_SANDBOX_DEF_TYPENUM_TABLE_ENTRY, _, SANDBOX_TYPENUM_TYPES)};
extern const wasm_size_t mkxp_sandbox::typenum_table_size = SANDBOX_NUM_TYPENUMS;
void mkxp_sandbox::dfree(wasm_objkey_t key) {
sb()->destroy_object(key);
}

View file

@ -24,24 +24,10 @@
#include <type_traits>
#include <boost/optional.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include "core.h"
#include "sandbox-serial-util.h"
#include "exception.h"
#include "sandbox.h"
#include "bitmap.h"
#include "etc.h"
#include "font.h"
#include "plane.h"
#include "sprite.h"
#include "table.h"
#include "tilemap.h"
#include "tilemapvx.h"
#include "viewport.h"
#include "window.h"
#include "windowvx.h"
#define SANDBOX_SLOT(slot_index) (::mkxp_sandbox::sb()->ref<typename ::mkxp_sandbox::slot_type<(slot_index), slots>::type>(::mkxp_sandbox::sb()->stack_pointer() + ::mkxp_sandbox::slot_offset<(slot_index), slots>::value))
#define SANDBOX_AWAIT(coroutine, ...) \
@ -457,37 +443,7 @@
#define SANDBOX_GUARD_LF(finalizer, ...) do { GFX_LOCK; SANDBOX_GUARD_F(finalizer; GFX_UNLOCK, __VA_ARGS__); GFX_UNLOCK; } while (0)
#define SANDBOX_GUARD_L(...) SANDBOX_GUARD_LF(, __VA_ARGS__)
#define SANDBOX_TYPENUM_TYPES \
(Bitmap) \
(Color) \
(Font) \
(Plane) \
(Rect) \
(Sprite) \
(Table) \
(Tilemap) \
(Tilemap::Autotiles) \
(TilemapVX) \
(TilemapVX::BitmapArray) \
(Tone) \
(Viewport) \
(Window) \
(WindowVX) \
#define SANDBOX_NUM_TYPENUMS BOOST_PP_SEQ_SIZE(SANDBOX_TYPENUM_TYPES)
#define _SANDBOX_DEF_GET_TYPENUM_DETAIL(T, num) template <> struct get_typenum<T> { \
static_assert(num != 0, "typenum should not be 0"); \
static_assert(num <= SANDBOX_NUM_TYPENUMS, "typenum should not be greater than the number of typenums"); \
static constexpr wasm_size_t value = num; \
};
#define _SANDBOX_DEF_GET_TYPENUM(_r, _data, T) _SANDBOX_DEF_GET_TYPENUM_DETAIL(T, __COUNTER__ - _get_typenum_counter_start)
namespace mkxp_sandbox {
template <typename T> struct get_typenum;
static constexpr wasm_size_t _get_typenum_counter_start = __COUNTER__;
BOOST_PP_SEQ_FOR_EACH(_SANDBOX_DEF_GET_TYPENUM, _, SANDBOX_TYPENUM_TYPES);
// We need these helper functions so that the arguments to `SANDBOX_AWAIT`/`SANDBOX_AWAIT_R`/`SANDBOX_AWAIT_S` are evaluated before `sb()->bind` is called instead of after.
// The reverse happening can lead to incorrect behaviour if one or more of the arguments is using `SANDBOX_SLOT` or other macros that need the state of the sandbox.
template <typename Coroutine, typename... Args> bool _sandbox_await(Args... args) {

View file

@ -19,7 +19,6 @@
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#include <utility>
#include "sandbox-serial-util.h"
#include "etc-internal.h"
#include "quad.h"
@ -40,6 +39,76 @@ using namespace mkxp_sandbox;
max_size -= (bytes); \
} while (0)
template <typename T> static typename std::enable_if<std::is_constructible<T>::value, void *>::type construct() {
return new T;
}
template <typename T> static typename std::enable_if<!std::is_constructible<T>::value && std::is_constructible<T, Exception &>::value, void *>::type construct() {
Exception e;
T *obj = new T(e);
if (e.is_ok()) {
return obj;
} else {
delete obj;
return nullptr;
}
}
template <typename T> static void destroy(void *self) {
if (self != nullptr) {
delete (T *)self;
}
}
template <typename T> static typename std::enable_if<std::is_base_of<Disposable, T>::value>::type dispose(void *self) {
if (self != nullptr) {
((T *)self)->dispose();
}
}
template <typename T> static typename std::enable_if<!std::is_base_of<Disposable, T>::value>::type dispose(void *self) {}
template <typename T> static typename std::enable_if<std::is_base_of<Disposable, T>::value, bool>::type disposed(void *self) {
return self == nullptr || ((T *)self)->isDisposed();
}
template <typename T> static typename std::enable_if<!std::is_base_of<Disposable, T>::value, bool>::type disposed(void *self) {
return self == nullptr;
}
template <typename T> static bool serialize(const void *self, void *&data, wasm_size_t &max_size) {
return ((const T *)self)->sandbox_serialize(data, max_size);
}
template <typename T> static bool deserialize(void *self, const void *&data, wasm_size_t &max_size) {
return ((T *)self)->sandbox_deserialize(data, max_size);
}
template <typename T> using deserialize_begin_declaration_with_is_new = decltype(std::declval<T *>()->sandbox_deserialize_begin(std::declval<bool>()));
template <typename T> using deserialize_begin_declaration_without_is_new = decltype(std::declval<T *>()->sandbox_deserialize_begin());
template <typename T> static typename std::enable_if<boost::is_detected<deserialize_begin_declaration_with_is_new, T>::value>::type deserialize_begin(void *self, bool is_new) {
((T *)self)->sandbox_deserialize_begin(is_new);
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_begin_declaration_with_is_new, T>::value && boost::is_detected<deserialize_begin_declaration_without_is_new, T>::value>::type deserialize_begin(void *self, bool is_new) {
((T *)self)->sandbox_deserialize_begin();
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_begin_declaration_with_is_new, T>::value && !boost::is_detected<deserialize_begin_declaration_without_is_new, T>::value>::type deserialize_begin(void *self, bool is_new) {}
template <typename T> using deserialize_end_declaration = decltype(std::declval<T *>()->sandbox_deserialize_end());
template <typename T> static typename std::enable_if<boost::is_detected<deserialize_end_declaration, T>::value>::type deserialize_end(void *self) {
((T *)self)->sandbox_deserialize_end();
}
template <typename T> static typename std::enable_if<!boost::is_detected<deserialize_end_declaration, T>::value>::type deserialize_end(void *self) {}
#define _SANDBOX_DEF_TYPENUM_TABLE_ENTRY(_r, _data, T) {construct<T>, destroy<T>, dispose<T>, disposed<T>, serialize<T>, deserialize<T>, deserialize_begin<T>, deserialize_end<T>},
extern const struct typenum_table_entry mkxp_sandbox::typenum_table[SANDBOX_NUM_TYPENUMS] = {BOOST_PP_SEQ_FOR_EACH(_SANDBOX_DEF_TYPENUM_TABLE_ENTRY, _, SANDBOX_TYPENUM_TYPES)};
extern const wasm_size_t mkxp_sandbox::typenum_table_size = SANDBOX_NUM_TYPENUMS;
std::vector<std::tuple<const void *, wasm_size_t>> mkxp_sandbox::extra_objects;
std::unordered_map<wasm_size_t, struct sandbox_object_deser_info> mkxp_sandbox::objects_deser;
std::unordered_map<wasm_size_t, struct sandbox_object_deser_info> mkxp_sandbox::extra_objects_deser;

View file

@ -25,12 +25,56 @@
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/type_traits/is_detected.hpp>
#include "binding-util.h"
#include "bitmap.h"
#include "etc.h"
#include "font.h"
#include "plane.h"
#include "quadarray.h"
#include "sprite.h"
#include "table.h"
#include "tilemap.h"
#include "tilemapvx.h"
#include "viewport.h"
#include "window.h"
#include "windowvx.h"
#define SANDBOX_TYPENUM_TYPES \
(Bitmap) \
(Color) \
(Font) \
(Plane) \
(Rect) \
(Sprite) \
(Table) \
(Tilemap) \
(Tilemap::Autotiles) \
(TilemapVX) \
(TilemapVX::BitmapArray) \
(Tone) \
(Viewport) \
(Window) \
(WindowVX) \
#define SANDBOX_NUM_TYPENUMS BOOST_PP_SEQ_SIZE(SANDBOX_TYPENUM_TYPES)
#define _SANDBOX_DEF_GET_TYPENUM_DETAIL(T, num) template <> struct get_typenum<T> { \
static_assert(num != 0, "typenum should not be 0"); \
static_assert(num <= SANDBOX_NUM_TYPENUMS, "typenum should not be greater than the number of typenums"); \
static constexpr wasm_size_t value = num; \
};
#define _SANDBOX_DEF_GET_TYPENUM(_r, _data, T) _SANDBOX_DEF_GET_TYPENUM_DETAIL(T, __COUNTER__ - _get_typenum_counter_start)
namespace mkxp_sandbox {
template <typename T> struct get_typenum;
static constexpr wasm_size_t _get_typenum_counter_start = __COUNTER__;
BOOST_PP_SEQ_FOR_EACH(_SANDBOX_DEF_GET_TYPENUM, _, SANDBOX_TYPENUM_TYPES);
struct sandbox_object_deser_info {
template <typename T> sandbox_object_deser_info(T *&ref) : ptr(new std::vector<void **>({(void **)&ref})), typenum(mkxp_sandbox::get_typenum<T>::value), ref_count(1), exists(false) {}
sandbox_object_deser_info(void *ptr, wasm_size_t typenum);

View file

@ -32,7 +32,6 @@
#include <alext.h>
#include <fluidsynth.h>
#include "binding-util.h"
#include "mkxp-polyfill.h" // std::mutex, std::strtoul
#include "git-hash.h"