// // LZMALenDecoder.swift // SWCompression // // Created by Timofey Solomko on 23.12.16. // Copyright © 2017 Timofey Solomko. All rights reserved. // import Foundation final class LZMALenDecoder { private var pointerData: DataWithPointer private var choice: Int = LZMAConstants.probInitValue private var choice2: Int = LZMAConstants.probInitValue private var lowCoder: [LZMABitTreeDecoder] = [] private var midCoder: [LZMABitTreeDecoder] = [] private var highCoder: LZMABitTreeDecoder init(_ pointerData: inout DataWithPointer) { self.pointerData = pointerData self.highCoder = LZMABitTreeDecoder(numBits: 8, &self.pointerData) for _ in 0..<(1 << LZMAConstants.numPosBitsMax) { self.lowCoder.append(LZMABitTreeDecoder(numBits: 3, &self.pointerData)) self.midCoder.append(LZMABitTreeDecoder(numBits: 3, &self.pointerData)) } } /// Decodes zero-based match length. func decode(with rangeDecoder: inout LZMARangeDecoder, posState: Int) -> Int { // There can be one of three options. // We need one or two bits to find out which decoding scheme to use. // `choice` is used to decode first bit. // `choice2` is used to decode second bit. // If binary sequence starts with 0 then: if rangeDecoder.decode(bitWithProb: &self.choice) == 0 { return self.lowCoder[posState].decode(with: &rangeDecoder) } // If binary sequence starts with 1 0 then: if rangeDecoder.decode(bitWithProb: &self.choice2) == 0 { return 8 + self.midCoder[posState].decode(with: &rangeDecoder) } // If binary sequence starts with 1 1 then: return 16 + self.highCoder.decode(with: &rangeDecoder) } }