#include <stdint.h>
#include <string.h>
#include <zlib.h>
// header stolen from the EOF marker
static const char header[18] = "\x1f\x8b\x8\x4\0\0\0\0\0\xff\x6\0\x42\x43\x2\0" ;
// Compresses one bgzf chunk. We assemble the header ourselves and call
// deflate in raw mode, because some tools seems to be extremely picky
// about irrelevant details.
int compress_chunk ( char *dest, int *dest_len, char *source, int source_len, int level )
{
z_stream stream = {0} ;
stream.next_in = source ;
stream.next_out = dest + 18 ;
stream.avail_in = source_len ;
stream.avail_out = *dest_len ;
memmove( dest, header, 16 ) ;
int rc = deflateInit2( &stream, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY ) ;
if( rc != Z_OK ) return rc ;
rc = deflate( &stream, Z_FINISH ) ;
int rc2 = deflateEnd( &stream ) ;
if( rc != Z_STREAM_END ) return rc ;
if( rc2 != Z_OK ) return rc2 ;
long crc = crc32( crc32( 0, 0, 0 ), source, source_len ) ;
int compressed_length = 18 + 8 + stream.total_out ;
if (compressed_length > 65536) return Z_BUF_ERROR ;
dest[16] = (compressed_length-1) & 0xff ;
dest[17] = (compressed_length-1) >> 8 ;
*(uint32_t*)(dest+compressed_length-8) = crc ;
*(uint32_t*)(dest+compressed_length-4) = source_len ;
*dest_len = compressed_length ;
return Z_OK ;
}
// Decompresses one bgzf chunk. We receive no header, so we call
// inflate in raw mode and check the crc32 ourselves.
int decompress_chunk ( char *dest, int dest_len, char *source, int source_len )
{
z_stream stream = {0} ;
stream.next_in = source ;
stream.next_out = dest ;
stream.avail_in = source_len - 8 ;
stream.avail_out = dest_len ;
int rc = inflateInit2( &stream, -15 ) ;
if( rc != Z_OK ) return rc ;
rc = inflate( &stream, Z_FINISH ) ;
int rc2 = inflateEnd( &stream ) ;
if( rc != Z_STREAM_END ) return rc ;
if( rc2 != Z_OK ) return rc2 ;
long crc = crc32( crc32( 0, 0, 0 ), dest, dest_len ) ;
return *(uint32_t*)(dest+dest_len-8) == crc && stream.avail_out == 0 ? Z_OK : Z_STREAM_ERROR ;
}