mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[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.
cf78eddbb6
This commit is contained in:
parent
8d2af51a78
commit
0f1e8f38c9
2 changed files with 76 additions and 15 deletions
|
@ -15,25 +15,53 @@ module Fiddle
|
||||||
|
|
||||||
def self.offsetof(name, members, types) # :nodoc:
|
def self.offsetof(name, members, types) # :nodoc:
|
||||||
offset = 0
|
offset = 0
|
||||||
index = 0
|
worklist = name.split('.')
|
||||||
member_index = members.index(name)
|
this_type = self
|
||||||
|
while search_name = worklist.shift
|
||||||
|
index = 0
|
||||||
|
member_index = members.index(search_name)
|
||||||
|
|
||||||
types.each { |type, count = 1|
|
unless member_index
|
||||||
orig_offset = offset
|
# Possibly a sub-structure
|
||||||
if type.respond_to?(:entity_class)
|
member_index = members.index { |member_name, _|
|
||||||
align = type.alignment
|
member_name == search_name
|
||||||
type_size = type.size
|
}
|
||||||
else
|
return unless member_index
|
||||||
align = PackInfo::ALIGN_MAP[type]
|
|
||||||
type_size = PackInfo::SIZE_MAP[type]
|
|
||||||
end
|
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
|
||||||
|
|
||||||
offset += (type_size * count)
|
# Unions shouldn't advance the offset
|
||||||
index += 1
|
if this_type.entity_class == CUnionEntity
|
||||||
}
|
type_size = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,45 @@ begin
|
||||||
require_relative 'helper'
|
require_relative 'helper'
|
||||||
require 'fiddle/struct'
|
require 'fiddle/struct'
|
||||||
require 'fiddle/cparser'
|
require 'fiddle/cparser'
|
||||||
|
require 'fiddle/import'
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
end
|
end
|
||||||
|
|
||||||
module Fiddle
|
module Fiddle
|
||||||
class TestCStructBuilder < TestCase
|
class TestCStructBuilder < TestCase
|
||||||
include Fiddle::CParser
|
include Fiddle::CParser
|
||||||
|
extend Fiddle::Importer
|
||||||
|
|
||||||
|
RBasic = struct ['void * flags',
|
||||||
|
'void * klass' ]
|
||||||
|
|
||||||
|
|
||||||
|
RObject = struct [
|
||||||
|
{ 'basic' => RBasic },
|
||||||
|
{ 'as' => union([
|
||||||
|
{ 'heap'=> struct([ 'uint32_t numiv',
|
||||||
|
'void * ivptr',
|
||||||
|
'void * iv_index_tbl' ]) },
|
||||||
|
'void *ary[3]' ])}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_basic_embedded_members
|
||||||
|
assert_equal 0, RObject.offsetof("basic.flags")
|
||||||
|
assert_equal Fiddle::SIZEOF_VOIDP, RObject.offsetof("basic.klass")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_embedded_union_members
|
||||||
|
assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as")
|
||||||
|
assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap")
|
||||||
|
assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.numiv")
|
||||||
|
assert_equal 3 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.ivptr")
|
||||||
|
assert_equal 4 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.heap.iv_index_tbl")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_as_ary
|
||||||
|
assert_equal 2 * Fiddle::SIZEOF_VOIDP, RObject.offsetof("as.ary")
|
||||||
|
end
|
||||||
|
|
||||||
def test_offsetof
|
def test_offsetof
|
||||||
types, members = parse_struct_signature(['int64_t i','char c'])
|
types, members = parse_struct_signature(['int64_t i','char c'])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue