Class: Distillery::ROMArchive

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/distillery/rom-archive.rb

Overview

Deal with ROM embedded in an archive file.

Constant Summary collapse

PREFERED =

Prefered

'7z'
EXTENSIONS =

Allowed extension names

Set[ '7z', 'zip' ]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(file) ⇒ ROMArchive

Create an empty archive

Parameters:

  • file (String)

    archive file



79
80
81
82
# File 'lib/distillery/rom-archive.rb', line 79

def initialize(file)
    @file   = file
    @roms   = {}
end

Instance Attribute Details

#fileString (readonly)

Archive file

Returns:

  • (String)


258
259
260
# File 'lib/distillery/rom-archive.rb', line 258

def file
  @file
end

Class Method Details

.archive?(file, archives: EXTENSIONS) ⇒ Boolean

Check using extension if file is an archive

Parameters:

  • file (String)

    file to test

Returns:

  • (Boolean)


48
49
50
51
# File 'lib/distillery/rom-archive.rb', line 48

def self.archive?(file, archives: EXTENSIONS)
    return false if archives.nil?
    archives.include?(File.extname(file)[1..-1])
end

.bufsize=(size) ⇒ Object

Set buffer size used when processing archive content

Parameters:

  • size (Integer)

    size in kbytes



37
38
39
# File 'lib/distillery/rom-archive.rb', line 37

def self.bufsize=(size)
    @@bufsize = size << 10
end

.from_file(file, headers: nil) ⇒ ROMArchive

Read ROM archive from file

Parameters:

  • file (String)

    path to archive file

  • headers (Array, nil, false) (defaults to: nil)

    header definition list

Returns:



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/distillery/rom-archive.rb', line 61

def self.from_file(file, headers: nil)
    # Create archive object
    archive = self.new(file)

    # 
    Distillery::Archiver.for(file).each {|entry, i|
        path = ROM::Path::Archive.new(archive, entry)
        archive[entry] = ROM.new(path, **ROM.info(i, headers: headers))
    }

    archive
end

Instance Method Details

#==(o) ⇒ Boolean

Test if archive is identical (same file, same content)

Parameters:

Returns:

  • (Boolean)


123
124
125
126
127
# File 'lib/distillery/rom-archive.rb', line 123

def ==(o)
    o.kind_of?(ROMArchive) 						&&
        (self.entries.to_set == o.entries.to_set) 			&&
        self.entries.all? {|entry| self[entry].same?(o[entry]) }
end

#[](entry) ⇒ ROM

Get ROM by entry

Parameters:

  • entry (String)

    archive entry

Returns:



171
172
173
# File 'lib/distillery/rom-archive.rb', line 171

def [](entry)
    @roms[entry]
end

#[]=(entry, rom) ⇒ ROM

Assign a ROM to the archive

Parameters:

  • entry (String)

    archive entry name

  • rom (ROM)

    ROM

Returns:

  • (ROM)

    the assigned ROM



99
100
101
102
103
104
105
# File 'lib/distillery/rom-archive.rb', line 99

def []=(entry, rom)
    @roms.merge!(entry => rom) {|key, old_rom, new_rom|
        warn "replacing ROM entry \"#{key}\" (#{to_s})"
        new_rom
    }
    rom
end

#delete!(entry) ⇒ Boolean

Delete entry

Parameters:

  • entry (String)

    archive entry

Returns:

  • (Boolean)

    operation status



182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/distillery/rom-archive.rb', line 182

def delete!(entry)
    Distillery::Archiver.for(@file) {|archive|
        if archive.delete!(entry)
            if archive.empty?
                File.unlink(@file)
            end
            true
        else
            false
        end
    }
end

#each {|rom| ... } ⇒ self, Enumerator

Iterate over each ROM

Yield Parameters:

Returns:

  • (self, Enumerator)


143
144
145
146
# File 'lib/distillery/rom-archive.rb', line 143

def each
    block_given? ? @roms.each_value {|r| yield(r) }
                 : @roms.each_value
end

#entriesArray<String>

List of archive entries

Returns:

  • (Array<String>)


161
162
163
# File 'lib/distillery/rom-archive.rb', line 161

def entries
    @roms.keys
end

#extract(entry, to, length = nil, offset = 0, force: false) ⇒ Boolean

Extract rom to the filesystem

Parameters:

  • entry (String)

    entry (rom) to extract

  • to (String)

    destination

  • length (Integer, nil) (defaults to: nil)

    data length to be copied

  • offset (Integer) (defaults to: 0)

    data offset

  • force (Boolean) (defaults to: false)

    remove previous file if necessary

Returns:

  • (Boolean)

    operation status



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/distillery/rom-archive.rb', line 220

def extract(entry, to, length = nil, offset = 0, force: false)
    Distillery::Archiver.for(@file).reader(entry) {|i|
        # Copy file
        begin
            op = force ? File::TRUNC : File::EXCL
            File.open(to, File::CREAT|File::WRONLY|op) {|o|
                while (skip = [ offset, @@bufsize ].min) > 0
                    i.read(skip)
                    offset -= skip
                end

                if length.nil?
                    while data = i.read(@@bufsize)
                        o.write(data)
                    end
                else
                    while ((sz = [ length, @@bufsize ].min) > 0) &&
                          (data = i.read(sz))
                        o.write(data)
                        length -= sz
                    end
                end
            }
        rescue Errno::EEXIST
            return false
        end
        
        # Assuming entries are unique
        return true
    }
    
    # Was not found
    return false
end

#reader(entry) {|io| ... } ⇒ Object

Note:

Can be costly, to be avoided.

Read ROM.

Parameters:

  • entry (String)

    archive entry

Yield Parameters:

  • io (#read)

    stream for reading

Returns:

  • block value



205
206
207
# File 'lib/distillery/rom-archive.rb', line 205

def reader(entry, &block)
    Distillery::Archiver.for(@file).reader(entry, &block)
end

#romsArray<ROM>

List of ROMs

Returns:



152
153
154
# File 'lib/distillery/rom-archive.rb', line 152

def roms
    @roms.values
end

#same_file?(o) ⇒ Boolean

Same archive file

Parameters:

Returns:

  • (Boolean)


113
114
115
# File 'lib/distillery/rom-archive.rb', line 113

def same_file?(o)
    self.file == o.file
end

#sizeInteger

Archive size (number of entries)

Returns:

  • (Integer)


132
133
134
# File 'lib/distillery/rom-archive.rb', line 132

def size
    @roms.size
end

#to_sString

String representation of the archive

Returns:

  • (String)


87
88
89
# File 'lib/distillery/rom-archive.rb', line 87

def to_s
    @file
end