From 369da20c165cc2ea44e9b2e7d731c7210ff77f42 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 8 Jul 2017 21:59:29 +0300 Subject: [PATCH] Adopted DWP-BitReader split everywhere I've also removed a most occurrences of inout keyword because DWP (and BitReader) are classes and they are already passed by reference in arguments. --- Sources/BZip2.swift | 44 ++++++++++++------------ Sources/Deflate.swift | 46 +++++++++++++------------- Sources/DeflateCompression.swift | 17 +++++----- Sources/GzipArchive.swift | 20 +++++------ Sources/GzipHeader.swift | 6 ++-- Sources/HuffmanTree.swift | 14 ++++---- Sources/LZMA.swift | 8 ++--- Sources/LZMA2.swift | 8 ++--- Sources/LZMADecoder.swift | 4 +-- Sources/LZMARangeDecoder.swift | 4 +-- Sources/TarContainer.swift | 10 +++--- Sources/TarEntry.swift | 2 +- Sources/XZArchive.swift | 38 ++++++++++----------- Sources/ZipCentralDirectoryEntry.swift | 2 +- Sources/ZipContainer.swift | 18 +++++----- Sources/ZipEndOfCentralDirectory.swift | 2 +- Sources/ZipEntry.swift | 38 ++++++++++----------- Sources/ZipLocalHeader.swift | 2 +- Sources/ZlibArchive.swift | 8 ++--- Sources/ZlibHeader.swift | 18 +++++----- 20 files changed, 154 insertions(+), 155 deletions(-) diff --git a/Sources/BZip2.swift b/Sources/BZip2.swift index cc52b24c..2c5c1f26 100644 --- a/Sources/BZip2.swift +++ b/Sources/BZip2.swift @@ -22,21 +22,21 @@ public class BZip2: DecompressionAlgorithm { */ public static func decompress(data: Data) throws -> Data { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .straight) - return Data(bytes: try decompress(&pointerData)) + let bitReader = BitReader(data: data, bitOrder: .straight) + return Data(bytes: try decompress(bitReader)) } - static func decompress(_ pointerData: inout DataWithPointer) throws -> [UInt8] { + static func decompress(_ bitReader: BitReader) throws -> [UInt8] { /// An array for storing output data var out = [UInt8]() - let magic = pointerData.intFromBits(count: 16) + let magic = bitReader.intFromBits(count: 16) guard magic == 0x425a else { throw BZip2Error.wrongMagic } - let method = pointerData.intFromBits(count: 8) + let method = bitReader.intFromBits(count: 8) guard method == 104 else { throw BZip2Error.wrongCompressionMethod } - var blockSize = pointerData.intFromBits(count: 8) + var blockSize = bitReader.intFromBits(count: 8) if blockSize >= 49 && blockSize <= 57 { blockSize -= 48 } else { @@ -45,12 +45,12 @@ public class BZip2: DecompressionAlgorithm { var totalCRC: UInt32 = 0 while true { - let blockType: Int64 = Int64(pointerData.intFromBits(count: 48)) - // Next 32 bits are crc (which currently is not checked). - let blockCRC32 = UInt32(truncatingBitPattern: pointerData.intFromBits(count: 32)) + let blockType: Int64 = Int64(bitReader.intFromBits(count: 48)) + + let blockCRC32 = UInt32(truncatingBitPattern: bitReader.intFromBits(count: 32)) if blockType == 0x314159265359 { - let blockBytes = try decode(data: &pointerData) + let blockBytes = try decode(bitReader) guard CheckSums.bzip2CRC32(blockBytes) == blockCRC32 else { throw BZip2Error.wrongCRC(Data(bytes: out)) } for byte in blockBytes { @@ -70,19 +70,19 @@ public class BZip2: DecompressionAlgorithm { return out } - private static func decode(data: inout DataWithPointer) throws -> [UInt8] { - let isRandomized = data.bit() + private static func decode(_ bitReader: BitReader) throws -> [UInt8] { + let isRandomized = bitReader.bit() guard isRandomized != 1 else { throw BZip2Error.randomizedBlock } - var pointer = data.intFromBits(count: 24) + var pointer = bitReader.intFromBits(count: 24) func computeUsed() -> [Bool] { - let huffmanUsedMap = data.intFromBits(count: 16) + let huffmanUsedMap = bitReader.intFromBits(count: 16) var mapMask = 1 << 15 var used: [Bool] = [] while mapMask > 0 { if huffmanUsedMap & mapMask > 0 { - let huffmanUsedBitmap = data.intFromBits(count: 16) + let huffmanUsedBitmap = bitReader.intFromBits(count: 16) var bitMask = 1 << 15 while bitMask > 0 { used.append(huffmanUsedBitmap & bitMask > 0) @@ -100,18 +100,18 @@ public class BZip2: DecompressionAlgorithm { let used = computeUsed() - let huffmanGroups = data.intFromBits(count: 3) + let huffmanGroups = bitReader.intFromBits(count: 3) guard huffmanGroups >= 2 && huffmanGroups <= 6 else { throw BZip2Error.wrongHuffmanGroups } func computeSelectorsList() throws -> [Int] { - let selectorsUsed = data.intFromBits(count: 15) + let selectorsUsed = bitReader.intFromBits(count: 15) var mtf: [Int] = Array(0.. 0 { + while bitReader.bit() > 0 { c += 1 guard c < huffmanGroups else { throw BZip2Error.wrongSelector } } @@ -131,16 +131,16 @@ public class BZip2: DecompressionAlgorithm { func computeTables() throws -> [HuffmanTree] { var tables: [HuffmanTree] = [] for _ in 0..= 0 && length <= 20 else { throw BZip2Error.wrongHuffmanLengthCode } - while data.bit() > 0 { - length -= (Int(data.bit() * 2) - 1) + while bitReader.bit() > 0 { + length -= (Int(bitReader.bit() * 2) - 1) } lengths.append(length) } - let codes = HuffmanTree(lengthsToOrder: lengths, &data) + let codes = HuffmanTree(lengthsToOrder: lengths, bitReader) tables.append(codes) } diff --git a/Sources/Deflate.swift b/Sources/Deflate.swift index 2707ad97..402553cf 100644 --- a/Sources/Deflate.swift +++ b/Sources/Deflate.swift @@ -57,31 +57,31 @@ public class Deflate: DecompressionAlgorithm { */ public static func decompress(data: Data) throws -> Data { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) - return Data(bytes: try decompress(&pointerData)) + let bitReader = BitReader(data: data, bitOrder: .reversed) + return Data(bytes: try decompress(bitReader)) } - static func decompress(_ pointerData: inout DataWithPointer) throws -> [UInt8] { + static func decompress(_ bitReader: BitReader) throws -> [UInt8] { /// An array for storing output data var out: [UInt8] = [] while true { /// Is this a last block? - let isLastBit = pointerData.bit() + let isLastBit = bitReader.bit() /// Type of the current block. - let blockType = [UInt8](pointerData.bits(count: 2).reversed()) + let blockType = [UInt8](bitReader.bits(count: 2).reversed()) if blockType == [0, 0] { // Uncompressed block. - pointerData.skipUntilNextByte() + bitReader.skipUntilNextByte() /// Length of the uncompressed data. - let length = pointerData.intFromBits(count: 16) + let length = bitReader.intFromBits(count: 16) /// 1-complement of the length. - let nlength = pointerData.intFromBits(count: 16) + let nlength = bitReader.intFromBits(count: 16) // Check if lengths are OK (nlength should be a 1-complement of length). guard length & nlength == 0 else { throw DeflateError.wrongUncompressedBlockLengths } // Process uncompressed data into the output for _ in 0..> 1) - 1) // And yes, distanceCode is not a first part of distance but rather an index for special array. let distance = Constants.distanceBase[distanceCode] + - pointerData.intFromBits(count: extraDistance) + bitReader.intFromBits(count: extraDistance) // We should repeat last 'distance' amount of data. // The amount of times we do this is round(length / distance). diff --git a/Sources/DeflateCompression.swift b/Sources/DeflateCompression.swift index ef54851d..939cacbc 100644 --- a/Sources/DeflateCompression.swift +++ b/Sources/DeflateCompression.swift @@ -100,7 +100,7 @@ public extension Deflate { } private static func encodeHuffmanBlock(_ bldCodes: [BLDCode]) throws -> [UInt8] { - var bitWriter = BitToByteWriter(bitOrder: .reversed) + let bitWriter = BitToByteWriter(bitOrder: .reversed) // Write block header. // Note: For now it is only static huffman blocks. @@ -109,7 +109,8 @@ public extension Deflate { bitWriter.write(bits: [1, 0]) /// Empty DWP object for creating Huffman trees. - var pointerData = DataWithPointer(data: Data(), bitOrder: .reversed) + /// TODO: Separate reading and writing trees, and make so this pointerData is not necessary. + let pointerData = BitReader(data: Data(), bitOrder: .reversed) // Constructing Huffman trees for the case of block with preset alphabets. // In this case codes for literals and distances are fixed. @@ -117,32 +118,32 @@ public extension Deflate { let staticHuffmanBootstrap = [[0, 8], [144, 9], [256, 7], [280, 8], [288, -1]] let staticHuffmanLengthsBootstrap = [[0, 5], [32, -1]] /// Huffman tree for literal and length symbols/codes. - let mainLiterals = HuffmanTree(bootstrap: staticHuffmanBootstrap, &pointerData, true) + let mainLiterals = HuffmanTree(bootstrap: staticHuffmanBootstrap, pointerData, true) /// Huffman tree for backward distance symbols/codes. - let mainDistances = HuffmanTree(bootstrap: staticHuffmanLengthsBootstrap, &pointerData, true) + let mainDistances = HuffmanTree(bootstrap: staticHuffmanLengthsBootstrap, pointerData, true) for code in bldCodes { switch code { case .byte(let byte): - try mainLiterals.code(symbol: byte.toInt(), &bitWriter, DeflateError.symbolNotFound) + try mainLiterals.code(symbol: byte.toInt(), bitWriter, DeflateError.symbolNotFound) case .lengthDistance(let length, let distance): let lengthSymbol = Constants.lengthCode[Int(length) - 3] let lengthExtraBits = Int(length) - Constants.lengthBase[lengthSymbol - 257] let lengthExtraBitsCount = (257 <= lengthSymbol && lengthSymbol <= 260) || lengthSymbol == 285 ? 0 : (((lengthSymbol - 257) >> 2) - 1) - try mainLiterals.code(symbol: lengthSymbol, &bitWriter, DeflateError.symbolNotFound) + try mainLiterals.code(symbol: lengthSymbol, bitWriter, DeflateError.symbolNotFound) bitWriter.write(number: lengthExtraBits, bitsCount: lengthExtraBitsCount) let distanceSymbol = ((Constants.distanceBase.index { $0 > Int(distance) }) ?? 30) - 1 let distanceExtraBits = Int(distance) - Constants.distanceBase[distanceSymbol] let distanceExtraBitsCount = distanceSymbol == 0 || distanceSymbol == 1 ? 0 : ((distanceSymbol >> 1) - 1) - try mainDistances.code(symbol: distanceSymbol, &bitWriter, DeflateError.symbolNotFound) + try mainDistances.code(symbol: distanceSymbol, bitWriter, DeflateError.symbolNotFound) bitWriter.write(number: distanceExtraBits, bitsCount: distanceExtraBitsCount) } } // End data symbol. - try mainLiterals.code(symbol: 256, &bitWriter, DeflateError.symbolNotFound) + try mainLiterals.code(symbol: 256, bitWriter, DeflateError.symbolNotFound) bitWriter.finish() return bitWriter.buffer diff --git a/Sources/GzipArchive.swift b/Sources/GzipArchive.swift index c64d9236..dcbf3390 100644 --- a/Sources/GzipArchive.swift +++ b/Sources/GzipArchive.swift @@ -38,9 +38,9 @@ public class GzipArchive: Archive { */ public static func unarchive(archive data: Data) throws -> Data { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let bitReader = BitReader(data: data, bitOrder: .reversed) - return try processMember(&pointerData).data + return try processMember(bitReader).data } /** @@ -62,25 +62,25 @@ public class GzipArchive: Archive { */ public static func multiUnarchive(archive data: Data) throws -> [Member] { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let bitReader = BitReader(data: data, bitOrder: .reversed) var result = [Member]() - while !pointerData.isAtTheEnd { - result.append(try processMember(&pointerData)) + while !bitReader.isAtTheEnd { + result.append(try processMember(bitReader)) } return result } - private static func processMember(_ pointerData: inout DataWithPointer) throws -> Member { - let header = try GzipHeader(&pointerData) + private static func processMember(_ bitReader: BitReader) throws -> Member { + let header = try GzipHeader(bitReader) - let memberData = Data(bytes: try Deflate.decompress(&pointerData)) + let memberData = Data(bytes: try Deflate.decompress(bitReader)) - let crc32 = pointerData.uint32FromAlignedBytes(count: 4) + let crc32 = bitReader.uint32FromAlignedBytes(count: 4) guard CheckSums.crc32(memberData) == crc32 else { throw GzipError.wrongCRC(memberData) } - let isize = pointerData.intFromAlignedBytes(count: 4) + let isize = bitReader.intFromAlignedBytes(count: 4) guard UInt64(memberData.count) % UInt64(1) << 32 == UInt64(isize) else { throw GzipError.wrongISize } return Member(header: header, data: memberData) diff --git a/Sources/GzipHeader.swift b/Sources/GzipHeader.swift index 9680bfc7..f8fc77f2 100644 --- a/Sources/GzipHeader.swift +++ b/Sources/GzipHeader.swift @@ -73,11 +73,11 @@ public struct GzipHeader { it might not be archived with GZip at all. */ public init(archive data: Data) throws { - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) - try self.init(&pointerData) + let pointerData = DataWithPointer(data: data) + try self.init(pointerData) } - init(_ pointerData: inout DataWithPointer) throws { + init(_ pointerData: DataWithPointer) throws { // First two bytes should be correct 'magic' bytes let magic = pointerData.intFromAlignedBytes(count: 2) guard magic == 0x8b1f else { throw GzipError.wrongMagic } diff --git a/Sources/HuffmanTree.swift b/Sources/HuffmanTree.swift index c03efd93..b7859617 100644 --- a/Sources/HuffmanTree.swift +++ b/Sources/HuffmanTree.swift @@ -7,7 +7,7 @@ import Foundation class HuffmanTree { - private var pointerData: DataWithPointer + private var bitReader: BitReader private var tree: [Int] private let leafCount: Int @@ -15,9 +15,9 @@ class HuffmanTree { private var codingIndices: [[Int]] private let coding: Bool - init(bootstrap: [[Int]], _ pointerData: inout DataWithPointer, _ coding: Bool = false) { + init(bootstrap: [[Int]], _ bitReader: BitReader, _ coding: Bool = false) { self.coding = coding - self.pointerData = pointerData + self.bitReader = bitReader // Fills the 'lengths' array with numerous HuffmanLengths from a 'bootstrap'. var lengths: [[Int]] = [] @@ -92,18 +92,18 @@ class HuffmanTree { } } - convenience init(lengthsToOrder: [Int], _ pointerData: inout DataWithPointer) { + convenience init(lengthsToOrder: [Int], _ bitReader: BitReader) { var addedLengths = lengthsToOrder addedLengths.append(-1) let lengthsCount = addedLengths.count let range = Array(0...lengthsCount) - self.init(bootstrap: (zip(range, addedLengths)).map { [$0, $1] }, &pointerData) + self.init(bootstrap: (zip(range, addedLengths)).map { [$0, $1] }, bitReader) } func findNextSymbol() -> Int { var index = 0 while true { - let bit = pointerData.bit() + let bit = bitReader.bit() index = bit == 0 ? 2 * index + 1 : 2 * index + 2 guard index < self.leafCount else { return -1 @@ -114,7 +114,7 @@ class HuffmanTree { } } - func code(symbol: Int, _ bitWriter: inout BitToByteWriter, _ symbolNotFoundError: Error) throws { + func code(symbol: Int, _ bitWriter: BitToByteWriter, _ symbolNotFoundError: Error) throws { precondition(self.coding, "HuffmanTree is not initalized for coding!") guard symbol < self.codingIndices.count diff --git a/Sources/LZMA.swift b/Sources/LZMA.swift index 59e75a86..8c685d00 100644 --- a/Sources/LZMA.swift +++ b/Sources/LZMA.swift @@ -22,9 +22,9 @@ public class LZMA: DecompressionAlgorithm { */ public static func decompress(data: Data) throws -> Data { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let pointerData = DataWithPointer(data: data) - return Data(bytes: try decompress(&pointerData)) + return Data(bytes: try decompress(pointerData)) } /** @@ -32,8 +32,8 @@ public class LZMA: DecompressionAlgorithm { and decoder should use externally specified uncompressed size. Used in ZIP containers with LZMA compression. */ - static func decompress(_ pointerData: inout DataWithPointer, _ externalUncompressedSize: Int? = nil) throws -> [UInt8] { - let lzmaDecoder = try LZMADecoder(&pointerData) + static func decompress(_ pointerData: DataWithPointer, _ externalUncompressedSize: Int? = nil) throws -> [UInt8] { + let lzmaDecoder = try LZMADecoder(pointerData) try lzmaDecoder.decodeLZMA(externalUncompressedSize) return lzmaDecoder.out } diff --git a/Sources/LZMA2.swift b/Sources/LZMA2.swift index ab90a1b4..e59de692 100644 --- a/Sources/LZMA2.swift +++ b/Sources/LZMA2.swift @@ -22,16 +22,16 @@ public class LZMA2: DecompressionAlgorithm { */ public static func decompress(data: Data) throws -> Data { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let pointerData = DataWithPointer(data: data) let dictionarySize = try LZMA2.dictionarySize(pointerData.alignedByte()) - return Data(bytes: try LZMA2.decompress(dictionarySize, &pointerData)) + return Data(bytes: try LZMA2.decompress(dictionarySize, pointerData)) } - static func decompress(_ dictionarySize: Int, _ pointerData: inout DataWithPointer) throws -> [UInt8] { + static func decompress(_ dictionarySize: Int, _ pointerData: DataWithPointer) throws -> [UInt8] { // At this point lzmaDecoder will be in a VERY bad state. - let lzmaDecoder = try LZMADecoder(&pointerData) + let lzmaDecoder = try LZMADecoder(pointerData) try lzmaDecoder.decodeLZMA2(dictionarySize) return lzmaDecoder.out } diff --git a/Sources/LZMADecoder.swift b/Sources/LZMADecoder.swift index 894765ed..0e9b3558 100644 --- a/Sources/LZMADecoder.swift +++ b/Sources/LZMADecoder.swift @@ -75,7 +75,7 @@ class LZMADecoder { /// If that has happened, then stateReset is true. private var stateReset: Bool = false - init(_ pointerData: inout DataWithPointer) throws { + init(_ pointerData: DataWithPointer) throws { self.pointerData = pointerData self.alignDecoder = LZMABitTreeDecoder(numBits: LZMAConstants.numAlignBits) // There are two types of matches so we need two decoders for them. @@ -227,7 +227,7 @@ class LZMADecoder { } // First, we need to initialize Rande Decoder. - guard let rD = LZMARangeDecoder(&self.pointerData) else { + guard let rD = LZMARangeDecoder(pointerData) else { throw LZMAError.rangeDecoderInitError } self.rangeDecoder = rD diff --git a/Sources/LZMARangeDecoder.swift b/Sources/LZMARangeDecoder.swift index 8f1377fc..af220c5d 100644 --- a/Sources/LZMARangeDecoder.swift +++ b/Sources/LZMARangeDecoder.swift @@ -17,7 +17,7 @@ class LZMARangeDecoder { return self.code == 0 } - init?(_ pointerData: inout DataWithPointer) { + init?(_ pointerData: DataWithPointer) { self.pointerData = pointerData let byte = self.pointerData.alignedByte() @@ -31,7 +31,7 @@ class LZMARangeDecoder { } init() { - self.pointerData = DataWithPointer(data: Data(), bitOrder: .reversed) + self.pointerData = DataWithPointer(data: Data()) self.range = 0xFFFFFFFF self.code = 0 self.isCorrupted = false diff --git a/Sources/TarContainer.swift b/Sources/TarContainer.swift index 4fa4b0da..96cd9567 100644 --- a/Sources/TarContainer.swift +++ b/Sources/TarContainer.swift @@ -28,7 +28,7 @@ public class TarContainer: Container { guard data.count >= 512 else { throw TarError.tooSmallFileIsPassed } /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let pointerData = DataWithPointer(data: data) var output = [TarEntry]() @@ -45,7 +45,7 @@ public class TarContainer: Container { } else { pointerData.index -= 1024 } - let entry = try TarEntry(&pointerData, lastGlobalExtendedHeader, lastLocalExtendedHeader, + let entry = try TarEntry(pointerData, lastGlobalExtendedHeader, lastLocalExtendedHeader, longName, longLinkName) switch entry.type { case .globalExtendedHeader: @@ -54,11 +54,9 @@ public class TarContainer: Container { lastLocalExtendedHeader = String(data: entry.data(), encoding: .utf8) default: if entry.isLongName { - longName = try DataWithPointer(data: entry.data(), bitOrder: .reversed) - .nullEndedAsciiString(cutoff: entry.size) + longName = try DataWithPointer(data: entry.data()).nullEndedAsciiString(cutoff: entry.size) } else if entry.isLongLinkName { - longLinkName = try DataWithPointer(data: entry.data(), bitOrder: .reversed) - .nullEndedAsciiString(cutoff: entry.size) + longLinkName = try DataWithPointer(data: entry.data()).nullEndedAsciiString(cutoff: entry.size) } else { output.append(entry) lastLocalExtendedHeader = nil diff --git a/Sources/TarEntry.swift b/Sources/TarEntry.swift index 4c64074e..3a6e73aa 100644 --- a/Sources/TarEntry.swift +++ b/Sources/TarEntry.swift @@ -171,7 +171,7 @@ public class TarEntry: ContainerEntry { private let gnuLongName: String? private let gnuLongLinkName: String? - init(_ pointerData: inout DataWithPointer, _ globalExtendedHeader: String?, _ localExtendedHeader: String?, + init(_ pointerData: DataWithPointer, _ globalExtendedHeader: String?, _ localExtendedHeader: String?, _ longName: String?, _ longLinkName: String?) throws { if let longName = longName { gnuLongName = longName diff --git a/Sources/XZArchive.swift b/Sources/XZArchive.swift index dbd98779..c7e5ac01 100644 --- a/Sources/XZArchive.swift +++ b/Sources/XZArchive.swift @@ -27,7 +27,7 @@ public class XZArchive: Archive { */ public static func unarchive(archive data: Data) throws -> Data { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let pointerData = DataWithPointer(data: data) // First, we should check footer magic bytes. // If they are wrong, then file cannot be 'undamaged'. @@ -53,7 +53,7 @@ public class XZArchive: Archive { // Let's now go to the start of the file. pointerData.index = 0 - return try processStream(&pointerData) + return try processStream(pointerData) } @@ -75,7 +75,7 @@ public class XZArchive: Archive { */ public static func multiUnarchive(archive data: Data) throws -> [Data] { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let pointerData = DataWithPointer(data: data) // Note: for multi-stream archives we don't check footer's magic bytes, // because it is impossible to determine the end of each stream @@ -84,7 +84,7 @@ public class XZArchive: Archive { var result = [Data]() streamLoop: while !pointerData.isAtTheEnd { - result.append(try processStream(&pointerData)) + result.append(try processStream(pointerData)) guard !pointerData.isAtTheEnd else { break streamLoop } @@ -114,11 +114,11 @@ public class XZArchive: Archive { return result } - private static func processStream(_ pointerData: inout DataWithPointer) throws -> Data { + private static func processStream(_ pointerData: DataWithPointer) throws -> Data { var out: [UInt8] = [] // STREAM HEADER - let streamHeader = try processStreamHeader(&pointerData) + let streamHeader = try processStreamHeader(pointerData) // BLOCKS AND INDEX /// Zero value of blockHeaderSize means that we encountered INDEX. @@ -127,10 +127,10 @@ public class XZArchive: Archive { while true { let blockHeaderSize = pointerData.alignedByte() if blockHeaderSize == 0 { - indexSize = try processIndex(blockInfos, &pointerData) + indexSize = try processIndex(blockInfos, pointerData) break } else { - let blockInfo = try processBlock(blockHeaderSize, &pointerData) + let blockInfo = try processBlock(blockHeaderSize, pointerData) out.append(contentsOf: blockInfo.blockData) let checkSize: Int switch streamHeader.checkType { @@ -157,12 +157,12 @@ public class XZArchive: Archive { } // STREAM FOOTER - try processFooter(streamHeader, indexSize, &pointerData) + try processFooter(streamHeader, indexSize, pointerData) return Data(bytes: out) } - private static func processStreamHeader(_ pointerData: inout DataWithPointer) throws -> (checkType: UInt8, flagsCRC: UInt32) { + private static func processStreamHeader(_ pointerData: DataWithPointer) throws -> (checkType: UInt8, flagsCRC: UInt32) { // Check magic number. guard pointerData.uint64FromAlignedBytes(count: 6) == 0x005A587A37FD else { throw XZError.wrongMagic } @@ -192,7 +192,7 @@ public class XZArchive: Archive { } private static func processBlock(_ blockHeaderSize: UInt8, - _ pointerData: inout DataWithPointer) throws -> (blockData: [UInt8], unpaddedSize: Int, uncompressedSize: Int) { + _ pointerData: DataWithPointer) throws -> (blockData: [UInt8], unpaddedSize: Int, uncompressedSize: Int) { var blockBytes: [UInt8] = [] let blockHeaderStartIndex = pointerData.index - 1 blockBytes.append(blockHeaderSize) @@ -230,7 +230,7 @@ public class XZArchive: Archive { blockBytes.append(contentsOf: uncompressedSizeDecodeResult.bytesProcessed) } - var filters: [(inout DataWithPointer) throws -> [UInt8]] = [] + var filters: [(DataWithPointer) throws -> [UInt8]] = [] for _ in 0.. [UInt8] in - try LZMA2.decompress(LZMA2.dictionarySize(filterPropeties), &dwp) + let closure = { (dwp: DataWithPointer) -> [UInt8] in + try LZMA2.decompress(LZMA2.dictionarySize(filterPropeties), dwp) } filters.append(closure) default: @@ -269,13 +269,13 @@ public class XZArchive: Archive { var intResult = pointerData let compressedDataStart = pointerData.index for filterIndex in 0.. Int { + _ pointerData: DataWithPointer) throws -> Int { var indexBytes: [UInt8] = [0x00] let numberOfRecordsTuple = try pointerData.multiByteDecode() indexBytes.append(contentsOf: numberOfRecordsTuple.bytesProcessed) @@ -332,7 +332,7 @@ public class XZArchive: Archive { private static func processFooter(_ streamHeader: (checkType: UInt8, flagsCRC: UInt32), _ indexSize: Int, - _ pointerData: inout DataWithPointer) throws { + _ pointerData: DataWithPointer) throws { let footerCRC = pointerData.uint32FromAlignedBytes(count: 4) let storedBackwardSize = pointerData.alignedBytes(count: 4) let footerStreamFlags = pointerData.alignedBytes(count: 2) diff --git a/Sources/ZipCentralDirectoryEntry.swift b/Sources/ZipCentralDirectoryEntry.swift index c28c0873..7b7c8f63 100644 --- a/Sources/ZipCentralDirectoryEntry.swift +++ b/Sources/ZipCentralDirectoryEntry.swift @@ -29,7 +29,7 @@ struct ZipCentralDirectoryEntry { private(set) var modificationTimestamp: Int? - init(_ pointerData: inout DataWithPointer, _ currentDiskNumber: UInt32) throws { + init(_ pointerData: DataWithPointer, _ currentDiskNumber: UInt32) throws { // Check signature. guard pointerData.uint32FromAlignedBytes(count: 4) == 0x02014b50 else { throw ZipError.wrongSignature } diff --git a/Sources/ZipContainer.swift b/Sources/ZipContainer.swift index 44a66a9e..35d79526 100644 --- a/Sources/ZipContainer.swift +++ b/Sources/ZipContainer.swift @@ -26,31 +26,31 @@ public class ZipContainer: Container { */ public static func open(container data: Data) throws -> [ContainerEntry] { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let bitReader = BitReader(data: data, bitOrder: .reversed) var entries = [ZipEntry]() - pointerData.index = pointerData.size - 22 // 22 is a minimum amount which could take end of CD record. + bitReader.index = bitReader.size - 22 // 22 is a minimum amount which could take end of CD record. while true { // Check signature. - if pointerData.uint32FromAlignedBytes(count: 4) == 0x06054b50 { + if bitReader.uint32FromAlignedBytes(count: 4) == 0x06054b50 { // We found it! break } - if pointerData.index == 0 { + if bitReader.index == 0 { throw ZipError.notFoundCentralDirectoryEnd } - pointerData.index -= 5 + bitReader.index -= 5 } - let endOfCD = try ZipEndOfCentralDirectory(&pointerData) + let endOfCD = try ZipEndOfCentralDirectory(bitReader) let cdEntries = endOfCD.cdEntries // OK, now we are ready to read Central Directory itself. - pointerData.index = Int(UInt(truncatingBitPattern: endOfCD.cdOffset)) + bitReader.index = Int(UInt(truncatingBitPattern: endOfCD.cdOffset)) for _ in 0.. Data { // Now, let's move to the location of local header. - pointerData.index = Int(UInt32(truncatingBitPattern: self.cdEntry.offset)) + bitReader.index = Int(UInt32(truncatingBitPattern: self.cdEntry.offset)) if localHeader == nil { - localHeader = try ZipLocalHeader(&pointerData) + localHeader = try ZipLocalHeader(bitReader) // Check local header for consistency with Central Directory entry. guard localHeader!.generalPurposeBitFlags == cdEntry.generalPurposeBitFlags && localHeader!.compressionMethod == cdEntry.compressionMethod && @@ -103,45 +103,45 @@ public class ZipEntry: ContainerEntry { var crc32 = hasDataDescriptor ? cdEntry.crc32 : localHeader!.crc32 let fileBytes: [UInt8] - let fileDataStart = pointerData.index + let fileDataStart = bitReader.index switch localHeader!.compressionMethod { case 0: - fileBytes = pointerData.alignedBytes(count: uncompSize) + fileBytes = bitReader.alignedBytes(count: uncompSize) case 8: - fileBytes = try Deflate.decompress(&pointerData) - // Sometimes pointerData stays in not-aligned state after deflate decompression. + fileBytes = try Deflate.decompress(bitReader) + // Sometimes bitReader stays in not-aligned state after deflate decompression. // Following line ensures that this is not the case. - pointerData.skipUntilNextByte() + bitReader.skipUntilNextByte() case 12: #if (!SWCOMP_ZIP_POD_BUILD) || (SWCOMP_ZIP_POD_BUILD && SWCOMP_ZIP_POD_BZ2) - fileBytes = try BZip2.decompress(&pointerData) + fileBytes = try BZip2.decompress(bitReader) #else throw ZipError.compressionNotSupported #endif case 14: #if (!SWCOMP_ZIP_POD_BUILD) || (SWCOMP_ZIP_POD_BUILD && SWCOMP_ZIP_POD_LZMA) - pointerData.index += 4 // Skipping LZMA SDK version and size of properties. - fileBytes = try LZMA.decompress(&pointerData, uncompSize) + bitReader.index += 4 // Skipping LZMA SDK version and size of properties. + fileBytes = try LZMA.decompress(bitReader, uncompSize) #else throw ZipError.compressionNotSupported #endif default: throw ZipError.compressionNotSupported } - let realCompSize = pointerData.index - fileDataStart + let realCompSize = bitReader.index - fileDataStart if hasDataDescriptor { // Now we need to parse data descriptor itself. // First, it might or might not have signature. - let ddSignature = pointerData.uint32FromAlignedBytes(count: 4) + let ddSignature = bitReader.uint32FromAlignedBytes(count: 4) if ddSignature != 0x08074b50 { - pointerData.index -= 4 + bitReader.index -= 4 } // Now, let's update from CD with values from data descriptor. - crc32 = pointerData.uint32FromAlignedBytes(count: 4) + crc32 = bitReader.uint32FromAlignedBytes(count: 4) let sizeOfSizeField: UInt32 = localHeader!.zip64FieldsArePresent ? 8 : 4 - compSize = Int(pointerData.uint32FromAlignedBytes(count: sizeOfSizeField)) - uncompSize = Int(pointerData.uint32FromAlignedBytes(count: sizeOfSizeField)) + compSize = Int(bitReader.uint32FromAlignedBytes(count: sizeOfSizeField)) + uncompSize = Int(bitReader.uint32FromAlignedBytes(count: sizeOfSizeField)) } guard compSize == realCompSize && uncompSize == fileBytes.count @@ -152,9 +152,9 @@ public class ZipEntry: ContainerEntry { return Data(bytes: fileBytes) } - init(_ cdEntry: ZipCentralDirectoryEntry, _ pointerData: inout DataWithPointer) { + init(_ cdEntry: ZipCentralDirectoryEntry, _ bitReader: BitReader) { self.cdEntry = cdEntry - self.pointerData = pointerData + self.bitReader = bitReader var attributesDict = [FileAttributeKey: Any]() diff --git a/Sources/ZipLocalHeader.swift b/Sources/ZipLocalHeader.swift index f26204a7..41d74cc2 100644 --- a/Sources/ZipLocalHeader.swift +++ b/Sources/ZipLocalHeader.swift @@ -25,7 +25,7 @@ struct ZipLocalHeader { private(set) var accessTimestamp: Int? private(set) var creationTimestamp: Int? - init(_ pointerData: inout DataWithPointer) throws { + init(_ pointerData: DataWithPointer) throws { // Check signature. guard pointerData.uint32FromAlignedBytes(count: 4) == 0x04034b50 else { throw ZipError.wrongSignature } diff --git a/Sources/ZlibArchive.swift b/Sources/ZlibArchive.swift index 62e7ac53..5ecd595c 100644 --- a/Sources/ZlibArchive.swift +++ b/Sources/ZlibArchive.swift @@ -27,13 +27,13 @@ public class ZlibArchive: Archive { */ public static func unarchive(archive data: Data) throws -> Data { /// Object with input data which supports convenient work with bit shifts. - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) + let bitReader = BitReader(data: data, bitOrder: .reversed) - _ = try ZlibHeader(&pointerData) + _ = try ZlibHeader(bitReader) - let out = try Deflate.decompress(&pointerData) + let out = try Deflate.decompress(bitReader) - let adler32 = pointerData.intFromAlignedBytes(count: 4).reverseBytes() + let adler32 = bitReader.intFromAlignedBytes(count: 4).reverseBytes() guard CheckSums.adler32(out) == adler32 else { throw ZlibError.wrongAdler32(Data(bytes: out)) } return Data(bytes: out) diff --git a/Sources/ZlibHeader.swift b/Sources/ZlibHeader.swift index ad325c57..5f2c8b75 100644 --- a/Sources/ZlibHeader.swift +++ b/Sources/ZlibHeader.swift @@ -46,21 +46,21 @@ public struct ZlibHeader { it might not be archived with Zlib at all. */ public init(archive data: Data) throws { - var pointerData = DataWithPointer(data: data, bitOrder: .reversed) - try self.init(&pointerData) + let bitReader = BitReader(data: data, bitOrder: .reversed) + try self.init(bitReader) } - init(_ pointerData: inout DataWithPointer) throws { + init(_ bitReader: BitReader) throws { // First four bits are compression method. // Only compression method = 8 (DEFLATE) is supported. - let compressionMethod = pointerData.intFromBits(count: 4) + let compressionMethod = bitReader.intFromBits(count: 4) guard compressionMethod == 8 else { throw ZlibError.wrongCompressionMethod } self.compressionMethod = .deflate // Remaining four bits indicate window size. // For Deflate it must not be more than 7. - let compressionInfo = pointerData.intFromBits(count: 4) + let compressionInfo = bitReader.intFromBits(count: 4) guard compressionInfo <= 7 else { throw ZlibError.wrongCompressionInfo } let windowSize = 1 << (compressionInfo + 8) @@ -70,14 +70,14 @@ public struct ZlibHeader { let cmf = compressionInfo << 4 + compressionMethod // Next five bits are fcheck bits which are supposed to be integrity check. - let fcheck = pointerData.intFromBits(count: 5) + let fcheck = bitReader.intFromBits(count: 5) // Sixth bit indicate if archive contain Adler-32 checksum of preset dictionary. - let fdict = pointerData.intFromBits(count: 1) + let fdict = bitReader.intFromBits(count: 1) // Remaining bits indicate compression level. guard let compressionLevel = ZlibHeader.CompressionLevel(rawValue: - pointerData.intFromBits(count: 2)) else { throw ZlibError.wrongCompressionLevel } + bitReader.intFromBits(count: 2)) else { throw ZlibError.wrongCompressionLevel } self.compressionLevel = compressionLevel @@ -87,7 +87,7 @@ public struct ZlibHeader { // If preset dictionary is present 4 bytes will be skipped. if fdict == 1 { - pointerData.index += 4 + bitReader.index += 4 } }