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/BSDL ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (C) 2007-2011 Dion Mendel. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
data/COPYING CHANGED
@@ -1,6 +1,6 @@
1
1
  BinData is copyrighted free software by Dion Mendel <dion@lostrealm.com>.
2
- You can redistribute it and/or modify it under either the terms of the GPL
3
- version 2 (see the file GPL), or the conditions below:
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
4
 
5
5
  1. You may make and give away verbatim copies of the source form of the
6
6
  software without restriction, provided that you duplicate all of the
data/ChangeLog CHANGED
@@ -1,5 +1,17 @@
1
1
  = BinData Changelog
2
2
 
3
+ == Version 1.4.0 (2011-06-14)
4
+
5
+ * Record#snapshot now returns fields in order.
6
+ * Removed the need to call #register_self in subclasses.
7
+ * Wrapper is now deprecated. Use subclassing instead.
8
+ * Updated license to mimic changes to the Ruby License.
9
+ * Refactoring to reduce memory usage.
10
+
11
+ == Version 1.3.1 (2011-01-25)
12
+
13
+ * Fixed file permissions problem.
14
+
3
15
  == Version 1.3.0 (2011-01-25)
4
16
 
5
17
  * BinData objects can now assign values when instantiating.
data/NEWS CHANGED
@@ -1,3 +1,31 @@
1
+ = 1.4.0
2
+
3
+ == Deprecations
4
+
5
+ There is no longer any need to call #register_self when inheriting from
6
+ BinData::Base.
7
+
8
+ BinData::Wrapper is deprecated. You should use direct inheritance instead.
9
+
10
+ If your code looks like:
11
+ class Uint8Array < BinData::Wrapper
12
+ default_parameter :initial_element_value => 0
13
+
14
+ array :initial_length => 2 do
15
+ uint8 :initial_value => :initial_element_value
16
+ end
17
+ end
18
+
19
+ It should be changed to:
20
+ class Uint8Array < BinData::Array
21
+ default_parameter :initial_element_value => 0
22
+ default_parameter :initial_length => 2
23
+
24
+ uint8 :initial_value => :initial_element_value
25
+ end
26
+
27
+ See http://bindata.rubyforge.org/#extending_existing_types for details.
28
+
1
29
  = 1.3.0
2
30
 
3
31
  == New features
data/examples/list.rb CHANGED
@@ -2,7 +2,7 @@ require 'bindata'
2
2
 
3
3
  # An example of a recursively defined data format.
4
4
  #
5
- # This format is used to describe atoms and lists.
5
+ # This example format describes atoms and lists.
6
6
  # It is recursive because lists can contain other lists.
7
7
  #
8
8
  # Atoms - contain a single integer
@@ -49,10 +49,9 @@ require 'bindata'
49
49
  #
50
50
  # The declaration then becomes:
51
51
  #
52
- # class Term < BinData::Record; end # forward declaration
52
+ # class Term < BinData::Record; end # forward declaration
53
53
  #
54
- # class Atom < BinData::Wrapper
55
- # int32be
54
+ # class Atom < BinData::Int32be
56
55
  # end
57
56
  #
58
57
  # class List < BinData::Record
@@ -71,9 +70,7 @@ require 'bindata'
71
70
 
72
71
  class Term < BinData::Record; end # Forward declaration
73
72
 
74
- class Atom < BinData::Wrapper
75
- int32be
76
-
73
+ class Atom < BinData::Int32be
77
74
  def decode
78
75
  snapshot
79
76
  end
@@ -117,8 +114,11 @@ class Term < BinData::Record
117
114
  end
118
115
 
119
116
 
117
+ puts "A single Atom"
120
118
  p Term.encode(4)
121
119
  p Term.encode(4).decode
122
120
  puts
121
+
122
+ puts "A nested List"
123
123
  p Term.encode([1, [2, 3], 4])
124
124
  p Term.encode([1, [2, 3], 4]).decode
data/examples/nbt.rb CHANGED
@@ -30,44 +30,32 @@ module Nbt
30
30
  end
31
31
 
32
32
  # NBT.txt line 31
33
- class TagByte < BinData::Wrapper
34
- int8
35
-
33
+ class TagByte < BinData::Int8
36
34
  def to_formatted_s(indent = 0); to_s; end
37
35
  end
38
36
 
39
37
  # NBT.txt line 34
40
- class TagShort < BinData::Wrapper
41
- int16be
42
-
38
+ class TagShort < BinData::Int16be
43
39
  def to_formatted_s(indent = 0); to_s; end
44
40
  end
45
41
 
46
42
  # NBT.txt line 37
47
- class TagInt < BinData::Wrapper
48
- int32be
49
-
43
+ class TagInt < BinData::Int32be
50
44
  def to_formatted_s(indent = 0); to_s; end
51
45
  end
52
46
 
53
47
  # NBT.txt line 40
54
- class TagLong < BinData::Wrapper
55
- int64be
56
-
48
+ class TagLong < BinData::Int64be
57
49
  def to_formatted_s(indent = 0); to_s; end
58
50
  end
59
51
 
60
52
  # NBT.txt line 43
61
- class TagFloat < BinData::Wrapper
62
- float_be
63
-
53
+ class TagFloat < BinData::FloatBe
64
54
  def to_formatted_s(indent = 0); to_s; end
65
55
  end
66
56
 
67
57
  # NBT.txt line 46
68
- class TagDouble < BinData::Wrapper
69
- double_be
70
-
58
+ class TagDouble < BinData::DoubleBe
71
59
  def to_formatted_s(indent = 0); to_s; end
72
60
  end
73
61
 
@@ -106,28 +94,25 @@ module Nbt
106
94
  class TagList < BinData::Record; end
107
95
 
108
96
  # NBT.txt line 10
109
- class Payload < BinData::Wrapper
110
- mandatory_parameter :tag_selector
111
- choice :selection => :tag_selector do
112
- tag_end 0
113
- tag_byte 1
114
- tag_short 2
115
- tag_int 3
116
- tag_long 4
117
- tag_float 5
118
- tag_double 6
119
- tag_byte_array 7
120
- tag_string 8
121
- tag_list 9
122
- tag_compound 10
123
- end
97
+ class Payload < BinData::Choice
98
+ tag_end 0
99
+ tag_byte 1
100
+ tag_short 2
101
+ tag_int 3
102
+ tag_long 4
103
+ tag_float 5
104
+ tag_double 6
105
+ tag_byte_array 7
106
+ tag_string 8
107
+ tag_list 9
108
+ tag_compound 10
124
109
  end
125
110
 
126
111
  # NBT.txt line 6, 27
127
112
  class NamedTag < BinData::Record
128
113
  int8 :tag_id
129
114
  tag_string :name, :onlyif => :not_end_tag?
130
- payload :payload, :onlyif => :not_end_tag?, :tag_selector => :tag_id
115
+ payload :payload, :onlyif => :not_end_tag?, :selection => :tag_id
131
116
 
132
117
  def not_end_tag?
133
118
  tag_id != 0
@@ -145,7 +130,7 @@ module Nbt
145
130
  int8 :tag_id
146
131
  int32be :len, :value => lambda { data.length }
147
132
  array :data, :initial_length => :len do
148
- payload :tag_selector => :tag_id
133
+ payload :selection => :tag_id
149
134
  end
150
135
 
151
136
  def to_formatted_s(indent = 0)
@@ -175,9 +160,7 @@ module Nbt
175
160
  end
176
161
 
177
162
  # NBT.txt line 3
178
- class Nbt < BinData::Wrapper
179
- named_tag
180
-
163
+ class Nbt < NamedTag
181
164
  def self.read(io)
182
165
  require 'zlib'
183
166
  super(Zlib::GzipReader.new(io))
data/lib/bindata.rb CHANGED
@@ -31,5 +31,5 @@ require 'bindata/deprecated'
31
31
  #
32
32
  # Copyright (c) 2007 - 2011 Dion Mendel.
33
33
  module BinData
34
- VERSION = "1.3.1"
34
+ VERSION = "1.4.0"
35
35
  end
@@ -13,8 +13,6 @@ module BinData
13
13
  # MyRec.read("\x12\x34") #=> {"a" => 1, "b" => 3}
14
14
  #
15
15
  class ResumeByteAlignment < BinData::Base
16
- register_self
17
-
18
16
  def clear; end
19
17
  def clear?; true; end
20
18
  def assign(val); end
@@ -50,7 +48,7 @@ module BinData
50
48
  end
51
49
  def readbytes(n)
52
50
  n.times.inject("") do |bytes, i|
53
- bytes + @io.readbits(8, :big).chr
51
+ bytes << @io.readbits(8, :big).chr
54
52
  end
55
53
  end
56
54
  def method_missing(sym, *args, &block)
@@ -74,7 +72,6 @@ module BinData
74
72
  class BasePrimitive < BinData::Base
75
73
  def self.bit_aligned
76
74
  include BitAligned
77
- register_self
78
75
  end
79
76
  end
80
77
 
data/lib/bindata/array.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'bindata/base'
2
+ require 'bindata/dsl'
2
3
 
3
4
  module BinData
4
5
  # An Array is a list of data objects of the same type.
@@ -47,9 +48,10 @@ module BinData
47
48
  # Each data object in an array has the variable +index+ made available
48
49
  # to any lambda evaluated as a parameter of that data object.
49
50
  class Array < BinData::Base
51
+ include DSLMixin
50
52
  include Enumerable
51
53
 
52
- register_self
54
+ dsl_parser :array
53
55
 
54
56
  mandatory_parameter :type
55
57
  optional_parameters :initial_length, :read_until
@@ -57,7 +59,7 @@ module BinData
57
59
 
58
60
  class << self
59
61
 
60
- def sanitize_parameters!(params, sanitizer) #:nodoc:
62
+ def sanitize_parameters!(params) #:nodoc:
61
63
  unless params.has_parameter?(:initial_length) or
62
64
  params.has_parameter?(:read_until)
63
65
  # ensure one of :initial_length and :read_until exists
@@ -66,9 +68,11 @@ module BinData
66
68
 
67
69
  params.warn_replacement_parameter(:read_length, :initial_length)
68
70
 
71
+ params.merge!(dsl_params)
72
+
69
73
  if params.needs_sanitizing?(:type)
70
74
  el_type, el_params = params[:type]
71
- params[:type] = sanitizer.create_sanitized_object_prototype(el_type, el_params)
75
+ params[:type] = params.create_sanitized_object_prototype(el_type, el_params)
72
76
  end
73
77
  end
74
78
  end
@@ -321,7 +325,7 @@ module BinData
321
325
  nbytes = elements[i].do_num_bytes
322
326
 
323
327
  if nbytes.is_a?(Integer)
324
- (sum + nbytes).ceil
328
+ sum.ceil + nbytes
325
329
  else
326
330
  sum + nbytes
327
331
  end
data/lib/bindata/base.rb CHANGED
@@ -9,9 +9,11 @@ module BinData
9
9
  # Error raised when unexpected results occur when reading data from IO.
10
10
  class ValidityError < StandardError ; end
11
11
 
12
- # ArgExtractors take the arguments to BinData::Base.new and
13
- # separate them into [value, parameters, parent].
12
+ # ArgExtractors take the arguments passed to BinData::Base.new and
13
+ # separates them into [value, parameters, parent].
14
14
  class BaseArgExtractor
15
+ @@empty_hash = Hash.new.freeze
16
+
15
17
  def self.extract(the_class, the_args)
16
18
  args = the_args.dup
17
19
  value = parameters = parent = nil
@@ -28,7 +30,7 @@ module BinData
28
30
  value = args.pop
29
31
  end
30
32
 
31
- parameters ||= {}
33
+ parameters ||= @@empty_hash
32
34
 
33
35
  return [value, parameters, parent]
34
36
  end
@@ -59,27 +61,27 @@ module BinData
59
61
  RegisteredClasses.underscore_name(self.name)
60
62
  end
61
63
 
62
- # Registers this class for use.
63
- def register_self
64
- register_class(self)
64
+ # Call this method if this class is abstract and not to be used.
65
+ def unregister_self
66
+ RegisteredClasses.unregister(name)
65
67
  end
66
68
 
67
69
  # Registers all subclasses of this class for use
68
- def register_subclasses
70
+ def register_subclasses #:nodoc:
69
71
  class << self
70
72
  define_method(:inherited) do |subclass|
71
- register_class(subclass)
73
+ RegisteredClasses.register(subclass.name, subclass)
74
+ register_subclasses
72
75
  end
73
76
  end
74
77
  end
75
78
 
76
- def register_class(class_to_register) #:nodoc:
77
- RegisteredClasses.register(class_to_register.name, class_to_register)
78
- end
79
-
80
- private :register_self, :register_subclasses, :register_class
79
+ private :unregister_self, :register_subclasses
81
80
  end
82
81
 
82
+ # Register all subclasses of this class.
83
+ register_subclasses
84
+
83
85
  # Creates a new data object.
84
86
  #
85
87
  # Args are optional, but if present, must be in the following order.
@@ -93,11 +95,12 @@ module BinData
93
95
  # object resides under.
94
96
  def initialize(*args)
95
97
  value, parameters, parent = extract_args(args)
96
- @params = Sanitizer.sanitize(parameters, self.class)
98
+
99
+ @params = SanitizedParameters.sanitize(parameters, self.class)
100
+ @parent = parent
97
101
 
98
102
  add_methods_for_check_or_adjust_offset
99
103
 
100
- @parent = parent if parent
101
104
  initialize_shared_instance
102
105
  initialize_instance
103
106
  assign(value) if value
@@ -125,7 +128,7 @@ module BinData
125
128
  # parameters given at object construction to be overridden.
126
129
  #
127
130
  # Returns nil if +key+ does not refer to any parameter.
128
- def eval_parameter(key, overrides = {})
131
+ def eval_parameter(key, overrides = nil)
129
132
  LazyEvaluator.eval(self, get_parameter(key), overrides)
130
133
  end
131
134
 
@@ -255,7 +258,7 @@ module BinData
255
258
 
256
259
  # Performs sanity checks on the given parameters. This method converts
257
260
  # the parameters to the form expected by this data object.
258
- def self.sanitize_parameters!(parameters, sanitizer) #:nodoc:
261
+ def self.sanitize_parameters!(parameters) #:nodoc:
259
262
  end
260
263
 
261
264
  # Initializes the state of the object. All instance variables that
@@ -45,6 +45,7 @@ module BinData
45
45
  # or failure. Any other return is compared to
46
46
  # the value just read in.
47
47
  class BasePrimitive < BinData::Base
48
+ unregister_self
48
49
 
49
50
  optional_parameters :initial_value, :value, :check_value
50
51
  mutually_exclusive_parameters :initial_value, :value
data/lib/bindata/bits.rb CHANGED
@@ -12,7 +12,6 @@ module BinData
12
12
  unless BinData.const_defined?(name)
13
13
  BinData.module_eval <<-END
14
14
  class #{name} < BinData::BasePrimitive
15
- register_self
16
15
  BitField.define_methods(self, #{nbits}, :#{endian})
17
16
  end
18
17
  END
@@ -1,4 +1,5 @@
1
1
  require 'bindata/base'
2
+ require 'bindata/dsl'
2
3
 
3
4
  module BinData
4
5
  # A Choice is a collection of data objects of which only one is active
@@ -55,19 +56,22 @@ module BinData
55
56
  # selection to the current selection whenever the
56
57
  # selection changes. Default is false.
57
58
  class Choice < BinData::Base
59
+ include DSLMixin
58
60
 
59
- register_self
61
+ dsl_parser :choice
60
62
 
61
63
  mandatory_parameters :choices, :selection
62
64
  optional_parameter :copy_on_change
63
65
 
64
66
  class << self
65
67
 
66
- def sanitize_parameters!(params, sanitizer) #:nodoc:
68
+ def sanitize_parameters!(params) #:nodoc:
69
+ params.merge!(dsl_params)
70
+
67
71
  if params.needs_sanitizing?(:choices)
68
72
  choices = choices_as_hash(params[:choices])
69
73
  ensure_valid_keys(choices)
70
- params[:choices] = sanitizer.create_sanitized_choices(choices)
74
+ params[:choices] = params.create_sanitized_choices(choices)
71
75
  end
72
76
  end
73
77
 
@@ -100,6 +104,14 @@ module BinData
100
104
  end
101
105
  end
102
106
 
107
+ def initialize_shared_instance
108
+ if eval_parameter(:copy_on_change) == true
109
+ class << self
110
+ alias_method :hook_after_current_choice, :copy_previous_value
111
+ end
112
+ end
113
+ end
114
+
103
115
  def initialize_instance
104
116
  @choices = {}
105
117
  @last_selection = nil
@@ -110,33 +122,6 @@ module BinData
110
122
  eval_parameter(:selection)
111
123
  end
112
124
 
113
- # This method does not exist. This stub only exists to document why.
114
- # There is no #selection= method to complement the #selection method.
115
- # This is deliberate to promote the declarative nature of BinData.
116
- #
117
- # If you really *must* be able to programmatically adjust the selection
118
- # then try something like the following.
119
- #
120
- # class ProgrammaticChoice < BinData::Wrapper
121
- # choice :selection => :selection
122
- # attr_accessor :selection
123
- # end
124
- #
125
- # type1 = [:string, {:value => "Type1"}]
126
- # type2 = [:string, {:value => "Type2"}]
127
- #
128
- # choices = {5 => type1, 17 => type2}
129
- # pc = ProgrammaticChoice.new(:choices => choices)
130
- #
131
- # pc.selection = 5
132
- # pc #=> "Type1"
133
- #
134
- # pc.selection = 17
135
- # pc #=> "Type2"
136
- def selection=(sel)
137
- raise NoMethodError, "See rdoc BinData::Choice.selection= for details"
138
- end
139
-
140
125
  def clear #:nodoc:
141
126
  current_choice.clear
142
127
  end
@@ -178,6 +163,7 @@ module BinData
178
163
  private
179
164
 
180
165
  def hook_before_do_read; end
166
+ def hook_after_current_choice(*args); end
181
167
 
182
168
  def current_choice
183
169
  selection = eval_parameter(:selection)
@@ -186,7 +172,7 @@ module BinData
186
172
  end
187
173
 
188
174
  obj = get_or_instantiate_choice(selection)
189
- copy_previous_value_if_required(selection, obj)
175
+ hook_after_current_choice(selection, obj)
190
176
 
191
177
  obj
192
178
  end
@@ -203,18 +189,12 @@ module BinData
203
189
  prototype.instantiate(nil, self)
204
190
  end
205
191
 
206
- def copy_previous_value_if_required(selection, obj)
192
+ def copy_previous_value(selection, obj)
207
193
  prev = get_previous_choice(selection)
208
- if should_copy_value?(prev, obj)
209
- obj.assign(prev)
210
- end
194
+ obj.assign(prev) unless prev.nil?
211
195
  remember_current_selection(selection)
212
196
  end
213
197
 
214
- def should_copy_value?(prev, cur)
215
- prev != nil and eval_parameter(:copy_on_change) == true
216
- end
217
-
218
198
  def get_previous_choice(selection)
219
199
  if selection != @last_selection and @last_selection != nil
220
200
  @choices[@last_selection]
@@ -224,9 +204,7 @@ module BinData
224
204
  end
225
205
 
226
206
  def remember_current_selection(selection)
227
- if selection != @last_selection
228
- @last_selection = selection
229
- end
207
+ @last_selection = selection
230
208
  end
231
209
  end
232
210
  end