Module: BitStream::ClassMethods

Defined in:
lib/bitstream.rb

Class Method Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object



475
476
477
478
479
480
481
482
483
484
# File 'lib/bitstream.rb', line 475

def method_missing(name, *args)
  field_name = args.shift
  aliasee = resolve_alias(name, args)
  args.unshift(field_name)
  if aliasee.nil?
    super name, *args
  else
    return send(aliasee, *args)
  end
end

Class Method Details

.add_type(type, method_name = nil, bs = self) ⇒ Object



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
# File 'lib/bitstream.rb', line 303

def self.add_type(type, method_name = nil, bs = self)
  bs.instance_eval do
    define_method(method_name) do |*args|
      name = args.shift.intern
      #if respond_to? name
      #  raise "#{name} has already defined."
      #end
      
      props = @instance.bitstream_properties
      fields = props.fields
      queue = props.eval_queue
      user_props = props.user_props
      
      case props.mode
      when :field_def
        type_instance = get_type(method_name, user_props, *args)
        field = FieldReader.new(type_instance, @instance)
        queue.enq(field)

        name_in_method = name

        @instance.singleton_class.instance_eval do
          define_method name do
            field.value
          end
        end

        instance = @instance
        singleton_class.instance_eval do
          define_method name_in_method do
            instance.send(name_in_method)
          end
        end
      end
    end
  end
end

.alias_type(alias_name, aliasee) ⇒ Object



286
287
288
289
# File 'lib/bitstream.rb', line 286

def self.alias_type(alias_name, aliasee)
  @types[alias_name] = @types[aliasee]
  alias_method(alias_name, aliasee)
end

.register_type(type, name = nil) ⇒ Object



275
276
277
278
279
280
281
282
283
284
# File 'lib/bitstream.rb', line 275

def self.register_type(type, name = nil)
  if name.nil?
    name = Utils.class2symbol type
  end
  
  @types = {} if @types.nil?
  @types[name] = type

  add_type(type, name, self)
end

.register_types(types) ⇒ Object



269
270
271
272
273
# File 'lib/bitstream.rb', line 269

def self.register_types(types)
  types.each do |t|
    register_type(t, nil)
  end
end

.typesObject



265
266
267
# File 'lib/bitstream.rb', line 265

def self.types
  @types
end

Instance Method Details

#add_type(type, name = nil) ⇒ Object



448
449
450
451
452
453
454
# File 'lib/bitstream.rb', line 448

def add_type(type, name = nil)
  if name.nil?
    name = Utils.class2symbol(type)
  end
  @types[name] = type
  ClassMethods.add_type(type, name, self.singleton_class)
end

#array(name, size, type_name, *type_args) ⇒ Object



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/bitstream.rb', line 341

def array(name, size, type_name, *type_args)
  name = name.intern
  props = @instance.bitstream_properties
  queue = props.eval_queue
  user_props = props.user_props

  type_instance = get_type(type_name, user_props, *type_args)

  case props.mode
  when :field_def
    field = ArrayProxy.new(@instance)
    if size.respond_to?(:to_int) && size >= 0
      size.times do
        field_element = FieldReader.new(type_instance, @instance)
        field.add_field(field_element)
        queue.enq(field_element)
      end
    else
      queue.peek_back.index unless queue.empty?
      while props.curr_offset < props.raw_data.bytesize * 8
        field_element = FieldReader.new(type_instance, @instance)
        field.add_field(field_element)
        queue.enq(field_element)
        field_element.index
        #puts "curr_offset:#{props.curr_offset} bytesize:#{props.raw_data.bytesize}"
      end
    end

    @instance.singleton_class.instance_eval do
      define_method name do
        field
      end
    end

    name_in_method = name
    instance = @instance
    singleton_class.instance_eval do
      define_method name do
        instance.send(name_in_method)
      end
    end
  end
end

#byte_order(order) ⇒ Object



295
296
297
# File 'lib/bitstream.rb', line 295

def byte_order(order)
  @class_props[:byte_order] = order.intern
end

#create(s, props = {}) ⇒ Object



460
461
462
# File 'lib/bitstream.rb', line 460

def create(s, props = {})
  create_with_offset(s, 0, props)
end

#create_with_offset(s, offset, props = {}) ⇒ Object



464
465
466
467
468
469
470
471
472
473
# File 'lib/bitstream.rb', line 464

def create_with_offset(s, offset, props = {})
  props[:nest_chain] = [] unless props.include?(:nest_chain)
  klass = Class.new(self)
  instance = klass.new
  instance.initialize_properties(s, offset)
  instance.bitstream_properties.user_props = props
  initialize_instance(s, instance)
  instance.initialize_with_fields
  return instance
end

#dyn_array(name, type_name, *type_args) ⇒ Object



385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/bitstream.rb', line 385

def dyn_array(name, type_name, *type_args)
  name = name.intern
  props = @instance.bitstream_properties
  fields = props.fields
  queue = props.eval_queue
  user_props = props.user_props

  type_instance = get_type(type_name, user_props, *type_args)

  case props.mode
  when :field_def
    if fields[name].nil?
      fields[name] = ArrayProxy.new(@instance)
    end
    field = FieldReader.new(type_instance, @instance)
    fields[name].add_field(field)
    queue.enq(field)

    name_in_method = name
    
    @instance.singleton_class.instance_eval do
      define_method name do
        return fields[name_in_method]
      end
    end

    instance = @instance
    singleton_class.instance_eval do
      define_method name do
        instance.send(name_in_method)
      end
    end
  end
end

#fields(&field_def) ⇒ Object



233
234
235
# File 'lib/bitstream.rb', line 233

def fields(&field_def)
  @field_defs << field_def
end

#initialize_for_class_methods(types) ⇒ Object



222
223
224
225
226
227
228
229
230
231
# File 'lib/bitstream.rb', line 222

def initialize_for_class_methods(types)
  @field_defs = []
  @fields = {}
  @types = types.dup
  @index = 0
  @singleton_props = {}
  @class_props = {}
  @class_props_chain = [@class_props]
  @bitstream_mutex = Mutex.new
end

#initialize_instance(raw_data, instance) ⇒ Object



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# File 'lib/bitstream.rb', line 237

def initialize_instance(raw_data, instance)
  props = instance.bitstream_properties
  props.mode = :field_def
  
  user_props = props.user_props
  
  @class_props_chain.each do |class_props|
    user_props.merge!(class_props)
  end
  user_props[:nest_chain] = user_props[:nest_chain] + [instance]
  
  @bitstream_mutex.synchronize do
    @instance = instance

    @field_defs.each do |field_def|
      field_def.call
    end
  end
  substream_types = @singleton_props[:substream_types]
  substreams = props.substreams
  unless substream_types.nil?
    substreams.keys.each do |id|
      # TODO: Support multi type substreams.
      substreams[id] = substream_types[0].instance.read(substreams[id])
    end
  end
end

#instance(inherited_props, user_props = {}) ⇒ Object



486
487
488
# File 'lib/bitstream.rb', line 486

def instance(inherited_props, user_props = {})
  NestWrapper.new(self, inherited_props, user_props)
end

#propsObject



291
292
293
# File 'lib/bitstream.rb', line 291

def props
  @instance.bitstream_properties.user_props
end

#separate_substream(id) ⇒ Object



441
442
443
444
445
446
# File 'lib/bitstream.rb', line 441

def separate_substream(id)
  # TODO: Refactor here.
  top_stream = @instance.bitstream_properties.user_props[:nest_chain].first
  substreams = top_stream.bitstream_properties.substreams
  substreams[id] << LazyString.new
end

#substream(name, id, length) ⇒ Object



420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
# File 'lib/bitstream.rb', line 420

def substream(name, id, length)
  name = name.intern
  props = @instance.bitstream_properties
  user_props = props.user_props
  raw_data = props.raw_data
  queue = props.eval_queue
  top_stream = @instance.bitstream_properties.user_props[:nest_chain].first
  substreams = top_stream.bitstream_properties.substreams
  
  case props.mode
  when :field_def
    type_instance = SubStreamPacket.instance(length)
    field = FieldReader.new(type_instance, @instance)
    queue.enq(field)
    field.read
    
    substreams[id] << LazyString.new if substreams[id].empty?
    substreams[id].last << field.value
  end
end

#substream_types(*types) ⇒ Object



299
300
301
# File 'lib/bitstream.rb', line 299

def substream_types(*types)
  @singleton_props[:substream_types] = types
end