bindata 2.4.11 → 2.5.1
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 +40 -0
- data/LICENSE +25 -0
- data/NEWS.rdoc +5 -0
- data/README.md +7 -10
- data/bindata.gemspec +11 -5
- 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 +12 -22
- 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 +46 -51
- 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 +3 -2
- 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 +53 -37
- 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 +30 -15
- data/test/uint8_array_test.rb +6 -6
- data/test/virtual_test.rb +7 -7
- data/test/warnings_test.rb +14 -2
- metadata +22 -24
- 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/bits.rb
CHANGED
|
@@ -5,7 +5,7 @@ module BinData
|
|
|
5
5
|
# Defines a number of classes that contain a bit based integer.
|
|
6
6
|
# The integer is defined by endian and number of bits.
|
|
7
7
|
|
|
8
|
-
module BitField
|
|
8
|
+
module BitField # :nodoc: all
|
|
9
9
|
@@mutex = Mutex.new
|
|
10
10
|
|
|
11
11
|
class << self
|
|
@@ -99,14 +99,14 @@ module BinData
|
|
|
99
99
|
|
|
100
100
|
def create_dynamic_clamp_code(signed)
|
|
101
101
|
if signed == :signed
|
|
102
|
-
max = "
|
|
103
|
-
min = "
|
|
102
|
+
max = "(1 << (nbits - 1)) - 1"
|
|
103
|
+
min = "-((#{max}) + 1)"
|
|
104
104
|
else
|
|
105
|
-
max = "
|
|
106
|
-
min = "
|
|
105
|
+
max = "(1 << nbits) - 1"
|
|
106
|
+
min = "0"
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
"
|
|
109
|
+
"val = val.clamp(#{min}, #{max})"
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
def create_fixed_clamp_code(nbits, signed)
|
|
@@ -115,14 +115,14 @@ module BinData
|
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
if signed == :signed
|
|
118
|
-
max = "
|
|
119
|
-
min = "
|
|
118
|
+
max = "(1 << (#{nbits} - 1)) - 1"
|
|
119
|
+
min = "-((#{max}) + 1)"
|
|
120
120
|
else
|
|
121
|
-
min = "
|
|
122
|
-
max = "
|
|
121
|
+
min = "0"
|
|
122
|
+
max = "(1 << #{nbits}) - 1"
|
|
123
123
|
end
|
|
124
124
|
|
|
125
|
-
clamp = "(
|
|
125
|
+
clamp = "(val = val.clamp(#{min}, #{max}))"
|
|
126
126
|
|
|
127
127
|
if nbits == 1
|
|
128
128
|
# allow single bits to be used as booleans
|
|
@@ -156,10 +156,10 @@ module BinData
|
|
|
156
156
|
|
|
157
157
|
# Create classes for dynamic bitfields
|
|
158
158
|
{
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
159
|
+
'Bit' => :big,
|
|
160
|
+
'BitLe' => :little,
|
|
161
|
+
'Sbit' => [:big, :signed],
|
|
162
|
+
'SbitLe' => [:little, :signed]
|
|
163
163
|
}.each_pair { |name, args| BitField.define_class(name, :nbits, *args) }
|
|
164
164
|
|
|
165
165
|
# Create classes on demand
|
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,31 +104,20 @@ 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 eval_parameter_with_delayed_io(key, overrides = nil)
|
|
120
|
-
result = eval_parameter_without_delayed_io(key, overrides)
|
|
121
|
-
|
|
122
|
-
# Delay processing :onlyif until we do the actual read/write
|
|
123
|
-
result = true if key == :onlyif && ! result
|
|
124
|
-
|
|
125
|
-
result
|
|
126
|
-
end
|
|
127
|
-
alias_method :eval_parameter_without_delayed_io, :eval_parameter
|
|
128
|
-
alias_method :eval_parameter, :eval_parameter_with_delayed_io
|
|
129
|
-
|
|
130
119
|
def include_obj?
|
|
131
|
-
!
|
|
120
|
+
!has_parameter?(:onlyif) || eval_parameter(:onlyif)
|
|
132
121
|
end
|
|
133
122
|
|
|
134
123
|
# DelayedIO objects aren't read when #read is called.
|
|
@@ -137,7 +126,7 @@ module BinData
|
|
|
137
126
|
return unless include_obj?
|
|
138
127
|
raise IOError, "read from where?" unless @read_io
|
|
139
128
|
|
|
140
|
-
@read_io.
|
|
129
|
+
@read_io.seek_to_abs_offset(abs_offset)
|
|
141
130
|
start_read do
|
|
142
131
|
@type.do_read(@read_io)
|
|
143
132
|
end
|
|
@@ -149,7 +138,7 @@ module BinData
|
|
|
149
138
|
return unless include_obj?
|
|
150
139
|
raise IOError, "write to where?" unless @write_io
|
|
151
140
|
|
|
152
|
-
@write_io.
|
|
141
|
+
@write_io.seek_to_abs_offset(abs_offset)
|
|
153
142
|
@type.do_write(@write_io)
|
|
154
143
|
end
|
|
155
144
|
end
|
|
@@ -164,15 +153,16 @@ module BinData
|
|
|
164
153
|
end
|
|
165
154
|
end
|
|
166
155
|
|
|
167
|
-
# Add +auto_call_delayed_io+ keyword to BinData::Base.
|
|
168
156
|
class Base
|
|
157
|
+
# Add +auto_call_delayed_io+ keyword to BinData::Base.
|
|
169
158
|
class << self
|
|
170
159
|
# The +auto_call_delayed_io+ keyword sets a data object tree to perform
|
|
171
160
|
# multi pass I/O automatically.
|
|
172
161
|
def auto_call_delayed_io
|
|
162
|
+
include AutoCallDelayedIO
|
|
163
|
+
|
|
173
164
|
return if DelayedIO.method_defined? :initialize_instance_without_record_io
|
|
174
165
|
|
|
175
|
-
include AutoCallDelayedIO
|
|
176
166
|
DelayedIO.send(:alias_method, :initialize_instance_without_record_io, :initialize_instance)
|
|
177
167
|
DelayedIO.send(:define_method, :initialize_instance) do
|
|
178
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
|
|