diff options
Diffstat (limited to 'ext/dl/lib/dl/struct.rb')
-rw-r--r-- | ext/dl/lib/dl/struct.rb | 236 |
1 files changed, 0 insertions, 236 deletions
diff --git a/ext/dl/lib/dl/struct.rb b/ext/dl/lib/dl/struct.rb deleted file mode 100644 index e2d91a6d14..0000000000 --- a/ext/dl/lib/dl/struct.rb +++ /dev/null @@ -1,236 +0,0 @@ -require 'dl' -require 'dl/value' -require 'dl/pack.rb' - -module DL - # C struct shell - class CStruct - # accessor to DL::CStructEntity - def CStruct.entity_class() - CStructEntity - end - end - - # C union shell - class CUnion - # accessor to DL::CUnionEntity - def CUnion.entity_class() - CUnionEntity - end - end - - # Used to construct C classes (CUnion, CStruct, etc) - # - # DL::Importer#struct and DL::Importer#union wrap this functionality in an - # easy-to-use manner. - module CStructBuilder - # Construct a new class given a C: - # * class +klass+ (CUnion, CStruct, or other that provide an - # #entity_class) - # * +types+ (DL:TYPE_INT, DL::TYPE_SIZE_T, etc., see the C types - # constants) - # * corresponding +members+ - # - # DL::Importer#struct and DL::Importer#union wrap this functionality in an - # easy-to-use manner. - # - # Example: - # - # require 'dl/struct' - # require 'dl/cparser' - # - # include DL::CParser - # - # types, members = parse_struct_signature(['int i','char c']) - # - # MyStruct = DL::CStructBuilder.create(CUnion, types, members) - # - # obj = MyStruct.allocate - # - def create(klass, types, members) - new_class = Class.new(klass){ - define_method(:initialize){|addr| - @entity = klass.entity_class.new(addr, types) - @entity.assign_names(members) - } - define_method(:to_ptr){ @entity } - define_method(:to_i){ @entity.to_i } - members.each{|name| - define_method(name){ @entity[name] } - define_method(name + "="){|val| @entity[name] = val } - } - } - size = klass.entity_class.size(types) - new_class.module_eval(<<-EOS, __FILE__, __LINE__+1) - def new_class.size() - #{size} - end - def new_class.malloc() - addr = DL.malloc(#{size}) - new(addr) - end - EOS - return new_class - end - module_function :create - end - - # A C struct wrapper - class CStructEntity < (DL.fiddle? ? Fiddle::Pointer : CPtr) - include PackInfo - include ValueUtil - - # Allocates a C struct the +types+ provided. The C function +func+ is - # called when the instance is garbage collected. - def CStructEntity.malloc(types, func = nil) - addr = DL.malloc(CStructEntity.size(types)) - CStructEntity.new(addr, types, func) - end - - # Given +types+, returns the offset for the packed sizes of those types - # - # DL::CStructEntity.size([DL::TYPE_DOUBLE, DL::TYPE_INT, DL::TYPE_CHAR, - # DL::TYPE_VOIDP]) - # => 24 - def CStructEntity.size(types) - offset = 0 - - max_align = types.map { |type, count = 1| - last_offset = offset - - align = PackInfo::ALIGN_MAP[type] - offset = PackInfo.align(last_offset, align) + - (PackInfo::SIZE_MAP[type] * count) - - align - }.max - - PackInfo.align(offset, max_align) - end - - # Wraps the C pointer +addr+ as a C struct with the given +types+. The C - # function +func+ is called when the instance is garbage collected. - # - # See also DL::CPtr.new - def initialize(addr, types, func = nil) - set_ctypes(types) - super(addr, @size, func) - end - - # Set the names of the +members+ in this C struct - def assign_names(members) - @members = members - end - - # Given +types+, calculate the offsets and sizes for the types in the - # struct. - def set_ctypes(types) - @ctypes = types - @offset = [] - offset = 0 - - max_align = types.map { |type, count = 1| - orig_offset = offset - align = ALIGN_MAP[type] - offset = PackInfo.align(orig_offset, align) - - @offset << offset - - offset += (SIZE_MAP[type] * count) - - align - }.max - - @size = PackInfo.align(offset, max_align) - end - - # Fetch struct member +name+ - def [](name) - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - if( ty.is_a?(Array) ) - r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) - else - r = super(@offset[idx], SIZE_MAP[ty.abs]) - end - packer = Packer.new([ty]) - val = packer.unpack([r]) - case ty - when Array - case ty[0] - when TYPE_VOIDP - val = val.collect{|v| CPtr.new(v)} - end - when TYPE_VOIDP - val = CPtr.new(val[0]) - else - val = val[0] - end - 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])} - else - return val - end - end - - # Set struct member +name+, to value +val+ - def []=(name, val) - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - packer = Packer.new([ty]) - val = wrap_arg(val, ty, []) - buff = packer.pack([val].flatten()) - super(@offset[idx], buff.size, buff) - 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])} - else - return val - end - end - - def to_s() # :nodoc: - super(@size) - end - end - - # A C union wrapper - class CUnionEntity < CStructEntity - include PackInfo - - # Allocates a C union the +types+ provided. The C function +func+ is - # called when the instance is garbage collected. - def CUnionEntity.malloc(types, func=nil) - addr = DL.malloc(CUnionEntity.size(types)) - CUnionEntity.new(addr, types, func) - end - - # Given +types+, returns the size needed for the union. - # - # DL::CUnionEntity.size([DL::TYPE_DOUBLE, DL::TYPE_INT, DL::TYPE_CHAR, - # DL::TYPE_VOIDP]) - # => 8 - def CUnionEntity.size(types) - types.map { |type, count = 1| - PackInfo::SIZE_MAP[type] * count - }.max - end - - # Given +types+, calculate the necessary offset and for each union member - def set_ctypes(types) - @ctypes = types - @offset = Array.new(types.length, 0) - @size = self.class.size types - end - end -end - |