class Bai2::BaiFile

This class is the main wrapper around a Bai2 file.

Constants

DEFAULT_OPTIONS

Attributes

groups[R]

The groups contained within this file.

raw[R]

This is the raw data. Probably not super important.

Public Class Methods

new(raw, options = {}) click to toggle source

Parse a Bai2 data buffer:

f = BaiFile.new(bai2_data)
# File lib/bai2.rb, line 32
def initialize(raw, options = {})
  @raw = raw
  @groups = []
  @options = DEFAULT_OPTIONS.merge(options)
  parse(raw, options)
end
parse(path, options = {}) click to toggle source

Parse a file on disk:

f = BaiFile.parse('myfile.bai2')
# File lib/bai2.rb, line 23
def self.parse(path, options = {})
  self.new(File.read(path), options)
end

Public Instance Methods

file_creation_datetime() click to toggle source
# File lib/bai2.rb, line 55
def file_creation_datetime
  @header[:file_creation_date] + @header[:file_creation_time]
end

Private Instance Methods

assert_integrity!() click to toggle source

Asserts integrity of a fully-parsed BaiFile by calculating checksums.

# File lib/bai2/integrity.rb, line 15
def assert_integrity!
  expectation = {
    sum:      @trailer[:file_control_total],
    children: @trailer[:number_of_groups],
    records:  @trailer[:number_of_records],
  }

  # Check children count
  unless expectation[:children] == (actual = self.groups.count)
    raise IntegrityError.new("Number of groups invalid: " \
      + "expected #{expectation[:children]}, actually: #{actual}")
  end

  # Check sum vs. group sums
  actual_sum = self.groups.map do |group|
    group.instance_variable_get(:@trailer)[:group_control_total]
  end.reduce(0, &:+)

  unless expectation[:sum] == actual_sum
    raise IntegrityError.new(
      "Sums invalid: file: #{expectation[:sum]}, groups: #{actual_sum}")
  end

  # Run children assertions, which return number of records. May raise.
  records = self.groups.map {|g| g.send(:assert_integrity!, @options) }.reduce(0, &:+)

  unless expectation[:records] == (actual_num_records = records + 2)
    raise IntegrityError.new(
      "Record count invalid: file: #{expectation[:records]}, groups: #{actual_num_records}")
  end

  actual_num_records
end
parse(data, options) click to toggle source

This delegates most of the work to Bai2::Parser to build the ParseNode tree.

# File lib/bai2.rb, line 65
def parse(data, options)

  root = Parser.parse(data, options)

  # parse the file node; will descend tree and parse children
  parse_file_node(root)

  # assert integrity
  assert_integrity!
end
parse_file_node(n) click to toggle source

Parses the file_header root tree node, and creates the object hierarchy.

# File lib/bai2.rb, line 79
def parse_file_node(n)

  unless n.code == :file_header && n.records.count == 2 && \
      n.records.map(&:code) == [:file_header, :file_trailer]
    raise ParseError.new('Unexpected record.')
  end

  @header, @trailer = *n.records

  @groups = n.children.map {|child| Group.send(:parse, child) }
end