bindata 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +11 -2
- data/README +55 -19
- data/TODO +4 -0
- data/examples/gzip.rb +3 -3
- data/lib/bindata.rb +8 -1
- data/lib/bindata/array.rb +58 -26
- data/lib/bindata/base.rb +133 -83
- data/lib/bindata/choice.rb +142 -61
- data/lib/bindata/float.rb +4 -0
- data/lib/bindata/int.rb +14 -0
- data/lib/bindata/lazy.rb +19 -2
- data/lib/bindata/multi_value.rb +144 -0
- data/lib/bindata/registry.rb +13 -8
- data/lib/bindata/rest.rb +41 -0
- data/lib/bindata/sanitize.rb +36 -0
- data/lib/bindata/single.rb +31 -6
- data/lib/bindata/single_value.rb +203 -0
- data/lib/bindata/string.rb +57 -32
- data/lib/bindata/stringz.rb +15 -0
- data/lib/bindata/struct.rb +189 -204
- data/spec/array_spec.rb +66 -42
- data/spec/base_spec.rb +202 -80
- data/spec/choice_spec.rb +172 -51
- data/spec/int_spec.rb +5 -5
- data/spec/lazy_spec.rb +26 -23
- data/spec/multi_value_spec.rb +250 -0
- data/spec/registry_spec.rb +8 -8
- data/spec/rest_spec.rb +30 -0
- data/spec/sanitize_spec.rb +108 -0
- data/spec/single_spec.rb +63 -49
- data/spec/single_value_spec.rb +131 -0
- data/spec/string_spec.rb +47 -47
- data/spec/stringz_spec.rb +29 -29
- data/spec/struct_spec.rb +112 -198
- metadata +58 -57
data/lib/bindata/stringz.rb
CHANGED
|
@@ -7,6 +7,17 @@ module BinData
|
|
|
7
7
|
# For convenience, the zero terminator is not necessary when setting the
|
|
8
8
|
# value. Likewise, the returned value will not be zero terminated.
|
|
9
9
|
#
|
|
10
|
+
# require 'bindata'
|
|
11
|
+
#
|
|
12
|
+
# data = "abcd\x00efgh"
|
|
13
|
+
#
|
|
14
|
+
# obj = BinData::Stringz.new
|
|
15
|
+
# obj.read(data)
|
|
16
|
+
# obj.snapshot #=> "abcd"
|
|
17
|
+
# obj.value #=> "abcd"
|
|
18
|
+
# obj.num_bytes #=> 5
|
|
19
|
+
# obj.to_s #=> "abcd\000"
|
|
20
|
+
#
|
|
10
21
|
# == Parameters
|
|
11
22
|
#
|
|
12
23
|
# Stringz objects accept all the params that BinData::Single
|
|
@@ -15,6 +26,10 @@ module BinData
|
|
|
15
26
|
# <tt>:max_length</tt>:: The maximum length of the string including the zero
|
|
16
27
|
# byte.
|
|
17
28
|
class Stringz < Single
|
|
29
|
+
|
|
30
|
+
# Register this class
|
|
31
|
+
register(self.name, self)
|
|
32
|
+
|
|
18
33
|
# These are the parameters used by this class.
|
|
19
34
|
optional_parameters :max_length
|
|
20
35
|
|
data/lib/bindata/struct.rb
CHANGED
|
@@ -1,41 +1,24 @@
|
|
|
1
1
|
require 'bindata/base'
|
|
2
|
+
require 'bindata/sanitize'
|
|
2
3
|
|
|
3
4
|
module BinData
|
|
4
5
|
# A Struct is an ordered collection of named data objects.
|
|
5
6
|
#
|
|
6
7
|
# require 'bindata'
|
|
7
8
|
#
|
|
8
|
-
# class Tuple < BinData::
|
|
9
|
+
# class Tuple < BinData::MultiValue
|
|
9
10
|
# int8 :x
|
|
10
11
|
# int8 :y
|
|
11
12
|
# int8 :z
|
|
12
13
|
# end
|
|
13
14
|
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
# int16le :b
|
|
19
|
-
# tuple nil
|
|
20
|
-
# end
|
|
21
|
-
#
|
|
22
|
-
# obj = SomeStruct.new
|
|
15
|
+
# obj = BinData::Struct.new(:hide => :a,
|
|
16
|
+
# :fields => [ [:int32le, :a],
|
|
17
|
+
# [:int16le, :b],
|
|
18
|
+
# [:tuple, :nil] ])
|
|
23
19
|
# obj.field_names =># ["b", "x", "y", "z"]
|
|
24
20
|
#
|
|
25
21
|
#
|
|
26
|
-
# class PascalString < BinData::Struct
|
|
27
|
-
# delegate :data
|
|
28
|
-
#
|
|
29
|
-
# uint8 :len, :value => lambda { data.length }
|
|
30
|
-
# string :data, :read_length => :len
|
|
31
|
-
# end
|
|
32
|
-
#
|
|
33
|
-
# str = PascalString.new
|
|
34
|
-
# str.value = "a test string"
|
|
35
|
-
# str.single_value? =># true
|
|
36
|
-
# str.len =># 13
|
|
37
|
-
# str.num_bytes =># 17
|
|
38
|
-
#
|
|
39
22
|
# == Parameters
|
|
40
23
|
#
|
|
41
24
|
# Parameters may be provided at initialisation to control the behaviour of
|
|
@@ -52,9 +35,14 @@ module BinData
|
|
|
52
35
|
# from the outside world. Hidden fields don't appear
|
|
53
36
|
# in #snapshot or #field_names but are still accessible
|
|
54
37
|
# by name.
|
|
55
|
-
# <tt>:
|
|
56
|
-
#
|
|
57
|
-
|
|
38
|
+
# <tt>:endian</tt>:: Either :little or :big. This specifies the default
|
|
39
|
+
# endian of any numerics in this struct, or in any
|
|
40
|
+
# nested data objects.
|
|
41
|
+
class Struct < BinData::Base
|
|
42
|
+
|
|
43
|
+
# Register this class
|
|
44
|
+
register(self.name, self)
|
|
45
|
+
|
|
58
46
|
# A hash that can be accessed via attributes.
|
|
59
47
|
class Snapshot < Hash #:nodoc:
|
|
60
48
|
def method_missing(symbol, *args)
|
|
@@ -62,18 +50,17 @@ module BinData
|
|
|
62
50
|
end
|
|
63
51
|
end
|
|
64
52
|
|
|
65
|
-
# Register this class
|
|
66
|
-
register(self.name, self)
|
|
67
|
-
|
|
68
53
|
class << self
|
|
69
|
-
|
|
54
|
+
#### DEPRECATION HACK to allow inheriting from BinData::Struct
|
|
55
|
+
#
|
|
70
56
|
def inherited(subclass) #:nodoc:
|
|
71
|
-
|
|
72
|
-
|
|
57
|
+
if subclass != MultiValue
|
|
58
|
+
# warn about deprecated method - remove before releasing 1.0
|
|
59
|
+
warn "warning: inheriting from BinData::Struct in deprecated. Inherit from BinData::MultiValue instead."
|
|
73
60
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
61
|
+
register(subclass.name, subclass)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
77
64
|
def endian(endian = nil)
|
|
78
65
|
@endian ||= nil
|
|
79
66
|
if [:little, :big].include?(endian)
|
|
@@ -83,19 +70,6 @@ module BinData
|
|
|
83
70
|
end
|
|
84
71
|
@endian
|
|
85
72
|
end
|
|
86
|
-
|
|
87
|
-
# Returns the name of the delegate field for this struct. The delegate
|
|
88
|
-
# is set to +name+ if given.
|
|
89
|
-
def delegate(name=nil)
|
|
90
|
-
@delegate ||= nil
|
|
91
|
-
if name != nil
|
|
92
|
-
@delegate = name.to_s
|
|
93
|
-
end
|
|
94
|
-
@delegate
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Returns the names of any hidden fields in this struct. Any given args
|
|
98
|
-
# are appended to the hidden list.
|
|
99
73
|
def hide(*args)
|
|
100
74
|
# note that fields are stored in an instance variable not a class var
|
|
101
75
|
@hide ||= []
|
|
@@ -105,119 +79,185 @@ module BinData
|
|
|
105
79
|
end
|
|
106
80
|
@hide
|
|
107
81
|
end
|
|
108
|
-
|
|
109
|
-
|
|
82
|
+
def fields
|
|
83
|
+
@fields || []
|
|
84
|
+
end
|
|
110
85
|
def method_missing(symbol, *args)
|
|
111
86
|
name, params = args
|
|
112
87
|
|
|
113
88
|
type = symbol
|
|
114
|
-
name = name.
|
|
89
|
+
name = (name.nil? or name == "") ? nil : name.to_s
|
|
115
90
|
params ||= {}
|
|
116
91
|
|
|
117
|
-
if lookup(type).nil?
|
|
118
|
-
raise TypeError, "unknown type '#{type}' for #{self}", caller
|
|
119
|
-
end
|
|
120
|
-
|
|
121
92
|
# note that fields are stored in an instance variable not a class var
|
|
122
|
-
|
|
123
|
-
# check for duplicate names
|
|
124
93
|
@fields ||= []
|
|
125
|
-
if @fields.detect { |t, n, p| n == name and n != nil }
|
|
126
|
-
raise SyntaxError, "duplicate field '#{name}' in #{self}", caller
|
|
127
|
-
end
|
|
128
94
|
|
|
129
|
-
# check that
|
|
130
|
-
if
|
|
131
|
-
raise
|
|
132
|
-
"field '#{name}' shadows an existing method", caller
|
|
95
|
+
# check that type is known
|
|
96
|
+
if lookup(type, endian).nil?
|
|
97
|
+
raise TypeError, "unknown type '#{type}' for #{self}", caller
|
|
133
98
|
end
|
|
134
99
|
|
|
135
|
-
# check that name
|
|
136
|
-
if
|
|
137
|
-
|
|
138
|
-
|
|
100
|
+
# check that name is okay
|
|
101
|
+
if name != nil
|
|
102
|
+
# check for duplicate names
|
|
103
|
+
@fields.each do |t, n, p|
|
|
104
|
+
if n == name
|
|
105
|
+
raise SyntaxError, "duplicate field '#{name}' in #{self}", caller
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# check that name doesn't shadow an existing method
|
|
110
|
+
if self.instance_methods.include?(name)
|
|
111
|
+
raise NameError.new("", name),
|
|
112
|
+
"field '#{name}' shadows an existing method", caller
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# check that name isn't reserved
|
|
116
|
+
if ::Hash.instance_methods.include?(name)
|
|
117
|
+
raise NameError.new("", name),
|
|
118
|
+
"field '#{name}' is a reserved name", caller
|
|
119
|
+
end
|
|
139
120
|
end
|
|
140
121
|
|
|
141
122
|
# remember this field. These fields will be recalled upon creating
|
|
142
123
|
# an instance of this class
|
|
143
124
|
@fields.push([type, name, params])
|
|
144
125
|
end
|
|
126
|
+
def deprecated_hack(params, endian = nil)
|
|
127
|
+
params = params.dup
|
|
145
128
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
129
|
+
# possibly override endian
|
|
130
|
+
endian = params[:endian] || self.endian || endian
|
|
131
|
+
unless endian.nil?
|
|
132
|
+
params[:endian] = endian
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
params[:fields] = params[:fields] || self.fields
|
|
136
|
+
params[:hide] = params[:hide] || self.hide
|
|
137
|
+
|
|
138
|
+
[params, endian]
|
|
149
139
|
end
|
|
150
|
-
|
|
140
|
+
#
|
|
141
|
+
#### DEPRECATION HACK to allow inheriting from BinData::Struct
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Returns a sanitized +params+ that is of the form expected
|
|
145
|
+
# by #initialize.
|
|
146
|
+
def sanitize_parameters(params, endian = nil)
|
|
147
|
+
#### DEPRECATION HACK to allow inheriting from BinData::Struct
|
|
148
|
+
#
|
|
149
|
+
params, endian = deprecated_hack(params, endian)
|
|
150
|
+
#
|
|
151
|
+
#### DEPRECATION HACK to allow inheriting from BinData::Struct
|
|
152
|
+
|
|
153
|
+
params = params.dup
|
|
154
|
+
|
|
155
|
+
# possibly override endian
|
|
156
|
+
endian = params[:endian] || endian
|
|
157
|
+
if endian != nil
|
|
158
|
+
unless [:little, :big].include?(endian)
|
|
159
|
+
raise ArgumentError, "unknown value for endian '#{endian}'"
|
|
160
|
+
end
|
|
151
161
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
optional_parameters :endian, :hide, :delegate
|
|
162
|
+
params[:endian] = endian
|
|
163
|
+
end
|
|
155
164
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
165
|
+
if params.has_key?(:fields)
|
|
166
|
+
# ensure the names of fields are strings and that params is sanitized
|
|
167
|
+
all_fields = params[:fields].collect do |ftype, fname, fparams|
|
|
168
|
+
fname = fname.nil? ? "" : fname.to_s
|
|
169
|
+
klass = lookup(ftype, endian)
|
|
170
|
+
raise TypeError, "unknown type '#{ftype}' for #{self}" if klass.nil?
|
|
171
|
+
[klass, fname, SanitizedParameters.new(klass, fparams, endian)]
|
|
172
|
+
end
|
|
173
|
+
params[:fields] = all_fields
|
|
174
|
+
|
|
175
|
+
# collect all hidden names that correspond to a field name
|
|
176
|
+
hide = []
|
|
177
|
+
if params.has_key?(:hide)
|
|
178
|
+
hidden = params[:hide] || []
|
|
179
|
+
hidden.each do |h|
|
|
180
|
+
next if h.nil? or h == ""
|
|
181
|
+
h = h.to_s
|
|
182
|
+
hide << h if all_fields.find { |k,n,p| n == h }
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
params[:hide] = hide
|
|
172
186
|
end
|
|
173
187
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
188
|
+
# obtain SanitizedParameters
|
|
189
|
+
params = super(params, endian)
|
|
190
|
+
|
|
191
|
+
# now params are sanitized, check that parameter names are okay
|
|
192
|
+
|
|
193
|
+
field_names = []
|
|
194
|
+
instance_methods = self.instance_methods
|
|
195
|
+
reserved_names = ::Hash.instance_methods
|
|
196
|
+
|
|
197
|
+
params[:fields].each do |fklass, fname, fparams|
|
|
198
|
+
|
|
199
|
+
# check that name doesn't shadow an existing method
|
|
200
|
+
if instance_methods.include?(fname)
|
|
201
|
+
raise NameError.new("field '#{fname}' shadows an existing method in #{self}. Rename it.", fname)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# check that name isn't reserved
|
|
205
|
+
if reserved_names.include?(fname)
|
|
206
|
+
raise NameError.new("field '#{fname}' is a reserved name in #{self}. Rename it.", fname)
|
|
207
|
+
end
|
|
178
208
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
209
|
+
if fname == ""
|
|
210
|
+
fklass.all_possible_field_names(fparams).each do |name|
|
|
211
|
+
if field_names.include?(name)
|
|
212
|
+
raise NameError.new("field '#{name}' is defined multiple times in #{self}.", name)
|
|
213
|
+
end
|
|
214
|
+
field_names << name
|
|
215
|
+
end
|
|
216
|
+
else
|
|
217
|
+
if field_names.include?(fname)
|
|
218
|
+
raise NameError.new("field '#{fname}' is defined multiple times in #{self}.", fname)
|
|
219
|
+
end
|
|
220
|
+
field_names << fname
|
|
184
221
|
end
|
|
185
222
|
end
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
# no delegate so all instance methods of Hash are reserved
|
|
189
|
-
all_reserved_methods = Hash.instance_methods - all_methods
|
|
223
|
+
|
|
224
|
+
params
|
|
190
225
|
end
|
|
191
226
|
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
227
|
+
# Returns a list of the names of all possible field names for a Struct
|
|
228
|
+
# created with +sanitized_params+. Hidden names will not be included
|
|
229
|
+
# in the returned list.
|
|
230
|
+
def all_possible_field_names(sanitized_params)
|
|
231
|
+
unless SanitizedParameters === sanitized_params
|
|
232
|
+
raise ArgumentError, "parameters aren't sanitized"
|
|
233
|
+
end
|
|
196
234
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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)
|
|
235
|
+
hidden_names = sanitized_params[:hide]
|
|
236
|
+
|
|
237
|
+
names = []
|
|
238
|
+
sanitized_params[:fields].each do |fklass, fname, fparams|
|
|
239
|
+
if fname == ""
|
|
240
|
+
names.concat(fklass.all_possible_field_names(fparams))
|
|
241
|
+
else
|
|
242
|
+
names << fname unless hidden_names.include?(fname)
|
|
209
243
|
end
|
|
210
244
|
end
|
|
211
|
-
|
|
245
|
+
|
|
246
|
+
names
|
|
212
247
|
end
|
|
213
248
|
end
|
|
214
249
|
|
|
215
|
-
#
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
250
|
+
# These are the parameters used by this class.
|
|
251
|
+
mandatory_parameter :fields
|
|
252
|
+
optional_parameters :endian, :hide
|
|
253
|
+
|
|
254
|
+
# Creates a new Struct.
|
|
255
|
+
def initialize(params = {}, env = nil)
|
|
256
|
+
super(params, env)
|
|
257
|
+
|
|
258
|
+
# create instances of the fields
|
|
259
|
+
@fields = param(:fields).collect do |fklass, fname, fparams|
|
|
260
|
+
[fname, fklass.new(fparams, create_env)]
|
|
221
261
|
end
|
|
222
262
|
end
|
|
223
263
|
|
|
@@ -270,39 +310,36 @@ module BinData
|
|
|
270
310
|
|
|
271
311
|
# Returns a snapshot of this struct as a hash.
|
|
272
312
|
def snapshot
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
hash = Snapshot.new
|
|
277
|
-
field_names.each do |name|
|
|
278
|
-
hash[name] = find_obj_for_name(name).snapshot
|
|
279
|
-
end
|
|
280
|
-
hash
|
|
313
|
+
hash = Snapshot.new
|
|
314
|
+
field_names.each do |name|
|
|
315
|
+
hash[name] = find_obj_for_name(name).snapshot
|
|
281
316
|
end
|
|
317
|
+
hash
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Returns whether this data object contains a single value. Single
|
|
321
|
+
# value data objects respond to <tt>#value</tt> and <tt>#value=</tt>.
|
|
322
|
+
def single_value?
|
|
323
|
+
return false
|
|
282
324
|
end
|
|
283
325
|
|
|
284
326
|
# Returns a list of the names of all fields accessible through this
|
|
285
327
|
# object. +include_hidden+ specifies whether to include hidden names
|
|
286
328
|
# in the listing.
|
|
287
329
|
def field_names(include_hidden = false)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
@fields.each do |name, obj|
|
|
296
|
-
if name != ""
|
|
297
|
-
if include_hidden or not hidden.include?(name)
|
|
298
|
-
names << name
|
|
299
|
-
end
|
|
300
|
-
else
|
|
301
|
-
names.concat(obj.field_names)
|
|
330
|
+
# collect field names
|
|
331
|
+
names = []
|
|
332
|
+
hidden = param(:hide)
|
|
333
|
+
@fields.each do |name, obj|
|
|
334
|
+
if name != ""
|
|
335
|
+
if include_hidden or not hidden.include?(name)
|
|
336
|
+
names << name
|
|
302
337
|
end
|
|
338
|
+
else
|
|
339
|
+
names.concat(obj.field_names)
|
|
303
340
|
end
|
|
304
|
-
names
|
|
305
341
|
end
|
|
342
|
+
names
|
|
306
343
|
end
|
|
307
344
|
|
|
308
345
|
# Returns the data object that stores values for +name+.
|
|
@@ -332,18 +369,11 @@ module BinData
|
|
|
332
369
|
offset
|
|
333
370
|
end
|
|
334
371
|
|
|
335
|
-
# Override to include field names
|
|
372
|
+
# Override to include field names
|
|
336
373
|
alias_method :orig_respond_to?, :respond_to?
|
|
337
374
|
def respond_to?(symbol, include_private = false)
|
|
338
375
|
orig_respond_to?(symbol, include_private) ||
|
|
339
|
-
field_names(true).include?(symbol.id2name.chomp("="))
|
|
340
|
-
delegate_object.respond_to?(symbol, include_private)
|
|
341
|
-
end
|
|
342
|
-
|
|
343
|
-
# Returns whether this data object contains a single value. Single
|
|
344
|
-
# value data objects respond to <tt>#value</tt> and <tt>#value=</tt>.
|
|
345
|
-
def single_value?
|
|
346
|
-
delegate_object ? delegate_object.single_value? : false
|
|
376
|
+
field_names(true).include?(symbol.id2name.chomp("="))
|
|
347
377
|
end
|
|
348
378
|
|
|
349
379
|
def method_missing(symbol, *args, &block)
|
|
@@ -362,8 +392,6 @@ module BinData
|
|
|
362
392
|
else
|
|
363
393
|
obj
|
|
364
394
|
end
|
|
365
|
-
elsif delegate_object.respond_to?(symbol)
|
|
366
|
-
delegate_object.__send__(symbol, *args, &block)
|
|
367
395
|
else
|
|
368
396
|
super
|
|
369
397
|
end
|
|
@@ -372,52 +400,9 @@ module BinData
|
|
|
372
400
|
#---------------
|
|
373
401
|
private
|
|
374
402
|
|
|
375
|
-
# Returns the delegate object if any.
|
|
376
|
-
def delegate_object
|
|
377
|
-
if (name = param(:delegate))
|
|
378
|
-
find_obj_for_name(name)
|
|
379
|
-
else
|
|
380
|
-
nil
|
|
381
|
-
end
|
|
382
|
-
end
|
|
383
|
-
|
|
384
403
|
# Returns a list of all the bindata objects for this struct.
|
|
385
404
|
def bindata_objects
|
|
386
405
|
@fields.collect { |f| f[1] }
|
|
387
406
|
end
|
|
388
|
-
|
|
389
|
-
# Returns a hash of cleaned +params+. Cleaning means that param
|
|
390
|
-
# values are converted to a desired format.
|
|
391
|
-
def cleaned_params(params)
|
|
392
|
-
new_params = params.dup
|
|
393
|
-
|
|
394
|
-
# use fields defined in this class if no fields are passed as params
|
|
395
|
-
fields = new_params[:fields] || self.class.fields
|
|
396
|
-
|
|
397
|
-
# ensure the names of fields are strings and that params is a hash
|
|
398
|
-
new_params[:fields] = fields.collect do |t, n, p|
|
|
399
|
-
[t, n.to_s, (p || {}).dup]
|
|
400
|
-
end
|
|
401
|
-
|
|
402
|
-
# collect all non blank field names
|
|
403
|
-
field_names = new_params[:fields].collect { |f| f[1] }
|
|
404
|
-
field_names = field_names.delete_if { |n| n == "" }
|
|
405
|
-
|
|
406
|
-
# collect all hidden names that correspond to a field name
|
|
407
|
-
hide = []
|
|
408
|
-
(new_params[:hide] || self.class.hide).each do |h|
|
|
409
|
-
h = h.to_s
|
|
410
|
-
hide << h if field_names.include?(h)
|
|
411
|
-
end
|
|
412
|
-
new_params[:hide] = hide
|
|
413
|
-
|
|
414
|
-
# collect delegate name if it corresponds to a field name
|
|
415
|
-
if (delegate = (new_params[:delegate] || self.class.delegate))
|
|
416
|
-
delegate = delegate.to_s
|
|
417
|
-
new_params[:delegate] = delegate if field_names.include?(delegate)
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
new_params
|
|
421
|
-
end
|
|
422
407
|
end
|
|
423
408
|
end
|