bindata 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bindata might be problematic. Click here for more details.
- data/ChangeLog +8 -0
- data/Rakefile +2 -1
- data/lib/bindata.rb +1 -1
- data/lib/bindata/array.rb +26 -30
- data/lib/bindata/base.rb +60 -51
- data/lib/bindata/base_primitive.rb +35 -44
- data/lib/bindata/bits.rb +6 -7
- data/lib/bindata/choice.rb +18 -22
- data/lib/bindata/deprecated.rb +42 -0
- data/lib/bindata/dsl.rb +12 -0
- data/lib/bindata/float.rb +1 -1
- data/lib/bindata/int.rb +5 -5
- data/lib/bindata/lazy.rb +2 -2
- data/lib/bindata/primitive.rb +1 -1
- data/lib/bindata/record.rb +25 -0
- data/lib/bindata/string.rb +5 -5
- data/lib/bindata/stringz.rb +5 -5
- data/lib/bindata/struct.rb +29 -33
- data/lib/bindata/wrapper.rb +16 -27
- data/manual.md +1187 -0
- data/spec/base_primitive_spec.rb +6 -14
- data/spec/base_spec.rb +38 -37
- data/spec/deprecated_spec.rb +36 -0
- data/spec/primitive_spec.rb +9 -0
- data/spec/record_spec.rb +11 -0
- data/spec/string_spec.rb +5 -6
- metadata +5 -5
- data/lib/bench.rb +0 -102
data/ChangeLog
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
= BinData Changelog
|
2
2
|
|
3
|
+
== Version 1.2.2 (2010-12-14)
|
4
|
+
|
5
|
+
* Added Base.bindata_name method.
|
6
|
+
* Removed Base#done_read to reduce memory usage and cpu usage.
|
7
|
+
* Derived classes should now use do_read et al, instead of _do_read.
|
8
|
+
* Added predefinition of record fields to improve speed.
|
9
|
+
* Made compatible with ruby 1.9.2. Thanks to Andrew Watts.
|
10
|
+
|
3
11
|
== Version 1.2.1 (2010-07-20)
|
4
12
|
|
5
13
|
* Updated specs to be compatible with ruby 1.9.1
|
data/Rakefile
CHANGED
data/lib/bindata.rb
CHANGED
data/lib/bindata/array.rb
CHANGED
@@ -93,6 +93,16 @@ module BinData
|
|
93
93
|
@element_list = nil
|
94
94
|
end
|
95
95
|
|
96
|
+
def assign(array)
|
97
|
+
raise ArgumentError, "can't set a nil value for #{debug_name}" if array.nil?
|
98
|
+
|
99
|
+
@element_list = to_storage_formats(array.to_ary)
|
100
|
+
end
|
101
|
+
|
102
|
+
def snapshot
|
103
|
+
elements.collect { |el| el.snapshot }
|
104
|
+
end
|
105
|
+
|
96
106
|
def find_index(obj)
|
97
107
|
elements.index(obj)
|
98
108
|
end
|
@@ -224,6 +234,22 @@ module BinData
|
|
224
234
|
child.do_num_bytes.is_a?(Integer) ? sum.ceil : sum.floor
|
225
235
|
end
|
226
236
|
|
237
|
+
def do_read(io) #:nodoc:
|
238
|
+
if has_parameter?(:initial_length)
|
239
|
+
elements.each { |el| el.do_read(io) }
|
240
|
+
elsif has_parameter?(:read_until)
|
241
|
+
read_until(io)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
def do_write(io) #:nodoc:
|
246
|
+
elements.each { |el| el.do_write(io) }
|
247
|
+
end
|
248
|
+
|
249
|
+
def do_num_bytes #:nodoc:
|
250
|
+
sum_num_bytes_for_all_elements.ceil
|
251
|
+
end
|
252
|
+
|
227
253
|
#---------------
|
228
254
|
private
|
229
255
|
|
@@ -244,14 +270,6 @@ module BinData
|
|
244
270
|
element
|
245
271
|
end
|
246
272
|
|
247
|
-
def _do_read(io)
|
248
|
-
if has_parameter?(:initial_length)
|
249
|
-
elements.each { |el| el.do_read(io) }
|
250
|
-
elsif has_parameter?(:read_until)
|
251
|
-
read_until(io)
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
273
|
def read_until(io)
|
256
274
|
if get_parameter(:read_until) == :eof
|
257
275
|
read_until_eof(io)
|
@@ -282,28 +300,6 @@ module BinData
|
|
282
300
|
end
|
283
301
|
end
|
284
302
|
|
285
|
-
def _done_read
|
286
|
-
elements.each { |el| el.done_read }
|
287
|
-
end
|
288
|
-
|
289
|
-
def _do_write(io)
|
290
|
-
elements.each { |el| el.do_write(io) }
|
291
|
-
end
|
292
|
-
|
293
|
-
def _do_num_bytes
|
294
|
-
sum_num_bytes_for_all_elements.ceil
|
295
|
-
end
|
296
|
-
|
297
|
-
def _assign(array)
|
298
|
-
raise ArgumentError, "can't set a nil value for #{debug_name}" if array.nil?
|
299
|
-
|
300
|
-
@element_list = to_storage_formats(array.to_ary)
|
301
|
-
end
|
302
|
-
|
303
|
-
def _snapshot
|
304
|
-
elements.collect { |el| el.snapshot }
|
305
|
-
end
|
306
|
-
|
307
303
|
def elements
|
308
304
|
if @element_list.nil?
|
309
305
|
@element_list = []
|
data/lib/bindata/base.rb
CHANGED
@@ -43,6 +43,11 @@ module BinData
|
|
43
43
|
data
|
44
44
|
end
|
45
45
|
|
46
|
+
# The name of this class as used by Records, Arrays etc.
|
47
|
+
def bindata_name
|
48
|
+
RegisteredClasses.underscore_name(self.name)
|
49
|
+
end
|
50
|
+
|
46
51
|
# Registers this class for use.
|
47
52
|
def register_self
|
48
53
|
register_class(self)
|
@@ -74,6 +79,8 @@ module BinData
|
|
74
79
|
def initialize(parameters = {}, parent = nil)
|
75
80
|
@params = Sanitizer.sanitize(parameters, self.class)
|
76
81
|
@parent = parent
|
82
|
+
|
83
|
+
prepare_for_read_with_offset
|
77
84
|
end
|
78
85
|
|
79
86
|
attr_reader :parent
|
@@ -104,21 +111,24 @@ module BinData
|
|
104
111
|
def read(io)
|
105
112
|
io = BinData::IO.new(io) unless BinData::IO === io
|
106
113
|
|
114
|
+
@in_read = true
|
115
|
+
clear
|
107
116
|
do_read(io)
|
108
|
-
|
117
|
+
@in_read = false
|
118
|
+
|
109
119
|
self
|
110
120
|
end
|
111
121
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
_do_read(io)
|
116
|
-
end
|
122
|
+
#:nodoc:
|
123
|
+
attr_reader :in_read
|
124
|
+
protected :in_read
|
117
125
|
|
118
|
-
|
119
|
-
|
126
|
+
# Returns if this object is currently being read. This is used
|
127
|
+
# internally by BasePrimitive.
|
128
|
+
def reading? #:nodoc:
|
129
|
+
furthest_ancestor.in_read
|
120
130
|
end
|
121
|
-
protected :
|
131
|
+
protected :reading?
|
122
132
|
|
123
133
|
# Writes the value for this data object to +io+.
|
124
134
|
def write(io)
|
@@ -129,32 +139,11 @@ module BinData
|
|
129
139
|
self
|
130
140
|
end
|
131
141
|
|
132
|
-
def do_write(io) #:nodoc:
|
133
|
-
_do_write(io)
|
134
|
-
end
|
135
|
-
protected :do_write
|
136
|
-
|
137
142
|
# Returns the number of bytes it will take to write this data object.
|
138
143
|
def num_bytes
|
139
144
|
do_num_bytes.ceil
|
140
145
|
end
|
141
146
|
|
142
|
-
def do_num_bytes #:nodoc:
|
143
|
-
_do_num_bytes
|
144
|
-
end
|
145
|
-
protected :do_num_bytes
|
146
|
-
|
147
|
-
# Assigns the value of +val+ to this data object. Note that +val+ will
|
148
|
-
# always be deep copied to ensure no aliasing problems can occur.
|
149
|
-
def assign(val)
|
150
|
-
_assign(val)
|
151
|
-
end
|
152
|
-
|
153
|
-
# Returns a snapshot of this data object.
|
154
|
-
def snapshot
|
155
|
-
_snapshot
|
156
|
-
end
|
157
|
-
|
158
147
|
# Returns the string representation of this data object.
|
159
148
|
def to_binary_s
|
160
149
|
io = BinData::IO.create_string_io
|
@@ -213,6 +202,31 @@ module BinData
|
|
213
202
|
#---------------
|
214
203
|
private
|
215
204
|
|
205
|
+
def furthest_ancestor
|
206
|
+
if parent.nil?
|
207
|
+
self
|
208
|
+
else
|
209
|
+
an = parent
|
210
|
+
an = an.parent while an.parent
|
211
|
+
an
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def prepare_for_read_with_offset
|
216
|
+
if has_parameter?(:check_offset) or has_parameter?(:adjust_offset)
|
217
|
+
class << self
|
218
|
+
alias_method :do_read_without_offset, :do_read
|
219
|
+
alias_method :do_read, :do_read_with_offset
|
220
|
+
public :do_read # Ruby 1.9.2 bug. Should be protected
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def do_read_with_offset(io) #:nodoc:
|
226
|
+
check_or_adjust_offset(io)
|
227
|
+
do_read_without_offset(io)
|
228
|
+
end
|
229
|
+
|
216
230
|
def check_or_adjust_offset(io)
|
217
231
|
if has_parameter?(:check_offset)
|
218
232
|
check_offset(io)
|
@@ -268,6 +282,17 @@ module BinData
|
|
268
282
|
raise NotImplementedError
|
269
283
|
end
|
270
284
|
|
285
|
+
# Assigns the value of +val+ to this data object. Note that +val+ will
|
286
|
+
# always be deep copied to ensure no aliasing problems can occur.
|
287
|
+
def assign(val)
|
288
|
+
raise NotImplementedError
|
289
|
+
end
|
290
|
+
|
291
|
+
# Returns a snapshot of this data object.
|
292
|
+
def snapshot
|
293
|
+
raise NotImplementedError
|
294
|
+
end
|
295
|
+
|
271
296
|
# Returns the debug name of +child+. This only needs to be implemented
|
272
297
|
# by objects that contain child objects.
|
273
298
|
def debug_name_of(child) #:nodoc:
|
@@ -281,39 +306,23 @@ module BinData
|
|
281
306
|
end
|
282
307
|
|
283
308
|
# Reads the data for this data object from +io+.
|
284
|
-
def
|
285
|
-
raise NotImplementedError
|
286
|
-
end
|
287
|
-
|
288
|
-
# Trigger function that is called after #do_read.
|
289
|
-
def _done_read
|
309
|
+
def do_read(io) #:nodoc:
|
290
310
|
raise NotImplementedError
|
291
311
|
end
|
292
312
|
|
293
313
|
# Writes the value for this data to +io+.
|
294
|
-
def
|
314
|
+
def do_write(io) #:nodoc:
|
295
315
|
raise NotImplementedError
|
296
316
|
end
|
297
317
|
|
298
318
|
# Returns the number of bytes it will take to write this data.
|
299
|
-
def
|
300
|
-
raise NotImplementedError
|
301
|
-
end
|
302
|
-
|
303
|
-
# Assigns the value of +val+ to this data object. Note that +val+ will
|
304
|
-
# always be deep copied to ensure no aliasing problems can occur.
|
305
|
-
def _assign(val)
|
306
|
-
raise NotImplementedError
|
307
|
-
end
|
308
|
-
|
309
|
-
# Returns a snapshot of this data object.
|
310
|
-
def _snapshot
|
319
|
+
def do_num_bytes #:nodoc:
|
311
320
|
raise NotImplementedError
|
312
321
|
end
|
313
322
|
|
314
323
|
# Set visibility requirements of methods to implement
|
315
|
-
public :clear, :clear?, :debug_name_of, :offset_of
|
316
|
-
|
324
|
+
public :clear, :clear?, :assign, :snapshot, :debug_name_of, :offset_of
|
325
|
+
protected :do_read, :do_write, :do_num_bytes
|
317
326
|
|
318
327
|
# End To be implemented by subclasses
|
319
328
|
###########################################################################
|
@@ -36,8 +36,7 @@ module BinData
|
|
36
36
|
# either #read or explicitly set with #value=.
|
37
37
|
# [<tt>:value</tt>] The object will always have this value.
|
38
38
|
# Calls to #value= are ignored when
|
39
|
-
# using this param.
|
40
|
-
# calls to #do_read and #done_read, #value
|
39
|
+
# using this param. While reading, #value
|
41
40
|
# will return the value of the data read from the
|
42
41
|
# IO, not the result of the <tt>:value</tt> param.
|
43
42
|
# [<tt>:check_value</tt>] Raise an error unless the value read in meets
|
@@ -54,19 +53,35 @@ module BinData
|
|
54
53
|
def initialize(parameters = {}, parent = nil)
|
55
54
|
super
|
56
55
|
|
57
|
-
@value
|
58
|
-
@in_read = false
|
56
|
+
@value = nil
|
59
57
|
end
|
60
58
|
|
61
59
|
def clear #:nodoc:
|
62
60
|
@value = nil
|
63
|
-
@in_read = false
|
64
61
|
end
|
65
62
|
|
66
63
|
def clear? #:nodoc:
|
67
64
|
@value.nil?
|
68
65
|
end
|
69
66
|
|
67
|
+
def assign(val)
|
68
|
+
raise ArgumentError, "can't set a nil value for #{debug_name}" if val.nil?
|
69
|
+
|
70
|
+
unless has_parameter?(:value)
|
71
|
+
raw_val = val.respond_to?(:snapshot) ? val.snapshot : val
|
72
|
+
@value = begin
|
73
|
+
raw_val.dup
|
74
|
+
rescue TypeError
|
75
|
+
# can't dup Fixnums
|
76
|
+
raw_val
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def snapshot
|
82
|
+
_value
|
83
|
+
end
|
84
|
+
|
70
85
|
def value
|
71
86
|
# TODO: warn "#value is deprecated, use #snapshot instead"
|
72
87
|
snapshot
|
@@ -98,11 +113,7 @@ module BinData
|
|
98
113
|
snapshot.hash
|
99
114
|
end
|
100
115
|
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
def _do_read(io)
|
105
|
-
@in_read = true
|
116
|
+
def do_read(io) #:nodoc:
|
106
117
|
@value = read_and_return_value(io)
|
107
118
|
|
108
119
|
trace_value
|
@@ -112,6 +123,17 @@ module BinData
|
|
112
123
|
end
|
113
124
|
end
|
114
125
|
|
126
|
+
def do_write(io) #:nodoc:
|
127
|
+
io.writebytes(value_to_binary_string(_value))
|
128
|
+
end
|
129
|
+
|
130
|
+
def do_num_bytes #:nodoc:
|
131
|
+
value_to_binary_string(_value).length
|
132
|
+
end
|
133
|
+
|
134
|
+
#---------------
|
135
|
+
private
|
136
|
+
|
115
137
|
def trace_value
|
116
138
|
BinData::trace_message do |tracer|
|
117
139
|
value_string = _value.inspect
|
@@ -131,50 +153,19 @@ module BinData
|
|
131
153
|
end
|
132
154
|
end
|
133
155
|
|
134
|
-
def _done_read
|
135
|
-
@in_read = false
|
136
|
-
end
|
137
|
-
|
138
|
-
def _do_write(io)
|
139
|
-
raise "can't write whilst reading #{debug_name}" if @in_read
|
140
|
-
io.writebytes(value_to_binary_string(_value))
|
141
|
-
end
|
142
|
-
|
143
|
-
def _do_num_bytes
|
144
|
-
value_to_binary_string(_value).length
|
145
|
-
end
|
146
|
-
|
147
|
-
def _assign(val)
|
148
|
-
raise ArgumentError, "can't set a nil value for #{debug_name}" if val.nil?
|
149
|
-
|
150
|
-
unless has_parameter?(:value)
|
151
|
-
raw_val = val.respond_to?(:snapshot) ? val.snapshot : val
|
152
|
-
@value = begin
|
153
|
-
raw_val.dup
|
154
|
-
rescue TypeError
|
155
|
-
# can't dup Fixnums
|
156
|
-
raw_val
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def _snapshot
|
162
|
-
_value
|
163
|
-
end
|
164
|
-
|
165
156
|
# The unmodified value of this data object. Note that #value calls this
|
166
157
|
# method. This indirection is so that #value can be overridden in
|
167
158
|
# subclasses to modify the value.
|
168
159
|
def _value
|
169
160
|
# Table of possible preconditions and expected outcome
|
170
|
-
# 1. :value and !
|
171
|
-
# 2. :value and
|
161
|
+
# 1. :value and !reading? -> :value
|
162
|
+
# 2. :value and reading? -> @value
|
172
163
|
# 3. :initial_value and clear? -> :initial_value
|
173
164
|
# 4. :initial_value and !clear? -> @value
|
174
165
|
# 5. clear? -> sensible_default
|
175
166
|
# 6. !clear? -> @value
|
176
167
|
|
177
|
-
if
|
168
|
+
if has_parameter?(:value) and not reading?
|
178
169
|
# rule 1 above
|
179
170
|
eval_parameter(:value)
|
180
171
|
else
|
data/lib/bindata/bits.rb
CHANGED
@@ -23,23 +23,22 @@ module BinData
|
|
23
23
|
|
24
24
|
def define_methods(bit_class, nbits, endian)
|
25
25
|
bit_class.module_eval <<-END
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def _assign(val)
|
26
|
+
def assign(val)
|
30
27
|
#{create_clamp_code(nbits)}
|
31
28
|
super(val)
|
32
29
|
end
|
33
30
|
|
34
|
-
def
|
35
|
-
raise "can't write whilst reading \#{debug_name}" if @in_read
|
31
|
+
def do_write(io)
|
36
32
|
io.writebits(_value, #{nbits}, :#{endian})
|
37
33
|
end
|
38
34
|
|
39
|
-
def
|
35
|
+
def do_num_bytes
|
40
36
|
#{nbits / 8.0}
|
41
37
|
end
|
42
38
|
|
39
|
+
#---------------
|
40
|
+
private
|
41
|
+
|
43
42
|
def read_and_return_value(io)
|
44
43
|
io.readbits(#{nbits}, :#{endian})
|
45
44
|
end
|