bindata 2.4.10 → 2.5.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.
- checksums.yaml +4 -4
- data/ChangeLog.rdoc +39 -0
- data/LICENSE +25 -0
- data/NEWS.rdoc +5 -0
- data/README.md +6 -9
- data/bindata.gemspec +9 -4
- data/examples/NBT.txt +1 -1
- data/examples/list.rb +1 -1
- data/lib/bindata/alignment.rb +15 -7
- data/lib/bindata/array.rb +54 -54
- data/lib/bindata/base.rb +14 -25
- data/lib/bindata/base_primitive.rb +24 -20
- data/lib/bindata/bits.rb +15 -15
- data/lib/bindata/buffer.rb +89 -11
- data/lib/bindata/choice.rb +9 -6
- data/lib/bindata/count_bytes_remaining.rb +1 -1
- data/lib/bindata/delayed_io.rb +18 -10
- data/lib/bindata/dsl.rb +37 -35
- data/lib/bindata/float.rb +3 -3
- data/lib/bindata/framework.rb +8 -10
- data/lib/bindata/int.rb +14 -16
- data/lib/bindata/io.rb +276 -253
- data/lib/bindata/name.rb +1 -1
- data/lib/bindata/params.rb +9 -7
- data/lib/bindata/primitive.rb +3 -3
- data/lib/bindata/registry.rb +18 -18
- data/lib/bindata/rest.rb +1 -1
- data/lib/bindata/sanitize.rb +9 -16
- data/lib/bindata/section.rb +97 -0
- data/lib/bindata/skip.rb +140 -51
- data/lib/bindata/string.rb +9 -9
- data/lib/bindata/stringz.rb +12 -10
- data/lib/bindata/struct.rb +92 -68
- data/lib/bindata/trace.rb +35 -42
- data/lib/bindata/transform/brotli.rb +35 -0
- data/lib/bindata/transform/lz4.rb +35 -0
- data/lib/bindata/transform/lzma.rb +35 -0
- data/lib/bindata/transform/xor.rb +19 -0
- data/lib/bindata/transform/xz.rb +35 -0
- data/lib/bindata/transform/zlib.rb +33 -0
- data/lib/bindata/transform/zstd.rb +35 -0
- data/lib/bindata/uint8_array.rb +2 -2
- data/lib/bindata/version.rb +1 -1
- data/lib/bindata/virtual.rb +4 -7
- data/lib/bindata/warnings.rb +1 -1
- data/lib/bindata.rb +1 -0
- data/test/alignment_test.rb +8 -8
- data/test/array_test.rb +98 -96
- data/test/base_primitive_test.rb +47 -47
- data/test/base_test.rb +24 -24
- data/test/bits_test.rb +15 -15
- data/test/buffer_test.rb +31 -22
- data/test/choice_test.rb +32 -32
- data/test/count_bytes_remaining_test.rb +8 -8
- data/test/delayed_io_test.rb +91 -30
- data/test/float_test.rb +8 -8
- data/test/int_test.rb +14 -14
- data/test/io_test.rb +110 -302
- data/test/lazy_test.rb +38 -38
- data/test/params_test.rb +19 -19
- data/test/primitive_test.rb +26 -26
- data/test/record_test.rb +99 -99
- data/test/registry_test.rb +43 -43
- data/test/rest_test.rb +5 -5
- data/test/section_test.rb +111 -0
- data/test/skip_test.rb +71 -26
- data/test/string_test.rb +60 -60
- data/test/stringz_test.rb +34 -26
- data/test/struct_test.rb +167 -92
- data/test/system_test.rb +159 -41
- data/test/test_helper.rb +24 -13
- data/test/uint8_array_test.rb +6 -6
- data/test/virtual_test.rb +7 -7
- data/test/warnings_test.rb +14 -2
- metadata +19 -22
- data/.gitignore +0 -2
- data/.travis.yml +0 -15
- data/BSDL +0 -22
- data/COPYING +0 -52
- data/INSTALL +0 -12
- data/lib/bindata/offset.rb +0 -94
- data/test/offset_test.rb +0 -100
data/lib/bindata/buffer.rb
CHANGED
@@ -41,7 +41,7 @@ module BinData
|
|
41
41
|
# end
|
42
42
|
# end
|
43
43
|
# end
|
44
|
-
#
|
44
|
+
#
|
45
45
|
#
|
46
46
|
# == Parameters
|
47
47
|
#
|
@@ -80,29 +80,107 @@ module BinData
|
|
80
80
|
@type.snapshot
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
84
|
-
@type.respond_to?(symbol,
|
83
|
+
def respond_to_missing?(symbol, include_all = false) # :nodoc:
|
84
|
+
@type.respond_to?(symbol, include_all) || super
|
85
85
|
end
|
86
86
|
|
87
|
-
def method_missing(symbol, *args, &block)
|
87
|
+
def method_missing(symbol, *args, &block) # :nodoc:
|
88
88
|
@type.__send__(symbol, *args, &block)
|
89
89
|
end
|
90
90
|
|
91
|
-
def do_read(io)
|
92
|
-
|
93
|
-
|
91
|
+
def do_read(io) # :nodoc:
|
92
|
+
buf_len = eval_parameter(:length)
|
93
|
+
io.transform(BufferIO.new(buf_len)) do |transformed_io, _|
|
94
|
+
@type.do_read(transformed_io)
|
94
95
|
end
|
95
96
|
end
|
96
97
|
|
97
|
-
def do_write(io)
|
98
|
-
|
99
|
-
|
98
|
+
def do_write(io) # :nodoc:
|
99
|
+
buf_len = eval_parameter(:length)
|
100
|
+
io.transform(BufferIO.new(buf_len)) do |transformed_io, _|
|
101
|
+
@type.do_write(transformed_io)
|
100
102
|
end
|
101
103
|
end
|
102
104
|
|
103
|
-
def do_num_bytes
|
105
|
+
def do_num_bytes # :nodoc:
|
104
106
|
eval_parameter(:length)
|
105
107
|
end
|
108
|
+
|
109
|
+
# Transforms the IO stream to restrict access inside
|
110
|
+
# a buffer of specified length.
|
111
|
+
class BufferIO < IO::Transform
|
112
|
+
def initialize(length)
|
113
|
+
super()
|
114
|
+
@bytes_remaining = length
|
115
|
+
end
|
116
|
+
|
117
|
+
def before_transform
|
118
|
+
@buf_start = offset
|
119
|
+
@buf_end = @buf_start + @bytes_remaining
|
120
|
+
end
|
121
|
+
|
122
|
+
def num_bytes_remaining
|
123
|
+
[@bytes_remaining, super].min
|
124
|
+
rescue IOError
|
125
|
+
@bytes_remaining
|
126
|
+
end
|
127
|
+
|
128
|
+
def skip(n)
|
129
|
+
nbytes = buffer_limited_n(n)
|
130
|
+
@bytes_remaining -= nbytes
|
131
|
+
|
132
|
+
chain_skip(nbytes)
|
133
|
+
end
|
134
|
+
|
135
|
+
def seek_abs(n)
|
136
|
+
if n < @buf_start || n >= @buf_end
|
137
|
+
raise IOError, "can not seek to abs_offset outside of buffer"
|
138
|
+
end
|
139
|
+
|
140
|
+
@bytes_remaining -= (n - offset)
|
141
|
+
chain_seek_abs(n)
|
142
|
+
end
|
143
|
+
|
144
|
+
def read(n)
|
145
|
+
nbytes = buffer_limited_n(n)
|
146
|
+
@bytes_remaining -= nbytes
|
147
|
+
|
148
|
+
chain_read(nbytes)
|
149
|
+
end
|
150
|
+
|
151
|
+
def write(data)
|
152
|
+
nbytes = buffer_limited_n(data.size)
|
153
|
+
@bytes_remaining -= nbytes
|
154
|
+
if nbytes < data.size
|
155
|
+
data = data[0, nbytes]
|
156
|
+
end
|
157
|
+
|
158
|
+
chain_write(data)
|
159
|
+
end
|
160
|
+
|
161
|
+
def after_read_transform
|
162
|
+
read(nil)
|
163
|
+
end
|
164
|
+
|
165
|
+
def after_write_transform
|
166
|
+
write("\x00" * @bytes_remaining)
|
167
|
+
end
|
168
|
+
|
169
|
+
def buffer_limited_n(n)
|
170
|
+
if n.nil?
|
171
|
+
@bytes_remaining
|
172
|
+
elsif n.positive?
|
173
|
+
limit = @bytes_remaining
|
174
|
+
n > limit ? limit : n
|
175
|
+
# uncomment if we decide to allow backwards skipping
|
176
|
+
# elsif n.negative?
|
177
|
+
# limit = @bytes_remaining + @buf_start - @buf_end
|
178
|
+
# n < limit ? limit : n
|
179
|
+
else
|
180
|
+
0
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
106
184
|
end
|
107
185
|
|
108
186
|
class BufferArgProcessor < BaseArgProcessor
|
data/lib/bindata/choice.rb
CHANGED
@@ -82,18 +82,19 @@ module BinData
|
|
82
82
|
if selection.nil?
|
83
83
|
raise IndexError, ":selection returned nil for #{debug_name}"
|
84
84
|
end
|
85
|
+
|
85
86
|
selection
|
86
87
|
end
|
87
88
|
|
88
|
-
def respond_to?(symbol,
|
89
|
-
current_choice.respond_to?(symbol,
|
89
|
+
def respond_to?(symbol, include_all = false) # :nodoc:
|
90
|
+
current_choice.respond_to?(symbol, include_all) || super
|
90
91
|
end
|
91
92
|
|
92
|
-
def method_missing(symbol, *args, &block)
|
93
|
+
def method_missing(symbol, *args, &block) # :nodoc:
|
93
94
|
current_choice.__send__(symbol, *args, &block)
|
94
95
|
end
|
95
96
|
|
96
|
-
%w
|
97
|
+
%w[clear? assign snapshot do_read do_write do_num_bytes].each do |m|
|
97
98
|
module_eval <<-END
|
98
99
|
def #{m}(*args)
|
99
100
|
current_choice.#{m}(*args)
|
@@ -112,14 +113,16 @@ module BinData
|
|
112
113
|
def instantiate_choice(selection)
|
113
114
|
prototype = get_parameter(:choices)[selection]
|
114
115
|
if prototype.nil?
|
115
|
-
|
116
|
+
msg = "selection '#{selection}' does not exist in :choices for #{debug_name}"
|
117
|
+
raise IndexError, msg
|
116
118
|
end
|
119
|
+
|
117
120
|
prototype.instantiate(nil, self)
|
118
121
|
end
|
119
122
|
end
|
120
123
|
|
121
124
|
class ChoiceArgProcessor < BaseArgProcessor
|
122
|
-
def sanitize_parameters!(obj_class, params)
|
125
|
+
def sanitize_parameters!(obj_class, params) # :nodoc:
|
123
126
|
params.merge!(obj_class.dsl_params)
|
124
127
|
|
125
128
|
params.sanitize_choices(:choices) do |choices|
|
data/lib/bindata/delayed_io.rb
CHANGED
@@ -83,11 +83,11 @@ module BinData
|
|
83
83
|
@type.num_bytes
|
84
84
|
end
|
85
85
|
|
86
|
-
def
|
87
|
-
@type.respond_to?(symbol,
|
86
|
+
def respond_to_missing?(symbol, include_all = false) # :nodoc:
|
87
|
+
@type.respond_to?(symbol, include_all) || super
|
88
88
|
end
|
89
89
|
|
90
|
-
def method_missing(symbol, *args, &block)
|
90
|
+
def method_missing(symbol, *args, &block) # :nodoc:
|
91
91
|
@type.__send__(symbol, *args, &block)
|
92
92
|
end
|
93
93
|
|
@@ -104,24 +104,29 @@ module BinData
|
|
104
104
|
abs_offset
|
105
105
|
end
|
106
106
|
|
107
|
-
def do_read(io)
|
107
|
+
def do_read(io) # :nodoc:
|
108
108
|
@read_io = io
|
109
109
|
end
|
110
110
|
|
111
|
-
def do_write(io)
|
111
|
+
def do_write(io) # :nodoc:
|
112
112
|
@write_io = io
|
113
113
|
end
|
114
114
|
|
115
|
-
def do_num_bytes
|
115
|
+
def do_num_bytes # :nodoc:
|
116
116
|
0
|
117
117
|
end
|
118
118
|
|
119
|
+
def include_obj?
|
120
|
+
!has_parameter?(:onlyif) || eval_parameter(:onlyif)
|
121
|
+
end
|
122
|
+
|
119
123
|
# DelayedIO objects aren't read when #read is called.
|
120
124
|
# The reading is delayed until this method is called.
|
121
125
|
def read_now!
|
126
|
+
return unless include_obj?
|
122
127
|
raise IOError, "read from where?" unless @read_io
|
123
128
|
|
124
|
-
@read_io.
|
129
|
+
@read_io.seek_to_abs_offset(abs_offset)
|
125
130
|
start_read do
|
126
131
|
@type.do_read(@read_io)
|
127
132
|
end
|
@@ -130,8 +135,10 @@ module BinData
|
|
130
135
|
# DelayedIO objects aren't written when #write is called.
|
131
136
|
# The writing is delayed until this method is called.
|
132
137
|
def write_now!
|
138
|
+
return unless include_obj?
|
133
139
|
raise IOError, "write to where?" unless @write_io
|
134
|
-
|
140
|
+
|
141
|
+
@write_io.seek_to_abs_offset(abs_offset)
|
135
142
|
@type.do_write(@write_io)
|
136
143
|
end
|
137
144
|
end
|
@@ -146,15 +153,16 @@ module BinData
|
|
146
153
|
end
|
147
154
|
end
|
148
155
|
|
149
|
-
# Add +auto_call_delayed_io+ keyword to BinData::Base.
|
150
156
|
class Base
|
157
|
+
# Add +auto_call_delayed_io+ keyword to BinData::Base.
|
151
158
|
class << self
|
152
159
|
# The +auto_call_delayed_io+ keyword sets a data object tree to perform
|
153
160
|
# multi pass I/O automatically.
|
154
161
|
def auto_call_delayed_io
|
162
|
+
include AutoCallDelayedIO
|
163
|
+
|
155
164
|
return if DelayedIO.method_defined? :initialize_instance_without_record_io
|
156
165
|
|
157
|
-
include AutoCallDelayedIO
|
158
166
|
DelayedIO.send(:alias_method, :initialize_instance_without_record_io, :initialize_instance)
|
159
167
|
DelayedIO.send(:define_method, :initialize_instance) do
|
160
168
|
if @parent && !defined? @delayed_io_recorded
|
data/lib/bindata/dsl.rb
CHANGED
@@ -42,7 +42,7 @@ module BinData
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
def method_missing(symbol, *args, &block)
|
45
|
+
def method_missing(symbol, *args, &block) # :nodoc:
|
46
46
|
dsl_parser.__send__(symbol, *args, &block)
|
47
47
|
end
|
48
48
|
|
@@ -131,7 +131,8 @@ module BinData
|
|
131
131
|
choice: [:to_choice_params, :choices, [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]],
|
132
132
|
delayed_io: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames, :hidden_fields]],
|
133
133
|
primitive: [:to_struct_params, :struct, [:multiple_fields, :optional_fieldnames]],
|
134
|
-
|
134
|
+
section: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames]],
|
135
|
+
skip: [:to_object_params, :until_valid, [:multiple_fields, :optional_fieldnames]]
|
135
136
|
}
|
136
137
|
end
|
137
138
|
|
@@ -182,21 +183,21 @@ module BinData
|
|
182
183
|
begin
|
183
184
|
@validator.validate_field(parser.name)
|
184
185
|
append_field(parser.type, parser.name, parser.params)
|
185
|
-
rescue Exception =>
|
186
|
-
dsl_raise
|
186
|
+
rescue Exception => e
|
187
|
+
dsl_raise e.class, e.message
|
187
188
|
end
|
188
189
|
end
|
189
190
|
|
190
191
|
def append_field(type, name, params)
|
191
192
|
fields.add_field(type, name, params)
|
192
|
-
rescue BinData::UnRegisteredTypeError =>
|
193
|
-
raise TypeError, "unknown type '#{
|
193
|
+
rescue BinData::UnRegisteredTypeError => e
|
194
|
+
raise TypeError, "unknown type '#{e.message}'"
|
194
195
|
end
|
195
196
|
|
196
197
|
def parent_attribute(attr, default = nil)
|
197
198
|
parent = @the_class.superclass
|
198
199
|
parser = parent.respond_to?(:dsl_parser) ? parent.dsl_parser : nil
|
199
|
-
if parser
|
200
|
+
if parser&.respond_to?(attr)
|
200
201
|
parser.send(attr)
|
201
202
|
else
|
202
203
|
default
|
@@ -205,7 +206,7 @@ module BinData
|
|
205
206
|
|
206
207
|
def dsl_raise(exception, msg)
|
207
208
|
backtrace = caller
|
208
|
-
backtrace.shift while %r{bindata/dsl.rb}
|
209
|
+
backtrace.shift while %r{bindata/dsl.rb}.match?(backtrace.first)
|
209
210
|
|
210
211
|
raise exception, "#{msg} in #{@the_class}", backtrace
|
211
212
|
end
|
@@ -215,9 +216,9 @@ module BinData
|
|
215
216
|
when 0
|
216
217
|
{}
|
217
218
|
when 1
|
218
|
-
{key => fields[0].prototype}
|
219
|
+
{ key => fields[0].prototype }
|
219
220
|
else
|
220
|
-
{key=> [:struct, to_struct_params]}
|
221
|
+
{ key => [:struct, to_struct_params] }
|
221
222
|
end
|
222
223
|
end
|
223
224
|
|
@@ -225,16 +226,16 @@ module BinData
|
|
225
226
|
if fields.empty?
|
226
227
|
{}
|
227
228
|
elsif fields.all_field_names_blank?
|
228
|
-
{key => fields.collect(&:prototype)}
|
229
|
+
{ key => fields.collect(&:prototype) }
|
229
230
|
else
|
230
231
|
choices = {}
|
231
232
|
fields.each { |f| choices[f.name] = f.prototype }
|
232
|
-
{key => choices}
|
233
|
+
{ key => choices }
|
233
234
|
end
|
234
235
|
end
|
235
236
|
|
236
|
-
def to_struct_params(*
|
237
|
-
result = {fields: fields}
|
237
|
+
def to_struct_params(*_)
|
238
|
+
result = { fields: fields }
|
238
239
|
if !endian.nil?
|
239
240
|
result[:endian] = endian
|
240
241
|
end
|
@@ -274,7 +275,7 @@ module BinData
|
|
274
275
|
def override_new_in_class(bnl_class)
|
275
276
|
endian_classes = {
|
276
277
|
big: class_with_endian(bnl_class, :big),
|
277
|
-
little: class_with_endian(bnl_class, :little)
|
278
|
+
little: class_with_endian(bnl_class, :little)
|
278
279
|
}
|
279
280
|
bnl_class.define_singleton_method(:new) do |*args|
|
280
281
|
if self == bnl_class
|
@@ -290,7 +291,7 @@ module BinData
|
|
290
291
|
def delegate_field_creation(bnl_class)
|
291
292
|
endian_classes = {
|
292
293
|
big: class_with_endian(bnl_class, :big),
|
293
|
-
little: class_with_endian(bnl_class, :little)
|
294
|
+
little: class_with_endian(bnl_class, :little)
|
294
295
|
}
|
295
296
|
|
296
297
|
parser = bnl_class.dsl_parser
|
@@ -302,28 +303,28 @@ module BinData
|
|
302
303
|
|
303
304
|
def fixup_subclass_hierarchy(bnl_class)
|
304
305
|
parent = bnl_class.superclass
|
305
|
-
if obj_attribute(parent, :endian)
|
306
|
-
be_subclass = class_with_endian(bnl_class, :big)
|
307
|
-
be_parent = class_with_endian(parent, :big)
|
308
|
-
be_fields = obj_attribute(be_parent, :fields)
|
306
|
+
return if obj_attribute(parent, :endian) != :big_and_little
|
309
307
|
|
310
|
-
|
311
|
-
|
312
|
-
|
308
|
+
be_subclass = class_with_endian(bnl_class, :big)
|
309
|
+
be_parent = class_with_endian(parent, :big)
|
310
|
+
be_fields = obj_attribute(be_parent, :fields)
|
313
311
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
312
|
+
le_subclass = class_with_endian(bnl_class, :little)
|
313
|
+
le_parent = class_with_endian(parent, :little)
|
314
|
+
le_fields = obj_attribute(le_parent, :fields)
|
315
|
+
|
316
|
+
be_subclass.dsl_parser.define_singleton_method(:parent_fields) do
|
317
|
+
be_fields
|
318
|
+
end
|
319
|
+
le_subclass.dsl_parser.define_singleton_method(:parent_fields) do
|
320
|
+
le_fields
|
320
321
|
end
|
321
322
|
end
|
322
323
|
|
323
324
|
def class_with_endian(class_name, endian)
|
324
325
|
hints = {
|
325
326
|
endian: endian,
|
326
|
-
search_prefix: class_name.dsl_parser.search_prefix
|
327
|
+
search_prefix: class_name.dsl_parser.search_prefix
|
327
328
|
}
|
328
329
|
RegisteredClasses.lookup(class_name, hints)
|
329
330
|
end
|
@@ -377,8 +378,9 @@ module BinData
|
|
377
378
|
buffer: BinData::Buffer,
|
378
379
|
choice: BinData::Choice,
|
379
380
|
delayed_io: BinData::DelayedIO,
|
381
|
+
section: BinData::Section,
|
380
382
|
skip: BinData::Skip,
|
381
|
-
struct: BinData::Struct
|
383
|
+
struct: BinData::Struct
|
382
384
|
}
|
383
385
|
|
384
386
|
if bindata_classes.include?(@type)
|
@@ -420,7 +422,7 @@ module BinData
|
|
420
422
|
def ensure_valid_name(name)
|
421
423
|
if name && !option?(:fieldnames_are_values)
|
422
424
|
if malformed_name?(name)
|
423
|
-
raise
|
425
|
+
raise SyntaxError, "field '#{name}' is an illegal fieldname"
|
424
426
|
end
|
425
427
|
|
426
428
|
if duplicate_name?(name)
|
@@ -428,11 +430,11 @@ module BinData
|
|
428
430
|
end
|
429
431
|
|
430
432
|
if name_shadows_method?(name)
|
431
|
-
raise
|
433
|
+
raise SyntaxError, "field '#{name}' shadows an existing method"
|
432
434
|
end
|
433
435
|
|
434
436
|
if name_is_reserved?(name)
|
435
|
-
raise
|
437
|
+
raise SyntaxError, "field '#{name}' is a reserved name"
|
436
438
|
end
|
437
439
|
end
|
438
440
|
end
|
@@ -457,7 +459,7 @@ module BinData
|
|
457
459
|
end
|
458
460
|
|
459
461
|
def malformed_name?(name)
|
460
|
-
|
462
|
+
!/^[a-z_]\w*$/.match?(name.to_s)
|
461
463
|
end
|
462
464
|
|
463
465
|
def duplicate_name?(name)
|
data/lib/bindata/float.rb
CHANGED
@@ -4,7 +4,7 @@ module BinData
|
|
4
4
|
# Defines a number of classes that contain a floating point number.
|
5
5
|
# The float is defined by precision and endian.
|
6
6
|
|
7
|
-
module FloatingPoint
|
7
|
+
module FloatingPoint # :nodoc: all
|
8
8
|
class << self
|
9
9
|
PRECISION = {
|
10
10
|
single: 4,
|
@@ -15,7 +15,7 @@ module BinData
|
|
15
15
|
[:single, :little] => 'e',
|
16
16
|
[:single, :big] => 'g',
|
17
17
|
[:double, :little] => 'E',
|
18
|
-
[:double, :big] => 'G'
|
18
|
+
[:double, :big] => 'G'
|
19
19
|
}
|
20
20
|
|
21
21
|
def define_methods(float_class, precision, endian)
|
@@ -49,7 +49,7 @@ module BinData
|
|
49
49
|
nbytes = PRECISION[precision]
|
50
50
|
unpack = PACK_CODE[[precision, endian]]
|
51
51
|
|
52
|
-
"io.readbytes(#{nbytes}).
|
52
|
+
"io.readbytes(#{nbytes}).unpack1('#{unpack}')"
|
53
53
|
end
|
54
54
|
|
55
55
|
def create_to_binary_s_code(precision, endian)
|
data/lib/bindata/framework.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
module BinData
|
2
2
|
# Error raised when unexpected results occur when reading data from IO.
|
3
|
-
class ValidityError < StandardError
|
3
|
+
class ValidityError < StandardError; end
|
4
4
|
|
5
5
|
# All methods provided by the framework are to be implemented or overridden
|
6
6
|
# by subclasses of BinData::Base.
|
7
7
|
module Framework
|
8
8
|
# Initializes the state of the object. All instance variables that
|
9
9
|
# are used by the object must be initialized here.
|
10
|
-
def initialize_instance
|
11
|
-
end
|
10
|
+
def initialize_instance; end
|
12
11
|
|
13
12
|
# Initialises state that is shared by objects with the same parameters.
|
14
13
|
#
|
@@ -16,8 +15,7 @@ module BinData
|
|
16
15
|
# variables set here, and changes to the singleton class will be shared
|
17
16
|
# between all objects that are initialized with the same parameters.
|
18
17
|
# This method is called only once for a particular set of parameters.
|
19
|
-
def initialize_shared_instance
|
20
|
-
end
|
18
|
+
def initialize_shared_instance; end
|
21
19
|
|
22
20
|
# Returns true if the object has not been changed since creation.
|
23
21
|
def clear?
|
@@ -37,13 +35,13 @@ module BinData
|
|
37
35
|
|
38
36
|
# Returns the debug name of +child+. This only needs to be implemented
|
39
37
|
# by objects that contain child objects.
|
40
|
-
def debug_name_of(child)
|
38
|
+
def debug_name_of(child) # :nodoc:
|
41
39
|
debug_name
|
42
40
|
end
|
43
41
|
|
44
42
|
# Returns the offset of +child+. This only needs to be implemented
|
45
43
|
# by objects that contain child objects.
|
46
|
-
def offset_of(child)
|
44
|
+
def offset_of(child) # :nodoc:
|
47
45
|
0
|
48
46
|
end
|
49
47
|
|
@@ -53,17 +51,17 @@ module BinData
|
|
53
51
|
end
|
54
52
|
|
55
53
|
# Reads the data for this data object from +io+.
|
56
|
-
def do_read(io)
|
54
|
+
def do_read(io) # :nodoc:
|
57
55
|
raise NotImplementedError
|
58
56
|
end
|
59
57
|
|
60
58
|
# Writes the value for this data to +io+.
|
61
|
-
def do_write(io)
|
59
|
+
def do_write(io) # :nodoc:
|
62
60
|
raise NotImplementedError
|
63
61
|
end
|
64
62
|
|
65
63
|
# Returns the number of bytes it will take to write this data.
|
66
|
-
def do_num_bytes
|
64
|
+
def do_num_bytes # :nodoc:
|
67
65
|
raise NotImplementedError
|
68
66
|
end
|
69
67
|
|
data/lib/bindata/int.rb
CHANGED
@@ -5,7 +5,7 @@ module BinData
|
|
5
5
|
# Defines a number of classes that contain an integer. The integer
|
6
6
|
# is defined by endian, signedness and number of bytes.
|
7
7
|
|
8
|
-
module Int
|
8
|
+
module Int # :nodoc: all
|
9
9
|
@@mutex = Mutex.new
|
10
10
|
|
11
11
|
class << self
|
@@ -59,16 +59,14 @@ module BinData
|
|
59
59
|
|
60
60
|
def create_clamp_code(nbits, signed)
|
61
61
|
if signed == :signed
|
62
|
-
max = "
|
63
|
-
min = "
|
62
|
+
max = "(1 << (#{nbits} - 1)) - 1"
|
63
|
+
min = "-((#{max}) + 1)"
|
64
64
|
else
|
65
|
-
max = "
|
66
|
-
min = "
|
65
|
+
max = "(1 << #{nbits}) - 1"
|
66
|
+
min = "0"
|
67
67
|
end
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
"val = #{clamp}"
|
69
|
+
"val = val.clamp(#{min}, #{max})"
|
72
70
|
end
|
73
71
|
|
74
72
|
def create_read_code(nbits, endian, signed)
|
@@ -87,7 +85,7 @@ module BinData
|
|
87
85
|
"io.readbytes(1).ord"
|
88
86
|
else
|
89
87
|
unpack_str = create_read_unpack_code(nbits, endian, signed)
|
90
|
-
assemble_str = create_read_assemble_code(nbits, endian
|
88
|
+
assemble_str = create_read_assemble_code(nbits, endian)
|
91
89
|
|
92
90
|
"(#{unpack_str} ; #{assemble_str})"
|
93
91
|
end
|
@@ -100,7 +98,7 @@ module BinData
|
|
100
98
|
"ints = io.readbytes(#{nbytes}).unpack('#{pack_directive}')"
|
101
99
|
end
|
102
100
|
|
103
|
-
def create_read_assemble_code(nbits, endian
|
101
|
+
def create_read_assemble_code(nbits, endian)
|
104
102
|
nwords = nbits / bits_per_word(nbits)
|
105
103
|
|
106
104
|
idx = (0...nwords).to_a
|
@@ -119,7 +117,7 @@ module BinData
|
|
119
117
|
return "(val & 0xff).chr" if nbits == 8
|
120
118
|
|
121
119
|
pack_directive = pack_directive(nbits, endian, signed)
|
122
|
-
words = val_as_packed_words(nbits, endian
|
120
|
+
words = val_as_packed_words(nbits, endian)
|
123
121
|
pack_str = "[#{words}].pack('#{pack_directive}')"
|
124
122
|
|
125
123
|
if need_signed_conversion_code?(nbits, signed)
|
@@ -129,7 +127,7 @@ module BinData
|
|
129
127
|
end
|
130
128
|
end
|
131
129
|
|
132
|
-
def val_as_packed_words(nbits, endian
|
130
|
+
def val_as_packed_words(nbits, endian)
|
133
131
|
nwords = nbits / bits_per_word(nbits)
|
134
132
|
mask = (1 << bits_per_word(nbits)) - 1
|
135
133
|
|
@@ -138,7 +136,7 @@ module BinData
|
|
138
136
|
vals.reverse! if (endian == :big)
|
139
137
|
|
140
138
|
vals = vals.collect { |val| "#{val} & #{mask}" } # TODO: "& mask" is needed to work around jruby bug. Remove this line when fixed.
|
141
|
-
vals.join(
|
139
|
+
vals.join(',')
|
142
140
|
end
|
143
141
|
|
144
142
|
def create_int2uint_code(nbits)
|
@@ -159,10 +157,10 @@ module BinData
|
|
159
157
|
def pack_directive(nbits, endian, signed)
|
160
158
|
nwords = nbits / bits_per_word(nbits)
|
161
159
|
|
162
|
-
directives = { 8 =>
|
160
|
+
directives = { 8 => 'C', 16 => 'S', 32 => 'L', 64 => 'Q' }
|
163
161
|
|
164
162
|
d = directives[bits_per_word(nbits)]
|
165
|
-
d += ((endian == :big) ?
|
163
|
+
d += ((endian == :big) ? '>' : '<') unless d == 'C'
|
166
164
|
|
167
165
|
if signed == :signed && directives.key?(nbits)
|
168
166
|
(d * nwords).downcase
|
@@ -195,7 +193,7 @@ module BinData
|
|
195
193
|
/^Uint(\d+)be$/ => [:big, :unsigned],
|
196
194
|
/^Uint(\d+)le$/ => [:little, :unsigned],
|
197
195
|
/^Int(\d+)be$/ => [:big, :signed],
|
198
|
-
/^Int(\d+)le$/ => [:little, :signed]
|
196
|
+
/^Int(\d+)le$/ => [:little, :signed]
|
199
197
|
}
|
200
198
|
|
201
199
|
mappings.each_pair do |regex, args|
|