class TTFunk::ResourceFile

Data-fork suitcases resource file

Attributes

map[R]

Resource map

@return [Hash]

Public Class Methods

new(io) click to toggle source

@param io [IO]

# File lib/ttfunk/resource_file.rb, line 24
def initialize(io)
  @io = io

  data_offset, map_offset, map_length = @io.read(16).unpack('NNx4N')

  @map = {}
  # skip header copy, next map handle, file reference, and attrs
  @io.pos = map_offset + 24
  type_list_offset, name_list_offset = @io.read(4).unpack('n*')

  type_list_offset += map_offset
  name_list_offset += map_offset

  @io.pos = type_list_offset
  max_index = @io.read(2).unpack1('n')
  0.upto(max_index) do
    type, max_type_index, ref_list_offset = @io.read(8).unpack('A4nn')
    @map[type] = { list: [], named: {} }

    parse_from(type_list_offset + ref_list_offset) do
      0.upto(max_type_index) do
        id, name_ofs, attr = @io.read(5).unpack('nnC')
        data_ofs = @io.read(3)
        data_ofs = data_offset + [0, data_ofs].pack('CA*').unpack1('N')
        handle = @io.read(4).unpack1('N')

        entry = {
          id: id,
          attributes: attr,
          offset: data_ofs,
          handle: handle,
        }

        if name_list_offset + name_ofs < map_offset + map_length
          parse_from(name_ofs + name_list_offset) do
            len = @io.read(1).unpack1('C')
            entry[:name] = @io.read(len)
          end
        end

        @map[type][:list] << entry
        @map[type][:named][entry[:name]] = entry if entry[:name]
      end
    end
  end
end
open(path) { |file| ... } click to toggle source

Open a resource file

@param path [String, Pathname] @yieldparam resource_file [TTFunk::ResourceFile] @return [any] result of the block

# File lib/ttfunk/resource_file.rb, line 16
def self.open(path)
  ::File.open(path, 'rb') { |io|
    file = new(io)
    yield(file)
  }
end

Public Instance Methods

[](type, index = 0) click to toggle source

Get resource

@overload [](type, index = 0)

@param type [String]
@param inxed [Integer]
@return [String]

@overload [](type, name)

@param type [String]
@param name [String]
@return [String]
# File lib/ttfunk/resource_file.rb, line 81
def [](type, index = 0)
  if @map[type]
    collection = index.is_a?(Integer) ? :list : :named
    if @map[type][collection][index]
      parse_from(@map[type][collection][index][:offset]) do
        length = @io.read(4).unpack1('N')
        return @io.read(length)
      end
    end
  end
end
resources_for(type) click to toggle source

Get resource names

@param type [String] @return [Array<String>]

# File lib/ttfunk/resource_file.rb, line 97
def resources_for(type)
  ((@map[type] && @map[type][:named]) || {}).keys
end

Private Instance Methods

parse_from(offset) { || ... } click to toggle source
# File lib/ttfunk/resource_file.rb, line 103
def parse_from(offset)
  saved = @io.pos
  @io.pos = offset
  yield
ensure
  @io.pos = saved
end