Files
SWCompression/Sources/ZlibArchive.swift
T
Timofey Solomko a9cdb50e85 Remove intFromAlignedBytes function
Also changes were made to adopt this removal. This was done to improve behavior in some corner cases as well as enforce intentional usage of particular integer types.
2017-07-09 13:29:33 +03:00

76 lines
2.5 KiB
Swift

// Copyright (c) 2017 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import Foundation
/// Provides unarchive and archive functions for Zlib archives.
public class ZlibArchive: Archive {
/**
Unarchives Zlib archive.
If data passed is not actually a Zlib archive, `ZlibError` will be thrown.
If data in archive is not actually compressed with Deflate algorithm, `DeflateError` will be thrown.
- Note: This function is specification compliant.
- Parameter archive: Data archived with Zlib.
- Throws: `DeflateError` or `ZlibError` depending on the type of the problem.
It may indicate that either archive is damaged or
it might not be archived with Zlib or compressed with Deflate at all.
- Returns: Unarchived data.
*/
public static func unarchive(archive data: Data) throws -> Data {
/// Object with input data which supports convenient work with bit shifts.
let bitReader = BitReader(data: data, bitOrder: .reversed)
_ = try ZlibHeader(bitReader)
let out = try Deflate.decompress(bitReader)
let adler32 = bitReader.uint32().reverseBytes()
guard CheckSums.adler32(out) == adler32 else { throw ZlibError.wrongAdler32(Data(bytes: out)) }
return Data(bytes: out)
}
/**
Archives `data` into Zlib archive.
Data will be also compressed with Deflate algorithm.
It will also be specified in archive's header that the compressor used the slowest Deflate algorithm.
If during compression something goes wrong `DeflateError` will be thrown.
- Note: This function is specification compliant.
- Parameter data: Data to compress and archive.
- Throws: `DeflateError` if an error was encountered during compression.
- Returns: Resulting archive's data.
*/
public static func archive(data: Data) throws -> Data {
let out: [UInt8] = [
120, // CM (Compression Method) = 8 (DEFLATE), CINFO (Compression Info) = 7 (32K window size).
218 // Flags: slowest algorithm, no preset dictionary.
]
var outData = Data(bytes: out)
outData.append(try Deflate.compress(data: data))
let adler32 = CheckSums.adler32(data)
var adlerBytes = [UInt8]()
for i in 0..<4 {
adlerBytes.append(UInt8((adler32 & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8)))
}
outData.append(Data(bytes: adlerBytes))
return outData
}
}