mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
Change EncodingHuffmanTree API to be more consistent with decoding tree and cleanup usage
This commit is contained in:
@@ -712,10 +712,10 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
06E234811E06A6C200F18798 /* CheckSums.swift */,
|
||||
06CDFCB61F111E6900292758 /* BitReader.swift */,
|
||||
063DF1051DE1F07800F38082 /* DataWithPointer.swift */,
|
||||
063DF1061DE1F07800F38082 /* Extensions.swift */,
|
||||
063DF1091DE1F07800F38082 /* Protocols.swift */,
|
||||
063DF1051DE1F07800F38082 /* DataWithPointer.swift */,
|
||||
06CDFCB61F111E6900292758 /* BitReader.swift */,
|
||||
0681B3DD1E44F674001A9D79 /* BitWriter.swift */,
|
||||
063DF1081DE1F07800F38082 /* DecodingHuffmanTree.swift */,
|
||||
06FEAD911F54B9CD00AD016E /* EncodingHuffmanTree.swift */,
|
||||
|
||||
@@ -114,32 +114,36 @@ public extension Deflate {
|
||||
let staticHuffmanBootstrap = [[0, 8], [144, 9], [256, 7], [280, 8], [288, -1]]
|
||||
let staticHuffmanLengthsBootstrap = [[0, 5], [32, -1]]
|
||||
/// Huffman tree for literal and length symbols/codes.
|
||||
let mainLiterals = EncodingHuffmanTree(bootstrap: staticHuffmanBootstrap)
|
||||
let mainLiterals = EncodingHuffmanTree(bootstrap: staticHuffmanBootstrap,
|
||||
throw: DeflateError.symbolNotFound,
|
||||
bitWriter)
|
||||
/// Huffman tree for backward distance symbols/codes.
|
||||
let mainDistances = EncodingHuffmanTree(bootstrap: staticHuffmanLengthsBootstrap)
|
||||
let mainDistances = EncodingHuffmanTree(bootstrap: staticHuffmanLengthsBootstrap,
|
||||
throw: DeflateError.symbolNotFound,
|
||||
bitWriter)
|
||||
|
||||
for code in bldCodes {
|
||||
switch code {
|
||||
case .byte(let byte):
|
||||
try mainLiterals.code(symbol: byte.toInt(), bitWriter, DeflateError.symbolNotFound)
|
||||
try mainLiterals.code(symbol: byte.toInt())
|
||||
case .lengthDistance(let length, let distance):
|
||||
let lengthSymbol = Constants.lengthCode[Int(length) - 3]
|
||||
let lengthExtraBits = Int(length) - Constants.lengthBase[lengthSymbol - 257]
|
||||
let lengthExtraBitsCount = (257 <= lengthSymbol && lengthSymbol <= 260) || lengthSymbol == 285 ?
|
||||
0 : (((lengthSymbol - 257) >> 2) - 1)
|
||||
try mainLiterals.code(symbol: lengthSymbol, bitWriter, DeflateError.symbolNotFound)
|
||||
try mainLiterals.code(symbol: lengthSymbol)
|
||||
bitWriter.write(number: lengthExtraBits, bitsCount: lengthExtraBitsCount)
|
||||
|
||||
let distanceSymbol = ((Constants.distanceBase.index { $0 > Int(distance) }) ?? 30) - 1
|
||||
let distanceExtraBits = Int(distance) - Constants.distanceBase[distanceSymbol]
|
||||
let distanceExtraBitsCount = distanceSymbol == 0 || distanceSymbol == 1 ? 0 : ((distanceSymbol >> 1) - 1)
|
||||
try mainDistances.code(symbol: distanceSymbol, bitWriter, DeflateError.symbolNotFound)
|
||||
try mainDistances.code(symbol: distanceSymbol)
|
||||
bitWriter.write(number: distanceExtraBits, bitsCount: distanceExtraBitsCount)
|
||||
}
|
||||
}
|
||||
|
||||
// End data symbol.
|
||||
try mainLiterals.code(symbol: 256, bitWriter, DeflateError.symbolNotFound)
|
||||
try mainLiterals.code(symbol: 256)
|
||||
bitWriter.finish()
|
||||
|
||||
return bitWriter.buffer
|
||||
|
||||
@@ -7,9 +7,14 @@ import Foundation
|
||||
|
||||
class EncodingHuffmanTree {
|
||||
|
||||
private var bitWriter: BitWriter
|
||||
private let symbolNotFoundError: Error
|
||||
|
||||
private var codingIndices: [[Int]]
|
||||
|
||||
init(bootstrap: [[Int]]) {
|
||||
init(bootstrap: [[Int]], throw symbolNotFoundError: Error, _ bitWriter: BitWriter) {
|
||||
self.bitWriter = bitWriter
|
||||
self.symbolNotFoundError = symbolNotFoundError
|
||||
// Fills the 'lengths' array with numerous HuffmanLengths from a 'bootstrap'.
|
||||
var lengths: [[Int]] = []
|
||||
var start = bootstrap[0][0]
|
||||
@@ -67,29 +72,29 @@ class EncodingHuffmanTree {
|
||||
}
|
||||
}
|
||||
|
||||
convenience init(lengthsToOrder: [Int]) {
|
||||
convenience init(lengthsToOrder: [Int], throw symbolNotFoundError: Error, _ bitWriter: BitWriter) {
|
||||
var addedLengths = lengthsToOrder
|
||||
addedLengths.append(-1)
|
||||
let lengthsCount = addedLengths.count
|
||||
let range = Array(0...lengthsCount)
|
||||
self.init(bootstrap: (zip(range, addedLengths)).map { [$0, $1] })
|
||||
self.init(bootstrap: (zip(range, addedLengths)).map { [$0, $1] }, throw: symbolNotFoundError, bitWriter)
|
||||
}
|
||||
|
||||
func code(symbol: Int, _ bitWriter: BitWriter, _ symbolNotFoundError: Error) throws {
|
||||
func code(symbol: Int) throws {
|
||||
guard symbol < self.codingIndices.count
|
||||
else { throw symbolNotFoundError }
|
||||
else { throw self.symbolNotFoundError }
|
||||
|
||||
let codingIndex = self.codingIndices[symbol]
|
||||
|
||||
guard codingIndex[0] > -1
|
||||
else { throw symbolNotFoundError }
|
||||
else { throw self.symbolNotFoundError }
|
||||
|
||||
var treeCode = codingIndex[0]
|
||||
let bits = codingIndex[1]
|
||||
|
||||
for _ in 0..<bits {
|
||||
let bit = treeCode & 1
|
||||
bitWriter.write(bit: bit == 0 ? 0 : 1)
|
||||
self.bitWriter.write(bit: bit == 0 ? 0 : 1)
|
||||
treeCode >>= 1
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user