diff --git a/Sources/LZMA.swift b/Sources/LZMA.swift index 8c685d00..49b9c92c 100644 --- a/Sources/LZMA.swift +++ b/Sources/LZMA.swift @@ -27,14 +27,9 @@ public class LZMA: DecompressionAlgorithm { return Data(bytes: try decompress(pointerData)) } - /** - - Parameter externalUncompressedSize: stream doesn't contain uncompressed size property, - and decoder should use externally specified uncompressed size. - Used in ZIP containers with LZMA compression. - */ - static func decompress(_ pointerData: DataWithPointer, _ externalUncompressedSize: Int? = nil) throws -> [UInt8] { + static func decompress(_ pointerData: DataWithPointer) throws -> [UInt8] { let lzmaDecoder = try LZMADecoder(pointerData) - try lzmaDecoder.decodeLZMA(externalUncompressedSize) + try lzmaDecoder.decodeLZMA() return lzmaDecoder.out } diff --git a/Sources/LZMADecoder.swift b/Sources/LZMADecoder.swift index 98457cdf..f60ff0b9 100644 --- a/Sources/LZMADecoder.swift +++ b/Sources/LZMADecoder.swift @@ -86,18 +86,16 @@ class LZMADecoder { self.dictStart = self.dictEnd } - private func resetProperties() throws { - var properties = pointerData.byte() + private func resetProperties(_ properties: UInt8) throws { if properties >= (9 * 5 * 5) { throw LZMAError.wrongProperties } /// The number of literal context bits self.lc = properties % 9 - properties /= 9 /// The number of pos bits - self.pb = properties / 5 + self.pb = (properties / 9) / 5 /// The number of literal pos bits - self.lp = properties % 5 + self.lp = (properties / 9) % 5 // We need to 'reset state' because several properties of Decoder depend on the values of lc, lp, pb. self.resetState() @@ -151,10 +149,10 @@ class LZMADecoder { case 1: self.resetState() case 2: - try self.resetProperties() + try self.resetProperties(pointerData.byte()) dataStartIndex += 1 case 3: - try self.resetProperties() + try self.resetProperties(pointerData.byte()) dataStartIndex += 1 self.resetDictionary(dictSize) default: @@ -197,19 +195,19 @@ class LZMADecoder { and decoder should use externally specified uncompressed size. Used in ZIP containers with LZMA compression. */ - func decodeLZMA(_ externalUncompressedSize: Int? = nil) throws { + func decodeLZMA(_ externalUncompressedSize: Int? = nil, _ propertiesByte: UInt8? = nil, _ dSize: Int? = nil) throws { // Firstly, we need to parse LZMA properties. - try self.resetProperties() - let dictSize = pointerData.uint32().toInt() + try self.resetProperties(propertiesByte ?? pointerData.byte()) + let dictSize = dSize ?? pointerData.uint32().toInt() dictionarySize = dictSize < (1 << 12) ? 1 << 12 : dictSize /// Size of uncompressed data. -1 means it is unknown/undefined. - var uncompressedSize = pointerData.uint64().toInt() - uncompressedSize = Double(uncompressedSize) == pow(Double(2), Double(64)) - 1 ? -1 : uncompressedSize - + var uncompressedSize: Int if let extUncompSize = externalUncompressedSize { - pointerData.index -= 8 uncompressedSize = extUncompSize + } else { + uncompressedSize = pointerData.uint64().toInt() + uncompressedSize = Double(uncompressedSize) == pow(Double(2), Double(64)) - 1 ? -1 : uncompressedSize } try decode(&uncompressedSize) diff --git a/Sources/ZipEntry.swift b/Sources/ZipEntry.swift index 76647abd..2467e693 100644 --- a/Sources/ZipEntry.swift +++ b/Sources/ZipEntry.swift @@ -128,7 +128,9 @@ public class ZipEntry: ContainerEntry { 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) + let lzmaDecoder = try LZMADecoder(pointerData) + try lzmaDecoder.decodeLZMA(uncompSize) + fileBytes = lzmaDecoder.out #else throw ZipError.compressionNotSupported #endif