summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2021-06-30 17:35:04 -0700
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-07-13 19:37:46 +0900
commit5c0d8c6369f92915bf99924f58f0763abe4f493e (patch)
tree1b26c487b766527a3e5d3c4fcba89ab961952b94 /ext
parenta2c9e1b58a9bc1da0533171236da43fcb556ead7 (diff)
[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.rb43
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)