bindata 0.9.1 → 0.9.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.

@@ -60,7 +60,7 @@ module BinData
60
60
 
61
61
  # Returns a sanitized +params+ that is of the form expected
62
62
  # by #initialize.
63
- def sanitize_parameters(params, endian = nil)
63
+ def sanitize_parameters(sanitizer, params)
64
64
  params = params.dup
65
65
 
66
66
  if params.has_key?(:choices)
@@ -80,12 +80,7 @@ module BinData
80
80
 
81
81
  # collect sanitized choice values
82
82
  type, param = choices[key]
83
- klass = lookup(type, endian)
84
- if klass.nil?
85
- raise TypeError, "unknown type '#{type}' for #{self}"
86
- end
87
- val = [klass, SanitizedParameters.new(klass, param, endian)]
88
- new_choices[key] = val
83
+ new_choices[key] = sanitizer.sanitize(type, param)
89
84
  end
90
85
  params[:choices] = new_choices
91
86
  when ::Array
@@ -94,11 +89,7 @@ module BinData
94
89
  # allow sparse arrays
95
90
  nil
96
91
  else
97
- klass = lookup(type, endian)
98
- if klass.nil?
99
- raise TypeError, "unknown type '#{type}' for #{self}"
100
- end
101
- [klass, SanitizedParameters.new(klass, param, endian)]
92
+ sanitizer.sanitize(type, param)
102
93
  end
103
94
  end
104
95
  params[:choices] = choices
@@ -107,28 +98,7 @@ module BinData
107
98
  end
108
99
  end
109
100
 
110
- super(params, endian)
111
- end
112
-
113
- # Returns all the possible field names a :choice may have.
114
- def all_possible_field_names(sanitized_params)
115
- unless SanitizedParameters === sanitized_params
116
- raise ArgumentError, "parameters aren't sanitized"
117
- end
118
-
119
- choices = sanitized_params[:choices]
120
-
121
- names = []
122
- if ::Array === choices
123
- choices.each do |cklass, cparams|
124
- names.concat(cklass.all_possible_field_names(cparams))
125
- end
126
- elsif ::Hash === choices
127
- choices.values.each do |cklass, cparams|
128
- names.concat(cklass.all_possible_field_names(cparams))
129
- end
130
- end
131
- names
101
+ super(sanitizer, params)
132
102
  end
133
103
  end
134
104
 
@@ -140,15 +110,10 @@ module BinData
140
110
  @last_key = nil
141
111
  end
142
112
 
143
- def_delegators :the_choice, :clear, :clear?, :single_value?, :field_names
144
- def_delegators :the_choice, :snapshot, :done_read
113
+ def_delegators :the_choice, :clear, :clear?, :single_value?
114
+ def_delegators :the_choice, :done_read, :_snapshot
145
115
  def_delegators :the_choice, :_do_read, :_do_write, :_do_num_bytes
146
116
 
147
- # Returns the data object that stores values for +name+.
148
- def find_obj_for_name(name)
149
- field_names.include?(name) ? the_choice.find_obj_for_name(name) : nil
150
- end
151
-
152
117
  # Override to include selected data object.
153
118
  def respond_to?(symbol, include_private = false)
154
119
  super || the_choice.respond_to?(symbol, include_private)
data/lib/bindata/float.rb CHANGED
@@ -63,25 +63,25 @@ module BinData
63
63
 
64
64
 
65
65
  # Single precision floating point number in little endian format
66
- class FloatLe < Single
66
+ class FloatLe < BinData::Single
67
67
  register(self.name, self)
68
68
  Float.create_float_methods(self, true, :little)
69
69
  end
70
70
 
71
71
  # Single precision floating point number in big endian format
72
- class FloatBe < Single
72
+ class FloatBe < BinData::Single
73
73
  register(self.name, self)
74
74
  Float.create_float_methods(self, true, :big)
75
75
  end
76
76
 
77
77
  # Double precision floating point number in little endian format
78
- class DoubleLe < Single
78
+ class DoubleLe < BinData::Single
79
79
  register(self.name, self)
80
80
  Float.create_float_methods(self, false, :little)
81
81
  end
82
82
 
83
83
  # Double precision floating point number in big endian format
84
- class DoubleBe < Single
84
+ class DoubleBe < BinData::Single
85
85
  register(self.name, self)
86
86
  Float.create_float_methods(self, false, :big)
87
87
  end
data/lib/bindata/int.rb CHANGED
@@ -100,85 +100,85 @@ module BinData
100
100
 
101
101
 
102
102
  # Unsigned 1 byte integer.
103
- class Uint8 < Single
103
+ class Uint8 < BinData::Single
104
104
  register(self.name, self)
105
105
  Integer.create_uint_methods(self, 8, :little)
106
106
  end
107
107
 
108
108
  # Unsigned 2 byte little endian integer.
109
- class Uint16le < Single
109
+ class Uint16le < BinData::Single
110
110
  register(self.name, self)
111
111
  Integer.create_uint_methods(self, 16, :little)
112
112
  end
113
113
 
114
114
  # Unsigned 2 byte big endian integer.
115
- class Uint16be < Single
115
+ class Uint16be < BinData::Single
116
116
  register(self.name, self)
117
117
  Integer.create_uint_methods(self, 16, :big)
118
118
  end
119
119
 
120
120
  # Unsigned 4 byte little endian integer.
121
- class Uint32le < Single
121
+ class Uint32le < BinData::Single
122
122
  register(self.name, self)
123
123
  Integer.create_uint_methods(self, 32, :little)
124
124
  end
125
125
 
126
126
  # Unsigned 4 byte big endian integer.
127
- class Uint32be < Single
127
+ class Uint32be < BinData::Single
128
128
  register(self.name, self)
129
129
  Integer.create_uint_methods(self, 32, :big)
130
130
  end
131
131
 
132
132
  # Unsigned 8 byte little endian integer.
133
- class Uint64le < Single
133
+ class Uint64le < BinData::Single
134
134
  register(self.name, self)
135
135
  Integer.create_uint_methods(self, 64, :little)
136
136
  end
137
137
 
138
138
  # Unsigned 8 byte big endian integer.
139
- class Uint64be < Single
139
+ class Uint64be < BinData::Single
140
140
  register(self.name, self)
141
141
  Integer.create_uint_methods(self, 64, :big)
142
142
  end
143
143
 
144
144
  # Signed 1 byte integer.
145
- class Int8 < Single
145
+ class Int8 < BinData::Single
146
146
  register(self.name, self)
147
147
  Integer.create_int_methods(self, 8, :little)
148
148
  end
149
149
 
150
150
  # Signed 2 byte little endian integer.
151
- class Int16le < Single
151
+ class Int16le < BinData::Single
152
152
  register(self.name, self)
153
153
  Integer.create_int_methods(self, 16, :little)
154
154
  end
155
155
 
156
156
  # Signed 2 byte big endian integer.
157
- class Int16be < Single
157
+ class Int16be < BinData::Single
158
158
  register(self.name, self)
159
159
  Integer.create_int_methods(self, 16, :big)
160
160
  end
161
161
 
162
162
  # Signed 4 byte little endian integer.
163
- class Int32le < Single
163
+ class Int32le < BinData::Single
164
164
  register(self.name, self)
165
165
  Integer.create_int_methods(self, 32, :little)
166
166
  end
167
167
 
168
168
  # Signed 4 byte big endian integer.
169
- class Int32be < Single
169
+ class Int32be < BinData::Single
170
170
  register(self.name, self)
171
171
  Integer.create_int_methods(self, 32, :big)
172
172
  end
173
173
 
174
174
  # Signed 8 byte little endian integer.
175
- class Int64le < Single
175
+ class Int64le < BinData::Single
176
176
  register(self.name, self)
177
177
  Integer.create_int_methods(self, 64, :little)
178
178
  end
179
179
 
180
180
  # Signed 8 byte big endian integer.
181
- class Int64be < Single
181
+ class Int64be < BinData::Single
182
182
  register(self.name, self)
183
183
  Integer.create_int_methods(self, 64, :big)
184
184
  end
@@ -16,11 +16,11 @@ module BinData
16
16
  #
17
17
  # int32le :a
18
18
  # int16le :b
19
- # tuple nil
19
+ # tuple :s
20
20
  # end
21
21
  #
22
22
  # obj = SomeDataType.new
23
- # obj.field_names =># ["b", "x", "y", "z"]
23
+ # obj.field_names =># ["b", "s"]
24
24
  #
25
25
  #
26
26
  # == Parameters
@@ -31,10 +31,9 @@ module BinData
31
31
  # <tt>:fields</tt>:: An array specifying the fields for this struct.
32
32
  # Each element of the array is of the form [type, name,
33
33
  # params]. Type is a symbol representing a registered
34
- # type. Name is the name of this field. Name may be
35
- # nil as in the example above. Params is an optional
36
- # hash of parameters to pass to this field when
37
- # instantiating it.
34
+ # type. Name is the name of this field. Params is an
35
+ # optional hash of parameters to pass to this field
36
+ # when instantiating it.
38
37
  # <tt>:hide</tt>:: A list of the names of fields that are to be hidden
39
38
  # from the outside world. Hidden fields don't appear
40
39
  # in #snapshot or #field_names but are still accessible
@@ -42,7 +41,7 @@ module BinData
42
41
  # <tt>:endian</tt>:: Either :little or :big. This specifies the default
43
42
  # endian of any numerics in this struct, or in any
44
43
  # nested data objects.
45
- class MultiValue < Struct
44
+ class MultiValue < BinData::Struct
46
45
 
47
46
  class << self
48
47
  # Register the names of all subclasses of this class.
@@ -68,16 +67,14 @@ module BinData
68
67
  def hide(*args)
69
68
  # note that fields are stored in an instance variable not a class var
70
69
  @hide ||= []
71
- args.each do |name|
72
- next if name.nil?
73
- @hide << name.to_s
74
- end
70
+ @hide.concat(args.collect { |name| name.to_s })
75
71
  @hide
76
72
  end
77
73
 
78
- # Returns all stored fields. Should only be called by #sanitize_parameters
74
+ # Returns all stored fields.
75
+ # Should only be called by #sanitize_parameters
79
76
  def fields
80
- @fields || []
77
+ @fields ||= []
81
78
  end
82
79
 
83
80
  # Used to define fields for this structure.
@@ -85,37 +82,34 @@ module BinData
85
82
  name, params = args
86
83
 
87
84
  type = symbol
88
- name = (name.nil? or name == "") ? nil : name.to_s
85
+ name = name.to_s
89
86
  params ||= {}
90
87
 
91
88
  # note that fields are stored in an instance variable not a class var
92
89
  @fields ||= []
93
90
 
94
91
  # check that type is known
95
- if lookup(type, endian).nil?
92
+ unless Sanitizer.type_exists?(type, endian)
96
93
  raise TypeError, "unknown type '#{type}' for #{self}", caller
97
94
  end
98
95
 
99
- # check that name is okay
100
- if name != nil
101
- # check for duplicate names
102
- @fields.each do |t, n, p|
103
- if n == name
104
- raise SyntaxError, "duplicate field '#{name}' in #{self}", caller
105
- end
96
+ # check for duplicate names
97
+ @fields.each do |t, n, p|
98
+ if n == name
99
+ raise SyntaxError, "duplicate field '#{name}' in #{self}", caller
106
100
  end
101
+ end
107
102
 
108
- # check that name doesn't shadow an existing method
109
- if self.instance_methods.include?(name)
110
- raise NameError.new("", name),
111
- "field '#{name}' shadows an existing method", caller
112
- end
103
+ # check that name doesn't shadow an existing method
104
+ if self.instance_methods.include?(name)
105
+ raise NameError.new("", name),
106
+ "field '#{name}' shadows an existing method", caller
107
+ end
113
108
 
114
- # check that name isn't reserved
115
- if ::Hash.instance_methods.include?(name)
116
- raise NameError.new("", name),
117
- "field '#{name}' is a reserved name", caller
118
- end
109
+ # check that name isn't reserved
110
+ if self::RESERVED.include?(name)
111
+ raise NameError.new("", name),
112
+ "field '#{name}' is a reserved name", caller
119
113
  end
120
114
 
121
115
  # remember this field. These fields will be recalled upon creating
@@ -125,19 +119,18 @@ module BinData
125
119
 
126
120
  # Returns a sanitized +params+ that is of the form expected
127
121
  # by #initialize.
128
- def sanitize_parameters(params, endian = nil)
122
+ def sanitize_parameters(sanitizer, params)
129
123
  params = params.dup
130
124
 
131
- # possibly override endian
132
- endian = params[:endian] || self.endian || endian
133
- unless endian.nil?
134
- params[:endian] = endian
135
- end
125
+ endian = params[:endian] || self.endian
126
+ fields = params[:fields] || self.fields
127
+ hide = params[:hide] || self.hide
136
128
 
137
- params[:fields] = params[:fields] || self.fields
138
- params[:hide] = params[:hide] || self.hide
129
+ params[:endian] = endian unless endian.nil?
130
+ params[:fields] = fields
131
+ params[:hide] = hide
139
132
 
140
- super(params, endian)
133
+ super(sanitizer, params)
141
134
  end
142
135
  end
143
136
  end
data/lib/bindata/rest.rb CHANGED
@@ -15,7 +15,7 @@ module BinData
15
15
  # obj.a #=> "abcde"
16
16
  # obj.rest #=" "fghij"
17
17
  #
18
- class Rest < Single
18
+ class Rest < BinData::Single
19
19
 
20
20
  # Register this class
21
21
  register(self.name, self)
@@ -1,6 +1,91 @@
1
1
  require 'forwardable'
2
2
 
3
3
  module BinData
4
+ class Sanitizer
5
+ class << self
6
+ # Sanitize +params+ for +obj+.
7
+ # Returns sanitized parameters.
8
+ def sanitize(obj, params)
9
+ sanitizer = self.new
10
+ klass, new_params = sanitizer.sanitize(obj.class, params)
11
+ new_params
12
+ end
13
+
14
+ # Returns true if +type+ is registered.
15
+ def type_exists?(type, endian = nil)
16
+ lookup(type, endian) != nil
17
+ end
18
+
19
+ # Returns the class matching a previously registered +name+.
20
+ def lookup(name, endian)
21
+ name = name.to_s
22
+ klass = Registry.instance.lookup(name)
23
+ if klass.nil? and endian != nil
24
+ # lookup failed so attempt endian lookup
25
+ if /^u?int\d{1,3}$/ =~ name
26
+ new_name = name + ((endian == :little) ? "le" : "be")
27
+ klass = Registry.instance.lookup(new_name)
28
+ elsif ["float", "double"].include?(name)
29
+ new_name = name + ((endian == :little) ? "_le" : "_be")
30
+ klass = Registry.instance.lookup(new_name)
31
+ end
32
+ end
33
+ klass
34
+ end
35
+ end
36
+
37
+ # Create a new Sanitizer.
38
+ def initialize
39
+ @seen = []
40
+ @endian = nil
41
+ end
42
+
43
+ # Executes the given block with +endian+ set as the current endian.
44
+ def with_endian(endian, &block)
45
+ if endian != nil
46
+ saved_endian = @endian
47
+ @endian = endian
48
+ yield
49
+ @endian = saved_endian
50
+ else
51
+ yield
52
+ end
53
+ end
54
+
55
+ # Sanitizes +params+ for +type+.
56
+ # Returns [klass, sanitized_params]
57
+ def sanitize(type, params)
58
+ if Class === type
59
+ klass = type
60
+ else
61
+ klass = self.class.lookup(type, @endian)
62
+ raise TypeError, "unknown type '#{type}'" if klass.nil?
63
+ end
64
+
65
+ params ||= {}
66
+ if @seen.include?(klass)
67
+ # This klass is defined recursively. Remember the current endian
68
+ # and delay sanitizing the parameters until later.
69
+ if @endian != nil and klass.accepted_parameters.include?(:endian) and
70
+ not params.has_key?(:endian)
71
+ params = params.dup
72
+ params[:endian] = @endian
73
+ end
74
+ else
75
+ # subclasses of MultiValue may be defined recursively
76
+ # TODO: define a class field instead
77
+ possibly_recursive = (BinData.const_defined?(:MultiValue) and
78
+ klass.ancestors.include?(BinData.const_get(:MultiValue)))
79
+ @seen.push klass if possibly_recursive
80
+
81
+ new_params = klass.sanitize_parameters(self, params)
82
+ params = SanitizedParameters.new(klass, new_params)
83
+ end
84
+
85
+ [klass, params]
86
+ end
87
+ end
88
+
4
89
  # A BinData object accepts arbitrary parameters. This class ensures that
5
90
  # the parameters have been sanitized, and categorizes them according to
6
91
  # whether they are BinData::Base.accepted_parameters or are extra.
@@ -8,9 +93,8 @@ module BinData
8
93
  extend Forwardable
9
94
 
10
95
  # Sanitize the given parameters.
11
- def initialize(klass, params, *args)
12
- params ||= {}
13
- @hash = klass.sanitize_parameters(params, *args)
96
+ def initialize(klass, params)
97
+ @hash = params
14
98
  @accepted_parameters = {}
15
99
  @extra_parameters = {}
16
100
 
@@ -34,3 +118,4 @@ module BinData
34
118
  def_delegators :@hash, :[], :has_key?, :include?, :keys
35
119
  end
36
120
  end
121
+