Class: Cabriolet::SZDD::Decompressor
- Inherits:
-
Object
- Object
- Cabriolet::SZDD::Decompressor
- Defined in:
- lib/cabriolet/szdd/decompressor.rb
Overview
Decompressor is the main interface for SZDD file operations
SZDD files use LZSS compression and are decompressed using the Decompressors::LZSS class with appropriate mode settings.
Constant Summary collapse
- DEFAULT_BUFFER_SIZE =
Input buffer size for decompression
2048
Instance Attribute Summary collapse
-
#buffer_size ⇒ Object
Returns the value of attribute buffer_size.
-
#io_system ⇒ Object
readonly
Returns the value of attribute io_system.
-
#parser ⇒ Object
readonly
Returns the value of attribute parser.
Instance Method Summary collapse
-
#auto_output_filename(input_path, header) ⇒ String
Generate output filename from input filename and header.
-
#close(_header) ⇒ void
Close an SZDD file (no-op for compatibility).
-
#decompress(input_path, output_path = nil) ⇒ Integer
One-shot decompression from input file to output file.
-
#extract(header, output_path) ⇒ Integer
Extract an SZDD file to output.
-
#extract_to_memory(header) ⇒ String
Extract SZDD file to memory.
-
#initialize(io_system = nil) ⇒ Decompressor
constructor
Initialize a new SZDD decompressor.
-
#open(filename) ⇒ Models::SZDDHeader
Open and parse an SZDD file.
Constructor Details
#initialize(io_system = nil) ⇒ Decompressor
Initialize a new SZDD decompressor
20 21 22 23 24 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 20 def initialize(io_system = nil) @io_system = io_system || System::IOSystem.new @parser = Parser.new(@io_system) @buffer_size = DEFAULT_BUFFER_SIZE end |
Instance Attribute Details
#buffer_size ⇒ Object
Returns the value of attribute buffer_size.
11 12 13 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 11 def buffer_size @buffer_size end |
#io_system ⇒ Object (readonly)
Returns the value of attribute io_system.
10 11 12 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 10 def io_system @io_system end |
#parser ⇒ Object (readonly)
Returns the value of attribute parser.
10 11 12 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 10 def parser @parser end |
Instance Method Details
#auto_output_filename(input_path, header) ⇒ String
Generate output filename from input filename and header
171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 171 def auto_output_filename(input_path, header) # Get base filename without directory base = ::File.basename(input_path) # Use header's suggested filename method suggested = header.suggested_filename(base) # Combine with original directory dir = ::File.dirname(input_path) ::File.join(dir, suggested) end |
#close(_header) ⇒ void
This method returns an undefined value.
Close an SZDD file (no-op for compatibility)
41 42 43 44 45 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 41 def close(_header) # No resources to free in the header itself # File handles are managed separately during extraction nil end |
#decompress(input_path, output_path = nil) ⇒ Integer
One-shot decompression from input file to output file
This method combines open(), extract(), and close() for convenience. Similar to MS-DOS EXPAND.EXE behavior.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 150 def decompress(input_path, output_path = nil) # Parse header header = self.open(input_path) # Auto-detect output filename if not provided output_path ||= auto_output_filename(input_path, header) # Extract bytes_written = extract(header, output_path) # Close (no-op but kept for API consistency) close(header) bytes_written end |
#extract(header, output_path) ⇒ Integer
Extract an SZDD file to output
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 53 def extract(header, output_path) raise ArgumentError, "Header must not be nil" unless header raise ArgumentError, "Output path must not be nil" unless output_path input_handle = @io_system.open(header.filename, Constants::MODE_READ) output_handle = @io_system.open(output_path, Constants::MODE_WRITE) begin # Seek to compressed data start data_offset = @parser.data_offset(header.format) @io_system.seek(input_handle, data_offset, Constants::SEEK_START) # Determine LZSS mode based on format lzss_mode = if header.normal_format? Decompressors::LZSS::MODE_EXPAND else Decompressors::LZSS::MODE_QBASIC end # Create LZSS decompressor decompressor = Decompressors::LZSS.new( @io_system, input_handle, output_handle, @buffer_size, lzss_mode, ) # Decompress bytes_written = decompressor.decompress(header.length) # Verify decompressed size matches expected if bytes_written != header.length && Cabriolet.verbose && Cabriolet.verbose warn "[Cabriolet] WARNING; decompressed #{bytes_written} bytes, " \ "expected #{header.length} bytes" end bytes_written ensure @io_system.close(input_handle) if input_handle @io_system.close(output_handle) if output_handle end end |
#extract_to_memory(header) ⇒ String
Extract SZDD file to memory
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 102 def extract_to_memory(header) raise ArgumentError, "Header must not be nil" unless header input_handle = @io_system.open(header.filename, Constants::MODE_READ) output_handle = System::MemoryHandle.new("", Constants::MODE_WRITE) begin # Seek to compressed data start data_offset = @parser.data_offset(header.format) @io_system.seek(input_handle, data_offset, Constants::SEEK_START) # Determine LZSS mode based on format lzss_mode = if header.normal_format? Decompressors::LZSS::MODE_EXPAND else Decompressors::LZSS::MODE_QBASIC end # Create LZSS decompressor decompressor = Decompressors::LZSS.new( @io_system, input_handle, output_handle, @buffer_size, lzss_mode, ) # Decompress decompressor.decompress(header.length) # Return the decompressed data output_handle.data ensure @io_system.close(input_handle) if input_handle end end |
#open(filename) ⇒ Models::SZDDHeader
Open and parse an SZDD file
31 32 33 34 35 |
# File 'lib/cabriolet/szdd/decompressor.rb', line 31 def open(filename) header = @parser.parse(filename) header.filename = filename header end |