mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
Add new procedure for huffman code length generation
This commit is contained in:
@@ -160,6 +160,10 @@
|
||||
0693DF521F2E499F00602300 /* test_empty_dir.7z in Resources */ = {isa = PBXBuildFile; fileRef = 0693DF501F2E499F00602300 /* test_empty_dir.7z */; };
|
||||
0693DF531F2E499F00602300 /* test_empty_file.7z in Resources */ = {isa = PBXBuildFile; fileRef = 0693DF511F2E499F00602300 /* test_empty_file.7z */; };
|
||||
0693DF551F2E4AEE00602300 /* test_empty_cont.7z in Resources */ = {isa = PBXBuildFile; fileRef = 0693DF541F2E4AEE00602300 /* test_empty_cont.7z */; };
|
||||
06955E491F65C761004D5D79 /* BZip2+Lengths.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06955E481F65C761004D5D79 /* BZip2+Lengths.swift */; };
|
||||
06955E4A1F65C761004D5D79 /* BZip2+Lengths.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06955E481F65C761004D5D79 /* BZip2+Lengths.swift */; };
|
||||
06955E4B1F65C761004D5D79 /* BZip2+Lengths.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06955E481F65C761004D5D79 /* BZip2+Lengths.swift */; };
|
||||
06955E4C1F65C761004D5D79 /* BZip2+Lengths.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06955E481F65C761004D5D79 /* BZip2+Lengths.swift */; };
|
||||
0696E5C61ED0B22F00921D4D /* TarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0696E5C51ED0B22F00921D4D /* TarTests.swift */; };
|
||||
06991C701E05A9F70030FF07 /* test9.lzma in Resources */ = {isa = PBXBuildFile; fileRef = 06991C6D1E05A9F70030FF07 /* test9.lzma */; };
|
||||
06991C711E05A9F70030FF07 /* test10.lzma in Resources */ = {isa = PBXBuildFile; fileRef = 06991C6E1E05A9F70030FF07 /* test10.lzma */; };
|
||||
@@ -422,6 +426,7 @@
|
||||
0693DF501F2E499F00602300 /* test_empty_dir.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty_dir.7z; sourceTree = "<group>"; };
|
||||
0693DF511F2E499F00602300 /* test_empty_file.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty_file.7z; sourceTree = "<group>"; };
|
||||
0693DF541F2E4AEE00602300 /* test_empty_cont.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test_empty_cont.7z; sourceTree = "<group>"; };
|
||||
06955E481F65C761004D5D79 /* BZip2+Lengths.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "BZip2+Lengths.swift"; sourceTree = "<group>"; };
|
||||
0696E5C51ED0B22F00921D4D /* TarTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TarTests.swift; sourceTree = "<group>"; };
|
||||
06991C6D1E05A9F70030FF07 /* test9.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = test9.lzma; sourceTree = "<group>"; };
|
||||
06991C6E1E05A9F70030FF07 /* test10.lzma */ = {isa = PBXFileReference; lastKnownFileType = file; path = test10.lzma; sourceTree = "<group>"; };
|
||||
@@ -916,6 +921,7 @@
|
||||
06FED40B1DD7717E0013DFB2 /* BZip2.swift */,
|
||||
06CDFCA21F111D6C00292758 /* BZip2Error.swift */,
|
||||
06D95AC01F4C54E0006B46AC /* BZip2Compression.swift */,
|
||||
06955E481F65C761004D5D79 /* BZip2+Lengths.swift */,
|
||||
0634D9821F5207C30002B675 /* SuffixArray.swift */,
|
||||
06FEAD871F54B9AB00AD016E /* RecursiveHuffmanTree.swift */,
|
||||
);
|
||||
@@ -1241,6 +1247,7 @@
|
||||
061C06531F0E904600832F0C /* ZipEndOfCentralDirectory.swift in Sources */,
|
||||
06CDFCB81F111E6900292758 /* BitReader.swift in Sources */,
|
||||
06BB8F311E0C2C720079FB9E /* LZMA2.swift in Sources */,
|
||||
06955E4A1F65C761004D5D79 /* BZip2+Lengths.swift in Sources */,
|
||||
065569691DC65C2A00A47E66 /* ZlibArchive.swift in Sources */,
|
||||
061C064E1F0E901C00832F0C /* ZipLocalHeader.swift in Sources */,
|
||||
063DF10E1DE1F07800F38082 /* Extensions.swift in Sources */,
|
||||
@@ -1305,6 +1312,7 @@
|
||||
061C06541F0E904600832F0C /* ZipEndOfCentralDirectory.swift in Sources */,
|
||||
06CDFCB91F111E6900292758 /* BitReader.swift in Sources */,
|
||||
06BB8F321E0C2C720079FB9E /* LZMA2.swift in Sources */,
|
||||
06955E4B1F65C761004D5D79 /* BZip2+Lengths.swift in Sources */,
|
||||
063DF1191DE1F2E200F38082 /* DataWithPointer.swift in Sources */,
|
||||
061C064F1F0E901C00832F0C /* ZipLocalHeader.swift in Sources */,
|
||||
063DF11A1DE1F2E200F38082 /* Extensions.swift in Sources */,
|
||||
@@ -1369,6 +1377,7 @@
|
||||
061C06551F0E904600832F0C /* ZipEndOfCentralDirectory.swift in Sources */,
|
||||
06CDFCBA1F111E6900292758 /* BitReader.swift in Sources */,
|
||||
06BB8F331E0C2C720079FB9E /* LZMA2.swift in Sources */,
|
||||
06955E4C1F65C761004D5D79 /* BZip2+Lengths.swift in Sources */,
|
||||
065569771DC65C2B00A47E66 /* ZlibArchive.swift in Sources */,
|
||||
061C06501F0E901C00832F0C /* ZipLocalHeader.swift in Sources */,
|
||||
063DF10F1DE1F07800F38082 /* Extensions.swift in Sources */,
|
||||
@@ -1433,6 +1442,7 @@
|
||||
061C06521F0E904600832F0C /* ZipEndOfCentralDirectory.swift in Sources */,
|
||||
06CDFCB71F111E6900292758 /* BitReader.swift in Sources */,
|
||||
06BB8F301E0C2C720079FB9E /* LZMA2.swift in Sources */,
|
||||
06955E491F65C761004D5D79 /* BZip2+Lengths.swift in Sources */,
|
||||
06A393391DE0709300182E12 /* GzipArchive.swift in Sources */,
|
||||
061C064D1F0E901C00832F0C /* ZipLocalHeader.swift in Sources */,
|
||||
063DF10D1DE1F07800F38082 /* Extensions.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2017 Timofey Solomko
|
||||
// Licensed under MIT License
|
||||
//
|
||||
// See LICENSE for license information
|
||||
|
||||
import Foundation
|
||||
|
||||
// BZip2 specific function for generation of HuffmanLength array from stats.
|
||||
extension BZip2 {
|
||||
|
||||
/**
|
||||
Based on "procedure for generating the lists which specify a Huffman code table" (annexes C and K)
|
||||
from Recommendation T.81 of ITU (aka JPEG specfications).
|
||||
*/
|
||||
static func lengths(from stats: [Int]) -> [HuffmanLength] {
|
||||
if stats.count == 0 {
|
||||
return []
|
||||
} else if stats.count == 1 {
|
||||
return [HuffmanLength(symbol: 0, codeLength: 1)]
|
||||
}
|
||||
|
||||
/// Mutable copy of input `stats`.
|
||||
var stats = stats
|
||||
|
||||
var codeSizes = Array(repeating: 0, count: 259)
|
||||
var others = Array(repeating: -1, count: 259)
|
||||
|
||||
while true {
|
||||
var c1 = -1
|
||||
var minFreq = Int.max
|
||||
for i in 0..<stats.count {
|
||||
if stats[i] > 0 && stats[i] <= minFreq {
|
||||
minFreq = stats[i]
|
||||
c1 = i
|
||||
}
|
||||
}
|
||||
|
||||
var c2 = -1
|
||||
minFreq = Int.max
|
||||
for i in 0..<stats.count {
|
||||
if stats[i] > 0 && stats[i] <= minFreq && i != c1 {
|
||||
minFreq = stats[i]
|
||||
c2 = i
|
||||
}
|
||||
}
|
||||
|
||||
guard c2 >= 0
|
||||
else { break }
|
||||
|
||||
stats[c1] += stats[c2]
|
||||
stats[c2] = 0
|
||||
|
||||
codeSizes[c1] += 1
|
||||
while others[c1] >= 0 {
|
||||
c1 = others[c1]
|
||||
codeSizes[c1] += 1
|
||||
|
||||
}
|
||||
others[c1] = c2
|
||||
|
||||
codeSizes[c2] += 1
|
||||
while others[c2] >= 0 {
|
||||
c2 = others[c2]
|
||||
codeSizes[c2] += 1
|
||||
}
|
||||
}
|
||||
|
||||
// Now we count code lengths.
|
||||
// In worst case scenario the maximum code length is 258.
|
||||
var bits = Array(repeating: 0, count: 259)
|
||||
for i in 0..<bits.count {
|
||||
// We don't check for zero code length because we have unused element in `bits` array for them.
|
||||
bits[codeSizes[i]] += 1
|
||||
}
|
||||
|
||||
// Adjust_bits
|
||||
for i in stride(from: 258, to: 20, by: -1) {
|
||||
while bits[i] > 0 {
|
||||
var j = i - 2
|
||||
while bits[j] == 0 {
|
||||
j -= 1
|
||||
}
|
||||
bits[i] -= 2
|
||||
bits[i - 1] += 1
|
||||
bits[j + 1] += 2
|
||||
bits[j] -= 1
|
||||
}
|
||||
}
|
||||
|
||||
// Generate_size_table
|
||||
var symbol = 0
|
||||
var lengths = [HuffmanLength]()
|
||||
for i in 1...20 {
|
||||
var j = 1
|
||||
while j <= bits[i] {
|
||||
lengths.append(HuffmanLength(symbol: symbol, codeLength: i))
|
||||
symbol += 1
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
|
||||
return lengths
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user