From 142fd44dd28f3f30530ed982f36f4f24adbaebdd Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Tue, 8 Jan 2019 19:16:41 +0300 Subject: [PATCH] Remove old CodeLength initializer from Encoding(Huffman)Tree --- Sources/BZip2/BZip2+Compress.swift | 7 +++-- .../CodingTree/EncodingHuffmanTree.swift | 29 ------------------- Sources/Deflate/Deflate+Compress.swift | 4 +-- Sources/Deflate/Deflate+Constants.swift | 7 +++-- Sources/Deflate/Deflate+Lengths.swift | 1 + 5 files changed, 12 insertions(+), 36 deletions(-) diff --git a/Sources/BZip2/BZip2+Compress.swift b/Sources/BZip2/BZip2+Compress.swift index c3b30c33..9298ea4f 100644 --- a/Sources/BZip2/BZip2+Compress.swift +++ b/Sources/BZip2/BZip2+Compress.swift @@ -121,10 +121,11 @@ extension BZip2: CompressionAlgorithm { selectors.append(minimumSelector) } else { // Otherwise, let's create a new table and check if it gives us better results. - // First, we calculate code lengths for our current stats. + // First, we calculate code lengths and codes for our current stats. let lengths = BZip2.lengths(from: stats) - // Then, using these code lengths, we create a new Huffman tree. - let table = EncodingHuffmanTree(lengths: lengths, bitWriter) + let codes = Code.huffmanCodes(from: lengths) + // Then, using these codes, we create a new Huffman tree. + let table = EncodingHuffmanTree(codes: codes.codes, bitWriter) if table.bitSize(for: stats) < minimumSize { tables.append(table) tablesLengths.append(lengths.sorted { $0.symbol < $1.symbol }.map { $0.codeLength }) diff --git a/Sources/Common/CodingTree/EncodingHuffmanTree.swift b/Sources/Common/CodingTree/EncodingHuffmanTree.swift index 5a737f27..45be0d44 100644 --- a/Sources/Common/CodingTree/EncodingHuffmanTree.swift +++ b/Sources/Common/CodingTree/EncodingHuffmanTree.swift @@ -12,35 +12,6 @@ final class EncodingHuffmanTree { private let codingIndices: [[Int]] - /// `lengths` don't have to be properly sorted, but there must not be any 0 code lengths. - /// If `reverseCodes` is true, then bit order of tree codes will be reversed. Necessary for Deflate. - init(lengths: [CodeLength], _ bitWriter: BitWriter, reverseCodes: Bool = false) { - self.bitWriter = bitWriter - - // Sort `lengths` array to calculate canonical Huffman code. - let sortedLengths = lengths.sorted() - - var codingIndices = Array(repeating: [-1, -1], count: sortedLengths.count) - - // Calculates symbols for each length in 'sortedLengths' array and put them in the tree. - var loopBits = -1 - var symbol = -1 - for length in sortedLengths { - precondition(length.codeLength > 0, "Code length must not be 0 during HuffmanTree initialisation.") - symbol += 1 - // We sometimes need to make symbol to have length.bits bit length. - let bits = length.codeLength - if bits != loopBits { - symbol <<= (bits - loopBits) - loopBits = bits - } - // Then we reverse bit order of the symbol, if necessary. - let treeCode = reverseCodes ? symbol.reversed(bits: loopBits) : symbol - codingIndices[length.symbol] = [treeCode, bits] - } - self.codingIndices = codingIndices - } - init(codes: [Code], _ bitWriter: BitWriter, reverseCodes: Bool = false) { self.bitWriter = bitWriter diff --git a/Sources/Deflate/Deflate+Compress.swift b/Sources/Deflate/Deflate+Compress.swift index 8b628074..9aba6a24 100644 --- a/Sources/Deflate/Deflate+Compress.swift +++ b/Sources/Deflate/Deflate+Compress.swift @@ -106,10 +106,10 @@ extension Deflate: CompressionAlgorithm { // Constructing Huffman trees for the case of block with preset alphabets. // In this case codes for literals and distances are fixed. /// Huffman tree for literal and length symbols/codes. - let mainLiterals = EncodingHuffmanTree(lengths: Constants.staticHuffmanBootstrap, + let mainLiterals = EncodingHuffmanTree(codes: Constants.staticHuffmanBootstrap.codes, bitWriter, reverseCodes: true) /// Huffman tree for backward distance symbols/codes. - let mainDistances = EncodingHuffmanTree(lengths: Constants.staticHuffmanDistancesBootstrap, + let mainDistances = EncodingHuffmanTree(codes: Constants.staticHuffmanDistancesBootstrap.codes, bitWriter, reverseCodes: true) for code in bldCodes { diff --git a/Sources/Deflate/Deflate+Constants.swift b/Sources/Deflate/Deflate+Constants.swift index 8051da7b..8af6ac4a 100644 --- a/Sources/Deflate/Deflate+Constants.swift +++ b/Sources/Deflate/Deflate+Constants.swift @@ -8,9 +8,12 @@ import Foundation extension Deflate { struct Constants { + // TODO: Combine length bootstrapping and code generation. // Bootstraps for Static Huffman trees (first element in tuple is code, second is number of bits). - static let staticHuffmanBootstrap = CodeLength.lengths(from: [(0, 8), (144, 9), (256, 7), (280, 8), (288, -1)]) - static let staticHuffmanDistancesBootstrap = CodeLength.lengths(from: [(0, 5), (32, -1)]) + static let staticHuffmanBootstrap = Code.huffmanCodes(from: + CodeLength.lengths(from: [(0, 8), (144, 9), (256, 7), (280, 8), (288, -1)])) + static let staticHuffmanDistancesBootstrap = Code.huffmanCodes(from: + CodeLength.lengths(from: [(0, 5), (32, -1)])) static let codeLengthOrders: [Int] = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15] diff --git a/Sources/Deflate/Deflate+Lengths.swift b/Sources/Deflate/Deflate+Lengths.swift index 7917e511..eab5561b 100644 --- a/Sources/Deflate/Deflate+Lengths.swift +++ b/Sources/Deflate/Deflate+Lengths.swift @@ -8,6 +8,7 @@ import Foundation // Deflate specific functions for generation of HuffmanLength arrays from different inputs. extension Deflate { + // TODO: Make this work for both arrays and array slices. /// - Note: Skips zero codeLengths. static func lengths(from orderedCodeLengths: [Int]) -> [CodeLength] { var lengths = [CodeLength]()