ext/dl/lib/dl/struct.rb


DEFINITIONS

This source file includes following functions.


   1  # -*- ruby -*-
   2  
   3  require 'dl'
   4  require 'dl/import'
   5  
   6  module DL
   7    module Importable
   8      module Internal
   9        def define_struct(contents)
  10          init_types()
  11          Struct.new(@types, contents)
  12        end
  13        alias struct define_struct
  14  
  15        def define_union(contents)
  16          init_types()
  17          Union.new(@types, contents)
  18        end
  19        alias union define_union
  20  
  21        class Memory
  22          def initialize(ptr, names, ty, len, enc, dec)
  23            @ptr = ptr
  24            @names = names
  25            @ty    = ty
  26            @len   = len
  27            @enc   = enc
  28            @dec   = dec
  29  
  30            # define methods
  31            @names.each{|name|
  32              instance_eval [
  33                "def #{name}",
  34                "  v = @ptr[\"#{name}\"]",
  35                "  v = @dec[\"#{name}\"].call(v,@len[\"#{name}\"]) if @dec[\"#{name}\"]",
  36                "  return v",
  37                "end",
  38                "def #{name}=(v)",
  39                "  v = @enc[\"#{name}\"].call(v,@len[\"#{name}\"]) if @enc[\"#{name}\"]",
  40                "  @ptr[\"#{name}\"] = v",
  41                "  return v",
  42                "end",
  43              ].join("\n")
  44            }
  45          end
  46  
  47          def to_ptr
  48            return @ptr
  49          end
  50  
  51          def size
  52            return @ptr.size
  53          end
  54        end
  55  
  56        class Struct
  57          def initialize(types, contents)
  58            @names = []
  59            @ty   = {}
  60            @len  = {}
  61            @enc  = {}
  62            @dec  = {}
  63            @size = 0
  64            @tys  = ""
  65            @types = types
  66            parse(contents)
  67          end
  68  
  69          def size
  70            return @size
  71          end
  72  
  73          def members
  74            return @names
  75          end
  76  
  77          # ptr must be a PtrData object.
  78          def new(ptr)
  79            ptr.struct!(@tys, *@names)
  80            mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
  81            return mem
  82          end
  83  
  84          def malloc(size = nil)
  85            if( !size )
  86              size = @size
  87            end
  88            ptr = DL::malloc(size)
  89            return new(ptr)
  90          end
  91  
  92          def parse(contents)
  93            contents.each{|elem|
  94              name,ty,num,enc,dec = parse_elem(elem)
  95              @names.push(name)
  96              @ty[name]  = ty
  97              @len[name] = num
  98              @enc[name] = enc
  99              @dec[name] = dec
 100              if( num )
 101                @tys += "#{ty}#{num}"
 102              else
 103                @tys += ty
 104              end
 105            }
 106            @size = DL.sizeof(@tys)
 107          end
 108          
 109          def parse_elem(elem)
 110            elem.strip!
 111            case elem
 112            when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)$/
 113              ty = ($1 + $2).strip
 114              name = $3
 115              num = nil;
 116            when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)\[(\d+)\]$/
 117              ty = ($1 + $2).strip
 118              name = $3
 119              num = $4.to_i
 120            else
 121              raise(RuntimeError, "invalid element: #{elem}")
 122            end
 123            ty,_,_,enc,dec = @types.encode_type(ty)
 124            return [name,ty,num,enc,dec]
 125          end
 126        end  # class Struct
 127        
 128        class Union < Struct
 129          def new
 130            ptr = DL::malloc(@size)
 131            ptr.union!(@tys, *@names)
 132            mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
 133            return mem
 134          end
 135        end
 136      end  # module Internal
 137    end  # module Importable
 138  end  # module DL