Add ability to specify lzma properties for LZMADecoder externally

This commit is contained in:
Timofey Solomko
2017-07-25 22:02:56 +03:00
parent af5b4402e9
commit c608d2b48f
3 changed files with 17 additions and 22 deletions
+2 -7
View File
@@ -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
}
+12 -14
View File
@@ -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)
+3 -1
View File
@@ -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