Add ref_target attribute to primitive field references

develop
lethosor 2020-04-09 00:02:07 -04:00
parent 498eb2750b
commit 125f4b129b
3 changed files with 21 additions and 11 deletions

@ -536,6 +536,7 @@ static void field_reference(lua_State *state, const struct_field_info *field, vo
case struct_field_info::PRIMITIVE: case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT: case struct_field_info::SUBSTRUCT:
push_object_internal(state, field->type, ptr); push_object_internal(state, field->type, ptr);
get_object_ref_header(state, -1)->field_info = field;
return; return;
case struct_field_info::POINTER: case struct_field_info::POINTER:
@ -706,6 +707,16 @@ static type_identity *find_primitive_field(lua_State *state, int field, const ch
*/ */
static int meta_primitive_index(lua_State *state) static int meta_primitive_index(lua_State *state)
{ {
const char *attr = lua_tostring(state, -1);
if (attr == std::string("ref_target")) {
const struct_field_info *field_info = get_object_ref_header(state, 1)->field_info;
if (field_info && field_info->extra && field_info->extra->ref_target) {
LookupInTable(state, field_info->extra->ref_target, &DFHACK_TYPEID_TABLE_TOKEN);
} else {
lua_pushnil(state);
}
return 1;
}
uint8_t *ptr = get_object_addr(state, 1, 2, "read"); uint8_t *ptr = get_object_addr(state, 1, 2, "read");
auto type = find_primitive_field(state, 2, "read", &ptr); auto type = find_primitive_field(state, 2, "read", &ptr);
if (!type) if (!type)

@ -170,18 +170,24 @@ void LuaWrapper::push_object_ref(lua_State *state, void *ptr)
// stack: [metatable] // stack: [metatable]
auto ref = (DFRefHeader*)lua_newuserdata(state, sizeof(DFRefHeader)); auto ref = (DFRefHeader*)lua_newuserdata(state, sizeof(DFRefHeader));
ref->ptr = ptr; ref->ptr = ptr;
ref->field_info = NULL;
lua_swap(state); lua_swap(state);
lua_setmetatable(state, -2); lua_setmetatable(state, -2);
// stack: [userdata] // stack: [userdata]
} }
void *LuaWrapper::get_object_ref(lua_State *state, int val_index) DFRefHeader *LuaWrapper::get_object_ref_header(lua_State *state, int val_index)
{ {
assert(!lua_islightuserdata(state, val_index)); assert(!lua_islightuserdata(state, val_index));
auto ref = (DFRefHeader*)lua_touserdata(state, val_index); auto ref = (DFRefHeader*)lua_touserdata(state, val_index);
return ref->ptr; return ref;
}
void *LuaWrapper::get_object_ref(lua_State *state, int val_index)
{
return get_object_ref_header(state, val_index)->ptr;
} }
/** /**

@ -126,6 +126,7 @@ namespace LuaWrapper {
*/ */
struct DFRefHeader { struct DFRefHeader {
void *ptr; void *ptr;
const struct_field_info *field_info;
}; };
/** /**
@ -133,15 +134,7 @@ namespace LuaWrapper {
*/ */
void push_object_ref(lua_State *state, void *ptr); void push_object_ref(lua_State *state, void *ptr);
DFHACK_EXPORT void *get_object_ref(lua_State *state, int val_index); DFHACK_EXPORT void *get_object_ref(lua_State *state, int val_index);
DFHACK_EXPORT DFRefHeader *get_object_ref_header(lua_State *state, int val_index);
/*
* The system might be extended to carry some simple
* objects inline inside the reference buffer.
*/
inline bool is_self_contained(DFRefHeader *ptr) {
void **pp = &ptr->ptr;
return **(void****)pp == (pp + 1);
}
/** /**
* Report an error while accessing a field (index = field name). * Report an error while accessing a field (index = field name).