omnizip 0.3.24 → 0.3.26
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/CHANGELOG.md +20 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +31 -19
- data/lib/omnizip/algorithms/bzip2/bz2.rb +625 -0
- data/lib/omnizip/algorithms/bzip2.rb +11 -39
- data/lib/omnizip/version.rb +1 -1
- metadata +2 -5
- data/lib/omnizip/algorithms/bzip2/decoder.rb +0 -187
- data/lib/omnizip/algorithms/bzip2/encoder.rb +0 -231
- data/lib/omnizip/algorithms/bzip2/huffman.rb +0 -206
- data/lib/omnizip/algorithms/bzip2/mtf.rb +0 -101
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 86505c60d041512f5f031bf20d19c4db6654ffe112bd0e885a7eb76129eaf37a
|
|
4
|
+
data.tar.gz: 8ceca40e4225c272bc527f508d231629b3357959e25e5f3b4ad50ba91116171f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 51953cf6f14aa679b99fe0abfc9fcc171addd943787ca7dde5b4f70945bf45ecad4dc2d7e72029f89495ba7e5c73ee9f8b72bcd8dcbe681812ef4038b7228328
|
|
7
|
+
data.tar.gz: 73407d59fc5dc1e4c6a8b997724101181c1650b8fff434b73cfa2a8835d643292fb192dcfe8a85baea49114cb5ae5cedd7c32f1e40d5e653b18b9d8f9ebd5a48
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.26] - 2026-08-26
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- BZip2 codec emits the **standard .bz2 wire format** (`BZh` magic,
|
|
14
|
+
bzip2 CRC-32, RLE1, BWT, seeded MTF, RUNA/RUNB RLE2, canonical
|
|
15
|
+
Huffman with the delta-coded length tables, 2..=6 selectable
|
|
16
|
+
groups, MSB-first bit packing, EOS magic + combined CRC). Output
|
|
17
|
+
is decodable by `bzip2 -d`; input from the CLI decodes here.
|
|
18
|
+
The previous internal byte-aligned container is removed.
|
|
19
|
+
|
|
20
|
+
## [0.3.25] - 2026-08-26
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- BZip2 Burrows-Wheeler Transform: rotation comparator compares 4
|
|
24
|
+
big-endian bytes per step (Fixnum-safe, no modulo) over a doubled
|
|
25
|
+
byte array. 21x fewer allocations per 138 KB compressed, with
|
|
26
|
+
byte-identical output and 25 case-round-tripped correctness
|
|
27
|
+
(random and degenerate). The BZip2 codec itself does not emit a
|
|
28
|
+
standard bzip2 file format (pre-existing, separate issue).
|
|
29
|
+
|
|
10
30
|
## [0.3.24] - 2026-08-26
|
|
11
31
|
|
|
12
32
|
### Changed
|
|
@@ -49,13 +49,16 @@ module Omnizip
|
|
|
49
49
|
n = data.length
|
|
50
50
|
bytes = data.bytes
|
|
51
51
|
|
|
52
|
+
# Doubled bytes: rotation a's byte at offset o is
|
|
53
|
+
# dbl[a + o] — indexing needs no modulo, and comparisons
|
|
54
|
+
# can run 8 bytes at a time (modulo arithmetic in the
|
|
55
|
+
# comparator dominated the encoder's profile).
|
|
56
|
+
dbl = bytes * 2
|
|
57
|
+
|
|
52
58
|
# Build suffix array without creating rotation strings
|
|
53
|
-
# Use direct byte comparison for efficiency
|
|
54
59
|
suffix_array = (0...n).to_a
|
|
55
|
-
|
|
56
|
-
# Sort using optimized comparison that avoids string allocation
|
|
57
60
|
suffix_array.sort! do |a, b|
|
|
58
|
-
compare_rotations(
|
|
61
|
+
compare_rotations(dbl, a, b, n)
|
|
59
62
|
end
|
|
60
63
|
|
|
61
64
|
# Find primary index (position where suffix starts at 0)
|
|
@@ -63,7 +66,7 @@ module Omnizip
|
|
|
63
66
|
|
|
64
67
|
# Extract last column (character before each suffix)
|
|
65
68
|
transformed = suffix_array.map do |idx|
|
|
66
|
-
|
|
69
|
+
dbl[n + idx - 1]
|
|
67
70
|
end.pack("C*").b
|
|
68
71
|
|
|
69
72
|
[transformed, primary_index]
|
|
@@ -149,23 +152,32 @@ module Omnizip
|
|
|
149
152
|
# @param b [Integer] Second rotation start index
|
|
150
153
|
# @param n [Integer] Length
|
|
151
154
|
# @return [Integer] -1, 0, or 1 for comparison result
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
155
|
+
# Compare rotations a and b over the doubled byte array.
|
|
156
|
+
# Four big-endian bytes per step: the chunk fits a Fixnum (no
|
|
157
|
+
# Bignum allocation), the low-offset byte dominates so the
|
|
158
|
+
# order is lexicographic, and the doubled array removes the
|
|
159
|
+
# per-byte modulo.
|
|
160
|
+
def compare_rotations(dbl, a, b, n)
|
|
161
|
+
len = 0
|
|
162
|
+
while len + 4 <= n
|
|
163
|
+
wa = (dbl[a + len] << 24) |
|
|
164
|
+
(dbl[a + len + 1] << 16) |
|
|
165
|
+
(dbl[a + len + 2] << 8) |
|
|
166
|
+
dbl[a + len + 3]
|
|
167
|
+
wb = (dbl[b + len] << 24) |
|
|
168
|
+
(dbl[b + len + 1] << 16) |
|
|
169
|
+
(dbl[b + len + 2] << 8) |
|
|
170
|
+
dbl[b + len + 3]
|
|
171
|
+
return wa <=> wb if wa != wb
|
|
172
|
+
|
|
173
|
+
len += 4
|
|
159
174
|
end
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
(8...n).each do |offset|
|
|
163
|
-
byte_a = bytes[(a + offset) % n]
|
|
164
|
-
byte_b = bytes[(b + offset) % n]
|
|
165
|
-
cmp = byte_a <=> byte_b
|
|
175
|
+
while len < n
|
|
176
|
+
cmp = dbl[a + len] <=> dbl[b + len]
|
|
166
177
|
return cmp if cmp != 0
|
|
167
|
-
end
|
|
168
178
|
|
|
179
|
+
len += 1
|
|
180
|
+
end
|
|
169
181
|
0
|
|
170
182
|
end
|
|
171
183
|
|