Как принудительно сжать iOS lib в LZ4 в одном блоке?

Я хотел бы сжать буфер, размер которого превышает 64 КБ, только в одном блоке.

В настоящее время я использую сжатие lib для сжатия / распаковки LZ4, который отлично работает с буфером размером менее 64 КБ. При условии, что я удалил дополнительный заголовок Apple из блока, поскольку 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 для решения этой проблемы), он генерирует несколько блоков (для maxBlockSize 64 КБ). Если я уберу все заголовки, распаковать практически невозможно, не зная, где находится граница между блоками.

В заключение мой вопрос: - возможно ли заставить компрессор генерировать только один блок?

Мое расширение для удаления дополнений в ситуации с одним блоком:

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 ответов

Другие вопросы по тегам