bindata 1.3.1 → 1.4.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.

@@ -35,15 +35,12 @@ module BinData
35
35
  end
36
36
 
37
37
  class << self
38
+ def register_self
39
+ warn "#{caller[0]} `register_self' is no longer needed as of BinData 1.3.2. You can delete this line"
40
+ end
41
+
38
42
  def register(name, class_to_register)
39
- if class_to_register == self
40
- warn "#{caller[0]} `register(name, class_to_register)' is deprecated as of BinData 1.2.0. Replace with `register_self'"
41
- elsif /inherited/ =~ caller[0]
42
- warn "#{caller[0]} `def self.inherited(subclass); register(subclass.name, subclass); end' is deprecated as of BinData 1.2.0. Replace with `register_subclasses'"
43
- else
44
- warn "#{caller[0]} `register(name, class_to_register)' is deprecated as of BinData 1.2.0. Replace with `register_class(class_to_register)'"
45
- end
46
- register_class(class_to_register)
43
+ warn "#{caller[0]} `register' is no longer needed as of BinData 1.3.2. You can delete this line"
47
44
  end
48
45
  end
49
46
 
data/lib/bindata/dsl.rb CHANGED
@@ -5,20 +5,13 @@ module BinData
5
5
  end
6
6
 
7
7
  module ClassMethods
8
- # Defines the DSL Parser for this BinData object. Allowed +args+ are:
9
- #
10
- # [<tt>:only_one_field</tt>] Only one field may be declared.
11
- # [<tt>:multiple_fields</tt>] Multiple fields may be declared.
12
- # [<tt>:hidden_fields</tt>] Hidden fields are allowed.
13
- # [<tt>:sanitize_fields</tt>] Fields are to be sanitized.
14
- # [<tt>:mandatory_fieldnames</tt>] Fieldnames are mandatory.
15
- # [<tt>:optional_fieldnames</tt>] Fieldnames are optional.
16
- # [<tt>:fieldnames_for_choices</tt>] Fieldnames are choice keys.
17
- # [<tt>:no_fieldnames</tt>] Fieldnames are prohibited.
18
- # [<tt>:all_or_none_fieldnames</tt>] All fields must have names, or
19
- # none may have names.
20
- def dsl_parser(*args)
21
- @dsl_parser ||= DSLParser.new(self, *args)
8
+
9
+ def dsl_parser(parser_type = nil)
10
+ unless defined? @dsl_parser
11
+ parser_type = superclass.dsl_parser.parser_type if parser_type.nil?
12
+ @dsl_parser = DSLParser.new(self, parser_type)
13
+ end
14
+ @dsl_parser
22
15
  end
23
16
 
24
17
  def method_missing(symbol, *args, &block) #:nodoc:
@@ -30,39 +23,6 @@ module BinData
30
23
  def to_str; nil; end
31
24
  end
32
25
 
33
- # An array containing a field definition of the form
34
- # expected by BinData::Struct.
35
- class UnSanitizedField < ::Array
36
- def initialize(type, name, params)
37
- super()
38
- self << type << name << params
39
- end
40
- def type
41
- self[0]
42
- end
43
- def name
44
- self[1]
45
- end
46
- def params
47
- self[2]
48
- end
49
- def to_type_params
50
- [self.type, self.params]
51
- end
52
- end
53
-
54
- class UnSanitizedFields < ::Array
55
- def field_names
56
- collect { |f| f.name }
57
- end
58
-
59
- def add_field(type, name, params, endian)
60
- normalized_endian = endian.respond_to?(:endian) ? endian.endian : endian
61
- normalized_type = RegisteredClasses.normalize_name(type, normalized_endian)
62
- self << UnSanitizedField.new(normalized_type, name, params)
63
- end
64
- end
65
-
66
26
  # A DSLParser parses and accumulates field definitions of the form
67
27
  #
68
28
  # type name, params
@@ -73,35 +33,19 @@ module BinData
73
33
  # * +params+ is a hash containing any parameters
74
34
  #
75
35
  class DSLParser
76
- def initialize(the_class, *options)
77
- @the_class = the_class
78
-
79
- @options = parent_options_plus_these(options)
80
-
81
- @endian = parent_attribute(:endian, nil)
82
-
83
- if option?(:hidden_fields)
84
- @hide = parent_attribute(:hide, []).dup
85
- end
86
-
87
- if option?(:sanitize_fields)
88
- fields = parent_attribute(:fields, nil)
89
- @fields = Sanitizer.new.create_sanitized_fields(fields)
90
- else
91
- fields = parent_attribute(:fields, UnSanitizedFields.new)
92
- @fields = fields.dup
93
- end
36
+ def initialize(the_class, parser_type)
37
+ @the_class = the_class
38
+ @parser_type = parser_type
39
+ @endian = parent_attribute(:endian, nil)
94
40
  end
95
41
 
96
- attr_reader :options
42
+ attr_reader :parser_type
97
43
 
98
44
  def endian(endian = nil)
99
45
  if endian.nil?
100
46
  @endian
101
- elsif endian.respond_to? :endian
47
+ elsif endian == :big or endian == :little
102
48
  @endian = endian
103
- elsif [:little, :big].include?(endian)
104
- @endian = Sanitizer.new.create_sanitized_endian(endian)
105
49
  else
106
50
  dsl_raise ArgumentError, "unknown value for endian '#{endian}'"
107
51
  end
@@ -115,29 +59,42 @@ module BinData
115
59
  end
116
60
  name.to_sym
117
61
  end
62
+
63
+ unless defined? @hide
64
+ @hide = parent_attribute(:hide, []).dup
65
+ end
66
+
118
67
  @hide.concat(hidden.compact)
119
68
  @hide
120
69
  end
121
70
  end
122
71
 
123
72
  def fields
124
- @fields
125
- end
73
+ unless defined? @fields
74
+ fields = parent_attribute(:fields, nil)
75
+ klass = option?(:sanitize_fields) ? SanitizedFields : UnSanitizedFields
76
+ @fields = klass.new(endian)
77
+ @fields.copy_fields(fields) if fields
78
+ end
126
79
 
127
- def field
128
- @fields[0]
80
+ @fields
129
81
  end
130
82
 
131
- def to_struct_params
132
- result = {:fields => fields}
133
- if not endian.nil?
134
- result[:endian] = endian
135
- end
136
- if option?(:hidden_fields) and not hide.empty?
137
- result[:hide] = hide
83
+ def dsl_params
84
+ case @parser_type
85
+ when :struct
86
+ to_struct_params
87
+ when :array
88
+ to_array_params
89
+ when :choice
90
+ to_choice_params
91
+ when :primitive
92
+ to_struct_params
93
+ when :wrapper
94
+ raise "Wrapper is deprecated"
95
+ else
96
+ raise "unknown parser type #{@parser_type}"
138
97
  end
139
-
140
- result
141
98
  end
142
99
 
143
100
  def method_missing(symbol, *args, &block) #:nodoc:
@@ -151,15 +108,25 @@ module BinData
151
108
  #-------------
152
109
  private
153
110
 
154
- def dsl_raise(exception, message)
155
- backtrace = caller
156
- backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
157
-
158
- raise exception, message + " in #{@the_class}", backtrace
159
- end
160
-
161
111
  def option?(opt)
162
- @options.include?(opt)
112
+ options.include?(opt)
113
+ end
114
+
115
+ def options
116
+ case @parser_type
117
+ when :struct
118
+ [:multiple_fields, :optional_fieldnames, :sanitize_fields, :hidden_fields]
119
+ when :array
120
+ [:multiple_fields, :optional_fieldnames, :sanitize_fields]
121
+ when :choice
122
+ [:multiple_fields, :all_or_none_fieldnames, :sanitize_fields, :fieldnames_are_values]
123
+ when :primitive
124
+ [:multiple_fields, :optional_fieldnames, :sanitize_fields]
125
+ when :wrapper
126
+ [:only_one_field, :no_fieldnames]
127
+ else
128
+ raise "unknown parser type #{parser_type}"
129
+ end
163
130
  end
164
131
 
165
132
  def parent_attribute(attr, default = nil)
@@ -171,40 +138,20 @@ module BinData
171
138
  end
172
139
  end
173
140
 
174
- def parent_options_plus_these(options)
175
- result = parent_attribute(:options, []).dup
176
-
177
- mutexes = [
178
- [:only_one_field, :multiple_fields],
179
- [:mandatory_fieldnames, :optional_fieldnames, :no_fieldnames, :all_or_none_fieldnames]
180
- ]
181
-
182
- options.each do |opt|
183
- mutexes.each do |mutex|
184
- if mutex.include?(opt)
185
- result -= mutex
186
- end
187
- end
188
-
189
- result << opt
190
- end
191
-
192
- result
193
- end
194
-
195
141
  def name_from_field_declaration(args)
196
142
  name, params = args
197
- name = "" if name.nil? or name.is_a?(Hash)
198
- name = name.to_s if name.is_a?(Symbol)
199
-
200
- name
143
+ if name == "" or name.is_a?(Hash)
144
+ nil
145
+ else
146
+ name
147
+ end
201
148
  end
202
149
 
203
150
  def params_from_field_declaration(type, args, &block)
204
151
  params = params_from_args(args)
205
152
 
206
- if block_given? and BlockParsers.has_key?(type)
207
- params.merge(BlockParsers[type].extract_params(endian, &block))
153
+ if block_given?
154
+ params.merge(params_from_block(type, &block))
208
155
  else
209
156
  params
210
157
  end
@@ -217,32 +164,56 @@ module BinData
217
164
  params || {}
218
165
  end
219
166
 
220
- def append_field(type, name, params)
221
- if too_many_fields?
222
- dsl_raise SyntaxError, "attempting to wrap more than one type"
167
+ def params_from_block(type, &block)
168
+ bindata_classes = {
169
+ :array => BinData::Array,
170
+ :choice => BinData::Choice,
171
+ :struct => BinData::Struct
172
+ }
173
+
174
+ if bindata_classes.include?(type)
175
+ parser = DSLParser.new(bindata_classes[type], type)
176
+ parser.endian(endian)
177
+ parser.instance_eval(&block)
178
+
179
+ parser.dsl_params
180
+ else
181
+ {}
223
182
  end
183
+ end
224
184
 
225
- ensure_valid_name(name)
185
+ def append_field(type, name, params)
186
+ ensure_valid_field(name)
226
187
 
227
- fields.add_field(type, name, params, endian)
188
+ fields.add_field(type, name, params)
189
+ rescue ArgumentError => err
190
+ dsl_raise ArgumentError, err.message
228
191
  rescue UnRegisteredTypeError => err
229
192
  dsl_raise TypeError, "unknown type '#{err.message}'"
230
193
  end
231
194
 
232
- def ensure_valid_name(name)
233
- if must_not_have_a_name_failed?(name)
195
+ def ensure_valid_field(field_name)
196
+ if too_many_fields?
197
+ dsl_raise SyntaxError, "attempting to wrap more than one type"
198
+ end
199
+
200
+ if must_not_have_a_name_failed?(field_name)
234
201
  dsl_raise SyntaxError, "field must not have a name"
235
202
  end
236
203
 
237
- if all_or_none_names_failed?(name)
204
+ if all_or_none_names_failed?(field_name)
238
205
  dsl_raise SyntaxError, "fields must either all have names, or none must have names"
239
206
  end
240
207
 
241
- if must_have_a_name_failed?(name)
208
+ if must_have_a_name_failed?(field_name)
242
209
  dsl_raise SyntaxError, "field must have a name"
243
210
  end
244
211
 
245
- unless option?(:fieldnames_for_choices)
212
+ ensure_valid_name(field_name)
213
+ end
214
+
215
+ def ensure_valid_name(name)
216
+ if name and not option?(:fieldnames_are_values)
246
217
  if malformed_name?(name)
247
218
  dsl_raise NameError.new("", name), "field '#{name}' is an illegal fieldname"
248
219
  end
@@ -266,89 +237,115 @@ module BinData
266
237
  end
267
238
 
268
239
  def must_not_have_a_name_failed?(name)
269
- option?(:no_fieldnames) and name != ""
240
+ option?(:no_fieldnames) and name != nil
270
241
  end
271
242
 
272
243
  def must_have_a_name_failed?(name)
273
- option?(:mandatory_fieldnames) and name == ""
244
+ option?(:mandatory_fieldnames) and name.nil?
274
245
  end
275
246
 
276
247
  def all_or_none_names_failed?(name)
277
248
  if option?(:all_or_none_fieldnames) and not fields.empty?
278
- all_names_blank = fields.field_names.all? { |n| n == "" }
279
- no_names_blank = fields.field_names.all? { |n| n != "" }
249
+ all_names_blank = fields.all_field_names_blank?
250
+ no_names_blank = fields.no_field_names_blank?
280
251
 
281
- (name != "" and all_names_blank) or (name == "" and no_names_blank)
252
+ (name != nil and all_names_blank) or (name == nil and no_names_blank)
282
253
  else
283
254
  false
284
255
  end
285
256
  end
286
257
 
287
258
  def malformed_name?(name)
288
- name != "" and /^[a-z_]\w*$/ !~ name
259
+ /^[a-z_]\w*$/ !~ name.to_s
289
260
  end
290
261
 
291
262
  def duplicate_name?(name)
292
- name != "" and fields.field_names.include?(name)
263
+ fields.has_field_name?(name)
293
264
  end
294
265
 
295
266
  def name_shadows_method?(name)
296
- name != "" and @the_class.method_defined?(name)
267
+ @the_class.method_defined?(name)
297
268
  end
298
269
 
299
270
  def name_is_reserved?(name)
300
- name != "" and BinData::Struct::RESERVED.include?(name)
271
+ BinData::Struct::RESERVED.include?(name.to_sym)
301
272
  end
302
- end
303
273
 
304
- class StructBlockParser
305
- def self.extract_params(endian, &block)
306
- parser = DSLParser.new(BinData::Struct, :multiple_fields, :optional_fieldnames, :hidden_fields)
307
- parser.endian endian
308
- parser.instance_eval(&block)
274
+ def dsl_raise(exception, message)
275
+ backtrace = caller
276
+ backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
309
277
 
310
- parser.to_struct_params
278
+ raise exception, message + " in #{@the_class}", backtrace
311
279
  end
312
- end
313
280
 
314
- class ArrayBlockParser
315
- def self.extract_params(endian, &block)
316
- parser = DSLParser.new(BinData::Array, :multiple_fields, :optional_fieldnames)
317
- parser.endian endian
318
- parser.instance_eval(&block)
319
-
320
- if parser.fields.length == 1
321
- {:type => parser.field.to_type_params}
281
+ def to_array_params
282
+ case fields.length
283
+ when 0
284
+ {}
285
+ when 1
286
+ {:type => fields[0].prototype}
322
287
  else
323
- {:type => [:struct, parser.to_struct_params]}
288
+ {:type => [:struct, to_struct_params]}
324
289
  end
325
290
  end
326
- end
327
291
 
328
- class ChoiceBlockParser
329
- def self.extract_params(endian, &block)
330
- parser = DSLParser.new(BinData::Choice, :multiple_fields, :all_or_none_fieldnames, :fieldnames_for_choices)
331
- parser.endian endian
332
- parser.instance_eval(&block)
333
-
334
- if all_blank?(parser.fields.field_names)
335
- {:choices => parser.fields.collect { |f| f.to_type_params }}
292
+ def to_choice_params
293
+ if fields.length == 0
294
+ {}
295
+ elsif fields.all_field_names_blank?
296
+ {:choices => fields.collect { |f| f.prototype }}
336
297
  else
337
298
  choices = {}
338
- parser.fields.each { |f| choices[f.name] = f.to_type_params }
299
+ fields.each { |f| choices[f.name] = f.prototype }
339
300
  {:choices => choices}
340
301
  end
341
302
  end
342
303
 
343
- def self.all_blank?(array)
344
- array.all? { |el| el == "" }
304
+ def to_struct_params
305
+ result = {:fields => fields}
306
+ if not endian.nil?
307
+ result[:endian] = endian
308
+ end
309
+ if option?(:hidden_fields) and not hide.empty?
310
+ result[:hide] = hide
311
+ end
312
+
313
+ result
314
+ end
315
+ end
316
+
317
+ # An array containing a field definition of the form
318
+ # expected by BinData::Struct.
319
+ class UnSanitizedField < ::Array
320
+ def initialize(type, name, params)
321
+ super()
322
+ self << type << name << params
323
+ end
324
+ def type
325
+ self[0]
326
+ end
327
+ def name
328
+ self[1]
329
+ end
330
+ def params
331
+ self[2]
345
332
  end
346
333
  end
347
334
 
348
- BlockParsers = {
349
- :struct => StructBlockParser,
350
- :array => ArrayBlockParser,
351
- :choice => ChoiceBlockParser,
352
- }
335
+ class UnSanitizedFields < ::Array
336
+ def initialize(endian)
337
+ @endian = endian
338
+ end
339
+
340
+ def add_field(type, name, params)
341
+ normalized_endian = @endian.respond_to?(:endian) ? @endian.endian : @endian
342
+ normalized_type = RegisteredClasses.normalize_name(type, normalized_endian)
343
+ self << UnSanitizedField.new(normalized_type, name, params)
344
+ end
345
+
346
+ def copy_fields(other)
347
+ concat(other)
348
+ end
349
+ end
353
350
  end
354
351
  end