diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index 18c37d35..bbebc4fe 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -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 */, diff --git a/Sources/DeflateCompression.swift b/Sources/DeflateCompression.swift index 07126072..9ba7a604 100644 --- a/Sources/DeflateCompression.swift +++ b/Sources/DeflateCompression.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 diff --git a/Sources/EncodingHuffmanTree.swift b/Sources/EncodingHuffmanTree.swift index 8c2e1991..0bbfb19a 100644 --- a/Sources/EncodingHuffmanTree.swift +++ b/Sources/EncodingHuffmanTree.swift @@ -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..>= 1 } }