binary_parser 1.0.0

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.
@@ -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: []