Class: SmcUtil::FileReader

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ FileReader

Returns a new instance of FileReader.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# 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}" && next if line.nil? or 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

Instance Attribute Details

#headersObject (readonly)

Returns the value of attribute headers.



5
6
7
# File 'lib/smcutil/file_reader.rb', line 5

def headers
  @headers
end

#regionsObject (readonly)

Returns the value of attribute regions.



7
8
9
# File 'lib/smcutil/file_reader.rb', line 7

def regions
  @regions
end

#signatureObject (readonly)

Returns the value of attribute signature.



6
7
8
# File 'lib/smcutil/file_reader.rb', line 6

def signature
  @signature
end

Class Method Details

.parse(path) ⇒ Object



61
62
63
# File 'lib/smcutil/file_reader.rb', line 61

def self.parse(path)
   FileReader.new(File.open(path))
end