Class: Omnizip::Algorithms::LZMA2Encoder

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/algorithms/lzma2/encoder.rb

Overview

LZMA2 encoder - delegates to XzLZMA2Encoder

This class provides a backward-compatible API that delegates to the complete XzLZMA2Encoder implementation ported from XZ Utils.

Based on XZ Utils lzma2_encoder.c

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dict_size: 8 * 1024 * 1024, lc: 3, lp: 0, pb: 2, standalone: false) ⇒ LZMA2Encoder

Initialize the encoder

Parameters:

  • dict_size (Integer) (defaults to: 8 * 1024 * 1024)

    Dictionary size (default: 8MB)

  • lc (Integer) (defaults to: 3)

    Literal context bits (default: 3)

  • lp (Integer) (defaults to: 0)

    Literal position bits (default: 0)

  • pb (Integer) (defaults to: 2)

    Position bits (default: 2)

  • standalone (Boolean) (defaults to: false)

    If true, write property byte for standalone LZMA2 files (default: false)



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 22

def initialize(
  dict_size: 8 * 1024 * 1024,
  lc: 3,
  lp: 0,
  pb: 2,
  standalone: false,
  **
)
  @dict_size = dict_size
  @lc = lc
  @lp = lp
  @pb = pb
  @standalone = standalone

  # Create the SimpleLZMA2Encoder (uses working XzEncoder internally)
  @encoder = LZMA2::SimpleLZMA2Encoder.new(
    dict_size: dict_size,
    lc: lc,
    lp: lp,
    pb: pb,
    standalone: standalone,
  )
end

Instance Attribute Details

#dict_sizeObject (readonly)

Returns the value of attribute dict_size.



12
13
14
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 12

def dict_size
  @dict_size
end

#lcObject (readonly)

Returns the value of attribute lc.



12
13
14
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 12

def lc
  @lc
end

#lpObject (readonly)

Returns the value of attribute lp.



12
13
14
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 12

def lp
  @lp
end

#pbObject (readonly)

Returns the value of attribute pb.



12
13
14
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 12

def pb
  @pb
end

Class Method Details

.encode_dict_size(dict_size) ⇒ Integer

Encode dictionary size for LZMA2 properties Returns a single byte encoding the dictionary size

Parameters:

  • dict_size (Integer)

    Dictionary size to encode

Returns:

  • (Integer)

    Encoded dictionary size byte



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
138
139
140
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 108

def self.encode_dict_size(dict_size)
  # LZMA2 dictionary size encoding (XZ Utils format)
  # Byte value d encodes dictionary size as:
  #   If d < 40: size = 2^((d/2) + 12)  (for even d)
  #           or size = 3 * 2^((d-1)/2 + 11)  (for odd d)
  #   If d == 40: size = 0xFFFFFFFF (4GB - 1)

  # Clamp to valid range
  d = [dict_size, LZMA2Const::DICT_SIZE_MIN].max

  # For 8MB (8 * 1024 * 1024 = 8388608 = 2^23):
  # We want: 2^((d/2) + 12) = 2^23
  # So: (d/2) + 12 = 23
  # Therefore: d/2 = 11, d = 22

  # Calculate log2 of dict_size
  log2_size = 0
  temp = d
  while temp > 1
    log2_size += 1
    temp >>= 1
  end

  # Encoding formula for power-of-2 sizes:
  # d = 2 * (log2_size - 12)
  if d == (1 << log2_size)
    # Exact power of 2
    [(log2_size - 12) * 2, 40].min
  else
    # Between 2^n and 2^n + 2^(n-1), use odd encoding
    [((log2_size - 12) * 2) + 1, 40].min
  end
end

Instance Method Details

#compress(input_io, output_io, _level = nil) ⇒ Integer

Compress data from input stream to output stream This method provides compatibility with the AlgorithmRegistry interface

Parameters:

  • input_io (IO)

    Input stream to read from

  • output_io (IO)

    Output stream to write to

  • level (Integer)

    Compression level (not used, kept for compatibility)

Returns:

  • (Integer)

    Number of bytes written



61
62
63
64
65
66
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 61

def compress(input_io, output_io, _level = nil)
  input_data = input_io.read
  compressed = encode(input_data)
  output_io.write(compressed)
  compressed.bytesize
end

#decompress(input_io, output_io, _size = nil) ⇒ Integer

Decompress data from input stream to output stream This method provides compatibility with the AlgorithmRegistry interface

Parameters:

  • input_io (IO)

    Input stream to read from

  • output_io (IO)

    Output stream to write to

  • size (Integer)

    Expected uncompressed size (optional)

Returns:

  • (Integer)

    Number of bytes written



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 75

def decompress(input_io, output_io, _size = nil)
  # Check if this is being called for 7-Zip format (raw LZMA2 stream)
  # 7-Zip stores LZMA2 without a property byte
  # We can detect this by checking if input_io is a StringIO (which is used
  # by StreamDecompressor for 7-Zip format)
  raw_mode = input_io.is_a?(StringIO)

  # Create a decoder instance
  decoder = LZMA2::Decoder.new(input_io, raw_mode: raw_mode)

  # For raw_mode (7-Zip format), we need to provide dict_size
  # Use default 8MB if not specified
  if raw_mode
    # Re-create decoder with dict_size option
    decoder = LZMA2::Decoder.new(input_io,
                                 raw_mode: true,
                                 dict_size: @dict_size)
  end

  # Decode the stream
  result = decoder.decode_stream

  # Write to output
  output_io.write(result)

  result.bytesize
end

#encode(input) ⇒ String

Encode data into LZMA2 format

Parameters:

  • input (String)

    Input data to compress

Returns:

  • (String)

    LZMA2 compressed data



50
51
52
# File 'lib/omnizip/algorithms/lzma2/encoder.rb', line 50

def encode(input)
  @encoder.encode(input)
end