Added new enum for specifying bit order. United DataWithPointer and DataWithStraightPointer.

This commit is contained in:
Timofey Solomko
2016-11-15 22:32:36 +03:00
parent fc308aa69b
commit 615e8a1ff4
5 changed files with 47 additions and 52 deletions
+3 -3
View File
@@ -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)
+33 -44
View File
@@ -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
}
}
+1 -1
View File
@@ -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?
+8 -2
View File
@@ -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
+2 -2
View File
@@ -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) ||