diff options
author | Aaron Patterson <tenderlove@ruby-lang.org> | 2021-06-30 17:35:04 -0700 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2021-07-13 19:37:46 +0900 |
commit | 5c0d8c6369f92915bf99924f58f0763abe4f493e (patch) | |
tree | 1b26c487b766527a3e5d3c4fcba89ab961952b94 /ext | |
parent | a2c9e1b58a9bc1da0533171236da43fcb556ead7 (diff) | |
download | ruby-5c0d8c6369f92915bf99924f58f0763abe4f493e.tar.gz |
[ruby/fiddle] Add "offsetof" to Struct classes (https://github.com/ruby/fiddle/pull/83)
* Add "offsetof" to Struct classes
I need to get the offset of a member inside a struct without allocating
the struct. This patch adds an "offsetof" class method to structs that
are generated.
The usage is like this:
```ruby
MyStruct = struct [
"int64_t i",
"char c",
]
MyStruct.offsetof("i") # => 0
MyStruct.offsetof("c") # => 8
```
* Update test/fiddle/test_c_struct_builder.rb
Co-authored-by: Sutou Kouhei <kou@cozmixng.org>
https://github.com/ruby/fiddle/commit/4e3b60c5b6
Co-authored-by: Sutou Kouhei <kou@cozmixng.org>
Diffstat (limited to 'ext')
-rw-r--r-- | ext/fiddle/lib/fiddle/struct.rb | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb index a766eba83b..2353edcc94 100644 --- a/ext/fiddle/lib/fiddle/struct.rb +++ b/ext/fiddle/lib/fiddle/struct.rb @@ -13,6 +13,30 @@ module Fiddle CStructEntity end + 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] + end + offset = PackInfo.align(orig_offset, align) + + return offset if index == member_index + + offset += (type_size * count) + index += 1 + } + nil + end + def each return enum_for(__function__) unless block_given? @@ -75,6 +99,10 @@ module Fiddle def CUnion.entity_class CUnionEntity end + + def self.offsetof(name, members, types) # :nodoc: + 0 + end end # Wrapper for arrays within a struct @@ -172,6 +200,21 @@ module Fiddle define_method(:to_i){ @entity.to_i } define_singleton_method(:types) { types } define_singleton_method(:members) { members } + + # Return the offset of a struct member given its name. + # For example: + # + # MyStruct = struct [ + # "int64_t i", + # "char c", + # ] + # + # MyStruct.offsetof("i") # => 0 + # MyStruct.offsetof("c") # => 8 + # + define_singleton_method(:offsetof) { |name| + klass.offsetof(name, members, types) + } members.each{|name| name = name[0] if name.is_a?(Array) # name is a nested struct next if method_defined?(name) |