module BitStream::ClassMethods

Public Class Methods

add_type(type, method_name = nil, bs = self) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# File lib/bitstream.rb, line 269
def self.register_types(types)
  types.each do |t|
    register_type(t, nil)
  end
end
types() click to toggle source
# File lib/bitstream.rb, line 265
def self.types
  @types
end

Public Instance Methods

add_type(type, name = nil) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# File lib/bitstream.rb, line 295
def byte_order(order)
  @class_props[:byte_order] = order.intern
end
create(s, props = {}) click to toggle source
# File lib/bitstream.rb, line 460
def create(s, props = {})
  create_with_offset(s, 0, props)
end
create_with_offset(s, offset, props = {}) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# File lib/bitstream.rb, line 233
def fields(&field_def)
  @field_defs << field_def
end
initialize_for_class_methods(types) click to toggle source
# 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) click to toggle source
# 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 = {}) click to toggle source
# File lib/bitstream.rb, line 486
def instance(inherited_props, user_props = {})
  NestWrapper.new(self, inherited_props, user_props)
end
method_missing(name, *args) click to toggle source
Calls superclass method
# 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
props() click to toggle source
# File lib/bitstream.rb, line 291
def props
  @instance.bitstream_properties.user_props
end
separate_substream(id) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# File lib/bitstream.rb, line 299
def substream_types(*types)
  @singleton_props[:substream_types] = types
end

Private Instance Methods

get_type(type_name, props, *args) click to toggle source
# File lib/bitstream.rb, line 506
def get_type(type_name, props, *args)
  type = @types[type_name.intern]
  
  if type.nil?
    aliasee = resolve_alias(type_name, args)
    if aliasee.nil?
      raise BitStreamError, "There is no type named \"#{type_name}\""
    else
      type = @types[aliasee]
    end
  end
  
  return type.instance(props, *args)
end
resolve_alias(type_name, args) click to toggle source
# File lib/bitstream.rb, line 491
def resolve_alias(type_name, args)
  type_s = type_name.to_s
  if type_s =~ /^uint(\d+)$/
    bit_width = Regexp.last_match[1].to_i
    args.unshift(bit_width)
    return :unsigned
  elsif type_s =~ /^int(\d+)$/
    bit_width = Regexp.last_match[1].to_i
    args.unshift(bit_width)
    return :signed
  else
    return nil
  end
end