ruby-changes:61336
From: sinisterchipmunk <ko1@a...>
Date: Sat, 23 May 2020 14:29:33 +0900 (JST)
Subject: [ruby-changes:61336] 4a835621ce (master): [ruby/fiddle] Make array access override compatible with base class (#25)
https://git.ruby-lang.org/ruby.git/commit/?id=4a835621ce From 4a835621ced099316850a16f2a13534dea62a0b8 Mon Sep 17 00:00:00 2001 From: sinisterchipmunk <sinisterchipmunk@g...> Date: Wed, 22 Jan 2020 02:55:16 -0500 Subject: [ruby/fiddle] Make array access override compatible with base class (#25) * Allow access to a struct's underlying memory with `struct[offset, length]`. * Make accessing a struct's underlying memory more convenient. * refactor memory access unit tests for improved clarity https://github.com/ruby/fiddle/commit/c082c81bb5 diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb index 7c0dedb..f5385e5 100644 --- a/ext/fiddle/lib/fiddle/struct.rb +++ b/ext/fiddle/lib/fiddle/struct.rb @@ -54,6 +54,8 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/ext/fiddle/lib/fiddle/struct.rb#L54 @entity = klass.entity_class.new(addr, types) @entity.assign_names(members) } + define_method(:[]) { |*args| @entity.send(:[], *args) } + define_method(:[]=) { |*args| @entity.send(:[]=, *args) } define_method(:to_ptr){ @entity } define_method(:to_i){ @entity.to_i } members.each{|name| @@ -148,8 +150,21 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/ext/fiddle/lib/fiddle/struct.rb#L150 @size = PackInfo.align(offset, max_align) end - # Fetch struct member +name+ - def [](name) + # Fetch struct member +name+ if only one argument is specified. If two + # arguments are specified, the first is an offset and the second is a + # length and this method returns the string of +length+ bytes beginning at + # +offset+. + # + # Examples: + # + # my_struct = struct(['int id']).malloc + # my_struct.id = 1 + # my_struct['id'] # => 1 + # my_struct[0, 4] # => "\x01\x00\x00\x00".b + # + def [](*args) + return super(*args) if args.size > 1 + name = args[0] idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") @@ -182,8 +197,20 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/ext/fiddle/lib/fiddle/struct.rb#L197 end end - # Set struct member +name+, to value +val+ - def []=(name, val) + # Set struct member +name+, to value +val+. If more arguments are + # specified, writes the string of bytes to the memory at the given + # +offset+ and +length+. + # + # Examples: + # + # my_struct = struct(['int id']).malloc + # my_struct['id'] = 1 + # my_struct[0, 4] = "\x01\x00\x00\x00".b + # my_struct.id # => 1 + # + def []=(*args) + return super(*args) if args.size > 2 + name, val = *args idx = @members.index(name) if( idx.nil? ) raise(ArgumentError, "no such member: #{name}") diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb index 99294ea..778327b 100644 --- a/test/fiddle/test_import.rb +++ b/test/fiddle/test_import.rb @@ -54,6 +54,28 @@ module Fiddle https://github.com/ruby/ruby/blob/trunk/test/fiddle/test_import.rb#L54 assert_match(/call dlload before/, err.message) end + def test_struct_memory_access() + # check memory operations performed directly on struct + my_struct = Fiddle::Importer.struct(['int id']).malloc + my_struct[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT + assert_equal 0x01010101, my_struct.id + + my_struct.id = 0 + assert_equal "\x00".b * Fiddle::SIZEOF_INT, my_struct[0, Fiddle::SIZEOF_INT] + end + + def test_struct_ptr_array_subscript_multiarg() + # check memory operations performed on struct#to_ptr + struct = Fiddle::Importer.struct([ 'int x' ]).malloc + ptr = struct.to_ptr + + struct.x = 0x02020202 + assert_equal("\x02".b * Fiddle::SIZEOF_INT, ptr[0, Fiddle::SIZEOF_INT]) + + ptr[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT + assert_equal 0x01010101, struct.x + end + def test_malloc() s1 = LIBC::Timeval.malloc() s2 = LIBC::Timeval.malloc() -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/