mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
Add new XZBlock struct
This commit is contained in:
@@ -164,6 +164,10 @@
|
||||
0651461F1FA8E004007F83F4 /* XZStreamHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0651461D1FA8E004007F83F4 /* XZStreamHeader.swift */; };
|
||||
065146201FA8E004007F83F4 /* XZStreamHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0651461D1FA8E004007F83F4 /* XZStreamHeader.swift */; };
|
||||
065146211FA8E004007F83F4 /* XZStreamHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0651461D1FA8E004007F83F4 /* XZStreamHeader.swift */; };
|
||||
065146231FA8E20C007F83F4 /* XZBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065146221FA8E20C007F83F4 /* XZBlock.swift */; };
|
||||
065146241FA8E20C007F83F4 /* XZBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065146221FA8E20C007F83F4 /* XZBlock.swift */; };
|
||||
065146251FA8E20C007F83F4 /* XZBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065146221FA8E20C007F83F4 /* XZBlock.swift */; };
|
||||
065146261FA8E20C007F83F4 /* XZBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065146221FA8E20C007F83F4 /* XZBlock.swift */; };
|
||||
0651FEC21F8E2E9100C49646 /* ContainerEntryType+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */; };
|
||||
0651FEC31F8E2E9100C49646 /* ContainerEntryType+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */; };
|
||||
0651FEC41F8E2E9100C49646 /* ContainerEntryType+Tar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */; };
|
||||
@@ -525,6 +529,7 @@
|
||||
064F722E1F1E63D800017297 /* test1.7z */ = {isa = PBXFileReference; lastKnownFileType = file; path = test1.7z; sourceTree = "<group>"; };
|
||||
064F72301F1E63E200017297 /* 7zTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = 7zTests.swift; sourceTree = "<group>"; };
|
||||
0651461D1FA8E004007F83F4 /* XZStreamHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XZStreamHeader.swift; sourceTree = "<group>"; };
|
||||
065146221FA8E20C007F83F4 /* XZBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XZBlock.swift; sourceTree = "<group>"; };
|
||||
0651FEC11F8E2E9100C49646 /* ContainerEntryType+Tar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ContainerEntryType+Tar.swift"; sourceTree = "<group>"; };
|
||||
0655693F1DC659FF00A47E66 /* SWCompression.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SWCompression.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0655694C1DC65A8000A47E66 /* SWCompression.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SWCompression.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -815,6 +820,7 @@
|
||||
children = (
|
||||
06E2346B1E068E9600F18798 /* XZArchive.swift */,
|
||||
061C06201F0E89D900832F0C /* XZError.swift */,
|
||||
065146221FA8E20C007F83F4 /* XZBlock.swift */,
|
||||
0651461D1FA8E004007F83F4 /* XZStreamHeader.swift */,
|
||||
06CC3FE11F8AAF3100BD576D /* DataWithPointer+XZ.swift */,
|
||||
);
|
||||
@@ -1511,6 +1517,7 @@
|
||||
0620F4951F8E21BC001C9B7A /* Permissions.swift in Sources */,
|
||||
06CDFCB31F111DEC00292758 /* LZMA2Error.swift in Sources */,
|
||||
06DDB1721F8190D400035BEF /* BZip2+BlockSize.swift in Sources */,
|
||||
065146241FA8E20C007F83F4 /* XZBlock.swift in Sources */,
|
||||
061C065D1F0E90E600832F0C /* TarEntry.swift in Sources */,
|
||||
064F722A1F1E638A00017297 /* 7zError.swift in Sources */,
|
||||
06CDFCAE1F111DBE00292758 /* LZMAError.swift in Sources */,
|
||||
@@ -1604,6 +1611,7 @@
|
||||
0620F4961F8E21BC001C9B7A /* Permissions.swift in Sources */,
|
||||
06CDFCB41F111DEC00292758 /* LZMA2Error.swift in Sources */,
|
||||
06DDB1731F8190D400035BEF /* BZip2+BlockSize.swift in Sources */,
|
||||
065146251FA8E20C007F83F4 /* XZBlock.swift in Sources */,
|
||||
061C065E1F0E90E600832F0C /* TarEntry.swift in Sources */,
|
||||
064F722B1F1E638A00017297 /* 7zError.swift in Sources */,
|
||||
06CDFCAF1F111DBE00292758 /* LZMAError.swift in Sources */,
|
||||
@@ -1697,6 +1705,7 @@
|
||||
0620F4971F8E21BC001C9B7A /* Permissions.swift in Sources */,
|
||||
06CDFCB51F111DEC00292758 /* LZMA2Error.swift in Sources */,
|
||||
06DDB1741F8190D400035BEF /* BZip2+BlockSize.swift in Sources */,
|
||||
065146261FA8E20C007F83F4 /* XZBlock.swift in Sources */,
|
||||
061C065F1F0E90E600832F0C /* TarEntry.swift in Sources */,
|
||||
064F722C1F1E638A00017297 /* 7zError.swift in Sources */,
|
||||
06CDFCB01F111DBE00292758 /* LZMAError.swift in Sources */,
|
||||
@@ -1790,6 +1799,7 @@
|
||||
0620F4941F8E21BC001C9B7A /* Permissions.swift in Sources */,
|
||||
06CDFCB21F111DEC00292758 /* LZMA2Error.swift in Sources */,
|
||||
06DDB1711F8190D400035BEF /* BZip2+BlockSize.swift in Sources */,
|
||||
065146231FA8E20C007F83F4 /* XZBlock.swift in Sources */,
|
||||
061C065C1F0E90E600832F0C /* TarEntry.swift in Sources */,
|
||||
064F72291F1E638A00017297 /* 7zError.swift in Sources */,
|
||||
06CDFCAD1F111DBE00292758 /* LZMAError.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2017 Timofey Solomko
|
||||
// Licensed under MIT License
|
||||
//
|
||||
// See LICENSE for license information
|
||||
|
||||
import Foundation
|
||||
|
||||
struct XZBlock {
|
||||
|
||||
let bytes: [UInt8]
|
||||
let unpaddedSize: Int
|
||||
|
||||
var uncompressedSize: Int {
|
||||
return bytes.count
|
||||
}
|
||||
|
||||
init(_ blockHeaderSize: Int, _ pointerData: DataWithPointer) throws {
|
||||
let blockHeaderStartIndex = pointerData.index - 1
|
||||
guard blockHeaderSize >= 0x01 && blockHeaderSize <= 0xFF
|
||||
else { throw XZError.wrongFieldValue }
|
||||
let realBlockHeaderSize = (blockHeaderSize + 1) * 4
|
||||
|
||||
let blockFlags = pointerData.byte()
|
||||
/**
|
||||
Bit values 00, 01, 10, 11 indicate filters number from 1 to 4,
|
||||
so we actually need to add 1 to get filters' number.
|
||||
*/
|
||||
let filtersCount = blockFlags & 0x03 + 1
|
||||
guard blockFlags & 0x3C == 0
|
||||
else { throw XZError.fieldReservedValue }
|
||||
|
||||
/// Should match size of compressed data.
|
||||
let compressedSize = blockFlags & 0x40 != 0 ? try pointerData.multiByteDecode() : -1
|
||||
|
||||
/// Should match the size of data after decompression.
|
||||
let uncompressedSize = blockFlags & 0x80 != 0 ? try pointerData.multiByteDecode() : -1
|
||||
|
||||
var filters: [(DataWithPointer) throws -> [UInt8]] = []
|
||||
for _ in 0..<filtersCount {
|
||||
let filterID = try pointerData.multiByteDecode()
|
||||
guard UInt64(filterID) < 0x4000000000000000
|
||||
else { throw XZError.wrongFilterID }
|
||||
// Only LZMA2 filter is supported.
|
||||
if filterID == 0x21 {
|
||||
// First, we need to skip byte with the size of filter's properties
|
||||
_ = try pointerData.multiByteDecode()
|
||||
/// In case of LZMA2 filters property is a dicitonary size.
|
||||
let filterPropeties = pointerData.byte()
|
||||
let closure = { (dwp: DataWithPointer) -> [UInt8] in
|
||||
let decoder = try LZMA2Decoder(pointerData)
|
||||
try decoder.setDictionarySize(filterPropeties)
|
||||
|
||||
try decoder.decode()
|
||||
return decoder.out
|
||||
}
|
||||
filters.append(closure)
|
||||
} else {
|
||||
throw XZError.wrongFilterID
|
||||
}
|
||||
}
|
||||
|
||||
// We need to take into account 4 bytes for CRC32 so thats why "-4".
|
||||
while pointerData.index - blockHeaderStartIndex < realBlockHeaderSize - 4 {
|
||||
let byte = pointerData.byte()
|
||||
guard byte == 0x00
|
||||
else { throw XZError.wrongPadding }
|
||||
}
|
||||
|
||||
let blockHeaderCRC = pointerData.uint32()
|
||||
pointerData.index = blockHeaderStartIndex
|
||||
guard CheckSums.crc32(pointerData.bytes(count: realBlockHeaderSize - 4)) == blockHeaderCRC
|
||||
else { throw XZError.wrongInfoCRC }
|
||||
pointerData.index += 4
|
||||
|
||||
var intResult = pointerData
|
||||
let compressedDataStart = pointerData.index
|
||||
for filterIndex in 0..<filtersCount - 1 {
|
||||
var arrayResult = try filters[filtersCount.toInt() - filterIndex.toInt() - 1](intResult)
|
||||
intResult = DataWithPointer(array: &arrayResult)
|
||||
}
|
||||
guard compressedSize < 0 || compressedSize == pointerData.index - compressedDataStart
|
||||
else { throw XZError.wrongDataSize }
|
||||
|
||||
let out = try filters[filtersCount.toInt() - 1](intResult)
|
||||
guard uncompressedSize < 0 || uncompressedSize == out.count
|
||||
else { throw XZError.wrongDataSize }
|
||||
|
||||
let unpaddedSize = pointerData.index - blockHeaderStartIndex
|
||||
|
||||
if unpaddedSize % 4 != 0 {
|
||||
let paddingSize = 4 - unpaddedSize % 4
|
||||
for _ in 0..<paddingSize {
|
||||
let byte = pointerData.byte()
|
||||
guard byte == 0x00
|
||||
else { throw XZError.wrongPadding }
|
||||
}
|
||||
}
|
||||
|
||||
self.bytes = out
|
||||
self.unpaddedSize = unpaddedSize
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user