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.

data/lib/bindata/skip.rb CHANGED
@@ -25,8 +25,6 @@ module BinData
25
25
  #
26
26
  class Skip < BinData::BasePrimitive
27
27
 
28
- register_self
29
-
30
28
  mandatory_parameter :length
31
29
 
32
30
  #---------------
@@ -47,8 +47,6 @@ module BinData
47
47
  # not be trimmed when writing.
48
48
  class String < BinData::BasePrimitive
49
49
 
50
- register_self
51
-
52
50
  optional_parameters :read_length, :length, :trim_padding
53
51
  default_parameters :pad_char => "\0"
54
52
  mutually_exclusive_parameters :read_length, :length
@@ -56,7 +54,7 @@ module BinData
56
54
 
57
55
  class << self
58
56
 
59
- def sanitize_parameters!(params, sanitizer) #:nodoc:
57
+ def sanitize_parameters!(params) #:nodoc:
60
58
  params.warn_replacement_parameter(:initial_length, :read_length)
61
59
 
62
60
  if params.has_parameter?(:pad_char)
@@ -97,6 +95,8 @@ module BinData
97
95
  private
98
96
 
99
97
  def clamp_to_length(str)
98
+ str.force_encoding(Encoding::BINARY) if RUBY_VERSION >= "1.9"
99
+
100
100
  len = eval_parameter(:length) || str.length
101
101
  if str.length == len
102
102
  str
@@ -26,8 +26,6 @@ module BinData
26
26
  # byte.
27
27
  class Stringz < BinData::BasePrimitive
28
28
 
29
- register_self
30
-
31
29
  optional_parameters :max_length
32
30
 
33
31
  def assign(val)
@@ -69,6 +67,8 @@ module BinData
69
67
  end
70
68
 
71
69
  def trim_and_zero_terminate(str)
70
+ str.force_encoding(Encoding::BINARY) if RUBY_VERSION >= "1.9"
71
+
72
72
  str = truncate_after_first_zero_byte(str)
73
73
  str = trim_to(str, eval_parameter(:max_length))
74
74
  append_zero_byte_if_needed(str)
@@ -52,57 +52,46 @@ module BinData
52
52
  # calls to #read, #write, #num_bytes or #snapshot.
53
53
  class Struct < BinData::Base
54
54
 
55
- register_self
56
-
57
55
  mandatory_parameter :fields
58
56
  optional_parameters :endian, :hide
59
57
 
60
58
  # These reserved words may not be used as field names
61
59
  RESERVED = Hash[*
62
- (::Hash.instance_methods.collect { |meth| meth.to_s } +
60
+ (Hash.instance_methods +
63
61
  %w{alias and begin break case class def defined do else elsif
64
62
  end ensure false for if in module next nil not or redo
65
63
  rescue retry return self super then true undef unless until
66
64
  when while yield} +
67
- %w{array element index value} ).
65
+ %w{array element index value} ).collect { |name| name.to_sym }.
68
66
  uniq.collect { |key| [key, true] }.flatten
69
67
  ]
70
68
 
71
- # A hash that can be accessed via attributes.
72
- class Snapshot < Hash #:nodoc:
73
- def respond_to?(symbol, include_private = false)
74
- has_key?(symbol.to_s) || super
75
- end
76
-
77
- def method_missing(symbol, *args)
78
- self[symbol.to_s] || super
79
- end
80
- end
81
-
82
69
  class << self
83
70
 
84
- def sanitize_parameters!(params, sanitizer) #:nodoc:
85
- sanitize_endian(params, sanitizer)
86
- sanitize_fields(params, sanitizer)
87
- sanitize_hide(params, sanitizer)
71
+ def sanitize_parameters!(params) #:nodoc:
72
+ sanitize_endian(params)
73
+ sanitize_fields(params)
74
+ sanitize_hide(params)
88
75
  end
89
76
 
90
77
  #-------------
91
78
  private
92
79
 
93
- def sanitize_endian(params, sanitizer)
80
+ def sanitize_endian(params)
94
81
  if params.needs_sanitizing?(:endian)
95
- params[:endian] = sanitizer.create_sanitized_endian(params[:endian])
82
+ endian = params.create_sanitized_endian(params[:endian])
83
+ params[:endian] = endian
84
+ params.endian = endian # sync params[:endian] and params.endian
96
85
  end
97
86
  end
98
87
 
99
- def sanitize_fields(params, sanitizer)
88
+ def sanitize_fields(params)
100
89
  if params.needs_sanitizing?(:fields)
101
90
  fields = params[:fields]
102
91
 
103
- params[:fields] = sanitizer.create_sanitized_fields
92
+ params[:fields] = params.create_sanitized_fields
104
93
  fields.each do |ftype, fname, fparams|
105
- params[:fields].add_field(ftype, fname, fparams, params[:endian])
94
+ params[:fields].add_field(ftype, fname, fparams)
106
95
  end
107
96
 
108
97
  field_names = sanitized_field_names(params[:fields])
@@ -110,7 +99,7 @@ module BinData
110
99
  end
111
100
  end
112
101
 
113
- def sanitize_hide(params, sanitizer)
102
+ def sanitize_hide(params)
114
103
  if params.needs_sanitizing?(:hide) and params.has_parameter?(:fields)
115
104
  field_names = sanitized_field_names(params[:fields])
116
105
  hfield_names = hidden_field_names(params[:hide])
@@ -128,7 +117,7 @@ module BinData
128
117
  unless Symbol === h
129
118
  warn "Hidden field '#{h}' should be provided as a symbol. Using strings is deprecated"
130
119
  end
131
- h.to_s # TODO: change this to sym
120
+ h.to_sym
132
121
  end
133
122
  end
134
123
 
@@ -170,11 +159,11 @@ module BinData
170
159
 
171
160
  def assign(val)
172
161
  clear
173
- assign_fields(as_snapshot(val))
162
+ assign_fields(val)
174
163
  end
175
164
 
176
165
  def snapshot
177
- snapshot = Snapshot.new
166
+ snapshot = Snapshot.new(field_names)
178
167
  field_names.each do |name|
179
168
  obj = find_obj_for_name(name)
180
169
  snapshot[name] = obj.snapshot if include_obj(obj)
@@ -191,11 +180,11 @@ module BinData
191
180
  else
192
181
  hidden = get_parameter(:hide) || []
193
182
  @field_names.compact - hidden
194
- end
183
+ end.collect { |x| x.to_s }
195
184
  end
196
185
 
197
186
  def respond_to?(symbol, include_private = false) #:nodoc:
198
- field_names(true).include?(symbol.to_s.chomp("=")) || super
187
+ @field_names.include?(base_field_name(symbol)) || super
199
188
  end
200
189
 
201
190
  def method_missing(symbol, *args, &block) #:nodoc:
@@ -233,9 +222,28 @@ module BinData
233
222
  sum_num_bytes_for_all_fields
234
223
  end
235
224
 
225
+ def [](key)
226
+ find_obj_for_name(key)
227
+ end
228
+
229
+ def []=(key, value)
230
+ obj = find_obj_for_name(key)
231
+ if obj
232
+ obj.assign(value)
233
+ end
234
+ end
235
+
236
+ def has_key?(key)
237
+ @field_names.index(base_field_name(key))
238
+ end
239
+
236
240
  #---------------
237
241
  private
238
242
 
243
+ def base_field_name(name)
244
+ name.to_s.chomp("=").to_sym
245
+ end
246
+
239
247
  def invoke_field(obj, symbol, args)
240
248
  name = symbol.to_s
241
249
  is_writer = (name[-1, 1] == "=")
@@ -252,8 +260,7 @@ module BinData
252
260
  end
253
261
 
254
262
  def find_obj_for_name(name)
255
- field_name = name.to_s.chomp("=")
256
- index = @field_names.index(field_name)
263
+ index = @field_names.index(base_field_name(name))
257
264
  if index
258
265
  instantiate_obj_at(index)
259
266
  @field_objs[index]
@@ -273,27 +280,29 @@ module BinData
273
280
  end
274
281
  end
275
282
 
276
- def as_snapshot(val)
277
- if val.class == Hash
278
- snapshot = Snapshot.new
279
- val.each_pair { |k,v| snapshot[k.to_s] = v unless v.nil? }
280
- snapshot
281
- elsif val.nil?
282
- Snapshot.new
283
- else
284
- val
285
- end
286
- end
283
+ def assign_fields(val)
284
+ src = as_stringified_hash(val)
287
285
 
288
- def assign_fields(snapshot)
289
- field_names(true).each do |name|
286
+ @field_names.compact.each do |name|
290
287
  obj = find_obj_for_name(name)
291
- if obj and snapshot.respond_to?(name)
292
- obj.assign(snapshot.__send__(name))
288
+ if obj and src.has_key?(name)
289
+ obj.assign(src[name])
293
290
  end
294
291
  end
295
292
  end
296
293
 
294
+ def as_stringified_hash(val)
295
+ if BinData::Struct === val
296
+ val
297
+ elsif val.nil?
298
+ {}
299
+ else
300
+ hash = Snapshot.new(field_names)
301
+ val.each_pair { |k,v| hash[k] = v }
302
+ hash
303
+ end
304
+ end
305
+
297
306
  def sum_num_bytes_for_all_fields
298
307
  sum_num_bytes_below_index(@field_objs.length)
299
308
  end
@@ -314,5 +323,53 @@ module BinData
314
323
  def include_obj(obj)
315
324
  not obj.has_parameter?(:onlyif) or obj.eval_parameter(:onlyif)
316
325
  end
326
+
327
+ # A hash that can be accessed via attributes.
328
+ class Snapshot < ::Hash #:nodoc:
329
+ def initialize(order = [])
330
+ @order = order.compact
331
+ end
332
+
333
+ if RUBY_VERSION <= "1.9"
334
+ def keys
335
+ k = super
336
+ @order & k
337
+ end
338
+
339
+ def each
340
+ keys.each do |k|
341
+ yield [k, self[k]]
342
+ end
343
+ end
344
+
345
+ def each_pair
346
+ each do |el|
347
+ yield *el
348
+ end
349
+ end
350
+ end
351
+
352
+ def has_key?(key)
353
+ super(key.to_s)
354
+ end
355
+
356
+ def [](key)
357
+ super(key.to_s)
358
+ end
359
+
360
+ def []=(key, value)
361
+ if value != nil
362
+ super(key.to_s, value)
363
+ end
364
+ end
365
+
366
+ def respond_to?(symbol, include_private = false)
367
+ has_key?(symbol) || super
368
+ end
369
+
370
+ def method_missing(symbol, *args)
371
+ self[symbol] || super
372
+ end
373
+ end
317
374
  end
318
375
  end
@@ -2,6 +2,15 @@ require 'bindata/base'
2
2
  require 'bindata/dsl'
3
3
 
4
4
  module BinData
5
+ class SanitizedParameters < Hash
6
+ def move_unknown_parameters_to(dest)
7
+ unused_keys = keys - @the_class.accepted_parameters.all
8
+ unused_keys.each do |key|
9
+ dest[key] = delete(key)
10
+ end
11
+ end
12
+ end
13
+
5
14
  # A Wrapper allows the creation of new BinData types that
6
15
  # provide default parameters.
7
16
  #
@@ -24,19 +33,23 @@ module BinData
24
33
  class Wrapper < BinData::Base
25
34
  include DSLMixin
26
35
 
27
- register_subclasses
28
- dsl_parser :only_one_field, :no_fieldnames
36
+ unregister_self
37
+ dsl_parser :wrapper
29
38
 
30
39
  class << self
31
- def sanitize_parameters!(params, sanitizer) #:nodoc:
32
- raise "no wrapped type was specified in #{self}" if field.nil?
40
+ def sanitize_parameters!(params) #:nodoc:
41
+ raise "no wrapped type was specified in #{self}" if fields[0].nil?
33
42
 
34
- wrapped_type = field.type
35
- wrapped_params = field.params.dup
43
+ wrapped_type = fields[0].type
44
+ wrapped_params = fields[0].params.dup
36
45
 
37
46
  params.move_unknown_parameters_to(wrapped_params)
38
47
 
39
- params[:wrapped] = sanitizer.create_sanitized_object_prototype(wrapped_type, wrapped_params, endian)
48
+ params.endian = endian unless endian.nil?
49
+ params[:wrapped] = params.create_sanitized_object_prototype(wrapped_type, wrapped_params)
50
+
51
+ wrapped_class = params[:wrapped].instance_variable_get(:@obj_class)
52
+ warn "BinData::Wrapper is deprecated as of BinData 1.3.2. #{self} should derive from #{wrapped_class}\n See http://bindata.rubyforge.org/#extending_existing_types"
40
53
  end
41
54
  end
42
55
 
@@ -96,10 +109,10 @@ module BinData
96
109
  end
97
110
 
98
111
  def wrapped_class
99
- return nil if self.class.field.nil?
112
+ return nil if self.class.fields[0].nil?
100
113
 
101
114
  begin
102
- RegisteredClasses.lookup(self.class.field.type, self.class.endian)
115
+ RegisteredClasses.lookup(self.class.fields[0].type, self.class.endian)
103
116
  rescue BinData::UnRegisteredTypeError
104
117
  nil
105
118
  end
data/manual.haml CHANGED
@@ -1,16 +1,16 @@
1
1
  !!!
2
2
  %html{ :xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en" }
3
3
  %head
4
- %meta{ :content => "text/html; charset=iso-8859-1", "http-equiv" => "Content-Type" }
5
- %meta{ :description =>"How to easily parse binary data in Ruby" }
6
- %meta{ :keywords =>"ruby, parse binary data, read binary data" }
4
+ %meta{ :content => "text/html; charset=utf-8", "http-equiv" => "Content-Type" }
5
+ %meta{ :description =>"How to easily read and write binary data in Ruby" }
6
+ %meta{ :keywords =>"ruby, binary, binary data, parse binary data, read binary data, write binary data, binary file, read binary file, write binary file" }
7
7
  %title
8
- Parsing Binary Data in Ruby - BinData Reference Manual
8
+ Reading, writing and parsing binary data in Ruby
9
9
  :javascript
10
10
  var TINY={};function T$(i){return document.getElementById(i)}function T$$(e,p){return p.getElementsByTagName(e)}TINY.accordion=function(){function slider(n){this.n=n;this.a=[]}slider.prototype.init=function(t,e,m,o,k){var a=T$(t),i=s=0,n=a.childNodes,l=n.length;this.s=k||0;this.m=m||0;for(i;i<l;i++){var v=n[i];if(v.nodeType!=3){this.a[s]={};this.a[s].h=h=T$$(e,v)[0];this.a[s].c=c=T$$('div',v)[0];h.onclick=new Function(this.n+'.pr(0,'+s+')');if(o==s){h.className=this.s;c.style.height='auto';c.d=1}else{c.style.height=0;c.d=-1}s++}}this.l=s};slider.prototype.pr=function(f,d){for(var i=0;i<this.l;i++){var h=this.a[i].h,c=this.a[i].c,k=c.style.height;k=k=='auto'?1:parseInt(k);clearInterval(c.t);if((k!=1&&c.d==-1)&&(f==1||i==d)){c.style.height='';c.m=c.offsetHeight;c.style.height=k+'px';c.d=1;h.className=this.s;su(c,1)}else if(k>0&&(f==-1||this.m||i==d)){c.d=-1;h.className='';su(c,-1)}}};function su(c){c.t=setInterval(function(){sl(c)},20)};function sl(c){var h=c.offsetHeight,d=c.d==1?c.m-h:h;c.style.height=h+(Math.ceil(d/5)*c.d)+'px';c.style.opacity=h/c.m;c.style.filter='alpha(opacity='+h*100/c.m+')';if((c.d==1&&h>=c.m)||(c.d!=1&&h==1)){if(c.d==1){c.style.height='auto'}clearInterval(c.t)}};return{slider:slider}}();
11
11
 
12
- var menu1, menu2, menu3, menu4, menu5, menu6;
13
- var menu7, menu8, menu9, menu10, menu11, menu12, menu13;
12
+ var menu1, menu2, menu3, menu4, menu5, menu6, menu7;
13
+ var menu8, menu9, menu10, menu11, menu12, menu13, menu14;
14
14
 
15
15
  function init_accordion() {
16
16
  menu1 = new TINY.accordion.slider("menu1"); menu1.init("menu1","a",1,-1);
@@ -24,8 +24,9 @@
24
24
  menu9 = new TINY.accordion.slider("menu9"); menu9.init("menu9","a",1,-1);
25
25
  menu10 = new TINY.accordion.slider("menu10"); menu10.init("menu10","a",1,-1);
26
26
  menu11 = new TINY.accordion.slider("menu11"); menu11.init("menu11","a",1,-1);
27
- menu12 = new TINY.accordion.slider("menu12"); menu11.init("menu12","a",1,-1);
28
- menu13 = new TINY.accordion.slider("menu13"); menu11.init("menu13","a",1,-1);
27
+ menu12 = new TINY.accordion.slider("menu12"); menu12.init("menu12","a",1,-1);
28
+ menu13 = new TINY.accordion.slider("menu13"); menu13.init("menu13","a",1,-1);
29
+ menu14 = new TINY.accordion.slider("menu14"); menu14.init("menu14","a",1,-1);
29
30
  };
30
31
  window.onload = init_accordion;
31
32
 
@@ -108,6 +109,17 @@
108
109
  #main_content .ruby .global { color: #7FB; }
109
110
  #main_content .ruby .expr { color: #227; }
110
111
  #main_content .ruby .escape { color: #277; }
112
+ %script{:type => "text/javascript"}
113
+ :plain
114
+ var _gaq = _gaq || [];
115
+ _gaq.push(['_setAccount', 'UA-20958115-1']);
116
+ _gaq.push(['_trackPageview']);
117
+
118
+ (function() {
119
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
120
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
121
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
122
+ })();
111
123
 
112
124
  %body
113
125
  #left_frame
@@ -246,13 +258,13 @@
246
258
  .acc-content
247
259
  %li
248
260
  %a{ :href => "#user_defined_primitive_types" }
249
- User Defined Primitive Types
261
+ User-defined Primitive Types
250
262
  .acc-section
251
263
  .acc-content
252
264
  %ul.level3#menu8
253
265
  %li
254
266
  %a{ :href => "#advanced_user_defined_primitive_types" }
255
- Advanced User Defined Primitive Types
267
+ Advanced Example
256
268
  .acc-section
257
269
  .acc-content
258
270
  %li
@@ -293,37 +305,6 @@
293
305
  .acc-section
294
306
  .acc-content
295
307
  %ul.level2#menu11
296
- %li
297
- %a{ :href => "#skipping_over_unused_data" }
298
- Skipping over unused data
299
- .acc-section
300
- .acc-content
301
- %li
302
- %a{ :href => "#bitaligned_records" }
303
- Bit-aligned Records
304
- .acc-section
305
- .acc-content
306
- %li
307
- %a{ :href => "#wrappers" }
308
- Wrappers
309
- .acc-section
310
- .acc-content
311
- %li
312
- %a{ :href => "#parameterizing_user_defined_types" }
313
- Parameterizing User Defined Types
314
- .acc-section
315
- .acc-content
316
- %ul.level3#menu12
317
- %li
318
- %a{ :href => "#mandatory_parameters" }
319
- Mandatory Parameters
320
- .acc-section
321
- .acc-content
322
- %li
323
- %a{ :href => "#default_parameters" }
324
- Default Parameters
325
- .acc-section
326
- .acc-content
327
308
  %li
328
309
  %a{ :href => "#debugging" }
329
310
  Debugging
@@ -345,6 +326,58 @@
345
326
  Hidden fields
346
327
  .acc-section
347
328
  .acc-content
329
+ %li
330
+ %a{ :href => "#parameterizing_user_defined_types" }
331
+ Parameterizing Types
332
+ .acc-section
333
+ .acc-content
334
+ %ul.level3#menu12
335
+ %li
336
+ %a{ :href => "#mandatory_parameters" }
337
+ Mandatory Parameters
338
+ .acc-section
339
+ .acc-content
340
+ %li
341
+ %a{ :href => "#default_parameters" }
342
+ Default Parameters
343
+ .acc-section
344
+ .acc-content
345
+ %li
346
+ %a{ :href => "#extending_existing_types" }
347
+ Extending existing Types
348
+ .acc-section
349
+ .acc-content
350
+ %li
351
+ %a{ :href => "#skipping_over_unused_data" }
352
+ Skipping over unused data
353
+ .acc-section
354
+ .acc-content
355
+ %li
356
+ %a{ :href => "#bitaligned_records" }
357
+ Bit-aligned Records
358
+ .acc-section
359
+ .acc-content
360
+ %li
361
+ %a{ :href => "#faq" }
362
+ FAQ
363
+ .acc-section
364
+ .acc-content
365
+ %ul.level2#menu14
366
+ %li
367
+ %a{ :href => "#im_using_ruby_19_how_do_i_use_string_encodings_with_bindata" }
368
+ String encoding - Ruby 1.9
369
+ .acc-section
370
+ .acc-content
371
+ %li
372
+ %a{ :href => "#how_do_i_speed_up_initialization" }
373
+ Performance
374
+ .acc-section
375
+ .acc-content
376
+ %li
377
+ %a{ :href => "#how_do_i_model_this_complex_nested_format" }
378
+ Recursive declarations
379
+ .acc-section
380
+ .acc-content
348
381
  %li
349
382
  %a{ :href => "#alternatives" }
350
383
  Alternatives