class SmcUtil::FileReader

Attributes

headers[R]
regions[R]
signature[R]

Public Class Methods

new(data) click to toggle source
# File lib/smcutil/file_reader.rb, line 10
def initialize(data)

  # Setup the collected data
  @headers = []
  @signature = ''
  @regions = []

  current_region = nil

  data.each_line.with_index do |line, index|
    # Zero based indexing is not compatible with how people think about lines in a file
    index += 1

    # Prepare to parse the line
    line ||= line.strip!

    puts "INFO: #{line}" if line.start_with?('#')

    next if line.nil? || line.start_with?('#')
    match = LINE_COMMAND.match(line)
    raise "LINE #{index}: Does not match format" unless match

    # Validate Length
    raise "LINE #{index}: Length mismatch on line; expected #{match[:length]}, got #{match[:data].length / 2}" unless match[:length].to_i == match[:data].length / 2

    # Validate check digit
    data = match[:data].scan(/../).map { |x| x.hex.chr }.join
    check = match[:check].to_i(16)
    sum = data.codepoints.map { |c| c.to_i }.reduce(:+) & 0xFF
    raise "LINE #{index}: Checksum does not match; exptected #{check}, got #{sum}" unless sum == check

    case match[:type]
      when 'H'
        @headers << data
      when 'S'
        @signature += data
      when 'D'
        if match[:offset]
          current_offset = match[:offset].scan(/../).map { |x| x.hex.chr }.join.bytes.inject {|a, b| (a << 8) + b }

          current_region = SmcUtil::Region.new current_offset, ''
          @regions << current_region
        end

        current_region.data += data
      else
        raise "LINE #{index}: Command #{match[:type]} not recognised" unless match[:continue]
        raise "LINE #{index}: Continuation row with no data region set" unless current_region

        current_region.data += data
    end
  end
end
parse(path) click to toggle source
# File lib/smcutil/file_reader.rb, line 64
def self.parse(path)
   FileReader.new(File.open(path))
end