binary_parser 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/binary_parser.gemspec +2 -2
- data/lib/binary_parser/version.rb +1 -1
- data/lib/binary_parser.rb +5 -1
- data/lib/built_in_template/binary.rb +14 -0
- data/lib/built_in_template/uint.rb +74 -1
- data/lib/general_class/bit_position.rb +1 -1
- data/lib/general_class/condition.rb +4 -3
- data/lib/general_class/expression.rb +216 -40
- data/lib/general_class/free_condition.rb +20 -0
- data/lib/general_class/memorize.rb +36 -0
- data/lib/general_class/proxy.rb +14 -0
- data/lib/loop_list.rb +2 -0
- data/lib/scope.rb +46 -36
- data/lib/structure_definition.rb +88 -55
- data/lib/template_base.rb +14 -12
- data/lib/while_list.rb +31 -0
- data/unit_test/built_in_template/test_binary.rb +40 -0
- data/unit_test/built_in_template/test_uint.rb +87 -0
- data/unit_test/general_class/test_bit_position.rb +1 -1
- data/unit_test/general_class/test_condition.rb +2 -2
- data/unit_test/general_class/test_expression.rb +29 -5
- data/unit_test/general_class/test_free_condition.rb +20 -0
- data/unit_test/test_scope.rb +46 -0
- data/unit_test/test_structure_definition.rb +47 -6
- metadata +11 -4
data/lib/structure_definition.rb
CHANGED
@@ -3,96 +3,97 @@ module BinaryParser
|
|
3
3
|
|
4
4
|
DataDefinition = Struct.new(:bit_position, :bit_length, :conditions, :klass)
|
5
5
|
LoopDefinition = Struct.new(:bit_position, :bit_length, :conditions, :klass)
|
6
|
+
WhileDefinition = Struct.new(:bit_position, :bit_length, :conditions, :klass, :loop_condition)
|
6
7
|
|
7
|
-
|
8
|
+
KEYWORDS =
|
9
|
+
[
|
10
|
+
:data, :SPEND, :TIMES, :WHILE, :IF, :E, :cond, :match, :var, :len, :nextbits, :position,
|
11
|
+
:rest, :[]
|
12
|
+
]
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
attr_reader :parent_structure, :bit_at, :names
|
15
|
+
|
16
|
+
def initialize(forbidden_method_names=[], parent_structure=nil, &init_proc)
|
17
|
+
@forbidden_method_names = forbidden_method_names
|
11
18
|
@parent_structure = parent_structure
|
12
19
|
@bit_at = BitPosition.new
|
13
|
-
@data_def
|
20
|
+
@data_def = {}
|
14
21
|
@conditions, @names = [], []
|
15
|
-
instance_eval(&init_proc) if init_proc
|
22
|
+
Proxy.new(self, KEYWORDS).instance_eval(&init_proc) if init_proc
|
16
23
|
end
|
17
24
|
|
18
25
|
def data(name, klass, bit_length)
|
19
|
-
|
26
|
+
__check_new_def_name(name)
|
20
27
|
unless klass.ancestors.include?(TemplateBase)
|
21
28
|
raise DefinitionError, "Class #{klass} should be TemplateBase."
|
22
29
|
end
|
23
|
-
bit_at, bit_length =
|
24
|
-
|
25
|
-
@names << name
|
30
|
+
bit_at, bit_length = __process_bit_length(bit_length, name)
|
31
|
+
define(name, DataDefinition.new(bit_at, bit_length, @conditions.dup, klass))
|
26
32
|
end
|
27
33
|
|
28
34
|
def SPEND(bit_length, name, &block)
|
29
|
-
|
30
|
-
bit_at, bit_length =
|
35
|
+
__check_new_def_name(name)
|
36
|
+
bit_at, bit_length = __process_bit_length(bit_length, name)
|
31
37
|
klass = NamelessTemplateMaker.new(self, block)
|
32
|
-
|
33
|
-
@names << name
|
38
|
+
define(name, LoopDefinition.new(bit_at, bit_length, @conditions.dup, klass))
|
34
39
|
end
|
35
40
|
|
36
41
|
def TIMES(times, name, &block)
|
37
|
-
|
42
|
+
__check_new_def_name(name)
|
38
43
|
klass = NamelessTemplateMaker.new(self, block)
|
39
44
|
structure = klass.structure
|
40
45
|
if structure.bit_at.names.empty?
|
41
|
-
bit_at, bit_length =
|
42
|
-
|
46
|
+
bit_at, bit_length = __process_bit_length(times * structure.bit_at.imm, name)
|
47
|
+
define(name, LoopDefinition.new(bit_at, bit_length, @conditions.dup, klass))
|
43
48
|
else
|
44
|
-
bit_length = Expression.
|
45
|
-
structure.bit_at.names.each do |
|
46
|
-
depending_length_exp = structure[
|
47
|
-
depending_length_exp.
|
48
|
-
if structure[
|
49
|
-
raise DefinitionError, "In '#{name}', same level variable #{
|
49
|
+
bit_length = Expression.immediate(0)
|
50
|
+
structure.bit_at.names.each do |depending_token|
|
51
|
+
depending_length_exp = structure[depending_token.symbol].bit_length
|
52
|
+
depending_length_exp.variable_tokens.each do |token|
|
53
|
+
if structure[token.symbol]
|
54
|
+
raise DefinitionError, "In '#{name}', same level variable #{token.symbol} is referenced." +
|
50
55
|
"*** TIMES's inner structure's bit-length must be always same." +
|
51
56
|
"In other words, that bit-length must not rely on same level variables. ***"
|
52
57
|
end
|
53
58
|
end
|
54
59
|
bit_length += depending_length_exp
|
55
60
|
end
|
56
|
-
bit_at, bit_length =
|
57
|
-
|
61
|
+
bit_at, bit_length = __process_bit_length(bit_length * times, name)
|
62
|
+
define(name, LoopDefinition.new(bit_at, bit_length, @conditions.dup, klass))
|
58
63
|
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def define(name, data)
|
67
|
+
@data_def[name] = data
|
59
68
|
@names << name
|
60
69
|
end
|
61
70
|
|
71
|
+
def WHILE(condition, name, &block)
|
72
|
+
__check_new_def_name(name)
|
73
|
+
klass = NamelessTemplateMaker.new(self, block)
|
74
|
+
bit_at, bit_length = __process_bit_length(Expression.control_var(:non_fixed), name)
|
75
|
+
define(name, WhileDefinition.new(bit_at, bit_length, @conditions.dup, klass, condition))
|
76
|
+
end
|
77
|
+
|
62
78
|
def IF(condition, &block)
|
63
79
|
@conditions.push(condition)
|
64
80
|
block.call
|
65
81
|
@conditions.pop
|
66
82
|
end
|
67
83
|
|
68
|
-
def check_new_def_name(name)
|
69
|
-
if name[0..1] == "__"
|
70
|
-
raise DefinitionError, "Name that starts with '__' is system-reserved."
|
71
|
-
end
|
72
|
-
if @method_names.include?(name)
|
73
|
-
raise DefinitionError, "Name '#{name}' is already used as method name." +
|
74
|
-
"You should chanege to other name."
|
75
|
-
end
|
76
|
-
if @data_def[name]
|
77
|
-
raise DefinitionError, "Name #{name} is already defined." +
|
78
|
-
"You should change to other name."
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def name_solvable?(name, structure=self)
|
83
|
-
return structure[name] ||
|
84
|
-
(structure.parent_structure && name_solvable?(name, structure.parent_structure))
|
85
|
-
end
|
86
|
-
|
87
84
|
def cond(*var_names, &condition_proc)
|
88
85
|
var_names.each do |var_name|
|
89
|
-
unless
|
86
|
+
unless __name_resolvable?(var_name)
|
90
87
|
raise DefinitionError, "As condition variable, unsolvable variable #{var_name} is used."
|
91
88
|
end
|
92
89
|
end
|
93
90
|
return Condition.new(*var_names, &condition_proc)
|
94
91
|
end
|
95
92
|
|
93
|
+
def E(&condition_proc)
|
94
|
+
return FreeCondition.new(&condition_proc)
|
95
|
+
end
|
96
|
+
|
96
97
|
def match(var_name, value)
|
97
98
|
case value
|
98
99
|
when Integer
|
@@ -107,35 +108,48 @@ module BinaryParser
|
|
107
108
|
end
|
108
109
|
|
109
110
|
def var(var_name)
|
110
|
-
unless
|
111
|
+
unless __name_resolvable?(var_name)
|
111
112
|
raise DefinitionError, "Unsolvable variable #{var_name} is used."
|
112
113
|
end
|
113
|
-
return Expression.
|
114
|
+
return Expression.value_var(var_name)
|
114
115
|
end
|
115
116
|
|
116
117
|
def len(var_name)
|
117
|
-
unless
|
118
|
+
unless __name_resolvable?(var_name)
|
118
119
|
raise DefinitionError, "Unsolvable variable #{var_name} is used."
|
119
120
|
end
|
120
|
-
|
121
|
-
|
121
|
+
return Expression.length_var(var_name)
|
122
|
+
end
|
123
|
+
|
124
|
+
def nextbits(length)
|
125
|
+
return Expression.nextbits_var(length)
|
122
126
|
end
|
123
127
|
|
124
128
|
def position
|
125
|
-
|
129
|
+
Expression.control_var(:position)
|
126
130
|
end
|
127
131
|
|
128
132
|
def rest
|
129
|
-
|
133
|
+
Expression.control_var(:rest)
|
130
134
|
end
|
131
135
|
|
132
136
|
def [](var_name)
|
133
137
|
return @data_def[var_name]
|
134
138
|
end
|
135
139
|
|
140
|
+
def symbol_call(symbol, *args, &block)
|
141
|
+
if args.length == 0
|
142
|
+
return var(symbol)
|
143
|
+
elsif args.length == 2
|
144
|
+
return data(symbol, *args)
|
145
|
+
else
|
146
|
+
raise DefinitionError, "Unknown use of keyword '#{var_name}' with args(#{args})."
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
136
150
|
private
|
137
151
|
|
138
|
-
def
|
152
|
+
def __process_bit_length(bit_length, name)
|
139
153
|
bit_at = @bit_at
|
140
154
|
case bit_length
|
141
155
|
when Integer
|
@@ -144,10 +158,10 @@ module BinaryParser
|
|
144
158
|
else
|
145
159
|
@bit_at = @bit_at.add_name(name)
|
146
160
|
end
|
147
|
-
return bit_at, Expression.
|
161
|
+
return bit_at, Expression.immediate(bit_length)
|
148
162
|
when Expression
|
149
|
-
bit_length.
|
150
|
-
|
163
|
+
bit_length.variable_tokens.each do |token|
|
164
|
+
if (token.value_var? || token.length_var?) && !__name_resolvable?(token.symbol)
|
151
165
|
raise DefinitionError, "In #{name}, unsolvable variable #{symbol} is used."
|
152
166
|
end
|
153
167
|
end
|
@@ -157,5 +171,24 @@ module BinaryParser
|
|
157
171
|
raise DefinitionError, "Unknown type of bit_length (#{bit_length.class})."
|
158
172
|
end
|
159
173
|
end
|
174
|
+
|
175
|
+
def __check_new_def_name(name)
|
176
|
+
if name[0..1] == "__"
|
177
|
+
raise DefinitionError, "Name that starts with '__' is system-reserved."
|
178
|
+
end
|
179
|
+
if @forbidden_method_names.include?(name)
|
180
|
+
raise DefinitionError, "Name '#{name}' is already used as method name." +
|
181
|
+
"You should chanege to other name."
|
182
|
+
end
|
183
|
+
if @data_def[name]
|
184
|
+
raise DefinitionError, "Name #{name} is already defined." +
|
185
|
+
"You should change to other name."
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def __name_resolvable?(name, structure=self)
|
190
|
+
return structure[name] ||
|
191
|
+
(structure.parent_structure && __name_resolvable?(name, structure.parent_structure))
|
192
|
+
end
|
160
193
|
end
|
161
194
|
end
|
data/lib/template_base.rb
CHANGED
@@ -10,18 +10,7 @@ module BinaryParser
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.def_var_method(name)
|
13
|
-
define_method(name){|&block|
|
14
|
-
if block
|
15
|
-
case block.arity
|
16
|
-
when 0
|
17
|
-
@scope.load_var(name).instance_eval(&block)
|
18
|
-
when 1
|
19
|
-
block.call(@scope.load_var(name))
|
20
|
-
end
|
21
|
-
else
|
22
|
-
@scope.load_var(name)
|
23
|
-
end
|
24
|
-
}
|
13
|
+
define_method(name){|&block| load(name, &block) }
|
25
14
|
end
|
26
15
|
|
27
16
|
def self.Def(parent_structure=nil, &definition_proc)
|
@@ -36,6 +25,19 @@ module BinaryParser
|
|
36
25
|
@scope = Scope.new(self.class.structure, convert_into_abstract_binary(binary), parent_scope)
|
37
26
|
end
|
38
27
|
|
28
|
+
def load(name, &block)
|
29
|
+
if block
|
30
|
+
case block.arity
|
31
|
+
when 0
|
32
|
+
@scope.load_var(name).instance_eval(&block)
|
33
|
+
when 1
|
34
|
+
block.call(@scope.load_var(name))
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@scope.load_var(name)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
39
41
|
def convert_into_abstract_binary(object)
|
40
42
|
return object if object.is_a?(AbstractBinary)
|
41
43
|
if object.is_a?(String) && object.encoding == Encoding::BINARY
|
data/lib/while_list.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module BinaryParser
|
2
|
+
class WhileList < LoopList
|
3
|
+
|
4
|
+
attr_reader :bit_length
|
5
|
+
|
6
|
+
def initialize(definition, abstract_binary, parent_scope, name)
|
7
|
+
parsed_length = 0
|
8
|
+
list, rest_binary = [], abstract_binary
|
9
|
+
while continue?(definition, rest_binary, parent_scope, name)
|
10
|
+
template = definition.klass.new(rest_binary, parent_scope)
|
11
|
+
if template.structure_bit_length == 0
|
12
|
+
raise ParsingError, "0 bit-length repetition happens. This means infinite loop."
|
13
|
+
end
|
14
|
+
parsed_length += template.structure_bit_length
|
15
|
+
rest_binary = rest_binary.sub(:bit_index => template.structure_bit_length)
|
16
|
+
list << template
|
17
|
+
end
|
18
|
+
@list, @bit_length = list, parsed_length
|
19
|
+
end
|
20
|
+
|
21
|
+
def continue?(definition, rest_binary, parent_scope, name)
|
22
|
+
definition.loop_condition.eval do |token|
|
23
|
+
if token.nextbits_var?
|
24
|
+
TemplateBase.new(rest_binary.sub(:bit_length => token.length)).to_i
|
25
|
+
else
|
26
|
+
parent_scope.token_eval(token, name)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/binary_parser.rb'
|
10
|
+
|
11
|
+
class BinaryTemplateTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
class TestingTemplate < TemplateBase
|
14
|
+
def_structure do
|
15
|
+
data :b1, Binary, 16
|
16
|
+
data :b2, Binary, 16
|
17
|
+
data :b3, Binary, 16
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_data_method_block_call
|
22
|
+
t = gen(0x41, 0x42, 0x41, 0x42, 0, 0)
|
23
|
+
|
24
|
+
assert_equal(true, t.b1 == "AB")
|
25
|
+
assert_equal(false, t.b1 == "BA")
|
26
|
+
|
27
|
+
assert_equal(true, "AB" == t.b1)
|
28
|
+
assert_equal(false,"BA" == t.b1)
|
29
|
+
|
30
|
+
assert_equal(true, t.b1 == t.b2)
|
31
|
+
assert_equal(false, t.b1 == t.b3)
|
32
|
+
end
|
33
|
+
|
34
|
+
# helper for generating binary
|
35
|
+
def gen(*chars)
|
36
|
+
return TestingTemplate.new(chars.pack("C*"))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/binary_parser.rb'
|
10
|
+
|
11
|
+
class UIntTemplateTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
class TestingTemplate < TemplateBase
|
14
|
+
def_structure do
|
15
|
+
data :n1, UInt, 8
|
16
|
+
data :n2, UInt, 8
|
17
|
+
data :n3, UInt, 8
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_bit_access
|
22
|
+
t = gen(1, 2, 4)
|
23
|
+
|
24
|
+
assert_equal(1, t.n1[0])
|
25
|
+
assert_equal(0, t.n1[1])
|
26
|
+
assert_equal(0, t.n1[2])
|
27
|
+
|
28
|
+
assert_equal(0, t.n2[0])
|
29
|
+
assert_equal(1, t.n2[1])
|
30
|
+
assert_equal(0, t.n2[2])
|
31
|
+
|
32
|
+
assert_equal(0, t.n3[0])
|
33
|
+
assert_equal(0, t.n3[1])
|
34
|
+
assert_equal(1, t.n3[2])
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_to_s
|
38
|
+
t = gen(10, 16, 0)
|
39
|
+
|
40
|
+
assert_equal("10", t.n1.to_s)
|
41
|
+
assert_equal("a", t.n1.to_s(16))
|
42
|
+
assert_equal("10", t.n2.to_s(16))
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_operation
|
46
|
+
t = gen(2, 3, 3)
|
47
|
+
|
48
|
+
assert_equal(BuiltInTemplate::UInt, t.n1.class)
|
49
|
+
|
50
|
+
assert_equal(3, t.n1 + 1)
|
51
|
+
assert_equal(4, t.n1 * 2)
|
52
|
+
assert_equal(1, t.n1 - 1)
|
53
|
+
assert_equal(1, t.n1 / 2)
|
54
|
+
assert_equal(false, t.n1 == 1)
|
55
|
+
assert_equal(true, t.n1 == 2)
|
56
|
+
assert_equal(true, t.n1 != 1)
|
57
|
+
assert_equal(false, t.n1 != 2)
|
58
|
+
assert_equal(false, t.n1 < 1)
|
59
|
+
assert_equal(true, t.n1 > 1)
|
60
|
+
|
61
|
+
assert_equal(3, 1 + t.n1)
|
62
|
+
assert_equal(4, 2 * t.n1)
|
63
|
+
assert_equal(1, 3 - t.n1)
|
64
|
+
assert_equal(1, 2 / t.n1)
|
65
|
+
assert_equal(false, 1 == t.n1)
|
66
|
+
assert_equal(true, 2 == t.n1)
|
67
|
+
assert_equal(true, 1 != t.n1)
|
68
|
+
assert_equal(false, 2 != t.n1)
|
69
|
+
assert_equal(true, 1 < t.n1)
|
70
|
+
assert_equal(false, 1 > t.n1)
|
71
|
+
|
72
|
+
assert_equal(5, t.n1 + t.n2)
|
73
|
+
assert_equal(6, t.n1 * t.n2)
|
74
|
+
assert_equal(-1, t.n1 - t.n2)
|
75
|
+
assert_equal(0, t.n1 / t.n2)
|
76
|
+
|
77
|
+
assert_equal(false, t.n1 == t.n2)
|
78
|
+
assert_equal(true, t.n2 == t.n3)
|
79
|
+
end
|
80
|
+
|
81
|
+
# helper for generating binary
|
82
|
+
def gen(*chars)
|
83
|
+
return TestingTemplate.new(chars.pack("C*"))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -14,7 +14,7 @@ module BinaryParser
|
|
14
14
|
|
15
15
|
def test_bit_position
|
16
16
|
bp = BitPosition.new
|
17
|
-
pos = bp.add_imm(4).add_name(:hoge).add_imm(3).add_name(:fuga).eval{|
|
17
|
+
pos = bp.add_imm(4).add_name(:hoge).add_imm(3).add_name(:fuga).eval{|token| VAL[token.symbol]}
|
18
18
|
assert_equal(1017, pos)
|
19
19
|
end
|
20
20
|
end
|
@@ -15,8 +15,8 @@ module BinaryParser
|
|
15
15
|
def test_condition
|
16
16
|
cond1 = Condition.new(:hoge, :fuga){|v1, v2| v1 * 100 == v2}
|
17
17
|
cond2 = Condition.new(:hoge, :fuga){|v1, v2| v1 * 10 == v2}
|
18
|
-
assert_equal(true, cond1.eval{|
|
19
|
-
assert_equal(false, cond2.eval{|
|
18
|
+
assert_equal(true, cond1.eval{|token| VAL[token.symbol]})
|
19
|
+
assert_equal(false, cond2.eval{|token| VAL[token.symbol]})
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -9,13 +9,37 @@ module BinaryParser
|
|
9
9
|
require $LIBRARY_ROOT_PATH + '/lib/binary_parser.rb'
|
10
10
|
|
11
11
|
class ExpressionTest < Test::Unit::TestCase
|
12
|
-
VAL = {:
|
12
|
+
VAL = {:a => 1, :b => 2, :c => 3, :d => 4}
|
13
|
+
LEN = {:a => 5, :b => 6, :c => 7, :d => 8}
|
14
|
+
CON = {:a => -1, :b => -2, :c => -3, :d => -4}
|
13
15
|
|
14
16
|
def test_expression
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
exp = (1 + val(:a)) * len(:b) + 2 * con(:c) - (3 % val(:d))
|
18
|
+
res = exp.eval do |token|
|
19
|
+
if token.value_var?
|
20
|
+
VAL[token.symbol]
|
21
|
+
elsif token.length_var?
|
22
|
+
LEN[token.symbol]
|
23
|
+
elsif token.control_var?
|
24
|
+
CON[token.symbol]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_equal((1 + 1) * 6 + 2 * -3 - (3 % 4), res)
|
29
|
+
end
|
30
|
+
|
31
|
+
# helpers
|
32
|
+
|
33
|
+
def val(symbol)
|
34
|
+
Expression.value_var(symbol)
|
35
|
+
end
|
36
|
+
|
37
|
+
def len(symbol)
|
38
|
+
Expression.length_var(symbol)
|
39
|
+
end
|
40
|
+
|
41
|
+
def con(symbol)
|
42
|
+
Expression.control_var(symbol)
|
19
43
|
end
|
20
44
|
end
|
21
45
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/binary_parser.rb'
|
10
|
+
|
11
|
+
class FreeConditionTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_free_condition
|
14
|
+
cond1 = FreeCondition.new{ v1 * 100 == v2 }
|
15
|
+
assert_equal(true, cond1.eval{|token| {:v1 => 1, :v2 => 100}[token.symbol]})
|
16
|
+
assert_equal(false, cond1.eval{|token| {:v1 => 2, :v2 => 100}[token.symbol]})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/unit_test/test_scope.rb
CHANGED
@@ -213,6 +213,52 @@ module BinaryParser
|
|
213
213
|
assert_equal("AB", i.rest_binary.to_s)
|
214
214
|
end
|
215
215
|
|
216
|
+
# TEST CASE STRUCTURE 8
|
217
|
+
# * nextbits
|
218
|
+
class ST8 < TemplateBase
|
219
|
+
Def do
|
220
|
+
data :n1, UInt, nextbits(8) * 8
|
221
|
+
data :n2, UInt, 8
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_ST8_CASE1
|
226
|
+
i = ST8.new(gen_bin(3, 0, 0, 1))
|
227
|
+
assert_equal(24, i.n1.binary_bit_length)
|
228
|
+
assert_equal(0x030000, i.n1)
|
229
|
+
assert_equal(1, i.n2)
|
230
|
+
end
|
231
|
+
|
232
|
+
# TEST CASE STRUCTURE 9
|
233
|
+
# * WHILE
|
234
|
+
class ST9 < TemplateBase
|
235
|
+
Def do
|
236
|
+
WHILE E{ nextbits(4) == 0xA }, :ls do
|
237
|
+
data :id, UInt, 8
|
238
|
+
end
|
239
|
+
data :suffix, UInt, 8
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_ST9_CASE1
|
244
|
+
i = ST9.new(gen_bin(0xA1, 0xA2, 0xA3, 0xB4))
|
245
|
+
|
246
|
+
assert_equal(3, i.ls.length)
|
247
|
+
assert_equal(0xA1, i.ls[0].id)
|
248
|
+
assert_equal(0xA2, i.ls[1].id)
|
249
|
+
assert_equal(0xA3, i.ls[2].id)
|
250
|
+
assert_equal(0xB4, i.suffix)
|
251
|
+
assert_equal(4 * 8, i.structure_bit_length)
|
252
|
+
end
|
253
|
+
|
254
|
+
def test_ST9_CASE2
|
255
|
+
i = ST9.new(gen_bin(0xB0))
|
256
|
+
|
257
|
+
assert_equal(0, i.ls.length)
|
258
|
+
assert_equal(0xB0, i.suffix)
|
259
|
+
assert_equal(1 * 8, i.structure_bit_length)
|
260
|
+
end
|
261
|
+
|
216
262
|
# helpers
|
217
263
|
def gen_bin(*chars)
|
218
264
|
return AbstractBinary.new(chars.pack("C*"))
|
@@ -28,11 +28,11 @@ module BinaryParser
|
|
28
28
|
|
29
29
|
assert_equal(C2, st[:b].klass)
|
30
30
|
assert_equal(3, st[:b].bit_position.eval{})
|
31
|
-
assert_equal(24, st[:b].bit_length.eval{|
|
31
|
+
assert_equal(24, st[:b].bit_length.eval{|token| {:a => 3}[token.symbol]})
|
32
32
|
assert_equal([], st[:b].conditions)
|
33
33
|
|
34
34
|
assert_equal(C3, st[:c].klass)
|
35
|
-
assert_equal(27, st[:c].bit_position.eval{|
|
35
|
+
assert_equal(27, st[:c].bit_position.eval{|token| {:b => 24}[token.symbol]})
|
36
36
|
assert_equal(4, st[:c].bit_length.eval{})
|
37
37
|
assert_equal([], st[:c].conditions)
|
38
38
|
end
|
@@ -61,8 +61,8 @@ module BinaryParser
|
|
61
61
|
end
|
62
62
|
|
63
63
|
assert_equal(8, st[:list].bit_position.eval{})
|
64
|
-
assert_equal(12, st[:list].bit_length.eval{|
|
65
|
-
assert_equal(20, st[:foot].bit_position.eval{|
|
64
|
+
assert_equal(12, st[:list].bit_length.eval{|token| {:outer => 3}[token.symbol]})
|
65
|
+
assert_equal(20, st[:foot].bit_position.eval{|token| {:list => 12}[token.symbol]})
|
66
66
|
end
|
67
67
|
|
68
68
|
def test_IF
|
@@ -89,8 +89,8 @@ module BinaryParser
|
|
89
89
|
data :fuga, C1, 1
|
90
90
|
end
|
91
91
|
|
92
|
-
eval_proc = Proc.new do |
|
93
|
-
{:hoge => 1, :fuga => 1}[
|
92
|
+
eval_proc = Proc.new do |token|
|
93
|
+
{:hoge => 1, :fuga => 1}[token.symbol]
|
94
94
|
end
|
95
95
|
|
96
96
|
cond1 = st.match(:hoge, 1)
|
@@ -134,6 +134,47 @@ module BinaryParser
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
137
|
+
|
138
|
+
def test_E
|
139
|
+
st = StructureDefinition.new do
|
140
|
+
IF E{ hoge == 1 } do
|
141
|
+
data :fuga, C1, 8
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
assert_equal(true, st[:fuga].conditions[0].eval{|token| {:hoge => 1}[token.symbol]})
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_ABBREVIATED_NOTATION
|
149
|
+
st = StructureDefinition.new do
|
150
|
+
d2 C2, 8
|
151
|
+
end
|
152
|
+
|
153
|
+
assert_equal(8, st[:d2].bit_length.eval{})
|
154
|
+
end
|
155
|
+
|
156
|
+
def test_VARIABLE_RESOLUTION
|
157
|
+
st = StructureDefinition.new do
|
158
|
+
data :a, C1, 3
|
159
|
+
data :b, C2, a * 8
|
160
|
+
data :c, C3, 4
|
161
|
+
end
|
162
|
+
|
163
|
+
assert_equal(C1, st[:a].klass)
|
164
|
+
assert_equal(0, st[:a].bit_position.eval{})
|
165
|
+
assert_equal(3, st[:a].bit_length.eval{})
|
166
|
+
assert_equal([], st[:a].conditions)
|
167
|
+
|
168
|
+
assert_equal(C2, st[:b].klass)
|
169
|
+
assert_equal(3, st[:b].bit_position.eval{})
|
170
|
+
assert_equal(24, st[:b].bit_length.eval{|token| {:a => 3}[token.symbol]})
|
171
|
+
assert_equal([], st[:b].conditions)
|
172
|
+
|
173
|
+
assert_equal(C3, st[:c].klass)
|
174
|
+
assert_equal(27, st[:c].bit_position.eval{|token| {:b => 24}[token.symbol]})
|
175
|
+
assert_equal(4, st[:c].bit_length.eval{})
|
176
|
+
assert_equal([], st[:c].conditions)
|
177
|
+
end
|
137
178
|
end
|
138
179
|
end
|
139
180
|
end
|