bindata 1.1.0 → 1.2.0
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 +7 -0
- data/README +32 -1167
- data/lib/bindata.rb +3 -3
- data/lib/bindata/array.rb +5 -6
- data/lib/bindata/base.rb +40 -58
- data/lib/bindata/base_primitive.rb +7 -11
- data/lib/bindata/bits.rb +47 -44
- data/lib/bindata/choice.rb +7 -11
- data/lib/bindata/deprecated.rb +17 -2
- data/lib/bindata/dsl.rb +332 -0
- data/lib/bindata/float.rb +48 -50
- data/lib/bindata/int.rb +66 -88
- data/lib/bindata/params.rb +112 -59
- data/lib/bindata/primitive.rb +8 -88
- data/lib/bindata/record.rb +11 -99
- data/lib/bindata/registry.rb +16 -3
- data/lib/bindata/rest.rb +1 -1
- data/lib/bindata/sanitize.rb +71 -53
- data/lib/bindata/skip.rb +2 -1
- data/lib/bindata/string.rb +3 -3
- data/lib/bindata/stringz.rb +1 -1
- data/lib/bindata/struct.rb +21 -20
- data/lib/bindata/trace.rb +8 -0
- data/lib/bindata/wrapper.rb +13 -69
- data/manual.haml +2 -2
- data/spec/array_spec.rb +1 -1
- data/spec/base_primitive_spec.rb +4 -4
- data/spec/base_spec.rb +19 -6
- data/spec/bits_spec.rb +5 -1
- data/spec/choice_spec.rb +13 -2
- data/spec/deprecated_spec.rb +31 -0
- data/spec/example.rb +5 -1
- data/spec/io_spec.rb +2 -4
- data/spec/lazy_spec.rb +10 -5
- data/spec/primitive_spec.rb +13 -5
- data/spec/record_spec.rb +149 -45
- data/spec/registry_spec.rb +18 -6
- data/spec/spec_common.rb +31 -6
- data/spec/string_spec.rb +0 -1
- data/spec/stringz_spec.rb +4 -4
- data/spec/struct_spec.rb +2 -2
- data/spec/system_spec.rb +26 -19
- data/spec/wrapper_spec.rb +52 -4
- data/tasks/manual.rake +1 -1
- data/tasks/pkg.rake +13 -0
- metadata +121 -46
- data/TODO +0 -3
data/lib/bindata.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# BinData -- Binary data manipulator.
|
2
|
-
# Copyright (c) 2007 -
|
2
|
+
# Copyright (c) 2007 - 2010 Dion Mendel.
|
3
3
|
|
4
4
|
require 'bindata/array'
|
5
5
|
require 'bindata/bits'
|
@@ -28,7 +28,7 @@ require 'bindata/deprecated'
|
|
28
28
|
#
|
29
29
|
# BinData is released under the same license as Ruby.
|
30
30
|
#
|
31
|
-
# Copyright (c) 2007 -
|
31
|
+
# Copyright (c) 2007 - 2010 Dion Mendel.
|
32
32
|
module BinData
|
33
|
-
VERSION = "1.
|
33
|
+
VERSION = "1.2.0"
|
34
34
|
end
|
data/lib/bindata/array.rb
CHANGED
@@ -54,7 +54,7 @@ module BinData
|
|
54
54
|
class Array < BinData::Base
|
55
55
|
include Enumerable
|
56
56
|
|
57
|
-
|
57
|
+
register_self
|
58
58
|
|
59
59
|
mandatory_parameter :type
|
60
60
|
optional_parameters :initial_length, :read_until
|
@@ -69,7 +69,7 @@ module BinData
|
|
69
69
|
params[:initial_length] = 0
|
70
70
|
end
|
71
71
|
|
72
|
-
warn_replacement_parameter(
|
72
|
+
params.warn_replacement_parameter(:read_length, :initial_length)
|
73
73
|
|
74
74
|
if params.needs_sanitizing?(:type)
|
75
75
|
el_type, el_params = params[:type]
|
@@ -78,16 +78,15 @@ module BinData
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
def initialize(
|
82
|
-
super
|
81
|
+
def initialize(parameters = {}, parent = nil)
|
82
|
+
super
|
83
83
|
|
84
84
|
@element_list = nil
|
85
85
|
@element_prototype = get_parameter(:type)
|
86
86
|
end
|
87
87
|
|
88
88
|
def clear?
|
89
|
-
@element_list.nil? or
|
90
|
-
elements.inject(true) { |all_clear, el| all_clear and el.clear? }
|
89
|
+
@element_list.nil? or elements.all? { |el| el.clear? }
|
91
90
|
end
|
92
91
|
|
93
92
|
def clear
|
data/lib/bindata/base.rb
CHANGED
@@ -13,7 +13,7 @@ module BinData
|
|
13
13
|
# == Parameters
|
14
14
|
#
|
15
15
|
# Parameters may be provided at initialisation to control the behaviour of
|
16
|
-
# an object. These
|
16
|
+
# an object. These parameters are:
|
17
17
|
#
|
18
18
|
# [<tt>:check_offset</tt>] Raise an error if the current IO offset doesn't
|
19
19
|
# meet this criteria. A boolean return indicates
|
@@ -27,6 +27,11 @@ module BinData
|
|
27
27
|
# <tt>:check_offset</tt>, except that it will
|
28
28
|
# adjust the IO offset instead of raising an error.
|
29
29
|
class Base
|
30
|
+
include AcceptedParametersMixin
|
31
|
+
|
32
|
+
optional_parameters :check_offset, :adjust_offset
|
33
|
+
optional_parameter :onlyif # Used by Struct
|
34
|
+
mutually_exclusive_parameters :check_offset, :adjust_offset
|
30
35
|
|
31
36
|
class << self
|
32
37
|
|
@@ -38,74 +43,46 @@ module BinData
|
|
38
43
|
data
|
39
44
|
end
|
40
45
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
def optional_parameters(*args)
|
46
|
-
accepted_parameters.optional(*args)
|
47
|
-
end
|
48
|
-
|
49
|
-
def default_parameters(*args)
|
50
|
-
accepted_parameters.default(*args)
|
51
|
-
end
|
52
|
-
|
53
|
-
def mutually_exclusive_parameters(*args)
|
54
|
-
accepted_parameters.mutually_exclusive(*args)
|
46
|
+
# Registers this class for use.
|
47
|
+
def register_self
|
48
|
+
register_class(self)
|
55
49
|
end
|
56
50
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
ancestor = ancestors[1..-1].find { |cls|
|
64
|
-
cls.respond_to?(:accepted_parameters)
|
65
|
-
}
|
66
|
-
ancestor_params = ancestor.nil? ? nil : ancestor.accepted_parameters
|
67
|
-
@accepted_parameters = AcceptedParameters.new(ancestor_params)
|
51
|
+
# Registers all subclasses of this class for use
|
52
|
+
def register_subclasses
|
53
|
+
class << self
|
54
|
+
define_method(:inherited) do |subclass|
|
55
|
+
register_class(subclass)
|
56
|
+
end
|
68
57
|
end
|
69
|
-
@accepted_parameters
|
70
58
|
end
|
71
59
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
75
|
-
#-------------
|
76
|
-
private
|
77
|
-
|
78
|
-
def warn_replacement_parameter(params, bad_key, suggested_key)
|
79
|
-
if params.has_parameter?(bad_key)
|
80
|
-
warn ":#{bad_key} is not used with #{self}. " +
|
81
|
-
"You probably want to change this to :#{suggested_key}"
|
82
|
-
end
|
60
|
+
def register_class(class_to_register) #:nodoc:
|
61
|
+
RegisteredClasses.register(class_to_register.name, class_to_register)
|
83
62
|
end
|
84
63
|
|
85
|
-
|
86
|
-
RegisteredClasses.register(name, class_to_register)
|
87
|
-
end
|
64
|
+
private :register_self, :register_subclasses, :register_class
|
88
65
|
end
|
89
66
|
|
90
|
-
optional_parameters :check_offset, :adjust_offset
|
91
|
-
mutually_exclusive_parameters :check_offset, :adjust_offset
|
92
|
-
|
93
67
|
# Creates a new data object.
|
94
68
|
#
|
95
|
-
# +
|
96
|
-
# reference callable objects (methods or procs).
|
97
|
-
#
|
98
|
-
#
|
99
|
-
|
100
|
-
|
69
|
+
# +parameters+ is a hash containing symbol keys. Some parameters may
|
70
|
+
# reference callable objects (methods or procs).
|
71
|
+
#
|
72
|
+
# +parent+ is the parent data object (e.g. struct, array, choice) this
|
73
|
+
# object resides under.
|
74
|
+
def initialize(parameters = {}, parent = nil)
|
75
|
+
@params = Sanitizer.sanitize(parameters, self.class)
|
101
76
|
@parent = parent
|
102
77
|
end
|
103
78
|
|
104
79
|
attr_reader :parent
|
105
80
|
|
106
81
|
# Returns the result of evaluating the parameter identified by +key+.
|
82
|
+
#
|
107
83
|
# +overrides+ is an optional +parameters+ like hash that allow the
|
108
84
|
# parameters given at object construction to be overridden.
|
85
|
+
#
|
109
86
|
# Returns nil if +key+ does not refer to any parameter.
|
110
87
|
def eval_parameter(key, overrides = {})
|
111
88
|
LazyEvaluator.eval(self, get_parameter(key), overrides)
|
@@ -143,7 +120,7 @@ module BinData
|
|
143
120
|
end
|
144
121
|
protected :do_read, :done_read
|
145
122
|
|
146
|
-
# Writes the value for this data to +io+.
|
123
|
+
# Writes the value for this data object to +io+.
|
147
124
|
def write(io)
|
148
125
|
io = BinData::IO.new(io) unless BinData::IO === io
|
149
126
|
|
@@ -157,7 +134,7 @@ module BinData
|
|
157
134
|
end
|
158
135
|
protected :do_write
|
159
136
|
|
160
|
-
# Returns the number of bytes it will take to write this data.
|
137
|
+
# Returns the number of bytes it will take to write this data object.
|
161
138
|
def num_bytes
|
162
139
|
do_num_bytes.ceil
|
163
140
|
end
|
@@ -203,8 +180,8 @@ module BinData
|
|
203
180
|
|
204
181
|
# Returns a user friendly name of this object for debugging purposes.
|
205
182
|
def debug_name
|
206
|
-
if parent
|
207
|
-
parent.debug_name_of(self)
|
183
|
+
if @parent
|
184
|
+
@parent.debug_name_of(self)
|
208
185
|
else
|
209
186
|
"obj"
|
210
187
|
end
|
@@ -212,8 +189,8 @@ module BinData
|
|
212
189
|
|
213
190
|
# Returns the offset of this object wrt to its most distant ancestor.
|
214
191
|
def offset
|
215
|
-
if parent
|
216
|
-
parent.offset + parent.offset_of(self)
|
192
|
+
if @parent
|
193
|
+
@parent.offset + @parent.offset_of(self)
|
217
194
|
else
|
218
195
|
0
|
219
196
|
end
|
@@ -221,8 +198,8 @@ module BinData
|
|
221
198
|
|
222
199
|
# Returns the offset of this object wrt to its parent.
|
223
200
|
def rel_offset
|
224
|
-
if parent
|
225
|
-
parent.offset_of(self)
|
201
|
+
if @parent
|
202
|
+
@parent.offset_of(self)
|
226
203
|
else
|
227
204
|
0
|
228
205
|
end
|
@@ -276,6 +253,11 @@ module BinData
|
|
276
253
|
###########################################################################
|
277
254
|
# To be implemented by subclasses
|
278
255
|
|
256
|
+
# Performs sanity checks on the given parameters. This method converts
|
257
|
+
# the parameters to the form expected by this data object.
|
258
|
+
def self.sanitize_parameters!(parameters, sanitizer) #:nodoc:
|
259
|
+
end
|
260
|
+
|
279
261
|
# Resets the internal state to that of a newly created object.
|
280
262
|
def clear
|
281
263
|
raise NotImplementedError
|
@@ -51,8 +51,8 @@ module BinData
|
|
51
51
|
optional_parameters :initial_value, :value, :check_value
|
52
52
|
mutually_exclusive_parameters :initial_value, :value
|
53
53
|
|
54
|
-
def initialize(
|
55
|
-
super
|
54
|
+
def initialize(parameters = {}, parent = nil)
|
55
|
+
super
|
56
56
|
|
57
57
|
@value = nil
|
58
58
|
@in_read = false
|
@@ -77,8 +77,8 @@ module BinData
|
|
77
77
|
assign(val)
|
78
78
|
end
|
79
79
|
|
80
|
-
def respond_to?(symbol, include_private=false) #:nodoc:
|
81
|
-
|
80
|
+
def respond_to?(symbol, include_private = false) #:nodoc:
|
81
|
+
value.respond_to?(symbol, include_private) || super
|
82
82
|
end
|
83
83
|
|
84
84
|
def method_missing(symbol, *args, &block) #:nodoc:
|
@@ -115,11 +115,7 @@ module BinData
|
|
115
115
|
def trace_value
|
116
116
|
BinData::trace_message do |tracer|
|
117
117
|
value_string = _value.inspect
|
118
|
-
|
119
|
-
value_string = value_string.slice(0 .. 30) + "..."
|
120
|
-
end
|
121
|
-
|
122
|
-
tracer.trace("#{debug_name} => #{value_string}")
|
118
|
+
tracer.trace_obj(debug_name, value_string)
|
123
119
|
end
|
124
120
|
end
|
125
121
|
|
@@ -167,8 +163,8 @@ module BinData
|
|
167
163
|
end
|
168
164
|
|
169
165
|
# The unmodified value of this data object. Note that #value calls this
|
170
|
-
# method. This is so that #value can be overridden in
|
171
|
-
# modify the value.
|
166
|
+
# method. This indirection is so that #value can be overridden in
|
167
|
+
# subclasses to modify the value.
|
172
168
|
def _value
|
173
169
|
# Table of possible preconditions and expected outcome
|
174
170
|
# 1. :value and !in_read -> :value
|
data/lib/bindata/bits.rb
CHANGED
@@ -5,60 +5,63 @@ module BinData
|
|
5
5
|
# The integer is defined by endian and number of bits.
|
6
6
|
|
7
7
|
module BitField #:nodoc: all
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
BinData.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.create_methods(bit_class, nbits, endian)
|
23
|
-
min = 0
|
24
|
-
max = (1 << nbits) - 1
|
25
|
-
clamp = "val = (val < #{min}) ? #{min} : (val > #{max}) ? #{max} : val"
|
8
|
+
class << self
|
9
|
+
def define_class(nbits, endian)
|
10
|
+
name = "Bit#{nbits}"
|
11
|
+
name += "le" if endian == :little
|
12
|
+
unless BinData.const_defined?(name)
|
13
|
+
BinData.module_eval <<-END
|
14
|
+
class #{name} < BinData::BasePrimitive
|
15
|
+
register_self
|
16
|
+
BitField.define_methods(self, #{nbits}, :#{endian})
|
17
|
+
end
|
18
|
+
END
|
19
|
+
end
|
26
20
|
|
27
|
-
|
28
|
-
if nbits == 1
|
29
|
-
clamp = "val = (val == true) ? 1 : (not val) ? 0 : #{clamp}"
|
21
|
+
BinData.const_get(name)
|
30
22
|
end
|
31
23
|
|
32
|
-
define_methods(bit_class, nbits, endian
|
33
|
-
|
24
|
+
def define_methods(bit_class, nbits, endian)
|
25
|
+
bit_class.module_eval <<-END
|
26
|
+
#---------------
|
27
|
+
private
|
34
28
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
29
|
+
def _assign(val)
|
30
|
+
#{create_clamp_code(nbits)}
|
31
|
+
super(val)
|
32
|
+
end
|
39
33
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
34
|
+
def _do_write(io)
|
35
|
+
raise "can't write whilst reading \#{debug_name}" if @in_read
|
36
|
+
io.writebits(_value, #{nbits}, :#{endian})
|
37
|
+
end
|
44
38
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
39
|
+
def _do_num_bytes
|
40
|
+
#{nbits / 8.0}
|
41
|
+
end
|
49
42
|
|
50
|
-
|
51
|
-
|
52
|
-
|
43
|
+
def read_and_return_value(io)
|
44
|
+
io.readbits(#{nbits}, :#{endian})
|
45
|
+
end
|
53
46
|
|
54
|
-
|
55
|
-
|
56
|
-
|
47
|
+
def sensible_default
|
48
|
+
0
|
49
|
+
end
|
50
|
+
END
|
51
|
+
end
|
57
52
|
|
58
|
-
|
59
|
-
|
53
|
+
def create_clamp_code(nbits)
|
54
|
+
min = 0
|
55
|
+
max = (1 << nbits) - 1
|
56
|
+
clamp = "val = (val < #{min}) ? #{min} : (val > #{max}) ? #{max} : val"
|
57
|
+
|
58
|
+
if nbits == 1
|
59
|
+
# allow single bits to be used as booleans
|
60
|
+
"val = (val == true) ? 1 : (not val) ? 0 : #{clamp}"
|
61
|
+
else
|
62
|
+
clamp
|
60
63
|
end
|
61
|
-
|
64
|
+
end
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
data/lib/bindata/choice.rb
CHANGED
@@ -54,7 +54,7 @@ module BinData
|
|
54
54
|
# selection changes. Default is false.
|
55
55
|
class Choice < BinData::Base
|
56
56
|
|
57
|
-
|
57
|
+
register_self
|
58
58
|
|
59
59
|
mandatory_parameters :choices, :selection
|
60
60
|
optional_parameter :copy_on_change
|
@@ -98,8 +98,8 @@ module BinData
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
def initialize(
|
102
|
-
super
|
101
|
+
def initialize(parameters = {}, parent = nil)
|
102
|
+
super
|
103
103
|
|
104
104
|
@choices = {}
|
105
105
|
@last_selection = nil
|
@@ -133,8 +133,8 @@ module BinData
|
|
133
133
|
#
|
134
134
|
# pc.selection = 17
|
135
135
|
# pc #=> "Type2"
|
136
|
-
def selection=(
|
137
|
-
raise NoMethodError
|
136
|
+
def selection=(sel)
|
137
|
+
raise NoMethodError, "See rdoc BinData::Choice.selection= for details"
|
138
138
|
end
|
139
139
|
|
140
140
|
def clear #:nodoc:
|
@@ -146,7 +146,7 @@ module BinData
|
|
146
146
|
end
|
147
147
|
|
148
148
|
def respond_to?(symbol, include_private = false) #:nodoc:
|
149
|
-
|
149
|
+
current_choice.respond_to?(symbol, include_private) || super
|
150
150
|
end
|
151
151
|
|
152
152
|
def method_missing(symbol, *args, &block) #:nodoc:
|
@@ -164,11 +164,7 @@ module BinData
|
|
164
164
|
def trace_selection
|
165
165
|
BinData::trace_message do |tracer|
|
166
166
|
selection_string = eval_parameter(:selection).inspect
|
167
|
-
|
168
|
-
selection_string = selection_string.slice(0 .. 30) + "..."
|
169
|
-
end
|
170
|
-
|
171
|
-
tracer.trace("#{debug_name}-selection- => #{selection_string}")
|
167
|
+
tracer.trace_obj("#{debug_name}-selection-", selection_string)
|
172
168
|
end
|
173
169
|
end
|
174
170
|
|
data/lib/bindata/deprecated.rb
CHANGED
@@ -1,8 +1,23 @@
|
|
1
1
|
module BinData
|
2
|
+
class Base
|
3
|
+
class << self
|
4
|
+
def register(name, class_to_register)
|
5
|
+
if class_to_register == self
|
6
|
+
warn "#{caller[0]} `register(name, class_to_register)' is deprecated as of BinData 1.2.0. Replace with `register_self'"
|
7
|
+
elsif /inherited/ =~ caller[0]
|
8
|
+
warn "#{caller[0]} `def self.inherited(subclass); register(subclass.name, subclass); end' is deprecated as of BinData 1.2.0. Replace with `register_subclasses'"
|
9
|
+
else
|
10
|
+
warn "#{caller[0]} `register(name, class_to_register)' is deprecated as of BinData 1.2.0. Replace with `register_class(class_to_register)'"
|
11
|
+
end
|
12
|
+
register_class(class_to_register)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
2
17
|
class SingleValue
|
3
18
|
class << self
|
4
19
|
def inherited(subclass) #:nodoc:
|
5
|
-
fail "BinData::SingleValue is deprecated. Downgrade to BinData 0.11.1.\nYou will need to make changes to your code before you can use BinData 1.0.0"
|
20
|
+
fail "BinData::SingleValue is deprecated. Downgrade to BinData 0.11.1.\nYou will need to make changes to your code before you can use BinData >= 1.0.0"
|
6
21
|
end
|
7
22
|
end
|
8
23
|
end
|
@@ -10,7 +25,7 @@ module BinData
|
|
10
25
|
class MultiValue
|
11
26
|
class << self
|
12
27
|
def inherited(subclass) #:nodoc:
|
13
|
-
fail "BinData::MultiValue is deprecated. Downgrade to BinData 0.11.1.\nYou will need to make changes to your code before you can use BinData 1.0.0"
|
28
|
+
fail "BinData::MultiValue is deprecated. Downgrade to BinData 0.11.1.\nYou will need to make changes to your code before you can use BinData >= 1.0.0"
|
14
29
|
end
|
15
30
|
end
|
16
31
|
end
|