Class: Cabriolet::CHM::Decompressor

Inherits:
Object
  • Object
show all
Defined in:
lib/cabriolet/chm/decompressor.rb

Overview

Decompressor for CHM (Compiled HTML Help) files

Constant Summary collapse

LZX_FRAME_SIZE =
32_768

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io_system = nil) ⇒ Decompressor

Returns a new instance of Decompressor.



16
17
18
19
20
21
22
23
# File 'lib/cabriolet/chm/decompressor.rb', line 16

def initialize(io_system = nil)
  @io_system = io_system || System::IOSystem.new
  @chm = nil
  @input_handle = nil
  @lzx_state = nil
  @lzx_offset = 0
  @lzx_length = 0
end

Instance Attribute Details

#chmObject (readonly)

Returns the value of attribute chm.



14
15
16
# File 'lib/cabriolet/chm/decompressor.rb', line 14

def chm
  @chm
end

#io_systemObject (readonly)

Returns the value of attribute io_system.



14
15
16
# File 'lib/cabriolet/chm/decompressor.rb', line 14

def io_system
  @io_system
end

Instance Method Details

#closeObject

Close the CHM file



48
49
50
51
52
53
# File 'lib/cabriolet/chm/decompressor.rb', line 48

def close
  cleanup_lzx
  @input_handle&.close
  @input_handle = nil
  @chm = nil
end

#extract(file, output_path) ⇒ void

This method returns an undefined value.

Extract a file from the CHM archive

Parameters:

  • file (Models::CHMFile)

    File to extract

  • output_path (String)

    Output path for extracted file

Raises:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/cabriolet/chm/decompressor.rb', line 59

def extract(file, output_path)
  raise ArgumentError, "File is nil" if file.nil?
  raise ArgumentError, "File section is nil" if file.section.nil?

  # Handle empty files
  if file.empty?
    @io_system.open(output_path, Constants::MODE_WRITE).close
    return
  end

  case file.section.id
  when 0
    extract_uncompressed(file, output_path)
  when 1
    extract_compressed(file, output_path)
  else
    raise Errors::FormatError, "Invalid section ID: #{file.section.id}"
  end
end

#fast_find(filename) ⇒ Models::CHMFile?

Find a file by name using fast_find

Parameters:

  • filename (String)

    Name of the file to find

Returns:

Raises:



82
83
84
85
86
87
88
89
90
91
92
# File 'lib/cabriolet/chm/decompressor.rb', line 82

def fast_find(filename)
  raise ArgumentError, "CHM not opened" unless @chm

  # Use fast index search if available
  if @chm.index_root < @chm.num_chunks
    fast_search_pmgi(filename)
  else
    # Linear search through PMGL chunks
    fast_search_pmgl(filename)
  end
end

#fast_open(filename) ⇒ Models::CHMHeader

Open a CHM file quickly (without parsing file entries)

Parameters:

  • filename (String)

    Path to CHM file

Returns:



43
44
45
# File 'lib/cabriolet/chm/decompressor.rb', line 43

def fast_open(filename)
  open(filename, entire: false)
end

#open(filename, entire: true) ⇒ Models::CHMHeader

Open a CHM file

Parameters:

  • filename (String)

    Path to CHM file

  • entire (Boolean) (defaults to: true)

    If true, parse all file entries

Returns:



29
30
31
32
33
34
35
36
37
38
# File 'lib/cabriolet/chm/decompressor.rb', line 29

def open(filename, entire: true)
  @input_handle = @io_system.open(filename, Constants::MODE_READ)
  @chm = Parser.new(@input_handle).parse(entire: entire)
  @chm.filename = filename
  @chm
rescue StandardError => e
  @input_handle&.close
  @input_handle = nil
  raise e
end