Search code examples
iosobjective-ccompression

iOS (objective-c) compression_decode_buffer() returns zero


I'm converting a very large json result on my server to a compressed format that I can decompress on my objective c app. I would prefer to use the iOS 9 compression lib if possible (libcompression.tbd), described in Apple's CompressionSample/BlockCompression.c sample code.

I'm passing the compressed NSData result to the following method:

#include "compression.h"

...

    - (NSData *) getDecompressedData:(NSData *) compressed {
        size_t dst_buffer_size = 20000000;   //20MB
        uint8_t *dst_buffer = malloc(dst_buffer_size);
        uint8_t *src_buffer = malloc(compressed.length);
        [compressed getBytes:src_buffer length:compressed.length];

        size_t decompressedSize = compression_decode_buffer(dst_buffer, dst_buffer_size, src_buffer, compressed.length, nil, COMPRESSION_ZLIB);
        NSData *decompressed = [[NSData alloc] initWithBytes:dst_buffer length:decompressedSize];
        return decompressed;
    }

The compressed parameter has a length that matches my server logs, but the result from compression_decode_buffer is always zero and dst_buffer is not modified. I'm not receiving any errors, and the log has no relevant info.

I've tried ZLIB and LZ4 compression / decompression methods and several libraries on the server side, all with the same result.

What am I doing wrong here?


Solution

  • After much testing and research, I found that the compression library I was using on my server adds a compression header (1st two bytes), per RFC1950. I skipped those two bytes and compression_decode_buffer works like a champ!

    - (NSData *) getDecompressedData:(NSData *) compressed {
        size_t dst_buffer_size = 20000000;   //20MB
        uint8_t *dst_buffer = malloc(dst_buffer_size);
        uint8_t *src_buffer = malloc(compressed.length);
        [compressed getBytes:src_buffer range:NSMakeRange(2, compressed.length - 2)];
    
        size_t decompressedSize = compression_decode_buffer(dst_buffer, dst_buffer_size, src_buffer, compressed.length - 2, nil, COMPRESSION_ZLIB);
        NSData *decompressed = [[NSData alloc] initWithBytes:dst_buffer length:decompressedSize];
        return decompressed;
    }