Class: LibBin::DataConverter

Inherits:
Object
  • Object
show all
Includes:
Alignment
Defined in:
lib/libbin.rb,
lib/libbin/data_types.rb

Defined Under Namespace

Classes: Scalar, Str

Constant Summary collapse

SCALAR_TYPES =
{
 :c => [:Int8, :int8],
 :C => [:UInt8, :uint8],
 :s => [:Int16, :int16],
 :"s<" => [:Int16_LE, :int16_le],
 :"s>" => [:Int16_BE, :int16_be],
 :S => [:UInt16, :uint16],
 :"S<" => [:UInt16_LE, :uint16_le],
 :"S>" => [:UInt16_BE, :uint16_be],
 :v => [:UInt16_LE, :uint16_le],
 :n => [:UInt16_BE, :uint16_be],
 :l => [:Int32, :int32],
 :"l<" => [:Int32_LE, :int32_le],
 :"l>" => [:Int32_BE, :int32_be],
 :L => [:UInt32, :uint32],
 :"L<" => [:UInt32_LE, :uint32_le],
 :"L>" => [:UInt32_BE, :uint32_be],
 :V => [:UInt32_LE, :uint32_le],
 :N => [:UInt32_BE, :uint32_be],
 :q => [:Int64, :int64],
 :"q<" => [:Int64_LE, :int64_le],
 :"q>" => [:Int64_BE, :int64_be],
 :Q => [:UInt64, :uint64],
 :"Q<" => [:UInt64_LE, :uint64_le],
 :"Q>" => [:UInt64_BE, :uint64_be],
 :F => [:Flt, :float],
 :e => [:Flt_LE, :float_le],
 :g => [:Flt_BE, :float_be],
 :D => [:Double, :double],
 :E => [:Double_LE, :double_le],
 :G => [:Double_BE, :double_be],
 :half => [:Half, :half],
 :half_le => [:Half_LE, :half_le],
 :half_be => [:Half_BE, :half_be],
 :pghalf => [:PGHalf, :pghalf],
 :pghalf_le => [:PGHalf_LE, :pghalf_le],
 :pghalf_be => [:PGHalf_BE, :pghalf_be]
}
DATA_SIZES =
Hash::new { |h,k|
  if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
    m[1].to_i
  else
    nil
  end
}
DATA_ENDIAN =
{
  true => Hash::new { |h,k|
    if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
      l[k]
    else
      nil
    end
  },
  false => Hash::new { |h,k|
    if k.kind_of?(Symbol) && m = k.match(/a(\d+)/)
      l[k]
    else
      nil
    end
  }
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#__indexObject (readonly)

Returns the value of attribute __index.



29
30
31
# File 'lib/libbin.rb', line 29

def __index
  @__index
end

#__iteratorObject (readonly)

Returns the value of attribute __iterator.



30
31
32
# File 'lib/libbin.rb', line 30

def __iterator
  @__iterator
end

#__parentObject (readonly)

Returns the value of attribute __parent.



28
29
30
# File 'lib/libbin.rb', line 28

def __parent
  @__parent
end

#__positionObject (readonly)

Returns the value of attribute __position.



31
32
33
# File 'lib/libbin.rb', line 31

def __position
  @__position
end

Class Method Details

.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big?,, parent = nil, index = nil, length = nil) ⇒ Object



338
339
340
341
342
343
344
345
346
347
348
# File 'lib/libbin.rb', line 338

def self.convert(input, output, input_big = LibBin::default_big?, output_big = !LibBin::default_big?, parent = nil, index = nil, length = nil)
  if length
    length.times.collect {
      h = self::new
      h.__load(input, input_big, parent, index)
    }
  else
    h = self::new
    h.__convert(input, output, input_big, output_big, parent, index)
  end
end

.create_scalar_type(symbol) ⇒ Object



433
434
435
436
437
438
439
440
441
442
443
444
445
# File 'lib/libbin/data_types.rb', line 433

def self.create_scalar_type(symbol)
  klassname, name = SCALAR_TYPES[symbol]
  eval <<EOF
class #{klassname} < Scalar
  init(#{symbol.inspect})
end

def self.#{name}(field, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
  @fields.push(Field::new(field, #{klassname}, length, count, offset, sequence, condition, relative_offset))
  attr_accessor field
end
EOF
end

.dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil) ⇒ Object



362
363
364
365
366
367
368
369
370
371
# File 'lib/libbin.rb', line 362

def self.dump(value, output, output_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
  if length
    length.times.collect { |i|
      value[i].__dump(output, output_big, parent, index)
    }
    value
  else
    value.__dump(output, output_big, parent, index)
  end
end

.inherited(subclass) ⇒ Object



104
105
106
# File 'lib/libbin.rb', line 104

def self.inherited(subclass)
  subclass.instance_variable_set(:@fields, [])
end

.load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil) ⇒ Object



350
351
352
353
354
355
356
357
358
359
360
# File 'lib/libbin.rb', line 350

def self.load(input, input_big = LibBin::default_big?, parent = nil, index = nil, length = nil)
  if length
    length.times.collect {
      h = self::new
      h.__load(input, input_big, parent, index)
    }
  else
    h = self::new
    h.__load(input, input_big, parent, index)
  end
end

.register_field(field, type, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false) ⇒ Object



419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/libbin/data_types.rb', line 419

def self.register_field(field, type, length: nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
  if type.kind_of?(Symbol)
    if type[0] == 'a'
      real_type = Class::new(Str) do init(sym) end
    else
      real_type = const_get(SCALAR_TYPES[type][0])
    end
  else
    real_type = type
  end
  @fields.push(Field::new(field, real_type, length, count, offset, sequence, condition, relative_offset))
  attr_accessor field
end

.shape(value, previous_offset = 0, parent = nil, index = nil, kind = DataShape, length = nil) ⇒ Object



381
382
383
384
385
386
387
388
389
# File 'lib/libbin.rb', line 381

def self.shape(value, previous_offset = 0, parent = nil, index = nil, kind = DataShape, length = nil)
  if length
    kind::new(length.times.collect { |i|
      value[i].__shape(previous_offset, parent, index, kind)
    })
  else
    value.__shape(previous_offset, parent, index, kind)
  end
end

.size(value, previous_offset = 0, parent = nil, index = nil, length = nil) ⇒ Object



373
374
375
376
377
378
379
# File 'lib/libbin.rb', line 373

def self.size(value, previous_offset = 0, parent = nil, index = nil, length = nil)
  if length
    shape(value, previous_offset, parent, index, length).size
  else
    value.__shape(previous_offset, parent, index).size
  end
end

.string(field, length = nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false) ⇒ Object



480
481
482
483
484
485
486
487
# File 'lib/libbin/data_types.rb', line 480

def self.string( field, length = nil, count: nil, offset: nil, sequence: false, condition: nil, relative_offset: false)
  sym = (length ? :"a" : :"a*")
  c = Class::new(Str) do
    init(sym)
  end
  @fields.push(Field::new(field, c, length, count, offset, sequence, condition, relative_offset))
  attr_accessor field
end

Instance Method Details

#__convert(input, output, input_big, output_big, parent = nil, index = nil) ⇒ Object



317
318
319
320
321
322
# File 'lib/libbin.rb', line 317

def __convert(input, output, input_big, output_big, parent = nil, index = nil)
  __set_convert_type(input, output, input_big, output_big, parent, index)
  __convert_fields
  __unset_convert_type
  self
end

#__convert_field(field) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/libbin.rb', line 190

def __convert_field(field)
  __decode_static_conditions(field)
  vs = @__count.times.collect do |it|
    @__iterator = it
    if __decode_dynamic_conditions(field)
      @__type::convert(@__input, @__output, @__input_big, @__output_big, self, it, @__length)
    else
      nil
    end
  end
  __restore_context
  vs = vs.first unless field.count
  vs
end

#__convert_fieldsObject



272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/libbin.rb', line 272

def __convert_fields
  self.class.instance_variable_get(:@fields).each { |field|
    begin
      vs = catch(:ignored) do
        __convert_field(field)
      end
      send("#{field.name}=", vs)
    rescue
      STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
      raise
    end
  }
  self
end

#__decode_condition(condition) ⇒ Object



131
132
133
134
# File 'lib/libbin.rb', line 131

def __decode_condition(condition)
  return true unless condition
  __decode_expression(condition)
end

#__decode_count(count) ⇒ Object



136
137
138
139
# File 'lib/libbin.rb', line 136

def __decode_count(count)
  return 1 unless count
  __decode_expression(count)
end

#__decode_dynamic_conditions(field) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/libbin.rb', line 166

def __decode_dynamic_conditions(field)
  return true unless field.sequence?
  @__offset = nil
  @__condition = nil
  @__type = nil
  @__length = nil
  @__offset = __decode_seek_offset(field.offset, field.relative_offset?)
  return false if @__offset == false
  @__condition = __decode_condition(field.condition)
  return false unless @__condition
  @__type = __decode_type(field.type)
  @__length = __decode_length(field.length)
  return true
end

#__decode_expression(sym) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/libbin.rb', line 108

def __decode_expression(sym)
  case sym
  when Proc
    return sym.call
  when String
    exp = sym.gsub("..","__parent").gsub("\\",".")
    return eval(exp)
  else
    return sym
  end
end

#__decode_length(length) ⇒ Object



145
146
147
# File 'lib/libbin.rb', line 145

def __decode_length(length)
  __decode_expression(length)
end

#__decode_seek_offset(offset, relative_offset) ⇒ Object



120
121
122
123
124
125
126
127
128
129
# File 'lib/libbin.rb', line 120

def __decode_seek_offset(offset, relative_offset)
  return nil unless offset
  offset = __decode_expression(offset)
  return false if offset == 0x0
  offset += @__position if relative_offset
  @__cur_position = offset
  @__input.seek(offset) if @__input
  @__output.seek(offset) if @__output
  offset
end

#__decode_static_conditions(field) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/libbin.rb', line 149

def __decode_static_conditions(field)
  @__offset = nil
  @__condition = nil
  @__type = nil
  @__length = nil
  @__count = nil
  unless field.sequence?
    @__offset = __decode_seek_offset(field.offset, field.relative_offset?)
    throw :ignored, nil if @__offset == false
    @__condition = __decode_condition(field.condition)
    throw :ignored, nil unless @__condition
    @__type = __decode_type(field.type)
    @__length = __decode_length(field.length)
  end
  @__count = __decode_count(field.count)
end

#__decode_type(type) ⇒ Object



141
142
143
# File 'lib/libbin.rb', line 141

def __decode_type(type)
  return __decode_expression(type)
end

#__dump(output, output_big, parent = nil, index = nil) ⇒ Object



331
332
333
334
335
336
# File 'lib/libbin.rb', line 331

def __dump(output, output_big, parent = nil, index = nil)
  __set_dump_type(output, output_big, parent, index)
  __dump_fields
  __unset_dump_type
  self
end

#__dump_field(vs, field) ⇒ Object



220
221
222
223
224
225
226
227
228
229
230
# File 'lib/libbin.rb', line 220

def __dump_field(vs, field)
  __decode_static_conditions(field)
  vs = [vs] unless field.count
  vs.each_with_index do |v, it|
    @__iterator = it
    if __decode_dynamic_conditions(field)
      @__type::dump(v, @__output, @__output_big, self, it, @__length)
    end
  end
  __restore_context
end

#__dump_fieldsObject



302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'lib/libbin.rb', line 302

def __dump_fields
  self.class.instance_variable_get(:@fields).each { |field|
    begin
      vs = send(field.name)
      catch(:ignored) do
        __dump_field(vs, field)
      end
    rescue
      STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
      raise
    end
  }
  self
end

#__load(input, input_big, parent = nil, index = nil) ⇒ Object



324
325
326
327
328
329
# File 'lib/libbin.rb', line 324

def __load(input, input_big, parent = nil, index = nil)
  __set_load_type(input, input_big, parent, index)
  __load_fields
  __unset_load_type
  self
end

#__load_field(field) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/libbin.rb', line 205

def __load_field(field)
  __decode_static_conditions(field)
  vs = @__count.times.collect do |it|
    @__iterator = it
    if __decode_dynamic_conditions(field)
      @__type::load(@__input, @__input_big, self, it, @__length)
    else
      nil
    end
  end
  __restore_context
  vs = vs.first unless field.count
  vs
end

#__load_fieldsObject



287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/libbin.rb', line 287

def __load_fields
  self.class.instance_variable_get(:@fields).each { |field|
    begin
      vs = catch(:ignored) do
        __load_field(field)
      end
      send("#{field.name}=", vs)
    rescue
      STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
      raise
    end
  }
  self
end

#__restore_contextObject



181
182
183
184
185
186
187
188
# File 'lib/libbin.rb', line 181

def __restore_context
  @__iterator = nil
  @__type = nil
  @__length = nil
  @__count = nil
  @__offset = nil
  @__condition = nil
end

#__set_convert_type(input, output, input_big, output_big, parent, index) ⇒ Object



32
33
34
35
36
37
38
39
40
41
# File 'lib/libbin.rb', line 32

def __set_convert_type(input, output, input_big, output_big, parent, index)
  @__input_big = input_big
  @__output_big = output_big
  @__input = input
  @__output = output
  @__parent = parent
  @__index = index
  @__position = input.tell
  @__cur_position = @__position
end

#__set_dump_type(output, output_big, parent, index) ⇒ Object



59
60
61
62
63
64
65
66
# File 'lib/libbin.rb', line 59

def __set_dump_type(output, output_big, parent, index)
  @__output_big = output_big
  @__output = output
  @__parent = parent
  @__index = index
  @__position = output.tell
  @__cur_position = @__position
end

#__set_load_type(input, input_big, parent, index) ⇒ Object



50
51
52
53
54
55
56
57
# File 'lib/libbin.rb', line 50

def __set_load_type(input, input_big, parent, index)
  @__input_big = input_big
  @__input = input
  @__parent = parent
  @__index = index
  @__position = input.tell
  @__cur_position = @__position
end

#__set_size_type(position, parent, index) ⇒ Object



43
44
45
46
47
48
# File 'lib/libbin.rb', line 43

def __set_size_type(position, parent, index)
  @__parent = parent
  @__index = index
  @__position = position
  @__cur_position = @__position
end

#__shape(previous_offset = 0, parent = nil, index = nil, kind = DataShape) ⇒ Object



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/libbin.rb', line 252

def __shape(previous_offset = 0, parent = nil, index = nil, kind = DataShape)
  __set_size_type(previous_offset, parent, index)
  members = {}
  self.class.instance_variable_get(:@fields).each { |field|
    begin
      vs = send(field.name)
      member = catch(:ignored) do
        __shape_field(vs, previous_offset, kind, field)
      end
      members[field.name] = member
    rescue
      STDERR.puts "#{self.class}: #{field.name}(#{field.type})"
      raise
    end
  }
  __unset_size_type
  return nil if members.values.flatten.compact.size <= 0
  kind::new(members)
end

#__shape_field(vs, previous_offset, kind, field) ⇒ Object



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/libbin.rb', line 232

def __shape_field(vs, previous_offset, kind, field)
  __decode_static_conditions(field)
  vs = [vs] unless field.count
  vs = vs.each_with_index.collect do |v, it|
    @__iterator = it
    if __decode_dynamic_conditions(field)
      sh = @__type::shape(v, @__cur_position, self, it, kind, @__length)
      @__cur_position = sh.last + 1 if sh.last && sh.last >= 0
      sh
    end
  end
  __restore_context
  vs = vs.first unless field.count
  vs
end

#__size(previous_offset = 0, parent = nil, index = nil) ⇒ Object



248
249
250
# File 'lib/libbin.rb', line 248

def __size(previous_offset = 0, parent = nil, index = nil)
  __shape(previous_offset, parent, index, DataRange).size
end

#__unset_convert_typeObject



68
69
70
71
72
73
74
75
76
77
# File 'lib/libbin.rb', line 68

def __unset_convert_type
  @__input_big = nil
  @__output_big = nil
  @__input = nil
  @__output = nil
  @__parent = nil
  @__index = nil
  @__position = nil
  @__cur_position = nil
end

#__unset_dump_typeObject



95
96
97
98
99
100
101
102
# File 'lib/libbin.rb', line 95

def __unset_dump_type
  @__output_big = nil
  @__output = nil
  @__parent = nil
  @__index = nil
  @__position = nil
  @__cur_position = nil
end

#__unset_load_typeObject



86
87
88
89
90
91
92
93
# File 'lib/libbin.rb', line 86

def __unset_load_type
  @__input_big = nil
  @__input = nil
  @__parent = nil
  @__index = nil
  @__position = nil
  @__cur_position = nil
end

#__unset_size_typeObject



79
80
81
82
83
84
# File 'lib/libbin.rb', line 79

def __unset_size_type
  @__parent = nil
  @__index = nil
  @__position = nil
  @__cur_position = nil
end

#inspectObject



24
25
26
# File 'lib/libbin.rb', line 24

def inspect
  to_s
end