如何在一个块中强制iOS lib压缩到LZ4压缩?

时间:2018-02-23 21:06:37

标签: ios swift compression lz4

我想在一个块中压缩大小超过64Kb的缓冲区。

我目前使用lib压缩到LZ4压缩/解压缩,这适用于低于64Kb的缓冲区。如果Apple在the doc right there中添加了额外的字节,我会从块中剥离Apple额外的标题,说明: 此处记录了该帧,以便您可以轻松地包装另一个LZ4编码器/解码器,以在必要时生成/使用相同的数据流。 LZ4编码的缓冲区是一系列块,每个块都以标题开头。有三种可能的标题:

     1) A compressed block header consists of:
        a) the octets 0x62, 0x76, 0x34, and 0x31,
        b) followed by the size in bytes of the decoded (plaintext) data represented by the block
        c) and the size (in bytes) of the encoded data stored in the block.

不幸的是,由于我没有找到一种方法只在一个块中强制压缩(是否可能?常规LZ4压缩器提供maxBlockSize来解决这个问题),它会生成多个块(对于64Kb的maxBlockSize)。如果我删除所有标题,则几乎不可能解压缩,而不知道块之间的边界位置。

总结一下,我的问题是: - 是否可以强制压缩机只生成一个块?

我的延伸是在一个区块的情况下剥离额外的东西:

import Compression

extension Data {

   public func lz4Compress(removeAppleExtras:Bool, compressedBufferSize: Int = 500_000) -> Data? {
        func print(_ text: String) {
            Swift.print("Data.lz4Compress(): \(text)")
        }

        // Data to compress is self
        let dataToCompress = self

        let compressedBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: compressedBufferSize)

        guard let compressedSize = withUnsafeBytes ({ (dataToCompressBuffer: UnsafePointer<UInt8>) -> Int? in

            return compression_encode_buffer(
                compressedBuffer,     compressedBufferSize,
                dataToCompressBuffer, dataToCompress.count,
                nil,
                COMPRESSION_LZ4
            )

        }) else {
            print("*** Error: Unable to compress, returned size is 0 ")
            return nil
        }

        // Turn to Data not duplicating buffer
        let compressed = Data(bytesNoCopy: compressedBuffer, count: compressedSize, deallocator: .free)

        guard removeAppleExtras else {
            return compressed
        }

        // We must remove Apple extra header/footer

        let cz = compressedSize

        let axHeader            =  UInt32(bigEndian:    compressed.subdata(in:    0 ..<  4).withUnsafeBytes{$0.pointee})
        let axUncompressedSize  =  UInt32(littleEndian: compressed.subdata(in:    4 ..<  8).withUnsafeBytes{$0.pointee})
        let axCompressedSize    =  UInt32(littleEndian: compressed.subdata(in:    8 ..< 12).withUnsafeBytes{$0.pointee})

        print("LZ4 Apple extras for compressed size of \(compressedSize.hex()) (\(compressedSize)), uncompressed: \(dataToCompress.count.hex()) (\(dataToCompress.count))")
        print("Apple Header:     \(axHeader.hex()) (\(compressed.subdata(in: 0..<4).ascii()))")
        print("UncompressedSize: \(axUncompressedSize.hex()) (\(axUncompressedSize))")
        print("CompressedSize:   \(axCompressedSize.hex()) (\(axCompressedSize))")

        let bareBonesCompressed =                       compressed.subdata(in:   12 ..< (cz-4))

        let axFooter            =  UInt32(bigEndian:    compressed.subdata(in: cz-4 ..< cz).withUnsafeBytes{$0.pointee})

        print("Apple footer:     \(axFooter.hex()) (\(compressed.subdata(in: cz-4 ..< cz).ascii()))")

        return bareBonesCompressed
    }      // Data.lz4Compress()
}

0 个答案:

没有答案