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.

Files changed (47) hide show
  1. data/ChangeLog +7 -0
  2. data/README +32 -1167
  3. data/lib/bindata.rb +3 -3
  4. data/lib/bindata/array.rb +5 -6
  5. data/lib/bindata/base.rb +40 -58
  6. data/lib/bindata/base_primitive.rb +7 -11
  7. data/lib/bindata/bits.rb +47 -44
  8. data/lib/bindata/choice.rb +7 -11
  9. data/lib/bindata/deprecated.rb +17 -2
  10. data/lib/bindata/dsl.rb +332 -0
  11. data/lib/bindata/float.rb +48 -50
  12. data/lib/bindata/int.rb +66 -88
  13. data/lib/bindata/params.rb +112 -59
  14. data/lib/bindata/primitive.rb +8 -88
  15. data/lib/bindata/record.rb +11 -99
  16. data/lib/bindata/registry.rb +16 -3
  17. data/lib/bindata/rest.rb +1 -1
  18. data/lib/bindata/sanitize.rb +71 -53
  19. data/lib/bindata/skip.rb +2 -1
  20. data/lib/bindata/string.rb +3 -3
  21. data/lib/bindata/stringz.rb +1 -1
  22. data/lib/bindata/struct.rb +21 -20
  23. data/lib/bindata/trace.rb +8 -0
  24. data/lib/bindata/wrapper.rb +13 -69
  25. data/manual.haml +2 -2
  26. data/spec/array_spec.rb +1 -1
  27. data/spec/base_primitive_spec.rb +4 -4
  28. data/spec/base_spec.rb +19 -6
  29. data/spec/bits_spec.rb +5 -1
  30. data/spec/choice_spec.rb +13 -2
  31. data/spec/deprecated_spec.rb +31 -0
  32. data/spec/example.rb +5 -1
  33. data/spec/io_spec.rb +2 -4
  34. data/spec/lazy_spec.rb +10 -5
  35. data/spec/primitive_spec.rb +13 -5
  36. data/spec/record_spec.rb +149 -45
  37. data/spec/registry_spec.rb +18 -6
  38. data/spec/spec_common.rb +31 -6
  39. data/spec/string_spec.rb +0 -1
  40. data/spec/stringz_spec.rb +4 -4
  41. data/spec/struct_spec.rb +2 -2
  42. data/spec/system_spec.rb +26 -19
  43. data/spec/wrapper_spec.rb +52 -4
  44. data/tasks/manual.rake +1 -1
  45. data/tasks/pkg.rake +13 -0
  46. metadata +121 -46
  47. data/TODO +0 -3
@@ -1,5 +1,5 @@
1
1
  # BinData -- Binary data manipulator.
2
- # Copyright (c) 2007 - 2009 Dion Mendel.
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 - 2009 Dion Mendel.
31
+ # Copyright (c) 2007 - 2010 Dion Mendel.
32
32
  module BinData
33
- VERSION = "1.1.0"
33
+ VERSION = "1.2.0"
34
34
  end
@@ -54,7 +54,7 @@ module BinData
54
54
  class Array < BinData::Base
55
55
  include Enumerable
56
56
 
57
- register(self.name, self)
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(params, :read_length, :initial_length)
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(params = {}, parent = nil)
82
- super(params, parent)
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
@@ -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 params are:
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
- def mandatory_parameters(*args)
42
- accepted_parameters.mandatory(*args)
43
- end
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
- alias_method :mandatory_parameter, :mandatory_parameters
58
- alias_method :optional_parameter, :optional_parameters
59
- alias_method :default_parameter, :default_parameters
60
-
61
- def accepted_parameters
62
- unless defined? @accepted_parameters
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 sanitize_parameters!(params, sanitizer) #:nodoc:
73
- end
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
- def register(name, class_to_register)
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
- # +params+ is a hash containing symbol keys. Some params may
96
- # reference callable objects (methods or procs). +parent+ is the
97
- # parent data object (e.g. struct, array, choice) this object resides
98
- # under.
99
- def initialize(params = {}, parent = nil)
100
- @params = Sanitizer.sanitize(params, self.class)
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(params = {}, parent = nil)
55
- super(params, parent)
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
- super || value.respond_to?(symbol, include_private)
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
- if value_string.length > 30
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 subclasses to
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
@@ -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
- def self.define_class(nbits, endian)
9
- name = "Bit#{nbits}"
10
- name += "le" if endian == :little
11
- unless BinData.const_defined?(name)
12
- BinData.module_eval <<-END
13
- class #{name} < BinData::BasePrimitive
14
- register(self.name, self)
15
- BitField.create_methods(self, #{nbits}, :#{endian.to_s})
16
- end
17
- END
18
- end
19
- BinData.const_get(name)
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
- # allow single bits to be used as booleans
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.to_s, clamp)
33
- end
24
+ def define_methods(bit_class, nbits, endian)
25
+ bit_class.module_eval <<-END
26
+ #---------------
27
+ private
34
28
 
35
- def self.define_methods(bit_class, nbits, endian, clamp)
36
- bit_class.module_eval <<-END
37
- #---------------
38
- private
29
+ def _assign(val)
30
+ #{create_clamp_code(nbits)}
31
+ super(val)
32
+ end
39
33
 
40
- def _assign(val)
41
- #{clamp}
42
- super(val)
43
- end
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
- def _do_write(io)
46
- raise "can't write whilst reading \#{debug_name}" if @in_read
47
- io.writebits(_value, #{nbits}, :#{endian})
48
- end
39
+ def _do_num_bytes
40
+ #{nbits / 8.0}
41
+ end
49
42
 
50
- def _do_num_bytes
51
- #{nbits} / 8.0
52
- end
43
+ def read_and_return_value(io)
44
+ io.readbits(#{nbits}, :#{endian})
45
+ end
53
46
 
54
- def read_and_return_value(io)
55
- io.readbits(#{nbits}, :#{endian})
56
- end
47
+ def sensible_default
48
+ 0
49
+ end
50
+ END
51
+ end
57
52
 
58
- def sensible_default
59
- 0
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
- END
64
+ end
62
65
  end
63
66
  end
64
67
 
@@ -54,7 +54,7 @@ module BinData
54
54
  # selection changes. Default is false.
55
55
  class Choice < BinData::Base
56
56
 
57
- register(self.name, self)
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(params = {}, parent = nil)
102
- super(params, parent)
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=(v)
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
- super || current_choice.respond_to?(symbol, include_private)
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
- if selection_string.length > 30
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
 
@@ -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