Class: BinaryParser::StructureDefinition

Inherits:
Object
  • Object
show all
Defined in:
lib/binary_parser/structure_definition.rb

Defined Under Namespace

Classes: DataDefinition, LoopDefinition, WhileDefinition

Constant Summary collapse

KEYWORDS =
[
 :data, :SPEND, :TIMES, :WHILE, :IF, :E, :cond, :match, :var, :len, :nextbits, :position,
 :rest, :[]
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(forbidden_method_names = [], parent_structure = nil, &init_proc) ⇒ StructureDefinition

Returns a new instance of StructureDefinition.



16
17
18
19
20
21
22
23
# 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

Instance Attribute Details

#bit_atObject (readonly)

Returns the value of attribute bit_at.



14
15
16
# File 'lib/binary_parser/structure_definition.rb', line 14

def bit_at
  @bit_at
end

#namesObject (readonly)

Returns the value of attribute names.



14
15
16
# File 'lib/binary_parser/structure_definition.rb', line 14

def names
  @names
end

#parent_structureObject (readonly)

Returns the value of attribute parent_structure.



14
15
16
# File 'lib/binary_parser/structure_definition.rb', line 14

def parent_structure
  @parent_structure
end

Instance Method Details

#[](var_name) ⇒ Object



136
137
138
# File 'lib/binary_parser/structure_definition.rb', line 136

def [](var_name)
  return @data_def[var_name]
end

#cond(*var_names, &condition_proc) ⇒ Object



84
85
86
87
88
89
90
91
# 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) ⇒ Object



25
26
27
28
29
30
31
32
# 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) ⇒ Object



66
67
68
69
# File 'lib/binary_parser/structure_definition.rb', line 66

def define(name, data)
  @data_def[name] = data
  @names << name
end

#E(&condition_proc) ⇒ Object



93
94
95
# File 'lib/binary_parser/structure_definition.rb', line 93

def E(&condition_proc)
  return FreeCondition.new(&condition_proc)
end

#IF(condition, &block) ⇒ Object



78
79
80
81
82
# File 'lib/binary_parser/structure_definition.rb', line 78

def IF(condition, &block)
  @conditions.push(condition)
  block.call
  @conditions.pop
end

#len(var_name) ⇒ Object



117
118
119
120
121
122
# 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) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
# 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) ⇒ Object



124
125
126
# File 'lib/binary_parser/structure_definition.rb', line 124

def nextbits(length)
  return Expression.nextbits_var(length)
end

#positionObject



128
129
130
# File 'lib/binary_parser/structure_definition.rb', line 128

def position
  Expression.control_var(:position)
end

#restObject



132
133
134
# File 'lib/binary_parser/structure_definition.rb', line 132

def rest
  Expression.control_var(:rest)
end

#SPEND(bit_length, name, klass = nil, &block) ⇒ Object



34
35
36
37
38
39
# 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

#symbol_call(symbol, *args, &block) ⇒ Object



140
141
142
143
144
145
146
147
148
# 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

#TIMES(times, name, klass = nil, &block) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# 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

#var(var_name) ⇒ Object



110
111
112
113
114
115
# 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

#WHILE(condition, name, &block) ⇒ Object



71
72
73
74
75
76
# 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