Change EncodingHuffmanTree API to be more consistent with decoding tree and cleanup usage

This commit is contained in:
Timofey Solomko
2017-08-29 00:10:04 +03:00
parent 2aca494757
commit 12da128ddd
3 changed files with 24 additions and 15 deletions
+2 -2
View File
@@ -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 */,
+10 -6
View File
@@ -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
+12 -7
View File
@@ -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
}
}