10000 [ruby/fiddle] Fix assignment to array within struct (#26) · nobu/ruby@b036440 · GitHub
[go: up one dir, main page]

Skip to content

Commit b036440

Browse files
sinisterchipmunknobu
authored andcommitted
[ruby/fiddle] Fix assignment to array within struct (ruby#26)
* Allow access to a struct's underlying memory with `struct[offset, length]`. ruby/fiddle@24083690a6
1 parent 08b4069 commit b036440

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

ext/fiddle/lib/fiddle/struct.rb

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,33 @@ def CUnion.entity_class
2020
end
2121
end
2222

23+
# Wrapper for arrays within a struct
24+
class StructArray < Array
25+
include ValueUtil
26+
27+
def initialize(ptr, type, initial_values)
28+
@ptr = ptr
29+
@type = type
30+
@align = PackInfo::ALIGN_MAP[type]
31+
@size = Fiddle::PackInfo::SIZE_MAP[type]
32+
@pack_format = Fiddle::PackInfo::PACK_MAP[type]
33+
super(initial_values.collect { |v| unsigned_value(v, type) })
34+
end
35+
36+
def to_ptr
37+
@ptr
38+
end
39+
40+
def []=(index, value)
41+
if index < 0 || index >= size
42+
raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size]
43+
end
44+
45+
to_ptr[index * @size, @size] = [value].pack(@pack_format)
46 8000 +
super(index, value)
47+
end
48+
end
49+
2350
# Used to construct C classes (CUnion, CStruct, etc)
2451
#
2552
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
@@ -191,7 +218,7 @@ def [](*args)
191218
if( ty.is_a?(Integer) && (ty < 0) )
192219
return unsigned_value(val, ty)
193220
elsif( ty.is_a?(Array) && (ty[0] < 0) )
194-
return val.collect{|v| unsigned_value(v,ty[0])}
221+
return StructArray.new(self + @offset[idx], ty[0], val)
195222
else
196223
return val
197224
end

test/fiddle/test_import.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ def test_value()
129129
assert_equal([0,1,2], ary.value)
130130
end
131131

132+
def test_struct_array_assignment()
133+
instance = Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc
134+
instance.stages[0] = 1024
135+
instance.stages[1] = 10
136+
instance.stages[2] = 100
137+
assert_equal 1024, instance.stages[0]
138+
assert_equal 10, instance.stages[1]
139+
assert_equal 100, instance.stages[2]
140+
assert_equal [1024, 10, 100].pack(Fiddle::PackInfo::PACK_MAP[-Fiddle::TYPE_INT] * 3),
141+
instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT]
142+
assert_raise(IndexError) { instance.stages[-1] = 5 }
143+
assert_raise(IndexError) { instance.stages[3] = 5 }
144+
end
145+
132146
def test_struct()
133147
s = LIBC::MyStruct.malloc()
134148
s.num = [0,1,2,3,4]

0 commit comments

Comments
 (0)
0