bindata 0.8.0 → 0.8.1
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/ChangeLog +7 -0
- data/lib/bindata.rb +2 -2
- data/lib/bindata/array.rb +12 -17
- data/lib/bindata/base.rb +21 -13
- data/lib/bindata/choice.rb +2 -2
- data/lib/bindata/lazy.rb +20 -7
- data/lib/bindata/struct.rb +26 -15
- data/spec/base_spec.rb +5 -5
- data/spec/struct_spec.rb +19 -17
- metadata +41 -34
data/ChangeLog
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
= BinData Changelog
|
2
2
|
|
3
|
+
-== Version 0.8.1 (2008-01-14)
|
4
|
+
|
5
|
+
* Reduced memory consumption.
|
6
|
+
* Increased execution speed.
|
7
|
+
* Deprecated BinData::Base.parameters
|
8
|
+
* Fixed spec syntax (thanks to David Goodlad)
|
9
|
+
|
3
10
|
-== Version 0.8.0 (2007-10-14)
|
4
11
|
|
5
12
|
* Add reserved field names to Struct.
|
data/lib/bindata.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# BinData -- Binary data manipulator.
|
2
|
-
# Copyright (c) 2007 Dion Mendel.
|
2
|
+
# Copyright (c) 2007,2008 Dion Mendel.
|
3
3
|
|
4
4
|
require 'bindata/array'
|
5
5
|
require 'bindata/choice'
|
@@ -10,5 +10,5 @@ require 'bindata/stringz'
|
|
10
10
|
require 'bindata/struct'
|
11
11
|
|
12
12
|
module BinData
|
13
|
-
VERSION = "0.8.
|
13
|
+
VERSION = "0.8.1"
|
14
14
|
end
|
data/lib/bindata/array.rb
CHANGED
@@ -40,6 +40,9 @@ module BinData
|
|
40
40
|
mandatory_parameter :type
|
41
41
|
optional_parameters :initial_length, :read_until
|
42
42
|
|
43
|
+
# An empty hash shared by all instances
|
44
|
+
@@empty_hash = Hash.new.freeze
|
45
|
+
|
43
46
|
# Creates a new Array
|
44
47
|
def initialize(params = {}, env = nil)
|
45
48
|
super(cleaned_params(params), env)
|
@@ -51,7 +54,7 @@ module BinData
|
|
51
54
|
|
52
55
|
@element_list = nil
|
53
56
|
@element_klass = klass
|
54
|
-
@element_params = el_params ||
|
57
|
+
@element_params = el_params || @@empty_hash
|
55
58
|
end
|
56
59
|
|
57
60
|
# Clears the element at position +index+. If +index+ is not given, then
|
@@ -133,7 +136,7 @@ module BinData
|
|
133
136
|
# Returns the appended object, or value in the case of single_values.
|
134
137
|
def append(value = nil)
|
135
138
|
append_new_element
|
136
|
-
self[
|
139
|
+
self[-1] = value unless value.nil?
|
137
140
|
self.last
|
138
141
|
end
|
139
142
|
|
@@ -142,9 +145,9 @@ module BinData
|
|
142
145
|
def [](*index)
|
143
146
|
data = elements[*index]
|
144
147
|
if data.respond_to?(:each)
|
145
|
-
data.collect { |el| el.single_value? ? el.value : el }
|
148
|
+
data.collect { |el| (el && el.single_value?) ? el.value : el }
|
146
149
|
else
|
147
|
-
data.single_value? ? data.value : data
|
150
|
+
(data && data.single_value?) ? data.value : data
|
148
151
|
end
|
149
152
|
end
|
150
153
|
alias_method :slice, :[]
|
@@ -172,13 +175,9 @@ module BinData
|
|
172
175
|
# form returns an empty array.
|
173
176
|
def first(n = nil)
|
174
177
|
if n.nil?
|
175
|
-
self
|
178
|
+
self[0]
|
176
179
|
else
|
177
|
-
|
178
|
-
[n, self.length].min.times do |i|
|
179
|
-
array.push(self[i])
|
180
|
-
end
|
181
|
-
array
|
180
|
+
self[0, n]
|
182
181
|
end
|
183
182
|
end
|
184
183
|
|
@@ -187,14 +186,10 @@ module BinData
|
|
187
186
|
# form returns an empty array.
|
188
187
|
def last(n = nil)
|
189
188
|
if n.nil?
|
190
|
-
self
|
189
|
+
self[-1]
|
191
190
|
else
|
192
|
-
|
193
|
-
|
194
|
-
start.upto(self.length - 1) do |i|
|
195
|
-
array.push(self[i])
|
196
|
-
end
|
197
|
-
array
|
191
|
+
n = length if n > length
|
192
|
+
self[-n, n]
|
198
193
|
end
|
199
194
|
end
|
200
195
|
|
data/lib/bindata/base.rb
CHANGED
@@ -65,6 +65,8 @@ module BinData
|
|
65
65
|
|
66
66
|
# Returns both the mandatory and optional parameters used by this class.
|
67
67
|
def parameters
|
68
|
+
# warn about deprecated method - remove before releasing 1.0
|
69
|
+
warn "warning: #parameters is deprecated."
|
68
70
|
(mandatory_parameters + optional_parameters).uniq
|
69
71
|
end
|
70
72
|
|
@@ -112,6 +114,10 @@ module BinData
|
|
112
114
|
# reference callable objects (methods or procs). +env+ is the
|
113
115
|
# environment that these callable objects are evaluated in.
|
114
116
|
def initialize(params = {}, env = nil)
|
117
|
+
# all known parameters
|
118
|
+
mandatory = self.class.mandatory_parameters
|
119
|
+
optional = self.class.optional_parameters
|
120
|
+
|
115
121
|
# default :readwrite param to true if unspecified
|
116
122
|
if not params.has_key?(:readwrite)
|
117
123
|
params = params.dup
|
@@ -119,22 +125,20 @@ module BinData
|
|
119
125
|
end
|
120
126
|
|
121
127
|
# ensure mandatory parameters exist
|
122
|
-
|
128
|
+
mandatory.each do |prm|
|
123
129
|
if not params.has_key?(prm)
|
124
130
|
raise ArgumentError, "parameter ':#{prm}' must be specified " +
|
125
131
|
"in #{self}"
|
126
132
|
end
|
127
133
|
end
|
128
134
|
|
129
|
-
known_params = self.class.parameters
|
130
|
-
|
131
135
|
# partition parameters into known and extra parameters
|
132
136
|
@params = {}
|
133
137
|
extra = {}
|
134
138
|
params.each do |k,v|
|
135
139
|
k = k.to_sym
|
136
140
|
raise ArgumentError, "parameter :#{k} is nil in #{self}" if v.nil?
|
137
|
-
if
|
141
|
+
if mandatory.include?(k) or optional.include?(k)
|
138
142
|
@params[k] = v.freeze
|
139
143
|
else
|
140
144
|
extra[k] = v.freeze
|
@@ -149,18 +153,22 @@ module BinData
|
|
149
153
|
|
150
154
|
# Returns the class matching a previously registered +name+.
|
151
155
|
def klass_lookup(name)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
klass =
|
156
|
+
@cache ||= {}
|
157
|
+
klass = @cache[name]
|
158
|
+
if klass.nil?
|
159
|
+
klass = self.class.lookup(name)
|
160
|
+
if klass.nil? and @env.parent_data_object != nil
|
161
|
+
# lookup failed so retry in the context of the parent data object
|
162
|
+
klass = @env.parent_data_object.klass_lookup(name)
|
163
|
+
end
|
164
|
+
@cache[name] = klass
|
156
165
|
end
|
157
166
|
klass
|
158
167
|
end
|
159
168
|
|
160
|
-
# Returns a list of parameters that
|
161
|
-
def
|
162
|
-
|
163
|
-
self.class.parameters - supplied
|
169
|
+
# Returns a list of parameters that are accepted by this object
|
170
|
+
def accepted_parameters
|
171
|
+
(self.class.mandatory_parameters + self.class.optional_parameters).uniq
|
164
172
|
end
|
165
173
|
|
166
174
|
# Reads data into this bin object by calling #do_read then #done_read.
|
@@ -218,7 +226,7 @@ module BinData
|
|
218
226
|
# parameter from the +params+ hash used when creating the data object.
|
219
227
|
# +values+ contains data that may be accessed when evaluating +key+.
|
220
228
|
# Returns nil if +key+ does not refer to any parameter.
|
221
|
-
def eval_param(key, values =
|
229
|
+
def eval_param(key, values = nil)
|
222
230
|
@env.lazy_eval(@params[key], values)
|
223
231
|
end
|
224
232
|
|
data/lib/bindata/choice.rb
CHANGED
@@ -97,9 +97,9 @@ module BinData
|
|
97
97
|
super || the_choice.respond_to?(symbol, include_private)
|
98
98
|
end
|
99
99
|
|
100
|
-
def method_missing(symbol, *args)
|
100
|
+
def method_missing(symbol, *args, &block)
|
101
101
|
if the_choice.respond_to?(symbol)
|
102
|
-
the_choice.__send__(symbol, *args)
|
102
|
+
the_choice.__send__(symbol, *args, &block)
|
103
103
|
else
|
104
104
|
super
|
105
105
|
end
|
data/lib/bindata/lazy.rb
CHANGED
@@ -13,23 +13,35 @@ module BinData
|
|
13
13
|
# parent data object. This makes the lambda easier to read as we just write
|
14
14
|
# <tt>field</tt> instead of <tt>obj.field</tt>.
|
15
15
|
class LazyEvalEnv
|
16
|
+
# An empty hash shared by all instances
|
17
|
+
@@empty_hash = Hash.new.freeze
|
18
|
+
|
16
19
|
# Creates a new environment. +parent+ is the environment of the
|
17
20
|
# parent data object.
|
18
21
|
def initialize(parent = nil)
|
19
22
|
@parent = parent
|
20
|
-
@variables =
|
21
|
-
@overrides =
|
23
|
+
@variables = @@empty_hash
|
24
|
+
@overrides = @@empty_hash
|
25
|
+
@params = @@empty_hash
|
22
26
|
end
|
23
|
-
attr_reader :parent
|
24
|
-
attr_accessor :data_object
|
27
|
+
attr_reader :parent, :params
|
28
|
+
attr_accessor :data_object
|
25
29
|
|
26
30
|
# only accessible by another LazyEvalEnv
|
27
31
|
protected :data_object
|
28
32
|
|
33
|
+
# Set the parameters for this environment.
|
34
|
+
def params=(p)
|
35
|
+
@params = (p.nil? or p.empty?) ? @@empty_hash : p
|
36
|
+
end
|
37
|
+
|
29
38
|
# Add a variable with a pre-assigned value to this environment. +sym+
|
30
39
|
# will be accessible as a variable for any lambda evaluated
|
31
40
|
# with #lazy_eval.
|
32
41
|
def add_variable(sym, value)
|
42
|
+
if @variables.equal?(@@empty_hash)
|
43
|
+
@variables = {}
|
44
|
+
end
|
33
45
|
@variables[sym.to_sym] = value
|
34
46
|
end
|
35
47
|
|
@@ -47,15 +59,16 @@ module BinData
|
|
47
59
|
|
48
60
|
# Evaluates +obj+ in the context of this environment. Evaluation
|
49
61
|
# recurses until it yields a value that is not a symbol or lambda.
|
50
|
-
|
51
|
-
|
62
|
+
# +overrides+ is an optional +params+ like hash
|
63
|
+
def lazy_eval(obj, overrides = nil)
|
64
|
+
@overrides = overrides if overrides
|
52
65
|
if obj.is_a? Symbol
|
53
66
|
# treat :foo as lambda { foo }
|
54
67
|
obj = __send__(obj)
|
55
68
|
elsif obj.respond_to? :arity
|
56
69
|
obj = instance_eval(&obj)
|
57
70
|
end
|
58
|
-
@overrides =
|
71
|
+
@overrides = @@empty_hash
|
59
72
|
obj
|
60
73
|
end
|
61
74
|
|
data/lib/bindata/struct.rb
CHANGED
@@ -26,8 +26,8 @@ module BinData
|
|
26
26
|
# class PascalString < BinData::Struct
|
27
27
|
# delegate :data
|
28
28
|
#
|
29
|
-
#
|
30
|
-
# string
|
29
|
+
# uint8 :len, :value => lambda { data.length }
|
30
|
+
# string :data, :read_length => :len
|
31
31
|
# end
|
32
32
|
#
|
33
33
|
# str = PascalString.new
|
@@ -176,35 +176,46 @@ module BinData
|
|
176
176
|
all_reserved_methods = delegate.methods + delegate.field_names -
|
177
177
|
all_methods
|
178
178
|
|
179
|
-
# move
|
180
|
-
|
181
|
-
|
179
|
+
# move accepted params from this object to the delegate object
|
180
|
+
env_params = @env.params.dup
|
181
|
+
delegate.accepted_parameters.each do |p|
|
182
|
+
if (v = env_params.delete(p))
|
182
183
|
delegate_params[p] = v
|
183
184
|
end
|
184
185
|
end
|
186
|
+
@env.params = env_params
|
185
187
|
else
|
186
188
|
# no delegate so all instance methods of Hash are reserved
|
187
189
|
all_reserved_methods = Hash.instance_methods - all_methods
|
188
190
|
end
|
189
191
|
|
192
|
+
# check if field names conflict with any reserved names
|
193
|
+
field_names = param(:fields).collect { |f| f[1] }
|
194
|
+
field_names_okay = (all_methods & field_names).empty? &&
|
195
|
+
(all_reserved_methods & field_names).empty?
|
196
|
+
|
190
197
|
# create instances of the fields
|
191
198
|
@fields = param(:fields).collect do |type, name, params|
|
192
199
|
klass = klass_lookup(type)
|
193
200
|
raise TypeError, "unknown type '#{type}' for #{self}" if klass.nil?
|
194
|
-
if
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
201
|
+
if not field_names_okay
|
202
|
+
# at least one field names conflicts so test them all.
|
203
|
+
# rationale - #include? is expensive so we avoid it if possible.
|
204
|
+
if all_methods.include?(name)
|
205
|
+
raise NameError.new("field '#{name}' shadows an existing method",name)
|
206
|
+
end
|
207
|
+
if all_reserved_methods.include?(name)
|
208
|
+
raise NameError.new("field '#{name}' is a reserved name",name)
|
209
|
+
end
|
199
210
|
end
|
200
211
|
[name, klass.new(params, create_env)]
|
201
212
|
end
|
202
213
|
end
|
203
214
|
|
204
|
-
# Returns a list of parameters that
|
205
|
-
def
|
215
|
+
# Returns a list of parameters that are accepted by this object
|
216
|
+
def accepted_parameters
|
206
217
|
if delegate_object != nil
|
207
|
-
delegate_object.
|
218
|
+
delegate_object.accepted_parameters
|
208
219
|
else
|
209
220
|
super
|
210
221
|
end
|
@@ -335,7 +346,7 @@ module BinData
|
|
335
346
|
delegate_object ? delegate_object.single_value? : false
|
336
347
|
end
|
337
348
|
|
338
|
-
def method_missing(symbol, *args)
|
349
|
+
def method_missing(symbol, *args, &block)
|
339
350
|
name = symbol.id2name
|
340
351
|
|
341
352
|
is_writer = (name[-1, 1] == "=")
|
@@ -352,7 +363,7 @@ module BinData
|
|
352
363
|
obj
|
353
364
|
end
|
354
365
|
elsif delegate_object.respond_to?(symbol)
|
355
|
-
delegate_object.__send__(symbol, *args)
|
366
|
+
delegate_object.__send__(symbol, *args, &block)
|
356
367
|
else
|
357
368
|
super
|
358
369
|
end
|
data/spec/base_spec.rb
CHANGED
@@ -94,12 +94,12 @@ describe "A data object with parameters" do
|
|
94
94
|
obj.param(:p3).should respond_to(:arity)
|
95
95
|
end
|
96
96
|
|
97
|
-
it "should identify
|
97
|
+
it "should identify accepted parameters" do
|
98
98
|
obj = WithParam.new(:p1 => 1, :p3 => 3, :p4 => 4, :p5 => 5)
|
99
|
-
obj.
|
100
|
-
obj.
|
101
|
-
obj.
|
102
|
-
obj.
|
99
|
+
obj.accepted_parameters.should include(:p1)
|
100
|
+
obj.accepted_parameters.should include(:p2)
|
101
|
+
obj.accepted_parameters.should include(:p3)
|
102
|
+
obj.accepted_parameters.should_not include(:p4)
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
data/spec/struct_spec.rb
CHANGED
@@ -26,7 +26,7 @@ describe "A Struct with hidden fields" do
|
|
26
26
|
@obj.c = 15
|
27
27
|
@obj.c.should eql(15)
|
28
28
|
|
29
|
-
@obj.should respond_to
|
29
|
+
@obj.should respond_to(:b=)
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should not include hidden fields in snapshot" do
|
@@ -41,7 +41,7 @@ describe "A Struct that delegates" do
|
|
41
41
|
class DelegateStruct < BinData::Struct
|
42
42
|
delegate :b
|
43
43
|
int8 :a, :initial_value => :num
|
44
|
-
int8 'b'
|
44
|
+
int8 'b', :initial_value => 7
|
45
45
|
int8 :c, :value => :b
|
46
46
|
end
|
47
47
|
END
|
@@ -50,6 +50,7 @@ describe "A Struct that delegates" do
|
|
50
50
|
|
51
51
|
it "should access custom parameters" do
|
52
52
|
@obj.a.should eql(5)
|
53
|
+
@obj.b.should eql(7)
|
53
54
|
end
|
54
55
|
|
55
56
|
it "should have correct num_bytes" do
|
@@ -66,16 +67,16 @@ describe "A Struct that delegates" do
|
|
66
67
|
end
|
67
68
|
|
68
69
|
it "should delegate methods" do
|
69
|
-
@obj.should respond_to
|
70
|
-
@obj.value =
|
71
|
-
@obj.c.should eql(
|
70
|
+
@obj.should respond_to(:value)
|
71
|
+
@obj.value = 9
|
72
|
+
@obj.c.should eql(9)
|
72
73
|
end
|
73
74
|
|
74
|
-
it "should identify
|
75
|
-
@obj.
|
76
|
-
@obj.
|
77
|
-
@obj.
|
78
|
-
@obj.
|
75
|
+
it "should identify accepted parameters" do
|
76
|
+
@obj.accepted_parameters.should include(:check_value)
|
77
|
+
@obj.accepted_parameters.should include(:initial_value)
|
78
|
+
@obj.accepted_parameters.should include(:value)
|
79
|
+
@obj.accepted_parameters.should_not include(:endian)
|
79
80
|
end
|
80
81
|
|
81
82
|
it "should pass params when creating" do
|
@@ -104,13 +105,14 @@ describe "A Struct with nested delegation" do
|
|
104
105
|
end
|
105
106
|
|
106
107
|
it "should forward parameters" do
|
107
|
-
@obj.should respond_to
|
108
|
+
@obj.should respond_to(:value)
|
108
109
|
@obj.value.should eql(7)
|
109
110
|
end
|
110
111
|
|
111
|
-
it "should identify
|
112
|
-
@obj.
|
113
|
-
@obj.
|
112
|
+
it "should identify accepted parameters" do
|
113
|
+
@obj.accepted_parameters.should include(:check_value)
|
114
|
+
@obj.accepted_parameters.should include(:initial_value)
|
115
|
+
@obj.accepted_parameters.should include(:value)
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
@@ -211,9 +213,9 @@ describe "A Struct with multiple fields" do
|
|
211
213
|
@obj.num_bytes.should eql(2)
|
212
214
|
end
|
213
215
|
|
214
|
-
it "should identify
|
215
|
-
@obj.
|
216
|
-
@obj.
|
216
|
+
it "should identify accepted parameters" do
|
217
|
+
@obj.accepted_parameters.should include(:delegate)
|
218
|
+
@obj.accepted_parameters.should include(:endian)
|
217
219
|
end
|
218
220
|
|
219
221
|
it "should clear" do
|
metadata
CHANGED
@@ -1,33 +1,26 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.0
|
3
|
-
specification_version: 1
|
4
2
|
name: bindata
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.8.
|
7
|
-
date: 2007-10-14 00:00:00 +08:00
|
8
|
-
summary: A declarative way to read and write binary file formats
|
9
|
-
require_paths:
|
10
|
-
- lib
|
11
|
-
email: dion@lostrealm.com
|
12
|
-
homepage: http://bindata.rubyforge.org
|
13
|
-
rubyforge_project: bindata
|
14
|
-
description:
|
15
|
-
autorequire: bindata
|
16
|
-
default_executable:
|
17
|
-
bindir: bin
|
18
|
-
has_rdoc: true
|
19
|
-
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.0.0
|
24
|
-
version:
|
4
|
+
version: 0.8.1
|
25
5
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
|
-
post_install_message:
|
29
6
|
authors:
|
30
7
|
- Dion Mendel
|
8
|
+
autorequire: bindata
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-01-14 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: dion@lostrealm.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
31
24
|
files:
|
32
25
|
- COPYING
|
33
26
|
- GPL
|
@@ -49,7 +42,6 @@ files:
|
|
49
42
|
- spec/struct_spec.rb
|
50
43
|
- spec/float_spec.rb
|
51
44
|
- lib/bindata
|
52
|
-
- lib/bindata.rb
|
53
45
|
- lib/bindata/int.rb
|
54
46
|
- lib/bindata/string.rb
|
55
47
|
- lib/bindata/base.rb
|
@@ -61,20 +53,35 @@ files:
|
|
61
53
|
- lib/bindata/lazy.rb
|
62
54
|
- lib/bindata/single.rb
|
63
55
|
- lib/bindata/float.rb
|
64
|
-
|
65
|
-
|
56
|
+
- lib/bindata.rb
|
57
|
+
has_rdoc: true
|
58
|
+
homepage: http://bindata.rubyforge.org
|
59
|
+
post_install_message:
|
66
60
|
rdoc_options:
|
67
61
|
- README
|
68
62
|
- lib/bindata
|
69
63
|
- -m
|
70
64
|
- README
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
77
79
|
requirements: []
|
78
80
|
|
79
|
-
|
81
|
+
rubyforge_project: bindata
|
82
|
+
rubygems_version: 1.0.1
|
83
|
+
signing_key:
|
84
|
+
specification_version: 2
|
85
|
+
summary: A declarative way to read and write binary file formats
|
86
|
+
test_files: []
|
80
87
|
|