Last active
September 23, 2018 21:33
-
-
Save memfrag/d9a817ab9546b11b63ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import Compression | |
/// A convenience class for compressing an NSData object. | |
/// | |
/// Example: | |
/// ``` | |
/// let compression = Compression(algorithm: .ZLIB) | |
/// let compressedData = compression.compressData(data) | |
/// let decompressedData = compresison.decompressData(compressedData) | |
/// ``` | |
/// | |
public final class Compression { | |
public enum Algorithm { | |
case LZ4 | |
case LZFSE | |
case LZMA | |
case ZLIB | |
public func algorithm() -> compression_algorithm { | |
switch self { | |
case .LZ4: return COMPRESSION_LZ4 | |
case .LZFSE: return COMPRESSION_LZFSE | |
case .LZMA: return COMPRESSION_LZMA | |
case .ZLIB: return COMPRESSION_ZLIB | |
} | |
} | |
} | |
private let algorithm: Algorithm | |
private let bufferSize: Int | |
public init(algorithm: Algorithm, bufferSize: Int = 0x20000) { | |
self.algorithm = algorithm | |
self.bufferSize = bufferSize | |
} | |
public func compressData(data: NSData) -> NSData? { | |
return processData(data, algorithm: algorithm, bufferSize: bufferSize, compress: true) | |
} | |
public func decompressData(data: NSData) -> NSData? { | |
return processData(data, algorithm: algorithm, bufferSize: bufferSize, compress: true) | |
} | |
private func processData(inputData: NSData, algorithm: Algorithm, bufferSize: Int, compress: Bool) -> NSData? { | |
guard inputData.length > 0 else { return nil } | |
var stream = UnsafeMutablePointer<compression_stream>.alloc(1).memory | |
let initStatus = compression_stream_init(&stream, compress ? COMPRESSION_STREAM_ENCODE : COMPRESSION_STREAM_DECODE, algorithm.algorithm()) | |
guard initStatus != COMPRESSION_STATUS_ERROR else { | |
print("[Compression] \(compress ? "Compression" : "Decompression") with \(algorithm) failed to init stream with status \(initStatus).") | |
return nil | |
} | |
defer { | |
compression_stream_destroy(&stream) | |
} | |
stream.src_ptr = UnsafePointer<UInt8>(inputData.bytes) | |
stream.src_size = inputData.length | |
let buffer = UnsafeMutablePointer<UInt8>.alloc(bufferSize) | |
stream.dst_ptr = buffer | |
stream.dst_size = bufferSize | |
let outputData = NSMutableData() | |
while true { | |
let status = compression_stream_process(&stream, Int32(compress ? COMPRESSION_STREAM_FINALIZE.rawValue : 0)) | |
if status == COMPRESSION_STATUS_OK { | |
guard stream.dst_size == 0 else { continue } | |
outputData.appendBytes(buffer, length: bufferSize) | |
stream.dst_ptr = buffer | |
stream.dst_size = bufferSize | |
} else if status == COMPRESSION_STATUS_END { | |
guard stream.dst_ptr > buffer else { continue } | |
outputData.appendBytes(buffer, length: stream.dst_ptr - buffer) | |
return outputData | |
} else if status == COMPRESSION_STATUS_ERROR { | |
print("[Compression] \(compress ? "Compression" : "Decompression") with \(algorithm) failed with status \(status).") | |
return nil | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @brototyp, yeah you are right as we are decoding stream we have to set them false