binary_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,232 @@
1
+ # -*- coding: utf-8 -*-
2
+ $LIBRARY_ROOT_PATH = 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 TemplateStreamBaseTest < Test::Unit::TestCase
12
+ require 'stringio'
13
+
14
+ class TestingStreamTemplate < StreamTemplateBase
15
+ MyInt = Class.new(TemplateBase)
16
+ MyBin = Class.new(TemplateBase)
17
+
18
+ def_stream(3) do
19
+ data :id, MyInt, 8
20
+ data :flag, MyInt, 8
21
+ data :char, MyBin, 8
22
+ end
23
+ end
24
+
25
+ def test_get_next_SIMPLE_USE
26
+ st = gen_stream(1, 0, 0x41,
27
+ 2, 1, 0x42)
28
+
29
+ d1 = st.get_next
30
+ assert_equal(1, d1.id.to_i)
31
+ assert_equal(0, d1.flag.to_i)
32
+ assert_equal("A", d1.char.to_s)
33
+
34
+ d2 = st.get_next
35
+ assert_equal(2, d2.id.to_i)
36
+ assert_equal(1, d2.flag.to_i)
37
+ assert_equal("B", d2.char.to_s)
38
+
39
+ assert_not(st.rest?)
40
+ assert_equal(nil, st.get_next)
41
+ end
42
+
43
+ def test_get_next_BINARY_SHORTAGE_ERROR
44
+ st = gen_stream(1, 0, 0x41, 0)
45
+
46
+ st.get_next
47
+ assert_raise(ParsingError) do
48
+ st.get_next
49
+ end
50
+ end
51
+
52
+ def test_filter_AND_get_next
53
+ st = gen_stream(1, 0, 0,
54
+ 2, 1, 0,
55
+ 3, 0, 0,
56
+ 4, 1, 0)
57
+
58
+ d1 = st.filter{|a| a.flag.to_i == 1}.get_next
59
+ assert_equal(2, d1.id.to_i)
60
+
61
+ d2 = st.get_next
62
+ assert_equal(3, d2.id.to_i)
63
+
64
+ d3 = st.filter{|a| a.flag.to_i == 0}.get_next
65
+ assert_equal(nil, d3)
66
+
67
+ assert_not(st.rest?)
68
+
69
+ d4 = st.get_next
70
+ assert_equal(nil, d4)
71
+ end
72
+
73
+ def test_seek_top_POPULAR_CASE
74
+ st = gen_stream(1, 0, 0,
75
+ 2, 0, 0,
76
+ 3, 1, 0,
77
+ 4, 0, 0)
78
+
79
+ abandoned = st.seek_top{|a| a.flag.to_i == 1}
80
+ assert_equal(2, abandoned.size)
81
+ assert_equal(1, abandoned[0].id.to_i)
82
+ assert_equal(2, abandoned[1].id.to_i)
83
+
84
+ assert_equal(3, st.get_next.id.to_i)
85
+ end
86
+
87
+ def test_seek_top_SPECIAL_CASE1
88
+ st = gen_stream(1, 1, 0,
89
+ 2, 0, 0)
90
+
91
+ abandoned = st.seek_top{|a| a.flag.to_i == 1}
92
+ assert_equal(0, abandoned.size)
93
+ assert_equal(1, st.get_next.id.to_i)
94
+ end
95
+
96
+ def test_seek_top_SPECIAL_CASE2
97
+ st = gen_stream(1, 0, 0,
98
+ 2, 0, 0)
99
+
100
+ abandoned = st.seek_top{|a| a.flag.to_i == 1}
101
+ assert_equal(2, abandoned.size)
102
+ assert_not(st.rest?)
103
+ assert_equal(nil, st.get_next)
104
+ end
105
+
106
+ def test_seek_top_SPECIAL_CASE3
107
+ st = gen_stream()
108
+
109
+ abandoned = st.seek_top{|a| a.flag.to_i == 1}
110
+ assert_equal(0, abandoned.size)
111
+ assert_not(st.rest?)
112
+ assert_equal(nil, st.get_next)
113
+ end
114
+
115
+ def test_get_sequence_POPULAR_CASE
116
+ st = gen_stream(1, 0, 0,
117
+ 2, 1, 0,
118
+ 3, 0, 0,
119
+ 4, 0, 0,
120
+ 5, 1, 0)
121
+
122
+ seq = st.get_sequence{|a| a.flag.to_i == 1}
123
+ assert_equal(3, seq.size)
124
+ assert_equal(2, seq[0].id.to_i)
125
+ assert_equal(3, seq[1].id.to_i)
126
+ assert_equal(4, seq[2].id.to_i)
127
+
128
+ assert(st.rest?)
129
+ assert_equal(5, st.get_next.id.to_i)
130
+ end
131
+
132
+ def test_get_sequence_SPECIAL_CASE1
133
+ st = gen_stream(1, 1, 0,
134
+ 2, 0, 0,
135
+ 3, 1, 0)
136
+
137
+ seq = st.get_sequence{|a| a.flag.to_i == 1}
138
+ assert_equal(2, seq.size)
139
+
140
+ assert_equal(3, st.get_next.id.to_i)
141
+ end
142
+
143
+ def test_get_sequence_SPECIAL_CASE2
144
+ st = gen_stream(1, 1, 0,
145
+ 2, 1, 0,
146
+ 3, 0, 0)
147
+
148
+ seq = st.get_sequence{|a| a.flag.to_i == 1}
149
+ assert_equal(1, seq.size)
150
+
151
+ assert_equal(2, st.get_next.id.to_i)
152
+ end
153
+
154
+ def test_get_sequence_SPECIAL_CASE3_A
155
+ st = gen_stream(1, 1, 0,
156
+ 2, 0, 0)
157
+
158
+ seq = st.get_sequence{|a| a.flag.to_i == 1}
159
+ assert_equal(0, seq.size)
160
+
161
+ assert_not(st.rest?)
162
+ end
163
+
164
+ def test_get_sequence_SPECIAL_CASE3_B
165
+ st = gen_stream(1, 1, 0,
166
+ 2, 0, 0)
167
+
168
+ seq = st.get_sequence(true){|a| a.flag.to_i == 1}
169
+ assert_equal(2, seq.size)
170
+
171
+ assert_not(st.rest?)
172
+ end
173
+
174
+ def test_get_sequence_SPECIAL_CASE4
175
+ st = gen_stream(1, 0, 0,
176
+ 2, 0, 0)
177
+
178
+ seq = st.get_sequence{|a| a.flag.to_i == 1}
179
+ assert_equal(0, seq.size)
180
+
181
+ assert_not(st.rest?)
182
+ end
183
+
184
+ def test_get_sequence_SPECIAL_CASE5
185
+ st = gen_stream()
186
+
187
+ seq = st.get_sequence{|a| a.flag.to_i == 1}
188
+ assert_equal(0, seq.size)
189
+
190
+ assert_not(st.rest?)
191
+ end
192
+
193
+ def test_accumulate_POPULAR_CASE
194
+ st = gen_stream(1, 0, 0,
195
+ 2, 0, 0,
196
+ 3, 0, 0,
197
+ 4, 0, 0,
198
+ 5, 0, 0)
199
+
200
+ reduced_list = st.accumulate(0, 6){|acc, a| acc + a.id.to_i}
201
+ assert_equal(3, reduced_list.size)
202
+
203
+ assert_equal(4, st.get_next.id.to_i)
204
+ end
205
+
206
+ def test_accumulate_SPECIAL_CASE
207
+ st = gen_stream(1, 0, 0,
208
+ 2, 0, 0,
209
+ 3, 0, 0)
210
+
211
+ reduced_list = st.accumulate(0, 7){|acc, a| acc + a.id.to_i}
212
+ assert_equal(nil, reduced_list)
213
+
214
+ assert_not(st.rest?)
215
+ end
216
+
217
+ # helpers
218
+ def gen_bin(*chars)
219
+ return chars.pack("C*")
220
+ end
221
+
222
+ def gen_stream(*args)
223
+ binary_stream = StringIO.new(gen_bin(*args))
224
+ return TestingStreamTemplate.new(binary_stream)
225
+ end
226
+
227
+ def assert_not(object)
228
+ assert(!object)
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,115 @@
1
+ # -*- coding: utf-8 -*-
2
+ $LIBRARY_ROOT_PATH = 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 StructureDefinitionTest < Test::Unit::TestCase
12
+
13
+ C1 = Class.new(TemplateBase)
14
+ C2 = Class.new(TemplateBase)
15
+ C3 = Class.new(TemplateBase)
16
+
17
+ def test_data
18
+ st = StructureDefinition.new do
19
+ data :a, C1, 3
20
+ data :b, C2, var(:a) * 8
21
+ data :c, C3, 4
22
+ end
23
+
24
+ assert_equal(C1, st[:a].klass)
25
+ assert_equal(0, st[:a].bit_position.eval{})
26
+ assert_equal(3, st[:a].bit_length.eval{})
27
+ assert_equal([], st[:a].conditions)
28
+
29
+ assert_equal(C2, st[:b].klass)
30
+ assert_equal(3, st[:b].bit_position.eval{})
31
+ assert_equal(24, st[:b].bit_length.eval{|name| {:a => 3}[name]})
32
+ assert_equal([], st[:b].conditions)
33
+
34
+ assert_equal(C3, st[:c].klass)
35
+ assert_equal(27, st[:c].bit_position.eval{|name| {:b => 24}[name]})
36
+ assert_equal(4, st[:c].bit_length.eval{})
37
+ assert_equal([], st[:c].conditions)
38
+ end
39
+
40
+ def test_SPEND
41
+ st = StructureDefinition.new do
42
+ SPEND 48, :lp do
43
+ data :dat1, C1, 8
44
+ data :dat2, C2, 16
45
+ end
46
+ data :dat3, C3, 8
47
+ end
48
+
49
+ assert_equal(8, st[:lp].structure[:dat1].bit_length.eval{})
50
+ assert_equal(16, st[:lp].structure[:dat2].bit_length.eval{})
51
+ assert_equal(48, st[:dat3].bit_position.eval{})
52
+ end
53
+
54
+ def test_TIMES
55
+ st = StructureDefinition.new do
56
+ data :outer, C1, 8
57
+ TIMES 4, :list do
58
+ data :inner, C1, var(:outer)
59
+ end
60
+ data :foot, C1, 8
61
+ end
62
+
63
+ assert_equal(8, st[:list].bit_position.eval{})
64
+ assert_equal(12, st[:list].bit_length.eval{|name| {:outer => 3}[name]})
65
+ assert_equal(20, st[:foot].bit_position.eval{|name| {:list => 12}[name]})
66
+ end
67
+
68
+ def test_IF
69
+ st = StructureDefinition.new do
70
+ data :dat1, C1, 3
71
+ IF cond(:dat1){|v| v == 1} do
72
+ data :dat2, C2, var(:dat1) * 8
73
+ IF cond(:dat2){|v| v == 1} do
74
+ data :dat3, C3, var(:dat2) * 8
75
+ end
76
+ end
77
+ data :dat4, C1, 1
78
+ end
79
+
80
+ assert_equal(0, st[:dat1].conditions.size)
81
+ assert_equal(1, st[:dat2].conditions.size)
82
+ assert_equal(2, st[:dat3].conditions.size)
83
+ assert_equal(0, st[:dat4].conditions.size)
84
+ end
85
+
86
+ def test_VARIABLE_REFERENCE_ERROR
87
+ assert_raise(DefinitionError) do
88
+ st = StructureDefinition.new do
89
+ data :d1, C1, var(:d2) * 8
90
+ data :d2, C2, 8
91
+ end
92
+ end
93
+ end
94
+
95
+ def test_TIMES_WITH_NONFIXED_LENGTH
96
+ assert_nothing_raised do
97
+ st = StructureDefinition.new do
98
+ data :length, C1, 8
99
+ TIMES 1, :list do
100
+ data :dat, C2, var(:length) * 8
101
+ end
102
+ end
103
+ end
104
+ assert_raise(DefinitionError) do
105
+ st = StructureDefinition.new do
106
+ TIMES 1, :list do
107
+ data :length, C1, 8
108
+ data :dat, C2, var(:length) * 8
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,62 @@
1
+ # -*- coding: utf-8 -*-
2
+ $LIBRARY_ROOT_PATH = 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 TemplateBaseTest < Test::Unit::TestCase
12
+
13
+ class TestingTemplate < TemplateBase
14
+ def_structure do
15
+ data :number, UInt, 7
16
+ data :flag, Flag, 1
17
+ data :bytes, Binary, 32
18
+ end
19
+ end
20
+
21
+ def test_initialize_FROM_ABSTRACT_BINARY
22
+ bin_seq = [0b10000001, 0x41, 0x42, 0x43, 0x44]
23
+ t = TestingTemplate.new(AbstractBinary.new(bin_seq.pack("C*")))
24
+
25
+ assert_equal(0b1000000, t.number.to_i)
26
+ assert(t.flag.on?)
27
+ assert_equal("ABCD", t.bytes.to_s)
28
+ end
29
+
30
+ def test_initialize_FROM_BINARY_STRING
31
+ bin_seq = [0b10000001, 0x41, 0x42, 0x43, 0x44]
32
+ t = TestingTemplate.new(bin_seq.pack("C*"))
33
+
34
+ assert_equal(0b1000000, t.number.to_i)
35
+ assert(t.flag.on?)
36
+ assert_equal("ABCD", t.bytes.to_s)
37
+ end
38
+
39
+ def test_to_char
40
+ bin_seq = [0x01, 0x02, 0x3, 0x04, 0x05]
41
+ t = gen(*bin_seq)
42
+
43
+ assert_equal(bin_seq, t.to_chars)
44
+ end
45
+
46
+ def test_binary_bit_length
47
+ t = gen(0x01, 0x02, 0x3, 0x04, 0x05, 0x06)
48
+ assert_equal(6 * 8, t.binary_bit_length)
49
+ end
50
+
51
+ def test_structure_bit_length
52
+ t = gen(0x01, 0x02, 0x3, 0x04, 0x05, 0x06)
53
+ assert_equal(40, t.structure_bit_length)
54
+ end
55
+
56
+ # helper for generating binary
57
+ def gen(*chars)
58
+ return TestingTemplate.new(chars.pack("C*"))
59
+ end
60
+ end
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: binary_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - rokugats(u)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: "This library can parse all kind of binary-data structures including
42
+ non-fixed length of structures and nested structures.\nFor generic parsing, loop
43
+ and condition(if) statement to define structures is provided in this library.\nOf
44
+ course, values of neighbor binary-data can be used as the other binary-data's specification
45
+ of length.\n\nFurthermore, this library handles all binary-data under the lazy evaluation.\nSo
46
+ you can read required parts of a binary-data very quickly even if whole of the binary-data
47
+ is too big, \n"
48
+ email:
49
+ - sasasawada@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - binary_parser.gemspec
60
+ - lib/binary_parser.rb
61
+ - lib/binary_parser/version.rb
62
+ - lib/built_in_template/binary.rb
63
+ - lib/built_in_template/flag.rb
64
+ - lib/built_in_template/uint.rb
65
+ - lib/error.rb
66
+ - lib/general_class/abstract_binary.rb
67
+ - lib/general_class/bit_position.rb
68
+ - lib/general_class/condition.rb
69
+ - lib/general_class/expression.rb
70
+ - lib/loop_list.rb
71
+ - lib/nameless_template.rb
72
+ - lib/scope.rb
73
+ - lib/stream_template_base.rb
74
+ - lib/structure_definition.rb
75
+ - lib/template_base.rb
76
+ - unit_test/general_class/test_abstract_binary.rb
77
+ - unit_test/general_class/test_bit_position.rb
78
+ - unit_test/general_class/test_condition.rb
79
+ - unit_test/general_class/test_expression.rb
80
+ - unit_test/test_scope.rb
81
+ - unit_test/test_stream_template_base.rb
82
+ - unit_test/test_structure_definition.rb
83
+ - unit_test/test_template_base.rb
84
+ homepage: ''
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.0.3
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: An elegant DSL library for parsing binary-data.
108
+ test_files: []