diff --git a/library/DataDefs.cpp b/library/DataDefs.cpp index 712d4563f..3d6354743 100644 --- a/library/DataDefs.cpp +++ b/library/DataDefs.cpp @@ -51,6 +51,11 @@ void type_identity::do_copy_pod(void *tgt, const void *src) { memmove(tgt, src, size); }; +bool type_identity::do_destroy_pod(void *obj) { + free(obj); + return true; +} + void *type_identity::allocate() { if (can_allocate()) return do_allocate(); @@ -65,6 +70,13 @@ bool type_identity::copy(void *tgt, const void *src) { return false; } +bool type_identity::destroy(void *obj) { + if (can_allocate() && obj) + return do_destroy(obj); + else + return false; +} + void *enum_identity::do_allocate() { void *p = malloc(byte_size()); memcpy(p, &first_item_value, std::min(byte_size(), sizeof(int64_t))); diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp index bd9066a09..c38d6f288 100644 --- a/library/LuaWrapper.cpp +++ b/library/LuaWrapper.cpp @@ -593,10 +593,7 @@ static int meta_new(lua_State *state) void *ptr = id->allocate(); if (!ptr) - { - lua_pushnil(state); - return 1; - } + luaL_error(state, "Cannot allocate %s", id->getFullName().c_str()); if (lua_isuserdata(state, 1)) { @@ -630,6 +627,30 @@ static int meta_assign(lua_State *state) return 0; } +/** + * Method: deallocation for DF object references. + */ +static int meta_delete(lua_State *state) +{ + int argc = lua_gettop(state); + + if (argc != 1) + luaL_error(state, "Usage: object:delete() or df.delete(object)"); + + if (lua_isnil(state, 1)) + { + lua_pushboolean(state, true); + return 1; + } + + type_identity *id = get_object_identity(state, 1, "df.delete()", false); + + bool ok = id->destroy(get_object_ref(state, 1)); + + lua_pushboolean(state, ok); + return 1; +} + /** * Verify that the object is a DF ref with UPVAL_METATABLE. * If everything ok, extract the address. @@ -741,6 +762,10 @@ void LuaWrapper::SetPtrMethods(lua_State *state, int meta_idx, int read_idx) lua_setfield(state, meta_idx, "new"); EnableMetaField(state, read_idx, "new"); + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME); + lua_setfield(state, meta_idx, "delete"); + EnableMetaField(state, read_idx, "delete"); + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); lua_setfield(state, meta_idx, "assign"); EnableMetaField(state, read_idx, "assign"); @@ -1022,6 +1047,10 @@ static void DoAttach(lua_State *state) lua_pushcclosure(state, meta_assign, 1); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); + lua_pushcclosure(state, meta_delete, 1); + lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME); + luaL_register(state, "df", no_functions); { @@ -1035,6 +1064,8 @@ static void DoAttach(lua_State *state) lua_setfield(state, -2, "sizeof"); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME); lua_setfield(state, -2, "new"); + lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME); + lua_setfield(state, -2, "delete"); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_DISPLACE_NAME); lua_setfield(state, -2, "_displace"); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 0ec51f510..ca77e504f 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -73,10 +73,12 @@ namespace DFHack void *do_allocate_pod(); void do_copy_pod(void *tgt, const void *src); + bool do_destroy_pod(void *obj); virtual bool can_allocate() { return true; } virtual void *do_allocate() { return do_allocate_pod(); } virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } + virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); } public: virtual ~type_identity() {} @@ -101,6 +103,7 @@ namespace DFHack void *allocate(); bool copy(void *tgt, const void *src); + bool destroy(void *obj); }; class DFHACK_EXPORT constructed_identity : public type_identity { @@ -113,6 +116,7 @@ namespace DFHack virtual bool can_allocate() { return (allocator != NULL); } virtual void *do_allocate() { return allocator(NULL,NULL); } virtual void do_copy(void *tgt, const void *src) { allocator(tgt,src); } + virtual bool do_destroy(void *obj) { return allocator(NULL,obj) == obj; } public: virtual bool isPrimitive() { return false; } virtual bool isConstructed() { return true; } @@ -162,6 +166,7 @@ namespace DFHack virtual bool can_allocate() { return true; } virtual void *do_allocate() { return do_allocate_pod(); } virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } + virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); } public: bitfield_identity(size_t size, @@ -189,6 +194,7 @@ namespace DFHack virtual bool can_allocate() { return true; } virtual void *do_allocate(); virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } + virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); } public: enum_identity(size_t size, diff --git a/library/include/LuaWrapper.h b/library/include/LuaWrapper.h index 216887fe8..d043d96f7 100644 --- a/library/include/LuaWrapper.h +++ b/library/include/LuaWrapper.h @@ -68,6 +68,7 @@ namespace DFHack { namespace LuaWrapper { #define DFHACK_DISPLACE_NAME "DFHack::Displace" #define DFHACK_NEW_NAME "DFHack::New" #define DFHACK_ASSIGN_NAME "DFHack::Assign" +#define DFHACK_DELETE_NAME "DFHack::Delete" /* * Upvalue: contents of DFHACK_TYPETABLE_NAME