mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
Added new enum for specifying bit order. United DataWithPointer and DataWithStraightPointer.
This commit is contained in:
+3
-3
@@ -51,7 +51,7 @@ public class BZip2: DecompressionAlgorithm {
|
||||
var out = Data()
|
||||
|
||||
/// Object with input data which supports convenient work with bit shifts.
|
||||
let pointerData = DataWithStraightPointer(data: data)
|
||||
let pointerData = DataWithPointer(data: data, bitOrder: .straight)
|
||||
|
||||
let magic = pointerData.intFromBits(count: 16)
|
||||
guard magic == 0x425a else { throw BZip2Error.WrongMagic }
|
||||
@@ -85,7 +85,7 @@ public class BZip2: DecompressionAlgorithm {
|
||||
return out
|
||||
}
|
||||
|
||||
private static func decodeHuffmanBlock(data: DataWithStraightPointer) throws -> Data {
|
||||
private static func decodeHuffmanBlock(data: DataWithPointer) throws -> Data {
|
||||
let isRandomized = data.bit()
|
||||
guard isRandomized != 1 else { throw BZip2Error.RandomizedBlock }
|
||||
|
||||
@@ -189,7 +189,7 @@ public class BZip2: DecompressionAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
guard let symbolLength = t?.findNextSymbol(in: data.bits(count: 24), reversed: false, straightBitOrder: true) else {
|
||||
guard let symbolLength = t?.findNextSymbol(in: data.bits(count: 24), reversed: false, bitOrder: .straight) else {
|
||||
throw BZip2Error.SymbolNotFound
|
||||
}
|
||||
data.rewind(bitsCount: 24 - symbolLength.bits)
|
||||
|
||||
@@ -9,20 +9,28 @@
|
||||
import Foundation
|
||||
import CoreFoundation
|
||||
|
||||
enum BitOrder {
|
||||
case straight
|
||||
case reversed
|
||||
}
|
||||
|
||||
class DataWithPointer {
|
||||
|
||||
/// Only needed for creation of bitVector in initData()
|
||||
/// Only needed for creation of bitVector
|
||||
let data: Data
|
||||
|
||||
let bitOrder: BitOrder
|
||||
|
||||
fileprivate(set) var bitVector: CFBitVector?
|
||||
fileprivate(set) var index: Int
|
||||
fileprivate(set) var bitShift: Int
|
||||
|
||||
init(data: Data) {
|
||||
init(data: Data, bitOrder: BitOrder) {
|
||||
self.data = data
|
||||
self.index = 0
|
||||
self.bitShift = 0
|
||||
self.bitVector = nil
|
||||
self.bitOrder = bitOrder
|
||||
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
|
||||
self.bitVector = CFBitVectorCreate(kCFAllocatorDefault, bytes, data.count * 8)
|
||||
}
|
||||
@@ -33,8 +41,16 @@ class DataWithPointer {
|
||||
|
||||
var array: [UInt8] = []
|
||||
for _ in 0..<count {
|
||||
let currentIndex = 8 * (index + 1) - bitShift - 1
|
||||
let currentIndex: Int
|
||||
switch self.bitOrder {
|
||||
case .straight:
|
||||
currentIndex = 8 * index + bitShift
|
||||
case .reversed:
|
||||
currentIndex = 8 * (index + 1) - bitShift - 1
|
||||
}
|
||||
|
||||
array.append(UInt8(truncatingBitPattern: CFBitVectorGetBitAtIndex(self.bitVector!, currentIndex)))
|
||||
|
||||
self.bitShift += 1
|
||||
if self.bitShift >= 8 {
|
||||
self.bitShift = 0
|
||||
@@ -49,9 +65,20 @@ class DataWithPointer {
|
||||
guard count > 0 else { return 0 }
|
||||
var result = 0
|
||||
for i in 0..<count {
|
||||
let currentIndex = 8 * (index + 1) - bitShift - 1
|
||||
result += Int(pow(Double(2), Double(i))) *
|
||||
let currentIndex: Int
|
||||
let power: Int
|
||||
switch self.bitOrder {
|
||||
case .straight:
|
||||
currentIndex = 8 * index + bitShift
|
||||
power = count - i - 1
|
||||
case .reversed:
|
||||
currentIndex = 8 * (index + 1) - bitShift - 1
|
||||
power = i
|
||||
}
|
||||
|
||||
result += Int(pow(Double(2), Double(power))) *
|
||||
Int(bitPattern: UInt(CFBitVectorGetBitAtIndex(self.bitVector!, currentIndex)))
|
||||
|
||||
self.bitShift += 1
|
||||
if self.bitShift >= 8 {
|
||||
self.bitShift = 0
|
||||
@@ -74,7 +101,7 @@ class DataWithPointer {
|
||||
return returnData
|
||||
}
|
||||
|
||||
// MARK: Manipulation with index and bitShift
|
||||
// MARK: Manipulations with index and bitShift
|
||||
|
||||
func skipUntilNextByte() {
|
||||
self.index += 1
|
||||
@@ -93,41 +120,3 @@ class DataWithPointer {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class DataWithStraightPointer: DataWithPointer {
|
||||
|
||||
override func bits(count: Int) -> [UInt8] {
|
||||
guard count > 0 else { return [] }
|
||||
|
||||
var array: [UInt8] = []
|
||||
for _ in 0..<count {
|
||||
let currentIndex = 8 * index + bitShift
|
||||
array.append(UInt8(truncatingBitPattern: CFBitVectorGetBitAtIndex(self.bitVector!, currentIndex)))
|
||||
self.bitShift += 1
|
||||
if self.bitShift >= 8 {
|
||||
self.bitShift = 0
|
||||
self.index += 1
|
||||
}
|
||||
}
|
||||
|
||||
return array
|
||||
}
|
||||
|
||||
override func intFromBits(count: Int) -> Int {
|
||||
guard count > 0 else { return 0 }
|
||||
var result = 0
|
||||
for i in 0..<count {
|
||||
let currentIndex = 8 * index + bitShift
|
||||
result += Int(pow(Double(2), Double(count - i - 1))) *
|
||||
Int(bitPattern: UInt(CFBitVectorGetBitAtIndex(self.bitVector!, currentIndex)))
|
||||
self.bitShift += 1
|
||||
if self.bitShift >= 8 {
|
||||
self.bitShift = 0
|
||||
self.index += 1
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class Deflate: DecompressionAlgorithm {
|
||||
var out = Data()
|
||||
|
||||
/// Object with input data which supports convenient work with bit shifts.
|
||||
let pointerData = DataWithPointer(data: data)
|
||||
let pointerData = DataWithPointer(data: data, bitOrder: .reversed)
|
||||
|
||||
while true {
|
||||
/// Is this a last block?
|
||||
|
||||
@@ -73,10 +73,16 @@ extension UInt16 {
|
||||
|
||||
}
|
||||
|
||||
func convertToInt(uint8Array array: [UInt8], straightBitOrder: Bool = false) -> Int {
|
||||
func convertToInt(uint8Array array: [UInt8], bitOrder: BitOrder = .reversed) -> Int {
|
||||
var result = 0
|
||||
for i in 0..<array.count {
|
||||
let power = straightBitOrder ? array.count - i - 1 : i
|
||||
let power: Int
|
||||
switch bitOrder {
|
||||
case .straight:
|
||||
power = array.count - i - 1
|
||||
case .reversed:
|
||||
power = i
|
||||
}
|
||||
result += Int(pow(Double(2), Double(power))) * Int(bitPattern: UInt(array[i]))
|
||||
}
|
||||
return result
|
||||
|
||||
@@ -90,7 +90,7 @@ class HuffmanTable: CustomStringConvertible {
|
||||
self.init(bootstrap: (zip(range, addedLengths)).map { [$0, $1] })
|
||||
}
|
||||
|
||||
func findNextSymbol(in bitArray: [UInt8], reversed: Bool = true, straightBitOrder: Bool = false) -> HuffmanLength? {
|
||||
func findNextSymbol(in bitArray: [UInt8], reversed: Bool = true, bitOrder: BitOrder = .reversed) -> HuffmanLength? {
|
||||
var cachedLength = -1
|
||||
var cached: Int = -1
|
||||
|
||||
@@ -98,7 +98,7 @@ class HuffmanTable: CustomStringConvertible {
|
||||
let lbits = length.bits
|
||||
|
||||
if cachedLength != lbits {
|
||||
cached = convertToInt(uint8Array: Array(bitArray[0..<lbits]), straightBitOrder: straightBitOrder)
|
||||
cached = convertToInt(uint8Array: Array(bitArray[0..<lbits]), bitOrder: bitOrder)
|
||||
cachedLength = lbits
|
||||
}
|
||||
if (reversed && length.reversedSymbol == cached) ||
|
||||
|
||||
Reference in New Issue
Block a user