class BinaryParser::StructureDefinition

Constants

DataDefinition
KEYWORDS
LoopDefinition
WhileDefinition

Attributes

bit_at[R]
names[R]
parent_structure[R]

Public Class Methods

new(forbidden_method_names=[], parent_structure=nil, &init_proc) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 16
def initialize(forbidden_method_names=[], parent_structure=nil, &init_proc)
  @forbidden_method_names = forbidden_method_names
  @parent_structure = parent_structure
  @bit_at = BitPosition.new     
  @data_def = {}
  @conditions, @names = [], []
  Proxy.new(self, KEYWORDS).instance_eval(&init_proc) if init_proc
end

Public Instance Methods

E(&condition_proc) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 93
def E(&condition_proc)
  return FreeCondition.new(&condition_proc)
end
IF(condition, &block) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 78
def IF(condition, &block)
  @conditions.push(condition)
  block.call
  @conditions.pop
end
SPEND(bit_length, name, klass=nil, &block) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 34
def SPEND(bit_length, name, klass=nil, &block)
  __check_new_def_name(name)
  bit_at, bit_length = __process_bit_length(bit_length, name)
  klass ||= NamelessTemplateMaker.new(self, block)
  define(name, LoopDefinition.new(bit_at, bit_length, @conditions.dup, klass))
end
TIMES(times, name, klass=nil, &block) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 41
def TIMES(times, name, klass=nil, &block)
  __check_new_def_name(name)
  klass ||= NamelessTemplateMaker.new(self, block)
  structure = klass.structure
  if structure.bit_at.names.empty?
    bit_at, bit_length = __process_bit_length(times * structure.bit_at.imm, name)
    define(name, LoopDefinition.new(bit_at, bit_length, @conditions.dup, klass))
  else
    bit_length = Expression.immediate(0)
    structure.bit_at.names.each do |depending_token|
      depending_length_exp = structure[depending_token.symbol].bit_length
      depending_length_exp.variable_tokens.each do |token|
        if structure[token.symbol]
          raise DefinitionError, "In '#{name}', same level variable #{token.symbol} is referenced." + 
            "*** TIMES's inner structure's bit-length must be always same." +
            "In other words, that bit-length must not rely on same level variables. ***"
        end
      end
      bit_length += depending_length_exp
    end
    bit_at, bit_length = __process_bit_length(bit_length * times, name)
    define(name, LoopDefinition.new(bit_at, bit_length, @conditions.dup, klass))
  end
end
WHILE(condition, name, &block) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 71
def WHILE(condition, name, &block)
  __check_new_def_name(name)
  klass = NamelessTemplateMaker.new(self, block)
  bit_at, bit_length = __process_bit_length(Expression.control_var(:non_fixed), name)
  define(name, WhileDefinition.new(bit_at, bit_length, @conditions.dup, klass, condition))
end
[](var_name) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 136
def [](var_name)
  return @data_def[var_name]
end
cond(*var_names, &condition_proc) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 84
def cond(*var_names, &condition_proc)
  var_names.each do |var_name|
    unless __name_resolvable?(var_name)
      raise DefinitionError, "As condition variable, unsolvable variable #{var_name} is used."
    end
  end
  return Condition.new(*var_names, &condition_proc)
end
data(name, klass, bit_length) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 25
def data(name, klass, bit_length)
  __check_new_def_name(name)
  unless klass.ancestors.include?(TemplateBase)
    raise DefinitionError, "Class #{klass} should be TemplateBase."
  end
  bit_at, bit_length = __process_bit_length(bit_length, name)
  define(name, DataDefinition.new(bit_at, bit_length, @conditions.dup, klass))
end
define(name, data) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 66
def define(name, data)
  @data_def[name] = data
  @names << name
end
len(var_name) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 117
def len(var_name)
  unless __name_resolvable?(var_name)
    raise DefinitionError, "Unsolvable variable #{var_name} is used."
  end
  return Expression.length_var(var_name)
end
match(var_name, value) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 97
def match(var_name, value)
  case value
  when Integer
    return cond(var_name){|v| v.to_i == value}
  when String
    return cond(var_name){|v| v.to_s == value}
  when Symbol
    return cond(var_name, value){|v1, v2| v1.to_i == v2.to_i}
  else
    raise DefinitionError, "Unknown type of matching value(#{value}) '#{value.class}'."
  end
end
nextbits(length) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 124
def nextbits(length)
  return Expression.nextbits_var(length)
end
position() click to toggle source
# File lib/binary_parser/structure_definition.rb, line 128
def position
  Expression.control_var(:position)
end
rest() click to toggle source
# File lib/binary_parser/structure_definition.rb, line 132
def rest
  Expression.control_var(:rest)
end
symbol_call(symbol, *args, &block) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 140
def symbol_call(symbol, *args, &block)
  if args.length == 0
    return var(symbol)
  elsif args.length == 2
    return data(symbol, *args)
  else
    raise DefinitionError, "Unknown use of keyword '#{var_name}' with args(#{args})."
  end
end
var(var_name) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 110
def var(var_name)
  unless __name_resolvable?(var_name)
    raise DefinitionError, "Unsolvable variable #{var_name} is used."
  end
  return Expression.value_var(var_name)
end

Private Instance Methods

__check_new_def_name(name) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 175
def __check_new_def_name(name)
  if name[0..1] == "__"
    raise DefinitionError, "Name that starts with '__' is system-reserved."
  end
  if @forbidden_method_names.include?(name)
    raise DefinitionError, "Name '#{name}' is already used as method name." +
      "You should chanege to other name."
  end
  if @data_def[name]
    raise DefinitionError, "Name #{name} is already defined." +
      "You should change to other name."
  end
end
__name_resolvable?(name, structure=self) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 189
def __name_resolvable?(name, structure=self)
  return structure[name] ||
    (structure.parent_structure && __name_resolvable?(name, structure.parent_structure))
end
__process_bit_length(bit_length, name) click to toggle source
# File lib/binary_parser/structure_definition.rb, line 152
def __process_bit_length(bit_length, name)
  bit_at = @bit_at
  case bit_length
  when Integer
    if @conditions.empty?
      @bit_at = @bit_at.add_imm(bit_length)
    else
      @bit_at = @bit_at.add_name(name)
    end
    return bit_at, Expression.immediate(bit_length)
  when Expression
    bit_length.variable_tokens.each do |token|
      if (token.value_var? || token.length_var?) && !__name_resolvable?(token.symbol)
        raise DefinitionError, "In #{name}, unsolvable variable #{symbol} is used."
      end
    end
    @bit_at = @bit_at.add_name(name)
    return bit_at, bit_length
  else
    raise DefinitionError, "Unknown type of bit_length (#{bit_length.class})."
  end
end