summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsinisterchipmunk <sinisterchipmunk@gmail.com>2020-01-22 20:37:23 -0500
committerNobuyoshi Nakada <nobu@ruby-lang.org>2020-05-23 14:29:16 +0900
commit77cc13943cd9ec908d75133d7ac0b89c9ab57deb (patch)
tree43dcfca55a0d6c956eadb378780a987d61a5c849
parent4a835621ced099316850a16f2a13534dea62a0b8 (diff)
[ruby/fiddle] Fix assignment to array within struct (#26)
* Allow access to a struct's underlying memory with `struct[offset, length]`. https://github.com/ruby/fiddle/commit/24083690a6
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3068
-rw-r--r--ext/fiddle/lib/fiddle/struct.rb29
-rw-r--r--test/fiddle/test_import.rb14
2 files changed, 42 insertions, 1 deletions
diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb
index f5385e548c..8a48a1cb8b 100644
--- a/ext/fiddle/lib/fiddle/struct.rb
+++ b/ext/fiddle/lib/fiddle/struct.rb
@@ -20,6 +20,33 @@ module Fiddle
end
end
+ # Wrapper for arrays within a struct
+ class StructArray < Array
+ include ValueUtil
+
+ def initialize(ptr, type, initial_values)
+ @ptr = ptr
+ @type = type
+ @align = PackInfo::ALIGN_MAP[type]
+ @size = Fiddle::PackInfo::SIZE_MAP[type]
+ @pack_format = Fiddle::PackInfo::PACK_MAP[type]
+ super(initial_values.collect { |v| unsigned_value(v, type) })
+ end
+
+ def to_ptr
+ @ptr
+ end
+
+ def []=(index, value)
+ if index < 0 || index >= size
+ raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size]
+ end
+
+ to_ptr[index * @size, @size] = [value].pack(@pack_format)
+ super(index, value)
+ end
+ end
+
# Used to construct C classes (CUnion, CStruct, etc)
#
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
@@ -191,7 +218,7 @@ module Fiddle
if( ty.is_a?(Integer) && (ty < 0) )
return unsigned_value(val, ty)
elsif( ty.is_a?(Array) && (ty[0] < 0) )
- return val.collect{|v| unsigned_value(v,ty[0])}
+ return StructArray.new(self + @offset[idx], ty[0], val)
else
return val
end
diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb
index 778327b4b2..867f6960ee 100644
--- a/test/fiddle/test_import.rb
+++ b/test/fiddle/test_import.rb
@@ -129,6 +129,20 @@ module Fiddle
assert_equal([0,1,2], ary.value)
end
+ def test_struct_array_assignment()
+ instance = Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc
+ instance.stages[0] = 1024
+ instance.stages[1] = 10
+ instance.stages[2] = 100
+ assert_equal 1024, instance.stages[0]
+ assert_equal 10, instance.stages[1]
+ assert_equal 100, instance.stages[2]
+ assert_equal [1024, 10, 100].pack(Fiddle::PackInfo::PACK_MAP[-Fiddle::TYPE_INT] * 3),
+ instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT]
+ assert_raise(IndexError) { instance.stages[-1] = 5 }
+ assert_raise(IndexError) { instance.stages[3] = 5 }
+ end
+
def test_struct()
s = LIBC::MyStruct.malloc()
s.num = [0,1,2,3,4]