Class: Cabriolet::HLP::Decompressor
- Inherits:
-
Object
- Object
- Cabriolet::HLP::Decompressor
- Defined in:
- lib/cabriolet/hlp/decompressor.rb
Overview
Decompressor is the main interface for HLP file operations
HLP files use LZSS compression with MODE_MSHELP and contain an internal file system. Files are decompressed using the Decompressors::LZSS class.
NOTE: This implementation is based on the knowledge that HLP files use LZSS compression with MODE_MSHELP, but cannot be fully validated due to lack of test fixtures and incomplete libmspack implementation.
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
-
#close(_header) ⇒ void
Close an HLP file (no-op for compatibility).
-
#extract_all(header, output_dir) ⇒ Integer
Extract all files from HLP archive.
-
#extract_file(header, hlp_file, output_path) ⇒ Integer
Extract a file from HLP archive.
-
#extract_file_to_memory(header, hlp_file) ⇒ String
Extract a file to memory.
-
#initialize(io_system = nil) ⇒ Decompressor
constructor
Initialize a new HLP decompressor.
-
#open(filename) ⇒ Models::HLPHeader
Open and parse an HLP file.
Constructor Details
#initialize(io_system = nil) ⇒ Decompressor
Initialize a new HLP decompressor
24 25 26 27 28 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 24 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.
15 16 17 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 15 def buffer_size @buffer_size end |
#io_system ⇒ Object (readonly)
Returns the value of attribute io_system.
14 15 16 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 14 def io_system @io_system end |
#parser ⇒ Object (readonly)
Returns the value of attribute parser.
14 15 16 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 14 def parser @parser end |
Instance Method Details
#close(_header) ⇒ void
This method returns an undefined value.
Close an HLP file (no-op for compatibility)
45 46 47 48 49 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 45 def close(_header) # No resources to free in the header itself # File handles are managed separately during extraction nil end |
#extract_all(header, output_dir) ⇒ Integer
Extract all files from HLP archive
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 127 def extract_all(header, output_dir) raise ArgumentError, "Header must not be nil" unless header raise ArgumentError, "Output directory must not be nil" unless output_dir # Create output directory if needed FileUtils.mkdir_p(output_dir) extracted = 0 header.files.each do |hlp_file| output_path = ::File.join(output_dir, hlp_file.filename) # Create subdirectories if needed output_subdir = ::File.dirname(output_path) FileUtils.mkdir_p(output_subdir) extract_file(header, hlp_file, output_path) extracted += 1 end extracted end |
#extract_file(header, hlp_file, output_path) ⇒ Integer
Extract a file from HLP archive
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 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 58 def extract_file(header, hlp_file, output_path) raise ArgumentError, "Header must not be nil" unless header raise ArgumentError, "HLP file must not be nil" unless hlp_file 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 file data @io_system.seek(input_handle, hlp_file.offset, Constants::SEEK_START) bytes_written = if hlp_file.compressed? decompress_file(input_handle, output_handle, hlp_file) else copy_file(input_handle, output_handle, hlp_file) end # Verify size if expected if bytes_written != hlp_file.length && Cabriolet.verbose warn "[Cabriolet] WARNING: extracted #{bytes_written} bytes, " \ "expected #{hlp_file.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_file_to_memory(header, hlp_file) ⇒ String
Extract a file to memory
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 97 def extract_file_to_memory(header, hlp_file) raise ArgumentError, "Header must not be nil" unless header raise ArgumentError, "HLP file must not be nil" unless hlp_file input_handle = @io_system.open(header.filename, Constants::MODE_READ) output_handle = System::MemoryHandle.new("", Constants::MODE_WRITE) begin # Seek to file data @io_system.seek(input_handle, hlp_file.offset, Constants::SEEK_START) if hlp_file.compressed? decompress_file(input_handle, output_handle, hlp_file) else copy_file(input_handle, output_handle, hlp_file) end output_handle.data ensure @io_system.close(input_handle) if input_handle end end |
#open(filename) ⇒ Models::HLPHeader
Open and parse an HLP file
35 36 37 38 39 |
# File 'lib/cabriolet/hlp/decompressor.rb', line 35 def open(filename) header = @parser.parse(filename) header.filename = filename header end |