Class: TSparser::AribStringDecoder::Decoder

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

Overview


Class which is express decoding process. Receive all coding definition object when instance is maked.


Defined Under Namespace

Classes: CodeOutputer, ControlCodeProcessor, Decoded

Instance Method Summary collapse

Constructor Details

#initialize(caller, operator, set_map, proc_map, length_map, group_map, region_map, control_code_map) ⇒ Decoder

Returns a new instance of Decoder.



176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/arib_string_decoder.rb', line 176

def initialize(caller, operator, set_map, proc_map, length_map, group_map, region_map, control_code_map)
  @caller     = caller
  @operator   = operator
  @set_map    = set_map
  @proc_map   = proc_map
  @length_map = length_map
  @decoded    = Decoded.new
  @outputer   = CodeOutputer.new(proc_map, @decoded)
  @control_code_processor = ControlCodeProcessor.new(control_code_map, @decoded)
  @current_group_map  = group_map.dup
  @current_region_map = region_map.dup
  @current_single_region_map = Hash.new
end

Instance Method Details

#decode(binary) ⇒ Object



190
191
192
193
194
195
196
197
198
# File 'lib/arib_string_decoder.rb', line 190

def decode(binary)
  begin
    parse_one(binary) while binary.readable?
  rescue => error
    return @decoded if @decoded.to_s rescue nil
    parse_error(error, binary)
  end
  return @decoded
end

#output_code(byte, binary, target) ⇒ Object



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/arib_string_decoder.rb', line 226

def output_code(byte, binary, target)
  code_name = query_code(target)
  if @length_map[code_name] == 1
    byte  &= 0x7F if target == :GR
    @outputer.output(code_name, byte)
  elsif @length_map[code_name] == 2
    byte2 = binary.read_byte_as_binary(1)
    if target == :GR
      byte  &= 0x7F
      byte2 &= 0x7F
    end
    @outputer.output(code_name, byte, byte2)
  else
    raise "Unsupported code length #{@length_map[code_name]} (from #{code_name})."
  end
end

#parse_control_code(byte, binary) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/arib_string_decoder.rb', line 243

def parse_control_code(byte, binary)
  control_code = [byte]
  loop do
    caller_candidates   = @caller.candidates(control_code)
    operator_candidates = @operator.candidates(control_code, @set_map)
    if caller_candidates == 0 && operator_candidates == 0
      raise "Unacceptable control code (#{control_code})."
    end
    if caller_candidates == 1 && operator_candidates == 0
      set_target(*@caller.pull(control_code))
      break
    end
    if caller_candidates == 0 && operator_candidates == 1
      set_code_set(*@operator.pull(control_code, @set_map))
      break
    end
    unless binary.readable?
      raise "Binary is finished before accepting some operation code (now: #{control_code})."
    end
    control_code << binary.read_byte_as_binary(1)
  end
end

#parse_error(error, binary) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/arib_string_decoder.rb', line 200

def parse_error(error, binary)
  STDERR.puts "Error occurred on the way to decode following bytes."
  STDERR.puts " \"#{binary.dump}\""
  STDERR.puts "Now process pointer is pointing at #{binary.bit_pointer / 8}-th byte."
  begin
    STDERR.puts "Trying to print now decoded string..."
    STDERR.puts "Decoded: \"#{@decoded}\""
  rescue
    STDERR.puts "Sorry, failed."
  end
  raise error
end

#parse_one(binary) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/arib_string_decoder.rb', line 213

def parse_one(binary)
  byte = binary.read_byte_as_binary(1)
  if byte >= 0x21 && byte <= 0x7E
    output_code(byte, binary, :GL)
  elsif byte >= 0xA1 && byte <= 0xFE
    output_code(byte, binary, :GR)
  elsif @control_code_processor.match?(byte)
    @control_code_processor.process(byte, binary)
  else 
    parse_control_code(byte, binary)
  end
end

#query_code(region) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/arib_string_decoder.rb', line 281

def query_code(region)
  group_name = @current_single_region_map[region] || @current_region_map[region]
  unless group_name
    raise "No group is set to region \"#{region}\"."
  end
  code_name = @current_group_map[group_name]
  unless code_name
    raise "No code is set to group \"#{group_name}\"."
  end
  @current_single_region_map = Hash.new
  return code_name
end

#set_code_set(code_name, group_name) ⇒ Object



277
278
279
# File 'lib/arib_string_decoder.rb', line 277

def set_code_set(code_name, group_name)
  @current_group_map[group_name] = code_name
end

#set_target(group_name, target_region, call_type) ⇒ Object



266
267
268
269
270
271
272
273
274
275
# File 'lib/arib_string_decoder.rb', line 266

def set_target(group_name, target_region, call_type)
  case call_type
  when :locking
    @current_region_map[target_region] = group_name
  when :single
    @current_single_region_map[target_region] = group_name
  else
    raise "Unsupported call type \"#{call_type}\"."
  end
end