#include #include #include // 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 ; }