From fc10ed3df63f610fa4c3756ae121201f3c7a79f4 Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Mon, 27 Apr 2020 18:26:31 -0500 Subject: [PATCH 1/4] Implementation for df-other-vectors-type in C++. Still needs Lua and Ruby support. --- library/include/BitArray.h | 10 ++++++++++ library/include/DataDefs.h | 1 + 2 files changed, 11 insertions(+) diff --git a/library/include/BitArray.h b/library/include/BitArray.h index cfb859bd0..dfd187363 100644 --- a/library/include/BitArray.h +++ b/library/include/BitArray.h @@ -568,4 +568,14 @@ namespace DFHack root->next = link; } }; + + template + struct DfOtherVectors + { + std::vector & operator[](O other_id) + { + auto vectors = reinterpret_cast *>(this); + return vectors[other_id]; + } + }; } diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index fd70b7ba8..3b961df20 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -474,6 +474,7 @@ namespace df using DFHack::BitArray; using DFHack::DfArray; using DFHack::DfLinkedList; + using DFHack::DfOtherVectors; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" From 7cf9624de9d25383ba548d49fa180f28409c8202 Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Mon, 27 Apr 2020 18:56:48 -0500 Subject: [PATCH 2/4] add assert to make sure other_id array index is in bounds --- library/include/BitArray.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/include/BitArray.h b/library/include/BitArray.h index dfd187363..5858897a3 100644 --- a/library/include/BitArray.h +++ b/library/include/BitArray.h @@ -574,6 +574,8 @@ namespace DFHack { std::vector & operator[](O other_id) { + CHECK_INVALID_ARGUMENT(size_t(other_id) < sizeof(*this) / sizeof(std::vector)); + auto vectors = reinterpret_cast *>(this); return vectors[other_id]; } From 6c20fe4c804fa97018bb1a4374c0d86470d5e26f Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Tue, 28 Apr 2020 13:55:34 -0500 Subject: [PATCH 3/4] implement df-other-vectors-type for lua --- library/LuaTypes.cpp | 22 ++++++++++++++++++++++ library/include/DataDefs.h | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/library/LuaTypes.cpp b/library/LuaTypes.cpp index 306538f51..c46d7ce05 100644 --- a/library/LuaTypes.cpp +++ b/library/LuaTypes.cpp @@ -1422,6 +1422,28 @@ void struct_identity::build_metatable(lua_State *state) SetPtrMethods(state, base+1, base+2); } +void other_vectors_identity::build_metatable(lua_State *state) +{ + int base = lua_gettop(state); + MakeFieldMetatable(state, this, meta_struct_index, meta_struct_newindex); + + EnableMetaField(state, base+2, "_enum"); + + LookupInTable(state, index_enum, &DFHACK_TYPEID_TABLE_TOKEN); + lua_setfield(state, base+1, "_enum"); + + auto keys = &index_enum->getKeys()[-index_enum->getFirstItem()]; + + for (int64_t i = 0; i < index_enum->getLastItem(); i++) + { + lua_getfield(state, base+2, keys[i]); + lua_rawseti(state, base+2, int(i)); + } + + SetStructMethod(state, base+1, base+2, meta_struct_field_reference, "_field"); + SetPtrMethods(state, base+1, base+2); +} + void global_identity::build_metatable(lua_State *state) { int base = lua_gettop(state); diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 3b961df20..f4eff8510 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -334,6 +334,23 @@ namespace DFHack virtual identity_type type() { return IDTYPE_UNION; } }; + class DFHACK_EXPORT other_vectors_identity : public struct_identity { + enum_identity *index_enum; + + public: + other_vectors_identity(size_t size, TAllocateFn alloc, + compound_identity *scope_parent, const char *dfhack_name, + struct_identity *parent, const struct_field_info *fields, + enum_identity *index_enum) : + struct_identity(size, alloc, scope_parent, dfhack_name, parent, fields), + index_enum(index_enum) + {} + + enum_identity *getIndexEnum() { return index_enum; } + + virtual void build_metatable(lua_State *state); + }; + #ifdef _MSC_VER typedef void *virtual_ptr; #else @@ -465,6 +482,7 @@ namespace df using DFHack::global_identity; using DFHack::struct_identity; using DFHack::union_identity; + using DFHack::other_vectors_identity; using DFHack::struct_field_info; using DFHack::struct_field_info_extra; using DFHack::bitfield_item_info; From 28c34217d86a77b6eafe26aca1c3ff371cb65ecb Mon Sep 17 00:00:00 2001 From: Ben Lubar Date: Tue, 28 Apr 2020 14:26:33 -0500 Subject: [PATCH 4/4] Ruby implementation of df-other-vectors-type --- plugins/ruby/codegen.pl | 8 ++++++++ plugins/ruby/ruby-autogen-defs.rb | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/plugins/ruby/codegen.pl b/plugins/ruby/codegen.pl index 2a12a1bea..535a49694 100755 --- a/plugins/ruby/codegen.pl +++ b/plugins/ruby/codegen.pl @@ -240,6 +240,12 @@ sub render_global_class { } my $rbparent = ($parent ? rb_ucase($parent) : 'MemHack::Compound'); + my $ienum; + if (($type->getAttribute('ld:subtype') or '') eq 'df-other-vectors-type') + { + $rbparent = 'MemHack::OtherVectors'; + $ienum = rb_ucase($type->getAttribute('index-enum')); + } push @lines_rb, "class $rbname < $rbparent"; indent_rb { my $sz = sizeof($type); @@ -249,6 +255,8 @@ sub render_global_class { push @lines_rb, "rtti_classname :$rtti_name\n" if $rtti_name; + push @lines_rb, "ienum $ienum\n" if $ienum; + render_struct_fields($type); my $vms = $type->findnodes('child::virtual-methods')->[0]; diff --git a/plugins/ruby/ruby-autogen-defs.rb b/plugins/ruby/ruby-autogen-defs.rb index 10727894d..c72ffeb2b 100644 --- a/plugins/ruby/ruby-autogen-defs.rb +++ b/plugins/ruby/ruby-autogen-defs.rb @@ -205,6 +205,22 @@ module DFHack end end + class OtherVectors < Compound + class << self + attr_accessor :_enum + def ienum(enum) + @_enum = enum + end + end + + def [](i) + self.send(self.class._enum.sym(i)) + end + def []=(i, v) + self.send((self.class._enum.sym(i).to_s + "=").to_sym, v) + end + end + class Enum # number -> symbol def self.enum