From 0f1e8f38c9cd008eb24e6c957388a183eac910ca Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 19 Aug 2021 16:43:56 -0700 Subject: [ruby/fiddle] Improve "offsetof" calculations (https://github.com/ruby/fiddle/pull/90) I need to get the offset of members inside sub structures. This patch adds sub-structure offset support for structs. https://github.com/ruby/fiddle/commit/cf78eddbb6 --- ext/fiddle/lib/fiddle/struct.rb | 60 ++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 16 deletions(-) (limited to 'ext/fiddle') diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb index 2353edcc94..6d05bbd742 100644 --- a/ext/fiddle/lib/fiddle/struct.rb +++ b/ext/fiddle/lib/fiddle/struct.rb @@ -15,25 +15,53 @@ module Fiddle def self.offsetof(name, members, types) # :nodoc: offset = 0 - index = 0 - member_index = members.index(name) - - types.each { |type, count = 1| - orig_offset = offset - if type.respond_to?(:entity_class) - align = type.alignment - type_size = type.size - else - align = PackInfo::ALIGN_MAP[type] - type_size = PackInfo::SIZE_MAP[type] + worklist = name.split('.') + this_type = self + while search_name = worklist.shift + index = 0 + member_index = members.index(search_name) + + unless member_index + # Possibly a sub-structure + member_index = members.index { |member_name, _| + member_name == search_name + } + return unless member_index end - offset = PackInfo.align(orig_offset, align) - return offset if index == member_index + types.each { |type, count = 1| + orig_offset = offset + if type.respond_to?(:entity_class) + align = type.alignment + type_size = type.size + else + align = PackInfo::ALIGN_MAP[type] + type_size = PackInfo::SIZE_MAP[type] + end + + # Unions shouldn't advance the offset + if this_type.entity_class == CUnionEntity + type_size = 0 + end - offset += (type_size * count) - index += 1 - } + offset = PackInfo.align(orig_offset, align) + + if worklist.empty? + return offset if index == member_index + else + if index == member_index + subtype = types[member_index] + members = subtype.members + types = subtype.types + this_type = subtype + break + end + end + + offset += (type_size * count) + index += 1 + } + end nil end -- cgit v1.2.1