mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
63 lines
1.8 KiB
Swift
63 lines
1.8 KiB
Swift
// Copyright (c) 2026 Timofey Solomko
|
|
// Licensed under MIT License
|
|
//
|
|
// See LICENSE for license information
|
|
|
|
import Foundation
|
|
import BitByteData
|
|
|
|
fileprivate struct CodingIndex {
|
|
|
|
let treeCode: Int
|
|
let bitSize: Int
|
|
|
|
}
|
|
|
|
final class EncodingTree {
|
|
|
|
private let bitWriter: BitWriter
|
|
|
|
private let codingIndices: [CodingIndex]
|
|
|
|
init(codes: [Code], _ bitWriter: BitWriter, reverseCodes: Bool = false) {
|
|
self.bitWriter = bitWriter
|
|
|
|
var codingIndices = Array(repeating: CodingIndex(treeCode: -1, bitSize: -1), count: codes.count)
|
|
|
|
for code in codes {
|
|
// Codes have already been reversed.
|
|
// TODO: This assumption may be only correct for Huffman codes.
|
|
let treeCode = reverseCodes ? code.code : code.code.reversed(bits: code.bits)
|
|
codingIndices[code.symbol] = CodingIndex(treeCode: treeCode, bitSize: code.bits)
|
|
}
|
|
self.codingIndices = codingIndices
|
|
}
|
|
|
|
func code(symbol: Int) {
|
|
guard symbol < self.codingIndices.count
|
|
else { fatalError("Symbol is not found.") }
|
|
|
|
let codingIndex = self.codingIndices[symbol]
|
|
|
|
guard codingIndex.treeCode > -1
|
|
else { fatalError("Symbol is not found.") }
|
|
|
|
self.bitWriter.write(number: codingIndex.treeCode, bitsCount: codingIndex.bitSize)
|
|
}
|
|
|
|
func bitSize(for stats: [Int]) -> Int {
|
|
var totalSize = 0
|
|
for (symbol, count) in stats.enumerated() where count > 0 {
|
|
guard symbol < self.codingIndices.count
|
|
else { fatalError("Symbol is not found.") }
|
|
let codingIndex = self.codingIndices[symbol]
|
|
guard codingIndex.treeCode > -1
|
|
else { fatalError("Symbol is not found.") }
|
|
|
|
totalSize += count * codingIndex.bitSize
|
|
}
|
|
return totalSize
|
|
}
|
|
|
|
}
|