bindata 2.4.15 → 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 +16 -0
- data/README.md +7 -10
- data/bindata.gemspec +5 -4
- 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 +5 -5
- 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 +10 -10
- data/lib/bindata/dsl.rb +34 -32
- data/lib/bindata/float.rb +3 -3
- data/lib/bindata/framework.rb +8 -10
- data/lib/bindata/int.rb +9 -9
- 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 +83 -66
- 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/array_test.rb +10 -8
- data/test/buffer_test.rb +9 -0
- data/test/choice_test.rb +1 -1
- data/test/delayed_io_test.rb +16 -0
- data/test/io_test.rb +54 -246
- data/test/registry_test.rb +1 -1
- data/test/section_test.rb +111 -0
- data/test/skip_test.rb +55 -10
- data/test/string_test.rb +4 -4
- data/test/stringz_test.rb +8 -0
- data/test/struct_test.rb +87 -12
- data/test/system_test.rb +119 -1
- data/test/test_helper.rb +30 -15
- data/test/warnings_test.rb +12 -0
- metadata +20 -18
- data/lib/bindata/offset.rb +0 -94
- data/test/offset_test.rb +0 -100
data/lib/bindata/io.rb
CHANGED
@@ -5,217 +5,10 @@ module BinData
|
|
5
5
|
# interface for BinData objects to use when accessing the IO.
|
6
6
|
module IO
|
7
7
|
|
8
|
-
# Common operations for both Read and Write.
|
9
|
-
module Common
|
10
|
-
def initialize(io)
|
11
|
-
if self.class === io
|
12
|
-
raise ArgumentError, "io must not be a #{self.class}"
|
13
|
-
end
|
14
|
-
|
15
|
-
# wrap strings in a StringIO
|
16
|
-
if io.respond_to?(:to_str)
|
17
|
-
io = BinData::IO.create_string_io(io.to_str)
|
18
|
-
end
|
19
|
-
|
20
|
-
@raw_io = io
|
21
|
-
@buffer_end_points = nil
|
22
|
-
|
23
|
-
extend seekable? ? SeekableStream : UnSeekableStream
|
24
|
-
stream_init
|
25
|
-
end
|
26
|
-
|
27
|
-
#-------------
|
28
|
-
private
|
29
|
-
|
30
|
-
def seekable?
|
31
|
-
@raw_io.pos
|
32
|
-
rescue NoMethodError, Errno::ESPIPE, Errno::EPIPE, Errno::EINVAL
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
|
36
|
-
def seek(n)
|
37
|
-
seek_raw(buffer_limited_n(n))
|
38
|
-
end
|
39
|
-
|
40
|
-
def buffer_limited_n(n)
|
41
|
-
if @buffer_end_points
|
42
|
-
if n.nil? || n > 0
|
43
|
-
max = @buffer_end_points[1] - offset
|
44
|
-
n = max if n.nil? || n > max
|
45
|
-
else
|
46
|
-
min = @buffer_end_points[0] - offset
|
47
|
-
n = min if n < min
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
n
|
52
|
-
end
|
53
|
-
|
54
|
-
def with_buffer_common(n)
|
55
|
-
prev = @buffer_end_points
|
56
|
-
if prev
|
57
|
-
avail = prev[1] - offset
|
58
|
-
n = avail if n > avail
|
59
|
-
end
|
60
|
-
@buffer_end_points = [offset, offset + n]
|
61
|
-
begin
|
62
|
-
yield(*@buffer_end_points)
|
63
|
-
ensure
|
64
|
-
@buffer_end_points = prev
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Use #seek and #pos on seekable streams
|
69
|
-
module SeekableStream
|
70
|
-
# The number of bytes remaining in the input stream.
|
71
|
-
def num_bytes_remaining
|
72
|
-
start_mark = @raw_io.pos
|
73
|
-
@raw_io.seek(0, ::IO::SEEK_END)
|
74
|
-
end_mark = @raw_io.pos
|
75
|
-
|
76
|
-
if @buffer_end_points
|
77
|
-
if @buffer_end_points[1] < end_mark
|
78
|
-
end_mark = @buffer_end_points[1]
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
bytes_remaining = end_mark - start_mark
|
83
|
-
@raw_io.seek(start_mark, ::IO::SEEK_SET)
|
84
|
-
|
85
|
-
bytes_remaining
|
86
|
-
end
|
87
|
-
|
88
|
-
# All io calls in +block+ are rolled back after this
|
89
|
-
# method completes.
|
90
|
-
def with_readahead
|
91
|
-
mark = @raw_io.pos
|
92
|
-
begin
|
93
|
-
yield
|
94
|
-
ensure
|
95
|
-
@raw_io.seek(mark, ::IO::SEEK_SET)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
#-----------
|
100
|
-
private
|
101
|
-
|
102
|
-
def stream_init
|
103
|
-
@initial_pos = @raw_io.pos
|
104
|
-
end
|
105
|
-
|
106
|
-
def offset_raw
|
107
|
-
@raw_io.pos - @initial_pos
|
108
|
-
end
|
109
|
-
|
110
|
-
def seek_raw(n)
|
111
|
-
@raw_io.seek(n, ::IO::SEEK_CUR)
|
112
|
-
end
|
113
|
-
|
114
|
-
def read_raw(n)
|
115
|
-
@raw_io.read(n)
|
116
|
-
end
|
117
|
-
|
118
|
-
def write_raw(data)
|
119
|
-
@raw_io.write(data)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# Manually keep track of offset for unseekable streams.
|
124
|
-
module UnSeekableStream
|
125
|
-
def offset_raw
|
126
|
-
@offset
|
127
|
-
end
|
128
|
-
|
129
|
-
# The number of bytes remaining in the input stream.
|
130
|
-
def num_bytes_remaining
|
131
|
-
raise IOError, "stream is unseekable"
|
132
|
-
end
|
133
|
-
|
134
|
-
# All io calls in +block+ are rolled back after this
|
135
|
-
# method completes.
|
136
|
-
def with_readahead
|
137
|
-
mark = @offset
|
138
|
-
@read_data = ""
|
139
|
-
@in_readahead = true
|
140
|
-
|
141
|
-
class << self
|
142
|
-
alias_method :read_raw_without_readahead, :read_raw
|
143
|
-
alias_method :read_raw, :read_raw_with_readahead
|
144
|
-
end
|
145
|
-
|
146
|
-
begin
|
147
|
-
yield
|
148
|
-
ensure
|
149
|
-
@offset = mark
|
150
|
-
@in_readahead = false
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
#-----------
|
155
|
-
private
|
156
|
-
|
157
|
-
def stream_init
|
158
|
-
@offset = 0
|
159
|
-
end
|
160
|
-
|
161
|
-
def read_raw(n)
|
162
|
-
data = @raw_io.read(n)
|
163
|
-
@offset += data.size if data
|
164
|
-
data
|
165
|
-
end
|
166
|
-
|
167
|
-
def read_raw_with_readahead(n)
|
168
|
-
data = ""
|
169
|
-
|
170
|
-
unless @read_data.empty? || @in_readahead
|
171
|
-
bytes_to_consume = [n, @read_data.length].min
|
172
|
-
data += @read_data.slice!(0, bytes_to_consume)
|
173
|
-
n -= bytes_to_consume
|
174
|
-
|
175
|
-
if @read_data.empty?
|
176
|
-
class << self
|
177
|
-
alias_method :read_raw, :read_raw_without_readahead
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
raw_data = @raw_io.read(n)
|
183
|
-
data += raw_data if raw_data
|
184
|
-
|
185
|
-
if @in_readahead
|
186
|
-
@read_data += data
|
187
|
-
end
|
188
|
-
|
189
|
-
@offset += data.size
|
190
|
-
|
191
|
-
data
|
192
|
-
end
|
193
|
-
|
194
|
-
def write_raw(data)
|
195
|
-
@offset += data.size
|
196
|
-
@raw_io.write(data)
|
197
|
-
end
|
198
|
-
|
199
|
-
def seek_raw(n)
|
200
|
-
raise IOError, "stream is unseekable" if n < 0
|
201
|
-
|
202
|
-
# NOTE: how do we seek on a writable stream?
|
203
|
-
|
204
|
-
# skip over data in 8k blocks
|
205
|
-
while n > 0
|
206
|
-
bytes_to_read = [n, 8192].min
|
207
|
-
read_raw(bytes_to_read)
|
208
|
-
n -= bytes_to_read
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
8
|
# Creates a StringIO around +str+.
|
215
9
|
def self.create_string_io(str = "")
|
216
|
-
|
217
|
-
|
218
|
-
s
|
10
|
+
bin_str = str.dup.force_encoding(Encoding::BINARY)
|
11
|
+
StringIO.new(bin_str).tap(&:binmode)
|
219
12
|
end
|
220
13
|
|
221
14
|
# Create a new IO Read wrapper around +io+. +io+ must provide #read,
|
@@ -236,10 +29,17 @@ module BinData
|
|
236
29
|
# readbits(6), readbits(5) #=> [543210, a9876]
|
237
30
|
#
|
238
31
|
class Read
|
239
|
-
include Common
|
240
|
-
|
241
32
|
def initialize(io)
|
242
|
-
|
33
|
+
if self.class === io
|
34
|
+
raise ArgumentError, "io must not be a #{self.class}"
|
35
|
+
end
|
36
|
+
|
37
|
+
# wrap strings in a StringIO
|
38
|
+
if io.respond_to?(:to_str)
|
39
|
+
io = BinData::IO.create_string_io(io.to_str)
|
40
|
+
end
|
41
|
+
|
42
|
+
@io = RawIO.new(io)
|
243
43
|
|
244
44
|
# bits when reading
|
245
45
|
@rnbits = 0
|
@@ -247,25 +47,38 @@ module BinData
|
|
247
47
|
@rendian = nil
|
248
48
|
end
|
249
49
|
|
250
|
-
#
|
251
|
-
#
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
50
|
+
# Allow transforming data in the input stream.
|
51
|
+
# See +BinData::Buffer+ as an example.
|
52
|
+
#
|
53
|
+
# +io+ must be an instance of +Transform+.
|
54
|
+
#
|
55
|
+
# yields +self+ and +io+ to the given block
|
56
|
+
def transform(io)
|
57
|
+
reset_read_bits
|
58
|
+
|
59
|
+
saved = @io
|
60
|
+
@io = io.prepend_to_chain(@io)
|
61
|
+
yield(self, io)
|
62
|
+
io.after_read_transform
|
63
|
+
ensure
|
64
|
+
@io = saved
|
257
65
|
end
|
258
66
|
|
259
|
-
#
|
260
|
-
|
261
|
-
|
262
|
-
offset_raw
|
67
|
+
# The number of bytes remaining in the io steam.
|
68
|
+
def num_bytes_remaining
|
69
|
+
@io.num_bytes_remaining
|
263
70
|
end
|
264
71
|
|
265
72
|
# Seek +n+ bytes from the current position in the io stream.
|
266
|
-
def
|
73
|
+
def skipbytes(n)
|
267
74
|
reset_read_bits
|
268
|
-
|
75
|
+
@io.skip(n)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Seek to an absolute offset within the io stream.
|
79
|
+
def seek_to_abs_offset(n)
|
80
|
+
reset_read_bits
|
81
|
+
@io.seek_abs(n)
|
269
82
|
end
|
270
83
|
|
271
84
|
# Reads exactly +n+ bytes from +io+.
|
@@ -311,7 +124,7 @@ module BinData
|
|
311
124
|
private
|
312
125
|
|
313
126
|
def read(n = nil)
|
314
|
-
str =
|
127
|
+
str = @io.read(n)
|
315
128
|
if n
|
316
129
|
raise EOFError, "End of file reached" if str.nil?
|
317
130
|
raise IOError, "data truncated" if str.size < n
|
@@ -332,7 +145,7 @@ module BinData
|
|
332
145
|
end
|
333
146
|
|
334
147
|
def accumulate_big_endian_bits
|
335
|
-
byte = read(1).
|
148
|
+
byte = read(1).unpack1('C') & 0xff
|
336
149
|
@rval = (@rval << 8) | byte
|
337
150
|
@rnbits += 8
|
338
151
|
end
|
@@ -350,7 +163,7 @@ module BinData
|
|
350
163
|
end
|
351
164
|
|
352
165
|
def accumulate_little_endian_bits
|
353
|
-
byte = read(1).
|
166
|
+
byte = read(1).unpack1('C') & 0xff
|
354
167
|
@rval = @rval | (byte << @rnbits)
|
355
168
|
@rnbits += 8
|
356
169
|
end
|
@@ -368,36 +181,46 @@ module BinData
|
|
368
181
|
#
|
369
182
|
# See IO::Read for more information.
|
370
183
|
class Write
|
371
|
-
include Common
|
372
184
|
def initialize(io)
|
373
|
-
|
185
|
+
if self.class === io
|
186
|
+
raise ArgumentError, "io must not be a #{self.class}"
|
187
|
+
end
|
188
|
+
|
189
|
+
# wrap strings in a StringIO
|
190
|
+
if io.respond_to?(:to_str)
|
191
|
+
io = BinData::IO.create_string_io(io.to_str)
|
192
|
+
end
|
193
|
+
|
194
|
+
@io = RawIO.new(io)
|
374
195
|
|
375
196
|
@wnbits = 0
|
376
197
|
@wval = 0
|
377
198
|
@wendian = nil
|
378
199
|
end
|
379
200
|
|
380
|
-
#
|
381
|
-
# +
|
382
|
-
#
|
383
|
-
#
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
end
|
389
|
-
end
|
201
|
+
# Allow transforming data in the output stream.
|
202
|
+
# See +BinData::Buffer+ as an example.
|
203
|
+
#
|
204
|
+
# +io+ must be an instance of +Transform+.
|
205
|
+
#
|
206
|
+
# yields +self+ and +io+ to the given block
|
207
|
+
def transform(io)
|
208
|
+
flushbits
|
390
209
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
210
|
+
saved = @io
|
211
|
+
@io = io.prepend_to_chain(@io)
|
212
|
+
yield(self, io)
|
213
|
+
io.after_write_transform
|
214
|
+
ensure
|
215
|
+
@io = saved
|
395
216
|
end
|
396
217
|
|
397
|
-
# Seek
|
398
|
-
def
|
218
|
+
# Seek to an absolute offset within the io stream.
|
219
|
+
def seek_to_abs_offset(n)
|
220
|
+
raise IOError, "stream is unseekable" unless @io.seekable?
|
221
|
+
|
399
222
|
flushbits
|
400
|
-
|
223
|
+
@io.seek_abs(n)
|
401
224
|
end
|
402
225
|
|
403
226
|
# Writes the given string of bytes to the io stream.
|
@@ -438,12 +261,7 @@ module BinData
|
|
438
261
|
private
|
439
262
|
|
440
263
|
def write(data)
|
441
|
-
|
442
|
-
if n < data.size
|
443
|
-
data = data[0, n]
|
444
|
-
end
|
445
|
-
|
446
|
-
write_raw(data)
|
264
|
+
@io.write(data)
|
447
265
|
end
|
448
266
|
|
449
267
|
def write_big_endian_bits(val, nbits)
|
@@ -492,5 +310,210 @@ module BinData
|
|
492
310
|
(1 << nbits) - 1
|
493
311
|
end
|
494
312
|
end
|
313
|
+
|
314
|
+
# API used to access the raw data stream.
|
315
|
+
class RawIO
|
316
|
+
def initialize(io)
|
317
|
+
@io = io
|
318
|
+
@pos = 0
|
319
|
+
|
320
|
+
if is_seekable?(io)
|
321
|
+
@initial_pos = io.pos
|
322
|
+
else
|
323
|
+
singleton_class.prepend(UnSeekableIO)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
def is_seekable?(io)
|
328
|
+
io.pos
|
329
|
+
rescue NoMethodError, Errno::ESPIPE, Errno::EPIPE, Errno::EINVAL
|
330
|
+
nil
|
331
|
+
end
|
332
|
+
|
333
|
+
def seekable?
|
334
|
+
true
|
335
|
+
end
|
336
|
+
|
337
|
+
def num_bytes_remaining
|
338
|
+
start_mark = @io.pos
|
339
|
+
@io.seek(0, ::IO::SEEK_END)
|
340
|
+
end_mark = @io.pos
|
341
|
+
@io.seek(start_mark, ::IO::SEEK_SET)
|
342
|
+
|
343
|
+
end_mark - start_mark
|
344
|
+
end
|
345
|
+
|
346
|
+
def offset
|
347
|
+
@pos
|
348
|
+
end
|
349
|
+
|
350
|
+
def skip(n)
|
351
|
+
raise IOError, "can not skip backwards" if n.negative?
|
352
|
+
@io.seek(n, ::IO::SEEK_CUR)
|
353
|
+
@pos += n
|
354
|
+
end
|
355
|
+
|
356
|
+
def seek_abs(n)
|
357
|
+
@io.seek(n + @initial_pos, ::IO::SEEK_SET)
|
358
|
+
@pos = n
|
359
|
+
end
|
360
|
+
|
361
|
+
def read(n)
|
362
|
+
@io.read(n).tap { |data| @pos += (data&.size || 0) }
|
363
|
+
end
|
364
|
+
|
365
|
+
def write(data)
|
366
|
+
@io.write(data)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
# An IO stream may be transformed before processing.
|
371
|
+
# e.g. encoding, compression, buffered.
|
372
|
+
#
|
373
|
+
# Multiple transforms can be chained together.
|
374
|
+
#
|
375
|
+
# To create a new transform layer, subclass +Transform+.
|
376
|
+
# Override the public methods +#read+ and +#write+ at a minimum.
|
377
|
+
# Additionally the hook, +#before_transform+, +#after_read_transform+
|
378
|
+
# and +#after_write_transform+ are available as well.
|
379
|
+
#
|
380
|
+
# IMPORTANT! If your transform changes the size of the underlying
|
381
|
+
# data stream (e.g. compression), then call
|
382
|
+
# +::transform_changes_stream_length!+ in your subclass.
|
383
|
+
class Transform
|
384
|
+
class << self
|
385
|
+
# Indicates that this transform changes the length of the
|
386
|
+
# underlying data. e.g. performs compression or error correction
|
387
|
+
def transform_changes_stream_length!
|
388
|
+
prepend(UnSeekableIO)
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def initialize
|
393
|
+
@chain_io = nil
|
394
|
+
end
|
395
|
+
|
396
|
+
# Initialises this transform.
|
397
|
+
#
|
398
|
+
# Called before any IO operations.
|
399
|
+
def before_transform; end
|
400
|
+
|
401
|
+
# Flushes the input stream.
|
402
|
+
#
|
403
|
+
# Called after the final read operation.
|
404
|
+
def after_read_transform; end
|
405
|
+
|
406
|
+
# Flushes the output stream.
|
407
|
+
#
|
408
|
+
# Called after the final write operation.
|
409
|
+
def after_write_transform; end
|
410
|
+
|
411
|
+
# Prepends this transform to the given +chain+.
|
412
|
+
#
|
413
|
+
# Returns self (the new head of chain).
|
414
|
+
def prepend_to_chain(chain)
|
415
|
+
@chain_io = chain
|
416
|
+
before_transform
|
417
|
+
self
|
418
|
+
end
|
419
|
+
|
420
|
+
# Is the IO seekable?
|
421
|
+
def seekable?
|
422
|
+
@chain_io.seekable?
|
423
|
+
end
|
424
|
+
|
425
|
+
# How many bytes are available for reading?
|
426
|
+
def num_bytes_remaining
|
427
|
+
chain_num_bytes_remaining
|
428
|
+
end
|
429
|
+
|
430
|
+
# The current offset within the stream.
|
431
|
+
def offset
|
432
|
+
chain_offset
|
433
|
+
end
|
434
|
+
|
435
|
+
# Skips forward +n+ bytes in the input stream.
|
436
|
+
def skip(n)
|
437
|
+
chain_skip(n)
|
438
|
+
end
|
439
|
+
|
440
|
+
# Seeks to the given absolute position.
|
441
|
+
def seek_abs(n)
|
442
|
+
chain_seek_abs(n)
|
443
|
+
end
|
444
|
+
|
445
|
+
# Reads +n+ bytes from the stream.
|
446
|
+
def read(n)
|
447
|
+
chain_read(n)
|
448
|
+
end
|
449
|
+
|
450
|
+
# Writes +data+ to the stream.
|
451
|
+
def write(data)
|
452
|
+
chain_write(data)
|
453
|
+
end
|
454
|
+
|
455
|
+
#-------------
|
456
|
+
private
|
457
|
+
|
458
|
+
def create_empty_binary_string
|
459
|
+
String.new.force_encoding(Encoding::BINARY)
|
460
|
+
end
|
461
|
+
|
462
|
+
def chain_seekable?
|
463
|
+
@chain_io.seekable?
|
464
|
+
end
|
465
|
+
|
466
|
+
def chain_num_bytes_remaining
|
467
|
+
@chain_io.num_bytes_remaining
|
468
|
+
end
|
469
|
+
|
470
|
+
def chain_offset
|
471
|
+
@chain_io.offset
|
472
|
+
end
|
473
|
+
|
474
|
+
def chain_skip(n)
|
475
|
+
@chain_io.skip(n)
|
476
|
+
end
|
477
|
+
|
478
|
+
def chain_seek_abs(n)
|
479
|
+
@chain_io.seek_abs(n)
|
480
|
+
end
|
481
|
+
|
482
|
+
def chain_read(n)
|
483
|
+
@chain_io.read(n)
|
484
|
+
end
|
485
|
+
|
486
|
+
def chain_write(data)
|
487
|
+
@chain_io.write(data)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
# A module to be prepended to +RawIO+ or +Transform+ when the data
|
492
|
+
# stream is not seekable. This is either due to underlying stream
|
493
|
+
# being unseekable or the transform changes the number of bytes.
|
494
|
+
module UnSeekableIO
|
495
|
+
def seekable?
|
496
|
+
false
|
497
|
+
end
|
498
|
+
|
499
|
+
def num_bytes_remaining
|
500
|
+
raise IOError, "stream is unseekable"
|
501
|
+
end
|
502
|
+
|
503
|
+
def skip(n)
|
504
|
+
raise IOError, "can not skip backwards" if n.negative?
|
505
|
+
|
506
|
+
# skip over data in 8k blocks
|
507
|
+
while n > 0
|
508
|
+
bytes_to_read = [n, 8192].min
|
509
|
+
read(bytes_to_read)
|
510
|
+
n -= bytes_to_read
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
def seek_abs(n)
|
515
|
+
skip(n - offset)
|
516
|
+
end
|
517
|
+
end
|
495
518
|
end
|
496
519
|
end
|
data/lib/bindata/name.rb
CHANGED
data/lib/bindata/params.rb
CHANGED
@@ -27,7 +27,7 @@ module BinData
|
|
27
27
|
alias optional_parameter optional_parameters
|
28
28
|
alias default_parameter default_parameters
|
29
29
|
|
30
|
-
def accepted_parameters
|
30
|
+
def accepted_parameters # :nodoc:
|
31
31
|
@accepted_parameters ||= begin
|
32
32
|
ancestor_params = superclass.respond_to?(:accepted_parameters) ?
|
33
33
|
superclass.accepted_parameters : nil
|
@@ -114,13 +114,15 @@ module BinData
|
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
class << self
|
118
|
+
def invalid_parameter_names
|
119
|
+
@invalid_parameter_names ||= begin
|
120
|
+
all_names = LazyEvaluator.instance_methods(true)
|
121
|
+
allowed_names = [:name, :type]
|
122
|
+
invalid_names = (all_names - allowed_names).uniq
|
122
123
|
|
123
|
-
|
124
|
+
Hash[*invalid_names.collect { |key| [key.to_sym, true] }.flatten]
|
125
|
+
end
|
124
126
|
end
|
125
127
|
end
|
126
128
|
end
|
data/lib/bindata/primitive.rb
CHANGED
@@ -73,11 +73,11 @@ module BinData
|
|
73
73
|
@struct = BinData::Struct.new(get_parameter(:struct_params), self)
|
74
74
|
end
|
75
75
|
|
76
|
-
def respond_to?(symbol, include_private = false)
|
76
|
+
def respond_to?(symbol, include_private = false) # :nodoc:
|
77
77
|
@struct.respond_to?(symbol, include_private) || super
|
78
78
|
end
|
79
79
|
|
80
|
-
def method_missing(symbol, *args, &block)
|
80
|
+
def method_missing(symbol, *args, &block) # :nodoc:
|
81
81
|
if @struct.respond_to?(symbol)
|
82
82
|
@struct.__send__(symbol, *args, &block)
|
83
83
|
else
|
@@ -91,7 +91,7 @@ module BinData
|
|
91
91
|
@value = get
|
92
92
|
end
|
93
93
|
|
94
|
-
def debug_name_of(child)
|
94
|
+
def debug_name_of(child) # :nodoc:
|
95
95
|
debug_name + "-internal-"
|
96
96
|
end
|
97
97
|
|