omnizip 0.3.13 → 0.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/omnizip/algorithm.rb +36 -1
- data/lib/omnizip/algorithms/bzip2.rb +1 -3
- data/lib/omnizip/algorithms/deflate.rb +1 -3
- data/lib/omnizip/algorithms/deflate64.rb +2 -2
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +7 -8
- data/lib/omnizip/algorithms/lzma.rb +1 -1
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +5 -1
- data/lib/omnizip/algorithms/lzma2.rb +4 -12
- data/lib/omnizip/algorithms/zstandard/constants.rb +38 -25
- data/lib/omnizip/algorithms/zstandard/decoder.rb +101 -136
- data/lib/omnizip/algorithms/zstandard/encoder.rb +81 -138
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +17 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +42 -29
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +114 -117
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +434 -222
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +98 -176
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +21 -2
- data/lib/omnizip/algorithms/zstandard/huffman.rb +195 -188
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +232 -255
- data/lib/omnizip/algorithms/zstandard/literals.rb +170 -103
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +47 -199
- data/lib/omnizip/algorithms/zstandard/sequences.rb +260 -252
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +20 -24
- data/lib/omnizip/algorithms.rb +14 -1
- data/lib/omnizip/buffer.rb +1 -2
- data/lib/omnizip/commands/archive_list_command.rb +9 -7
- data/lib/omnizip/convenience.rb +1 -2
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/extraction/selective_extractor.rb +2 -10
- data/lib/omnizip/filter_pipeline.rb +1 -1
- data/lib/omnizip/filter_registry.rb +18 -16
- data/lib/omnizip/filters/bcj2.rb +1 -1
- data/lib/omnizip/filters/bcj_arm.rb +1 -1
- data/lib/omnizip/filters/bcj_arm64.rb +1 -1
- data/lib/omnizip/filters/bcj_ia64.rb +1 -1
- data/lib/omnizip/filters/bcj_ppc.rb +1 -1
- data/lib/omnizip/filters/bcj_sparc.rb +1 -1
- data/lib/omnizip/filters/bcj_x86.rb +1 -1
- data/lib/omnizip/filters.rb +0 -2
- data/lib/omnizip/formats/bzip2_file.rb +0 -7
- data/lib/omnizip/formats/cpio/entry.rb +6 -0
- data/lib/omnizip/formats/cpio.rb +0 -6
- data/lib/omnizip/formats/gzip.rb +0 -7
- data/lib/omnizip/formats/iso/directory_record.rb +7 -0
- data/lib/omnizip/formats/iso.rb +0 -5
- data/lib/omnizip/formats/lzip.rb +0 -7
- data/lib/omnizip/formats/lzma_alone.rb +0 -6
- data/lib/omnizip/formats/msi/entry.rb +6 -0
- data/lib/omnizip/formats/msi.rb +0 -9
- data/lib/omnizip/formats/ole/dirent.rb +6 -0
- data/lib/omnizip/formats/ole.rb +0 -9
- data/lib/omnizip/formats/rar.rb +0 -6
- data/lib/omnizip/formats/rar3/reader.rb +7 -0
- data/lib/omnizip/formats/rar5/reader.rb +7 -0
- data/lib/omnizip/formats/rpm/entry.rb +6 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +7 -0
- data/lib/omnizip/formats/seven_zip.rb +0 -6
- data/lib/omnizip/formats/tar/entry.rb +6 -0
- data/lib/omnizip/formats/tar.rb +2 -10
- data/lib/omnizip/formats/xar/entry.rb +6 -0
- data/lib/omnizip/formats/xar.rb +0 -6
- data/lib/omnizip/formats/zip.rb +0 -6
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +33 -31
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +177 -163
- data/lib/omnizip/implementations.rb +18 -4
- data/lib/omnizip/io/source.rb +3 -0
- data/lib/omnizip/metadata/entry_metadata.rb +7 -0
- data/lib/omnizip/parallel/engine.rb +48 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +5 -16
- data/lib/omnizip/parallel/parallel_extractor.rb +5 -16
- data/lib/omnizip/parallel.rb +1 -0
- data/lib/omnizip/profile/profile_registry.rb +1 -2
- data/lib/omnizip/registry.rb +0 -1
- data/lib/omnizip/rubyzip_compat.rb +0 -1
- data/lib/omnizip/temp/temp_file.rb +1 -2
- data/lib/omnizip/version.rb +1 -1
- data/lib/omnizip/zip/entry.rb +7 -0
- data/lib/omnizip/zip/file.rb +4 -8
- data/lib/omnizip.rb +1 -1
- metadata +7 -6
- data/lib/omnizip/filters/filter_base.rb +0 -6
- data/lib/omnizip/filters/registration.rb +0 -22
- data/lib/omnizip/filters/registry.rb +0 -111
- data/lib/omnizip/format_registry.rb +0 -100
|
@@ -24,160 +24,157 @@ module Omnizip
|
|
|
24
24
|
module Algorithms
|
|
25
25
|
class Zstandard
|
|
26
26
|
module FSE
|
|
27
|
-
#
|
|
27
|
+
# Reverse-direction bit reader matching the zstd C reference
|
|
28
|
+
# `BIT_DStream` (lib/common/bitstream.h).
|
|
28
29
|
#
|
|
29
|
-
#
|
|
30
|
-
#
|
|
30
|
+
# The bitstream is written forward by the encoder but read
|
|
31
|
+
# BACKWARDS: bytes are consumed from the last toward the first,
|
|
32
|
+
# and within each byte bits are consumed MSB-first. The reader
|
|
33
|
+
# keeps a 64-bit container (little-endian window onto 8 bytes)
|
|
34
|
+
# and takes bits from the high end after `bits_consumed`.
|
|
31
35
|
#
|
|
32
|
-
# The
|
|
33
|
-
#
|
|
36
|
+
# The last byte holds a 1 end-mark bit with 0-7 padding zero
|
|
37
|
+
# bits above it; the last byte can therefore never be 0x00.
|
|
34
38
|
class BitStream
|
|
35
|
-
|
|
36
|
-
attr_reader :data
|
|
39
|
+
MASK64 = 0xFFFFFFFFFFFFFFFF
|
|
37
40
|
|
|
38
|
-
#
|
|
39
|
-
|
|
41
|
+
# Reload statuses mirroring C's BIT_DStream_status.
|
|
42
|
+
UNFINISHED = :unfinished
|
|
43
|
+
END_OF_BUFFER = :end_of_buffer
|
|
44
|
+
COMPLETED = :completed
|
|
45
|
+
OVERFLOW = :overflow
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
# @param data [String]
|
|
47
|
+
attr_reader :data
|
|
48
|
+
|
|
49
|
+
# @param data [String] the full bitstream bytes (binary)
|
|
44
50
|
def initialize(data)
|
|
45
|
-
@data = data
|
|
46
|
-
|
|
51
|
+
@data = data
|
|
52
|
+
n = data.bytesize
|
|
53
|
+
last = n.positive? ? data.getbyte(n - 1) : 0
|
|
54
|
+
end_mark = last.positive? ? 8 - Constants.highbit32(last) : 0
|
|
55
|
+
|
|
56
|
+
if n >= 8
|
|
57
|
+
@ptr = n - 8
|
|
58
|
+
@container = read_le64(@ptr)
|
|
59
|
+
@bits_consumed = end_mark
|
|
60
|
+
else
|
|
61
|
+
@ptr = 0
|
|
62
|
+
@container = 0
|
|
63
|
+
n.times { |i| @container |= data.getbyte(i) << (i * 8) }
|
|
64
|
+
@bits_consumed = end_mark + ((8 - n) * 8)
|
|
65
|
+
end
|
|
47
66
|
end
|
|
48
67
|
|
|
49
|
-
# Read bits
|
|
50
|
-
#
|
|
51
|
-
# Bits are read from LSB to MSB, starting from the end of the stream.
|
|
68
|
+
# Read `count` bits, first-read bit becoming the value's MSB
|
|
69
|
+
# (little-endian value semantics per RFC 8878 §4.1).
|
|
52
70
|
#
|
|
53
|
-
# @param count [Integer]
|
|
54
|
-
# @return [Integer]
|
|
71
|
+
# @param count [Integer] 0..32
|
|
72
|
+
# @return [Integer]
|
|
55
73
|
def read_bits(count)
|
|
56
74
|
return 0 if count.zero?
|
|
57
75
|
|
|
58
|
-
|
|
59
|
-
count
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
result
|
|
76
|
+
shift_left = @bits_consumed & 63
|
|
77
|
+
shift_right = (64 - count) & 63
|
|
78
|
+
result = ((@container << shift_left) & MASK64) >> shift_right
|
|
79
|
+
@bits_consumed += count
|
|
80
|
+
result & ((1 << count) - 1)
|
|
64
81
|
end
|
|
65
82
|
|
|
66
|
-
# Peek
|
|
67
|
-
#
|
|
68
|
-
# @param count [Integer] Number of bits to peek
|
|
69
|
-
# @return [Integer] The peeked bits
|
|
83
|
+
# Peek `count` bits without consuming.
|
|
70
84
|
def peek_bits(count)
|
|
71
|
-
|
|
85
|
+
saved_ptr = @ptr
|
|
86
|
+
saved_container = @container
|
|
87
|
+
saved_consumed = @bits_consumed
|
|
72
88
|
result = read_bits(count)
|
|
73
|
-
@
|
|
89
|
+
@ptr = saved_ptr
|
|
90
|
+
@container = saved_container
|
|
91
|
+
@bits_consumed = saved_consumed
|
|
74
92
|
result
|
|
75
93
|
end
|
|
76
94
|
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
95
|
+
# Reload the container after enough bits have been consumed,
|
|
96
|
+
# mirroring C's BIT_reloadDStream.
|
|
97
|
+
def reload
|
|
98
|
+
return if @bits_consumed < 8
|
|
99
|
+
|
|
100
|
+
if @ptr >= 8
|
|
101
|
+
bytes_consumed = @bits_consumed >> 3
|
|
102
|
+
@ptr -= bytes_consumed
|
|
103
|
+
@ptr = 0 if @ptr.negative?
|
|
104
|
+
@bits_consumed &= 7
|
|
105
|
+
load_container
|
|
106
|
+
elsif @ptr.zero?
|
|
107
|
+
# No earlier bytes to load; leave the container as is.
|
|
108
|
+
else
|
|
109
|
+
nb_bytes = @bits_consumed >> 3
|
|
110
|
+
actual_bytes = [nb_bytes, @ptr].min
|
|
111
|
+
@ptr -= actual_bytes
|
|
112
|
+
@bits_consumed -= actual_bytes * 8
|
|
113
|
+
load_container
|
|
114
|
+
end
|
|
82
115
|
end
|
|
83
116
|
|
|
84
|
-
#
|
|
117
|
+
# Full reload that also reports the C reload status.
|
|
85
118
|
#
|
|
86
|
-
# @return [
|
|
87
|
-
|
|
88
|
-
|
|
119
|
+
# @return [Symbol] one of UNFINISHED, END_OF_BUFFER, COMPLETED,
|
|
120
|
+
# OVERFLOW
|
|
121
|
+
def reload_status
|
|
122
|
+
return OVERFLOW if @bits_consumed > 64
|
|
123
|
+
|
|
124
|
+
if @ptr >= 8
|
|
125
|
+
bytes_consumed = @bits_consumed >> 3
|
|
126
|
+
@ptr -= bytes_consumed
|
|
127
|
+
@ptr = 0 if @ptr.negative?
|
|
128
|
+
@bits_consumed &= 7
|
|
129
|
+
load_container
|
|
130
|
+
return UNFINISHED
|
|
131
|
+
end
|
|
132
|
+
return END_OF_BUFFER if @ptr.zero?
|
|
133
|
+
|
|
134
|
+
nb_bytes = @bits_consumed >> 3
|
|
135
|
+
actual_bytes = [nb_bytes, @ptr].min
|
|
136
|
+
@ptr -= actual_bytes
|
|
137
|
+
@bits_consumed -= actual_bytes * 8
|
|
138
|
+
load_container
|
|
139
|
+
actual_bytes < nb_bytes ? END_OF_BUFFER : UNFINISHED
|
|
89
140
|
end
|
|
90
141
|
|
|
91
|
-
#
|
|
142
|
+
# Skip to the next byte boundary (toward the stream start).
|
|
92
143
|
def align_to_byte
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
private
|
|
144
|
+
remainder = @bits_consumed % 8
|
|
145
|
+
return if remainder.zero?
|
|
97
146
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
# @return [Integer] 0 or 1
|
|
101
|
-
def read_single_bit
|
|
102
|
-
return 0 if @bit_position <= 0
|
|
103
|
-
|
|
104
|
-
@bit_position -= 1
|
|
105
|
-
byte_index = @bit_position / 8
|
|
106
|
-
bit_index = @bit_position % 8
|
|
107
|
-
|
|
108
|
-
return 0 if byte_index.negative? || byte_index >= @data.bytesize
|
|
109
|
-
|
|
110
|
-
byte = @data.getbyte(byte_index)
|
|
111
|
-
(byte >> bit_index) & 1
|
|
147
|
+
@bits_consumed += 8 - remainder
|
|
148
|
+
reload if @bits_consumed >= 8
|
|
112
149
|
end
|
|
113
|
-
end
|
|
114
150
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
attr_reader :data
|
|
121
|
-
|
|
122
|
-
# @return [Integer] Current bit position
|
|
123
|
-
attr_reader :bit_position
|
|
124
|
-
|
|
125
|
-
# Initialize bitstream with data
|
|
126
|
-
#
|
|
127
|
-
# @param data [String] The compressed bitstream data
|
|
128
|
-
# @param start_byte [Integer] Starting byte position
|
|
129
|
-
def initialize(data, start_byte = 0)
|
|
130
|
-
@data = data.dup.force_encoding(Encoding::BINARY)
|
|
131
|
-
@bit_position = start_byte * 8
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Read bits from the stream (in forward order)
|
|
135
|
-
#
|
|
136
|
-
# Bits are read from MSB to LSB within each byte.
|
|
137
|
-
#
|
|
138
|
-
# @param count [Integer] Number of bits to read
|
|
139
|
-
# @return [Integer] The read bits
|
|
140
|
-
def read_bits(count)
|
|
141
|
-
return 0 if count.zero?
|
|
142
|
-
|
|
143
|
-
result = 0
|
|
144
|
-
count.times do
|
|
145
|
-
result = (result << 1) | read_single_bit
|
|
146
|
-
end
|
|
147
|
-
result
|
|
151
|
+
# Bits not yet consumed, counting from the end of the data.
|
|
152
|
+
def remaining_bits
|
|
153
|
+
total = @data.bytesize * 8
|
|
154
|
+
consumed = bits_consumed_so_far
|
|
155
|
+
total >= consumed ? total - consumed : 0
|
|
148
156
|
end
|
|
149
157
|
|
|
150
|
-
# Check if bitstream is exhausted
|
|
151
|
-
#
|
|
152
|
-
# @return [Boolean]
|
|
153
158
|
def exhausted?
|
|
154
|
-
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
# Get current byte position
|
|
158
|
-
#
|
|
159
|
-
# @return [Integer]
|
|
160
|
-
def byte_position
|
|
161
|
-
@bit_position / 8
|
|
159
|
+
remaining_bits.zero?
|
|
162
160
|
end
|
|
163
161
|
|
|
164
162
|
private
|
|
165
163
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
byte_index = @bit_position / 8
|
|
173
|
-
bit_index = 7 - (@bit_position % 8) # MSB first
|
|
174
|
-
|
|
175
|
-
@bit_position += 1
|
|
164
|
+
def bits_consumed_so_far
|
|
165
|
+
bytes_after_window = @data.bytesize - (@ptr + 8)
|
|
166
|
+
bytes_after_window = 0 if bytes_after_window.negative?
|
|
167
|
+
(bytes_after_window * 8) + @bits_consumed
|
|
168
|
+
end
|
|
176
169
|
|
|
177
|
-
|
|
170
|
+
def read_le64(offset)
|
|
171
|
+
v = 0
|
|
172
|
+
8.times { |i| v |= @data.getbyte(offset + i) << (i * 8) }
|
|
173
|
+
v
|
|
174
|
+
end
|
|
178
175
|
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
def load_container
|
|
177
|
+
@container = read_le64(@ptr)
|
|
181
178
|
end
|
|
182
179
|
end
|
|
183
180
|
end
|