class TSparser::AribStringDecoder::Decoder


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


Public Class Methods

new(caller, operator, set_map, proc_map, length_map, group_map, region_map, control_code_map) click to toggle source
# File lib/arib_string_decoder.rb, line 175
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

Public Instance Methods

decode(binary) click to toggle source
# File lib/arib_string_decoder.rb, line 189
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) click to toggle source
# File lib/arib_string_decoder.rb, line 225
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) click to toggle source
# File lib/arib_string_decoder.rb, line 242
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) click to toggle source
# File lib/arib_string_decoder.rb, line 199
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) click to toggle source
# File lib/arib_string_decoder.rb, line 212
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) click to toggle source
# File lib/arib_string_decoder.rb, line 280
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) click to toggle source
# File lib/arib_string_decoder.rb, line 276
def set_code_set(code_name, group_name)
  @current_group_map[group_name] = code_name
end
set_target(group_name, target_region, call_type) click to toggle source
# File lib/arib_string_decoder.rb, line 265
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