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