// File: zeeev[P]DASVC/bamtools/src/api/internal/io/BgzfStream_p.cpp
// Function: BamTools::Internal::BgzfStream::DeflateBlock(int)
size_t BgzfStream::DeflateBlock(int32_t blockLength) {

    // initialize the gzip header
    char* buffer = m_compressedBlock.Buffer;
    memset(buffer, 0, 18);
    buffer[0]  = Constants::GZIP_ID1;
    buffer[1]  = Constants::GZIP_ID2;
    buffer[2]  = Constants::CM_DEFLATE;
    buffer[3]  = Constants::FLG_FEXTRA;
    buffer[9]  = Constants::OS_UNKNOWN;
    buffer[10] = Constants::BGZF_XLEN;
    buffer[12] = Constants::BGZF_ID1;
    buffer[13] = Constants::BGZF_ID2;
    buffer[14] = Constants::BGZF_LEN;

    // set compression level
    const int compressionLevel = ( m_isWriteCompressed ? Z_DEFAULT_COMPRESSION : 0 );

    // loop to retry for blocks that do not compress enough
    int inputLength = blockLength;
    size_t compressedLength = 0;
    const unsigned int bufferSize = Constants::BGZF_MAX_BLOCK_SIZE;

    while ( true ) {

        // initialize zstream values
        z_stream zs;
        zs.zalloc    = NULL;
        zs.zfree     = NULL;
        zs.next_in   = (Bytef*)m_uncompressedBlock.Buffer;
        zs.avail_in  = inputLength;
        zs.next_out  = (Bytef*)&buffer[Constants::BGZF_BLOCK_HEADER_LENGTH];
        zs.avail_out = bufferSize -
                       Constants::BGZF_BLOCK_HEADER_LENGTH -
                       Constants::BGZF_BLOCK_FOOTER_LENGTH;

        // initialize the zlib compression algorithm
        int status = deflateInit2(&zs,
                                  compressionLevel,
                                  Z_DEFLATED,
                                  Constants::GZIP_WINDOW_BITS,
                                  Constants::Z_DEFAULT_MEM_LEVEL,
                                  Z_DEFAULT_STRATEGY);
        if ( status != Z_OK )
            throw BamException("BgzfStream::DeflateBlock", "zlib deflateInit2 failed");

        // compress the data
        status = deflate(&zs, Z_FINISH);

        // if not at stream end
        if ( status != Z_STREAM_END ) {

            deflateEnd(&zs);

            // there was not enough space available in buffer
            // try to reduce the input length & re-start loop
            if ( status == Z_OK ) {
                inputLength -= 1024;
                if ( inputLength < 0 )
                    throw BamException("BgzfStream::DeflateBlock", "input reduction failed");
                continue;
            }

            throw BamException("BgzfStream::DeflateBlock", "zlib deflate failed");
        }

        // finalize the compression routine
        status = deflateEnd(&zs);
        if ( status != Z_OK )
            throw BamException("BgzfStream::DeflateBlock", "zlib deflateEnd failed");

        // update compressedLength
        compressedLength = zs.total_out +
                           Constants::BGZF_BLOCK_HEADER_LENGTH +
                           Constants::BGZF_BLOCK_FOOTER_LENGTH;
        if ( compressedLength > Constants::BGZF_MAX_BLOCK_SIZE )
            throw BamException("BgzfStream::DeflateBlock", "deflate overflow");

        // quit while loop
        break;
    }

    // store the compressed length
    BamTools::PackUnsignedShort(&buffer[16], static_cast<uint16_t>(compressedLength - 1));

    // store the CRC32 checksum
    uint32_t crc = crc32(0, NULL, 0);
    crc = crc32(crc, (Bytef*)m_uncompressedBlock.Buffer, inputLength);
    BamTools::PackUnsignedInt(&buffer[compressedLength - 8], crc);
    BamTools::PackUnsignedInt(&buffer[compressedLength - 4], inputLength);

    // ensure that we have less than a block of data left
    int remaining = blockLength - inputLength;
    if ( remaining > 0 ) {
        if ( remaining > inputLength )
            throw BamException("BgzfStream::DeflateBlock", "after deflate, remainder too large");
        memcpy(m_uncompressedBlock.Buffer, m_uncompressedBlock.Buffer + inputLength, remaining);
    }

    // update block data
    m_blockOffset = remaining;

    // return result
    return compressedLength;
}

// Assembly:
subq $0x348, %rsp            # imm = 0x348
movq %rdi, 0x340(%rsp)
movl %esi, 0x33c(%rsp)
movq 0x340(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0x30(%rax), %rax
movq %rax, 0x330(%rsp)
movq 0x330(%rsp), %rdi
xorl %esi, %esi
movl $0x12, %edx
callq 0x73d00
movq 0xa0(%rsp), %rax
movq 0x330(%rsp), %rcx
movb $0x1f, (%rcx)
movq 0x330(%rsp), %rcx
movb $-0x75, 0x1(%rcx)
movq 0x330(%rsp), %rcx
movb $0x8, 0x2(%rcx)
movq 0x330(%rsp), %rcx
movb $0x4, 0x3(%rcx)
movq 0x330(%rsp), %rcx
movb $-0x1, 0x9(%rcx)
movq 0x330(%rsp), %rcx
movb $0x6, 0xa(%rcx)
movq 0x330(%rsp), %rcx
movb $0x42, 0xc(%rcx)
movq 0x330(%rsp), %rcx
movb $0x43, 0xd(%rcx)
movq 0x330(%rsp), %rcx
movb $0x2, 0xe(%rcx)
movb 0x10(%rax), %dl
xorl %eax, %eax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
testb $0x1, %dl
cmovnel %ecx, %eax
movl %eax, 0x32c(%rsp)
movl 0x33c(%rsp), %eax
movl %eax, 0x328(%rsp)
movq $0x0, 0x320(%rsp)
movl $0x10000, 0x31c(%rsp) # imm = 0x10000
movq 0xa0(%rsp), %rax
movq $0x0, 0x2e8(%rsp)
movq $0x0, 0x2f0(%rsp)
movq 0x20(%rax), %rax
movq %rax, 0x2a8(%rsp)
movl 0x328(%rsp), %eax
movl %eax, 0x2b0(%rsp)
movq 0x330(%rsp), %rax
addq $0x12, %rax
movq %rax, 0x2c0(%rsp)
movl $0xffe6, 0x2c8(%rsp) # imm = 0xFFE6
movl 0x32c(%rsp), %esi
leaq 0x2a8(%rsp), %rdi
movl $0x8, %r8d
movl $0xfffffff1, %ecx       # imm = 0xFFFFFFF1
xorl %r9d, %r9d
leaq 0x1e687(%rip), %rax     # 0xebf89
movl %r8d, %edx
movq %rax, (%rsp)
movl $0x70, 0x8(%rsp)
callq 0x71480
movl %eax, 0x2a4(%rsp)
cmpl $0x0, 0x2a4(%rsp)
je 0xcda8c
movb $0x1, 0x246(%rsp)
movl $0x28, %edi
callq 0x737c0
movq %rax, 0x90(%rsp)
leaq 0x27f(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x7b5f0
movq 0x98(%rsp), %rdx
leaq 0x1e627(%rip), %rsi     # 0xebf90
leaq 0x280(%rsp), %rdi
callq 0x78e70
jmp 0xcd978
leaq 0x247(%rsp), %rdi
movq %rdi, 0x88(%rsp)
callq 0x7b5f0
movq 0x88(%rsp), %rdx
leaq 0x1e60d(%rip), %rsi     # 0xebfa9
leaq 0x248(%rsp), %rdi
callq 0x78e70
jmp 0xcd9ab
movq 0x90(%rsp), %rdi
leaq 0x280(%rsp), %rsi
leaq 0x248(%rsp), %rdx
callq 0x79cd0
jmp 0xcd9ca
movq 0x90(%rsp), %rdi
movb $0x0, 0x246(%rsp)
movq 0x4452f(%rip), %rsi     # 0x111f10
movq 0x44578(%rip), %rdx     # 0x111f60
callq 0x7b010
jmp 0xce2ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcda61
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcda43
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
leaq 0x248(%rsp), %rdi
callq 0x7cce8
jmp 0xcda41
jmp 0xcda43
leaq 0x247(%rsp), %rdi
callq 0x76f80
leaq 0x280(%rsp), %rdi
callq 0x7cce8
jmp 0xcda5f
jmp 0xcda61
leaq 0x27f(%rsp), %rdi
callq 0x76f80
testb $0x1, 0x246(%rsp)
jne 0xcda7a
jmp 0xcda87
movq 0x90(%rsp), %rdi
callq 0x74e00
jmp 0xce2d9
leaq 0x2a8(%rsp), %rdi
movl $0x4, %esi
callq 0x73500
movl %eax, 0x2a4(%rsp)
cmpl $0x1, 0x2a4(%rsp)
je 0xcdd8c
leaq 0x2a8(%rsp), %rdi
callq 0x743c0
cmpl $0x0, 0x2a4(%rsp)
jne 0xcdc43
movl 0x328(%rsp), %eax
subl $0x400, %eax            # imm = 0x400
movl %eax, 0x328(%rsp)
cmpl $0x0, 0x328(%rsp)
jge 0xcdc3e
movb $0x1, 0x1f6(%rsp)
movl $0x28, %edi
callq 0x737c0
movq %rax, 0x78(%rsp)
leaq 0x21f(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x7b5f0
movq 0x80(%rsp), %rdx
leaq 0x1e466(%rip), %rsi     # 0xebf90
leaq 0x220(%rsp), %rdi
callq 0x78e70
jmp 0xcdb39
leaq 0x1f7(%rsp), %rdi
movq %rdi, 0x70(%rsp)
callq 0x7b5f0
movq 0x70(%rsp), %rdx
leaq 0x1e46b(%rip), %rsi     # 0xebfc2
leaq 0x1f8(%rsp), %rdi
callq 0x78e70
jmp 0xcdb66
movq 0x78(%rsp), %rdi
leaq 0x220(%rsp), %rsi
leaq 0x1f8(%rsp), %rdx
callq 0x79cd0
jmp 0xcdb82
movq 0x78(%rsp), %rdi
movb $0x0, 0x1f6(%rsp)
movq 0x4437a(%rip), %rsi     # 0x111f10
movq 0x443c3(%rip), %rdx     # 0x111f60
callq 0x7b010
jmp 0xce2ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcdc16
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcdbf8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
leaq 0x1f8(%rsp), %rdi
callq 0x7cce8
jmp 0xcdbf6
jmp 0xcdbf8
leaq 0x1f7(%rsp), %rdi
callq 0x76f80
leaq 0x220(%rsp), %rdi
callq 0x7cce8
jmp 0xcdc14
jmp 0xcdc16
leaq 0x21f(%rsp), %rdi
callq 0x76f80
testb $0x1, 0x1f6(%rsp)
jne 0xcdc2f
jmp 0xcdc39
movq 0x78(%rsp), %rdi
callq 0x74e00
jmp 0xce2d9
jmp 0xcd885
movb $0x1, 0x1a6(%rsp)
movl $0x28, %edi
callq 0x737c0
movq %rax, 0x60(%rsp)
leaq 0x1cf(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x7b5f0
movq 0x68(%rsp), %rdx
leaq 0x1e318(%rip), %rsi     # 0xebf90
leaq 0x1d0(%rsp), %rdi
callq 0x78e70
jmp 0xcdc87
leaq 0x1a7(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x7b5f0
movq 0x58(%rsp), %rdx
leaq 0x1e334(%rip), %rsi     # 0xebfd9
leaq 0x1a8(%rsp), %rdi
callq 0x78e70
jmp 0xcdcb4
movq 0x60(%rsp), %rdi
leaq 0x1d0(%rsp), %rsi
leaq 0x1a8(%rsp), %rdx
callq 0x79cd0
jmp 0xcdcd0
movq 0x60(%rsp), %rdi
movb $0x0, 0x1a6(%rsp)
movq 0x4422c(%rip), %rsi     # 0x111f10
movq 0x44275(%rip), %rdx     # 0x111f60
callq 0x7b010
jmp 0xce2ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcdd64
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcdd46
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
leaq 0x1a8(%rsp), %rdi
callq 0x7cce8
jmp 0xcdd44
jmp 0xcdd46
leaq 0x1a7(%rsp), %rdi
callq 0x76f80
leaq 0x1d0(%rsp), %rdi
callq 0x7cce8
jmp 0xcdd62
jmp 0xcdd64
leaq 0x1cf(%rsp), %rdi
callq 0x76f80
testb $0x1, 0x1a6(%rsp)
jne 0xcdd7d
jmp 0xcdd87
movq 0x60(%rsp), %rdi
callq 0x74e00
jmp 0xce2d9
leaq 0x2a8(%rsp), %rdi
callq 0x743c0
movl %eax, 0x2a4(%rsp)
cmpl $0x0, 0x2a4(%rsp)
je 0xcdef7
movb $0x1, 0x156(%rsp)
movl $0x28, %edi
callq 0x737c0
movq %rax, 0x48(%rsp)
leaq 0x17f(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x7b5f0
movq 0x50(%rsp), %rdx
leaq 0x1e1ad(%rip), %rsi     # 0xebf90
leaq 0x180(%rsp), %rdi
callq 0x78e70
jmp 0xcddf2
leaq 0x157(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x7b5f0
movq 0x40(%rsp), %rdx
leaq 0x1e1dd(%rip), %rsi     # 0xebfed
leaq 0x158(%rsp), %rdi
callq 0x78e70
jmp 0xcde1f
movq 0x48(%rsp), %rdi
leaq 0x180(%rsp), %rsi
leaq 0x158(%rsp), %rdx
callq 0x79cd0
jmp 0xcde3b
movq 0x48(%rsp), %rdi
movb $0x0, 0x156(%rsp)
movq 0x440c1(%rip), %rsi     # 0x111f10
movq 0x4410a(%rip), %rdx     # 0x111f60
callq 0x7b010
jmp 0xce2ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcdecf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xcdeb1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x7cce8
jmp 0xcdeaf
jmp 0xcdeb1
leaq 0x157(%rsp), %rdi
callq 0x76f80
leaq 0x180(%rsp), %rdi
callq 0x7cce8
jmp 0xcdecd
jmp 0xcdecf
leaq 0x17f(%rsp), %rdi
callq 0x76f80
testb $0x1, 0x156(%rsp)
jne 0xcdee8
jmp 0xcdef2
movq 0x48(%rsp), %rdi
callq 0x74e00
jmp 0xce2d9
movq 0x2d0(%rsp), %rax
addq $0x12, %rax
addq $0x8, %rax
movq %rax, 0x320(%rsp)
cmpq $0x10000, 0x320(%rsp) # imm = 0x10000
jbe 0xce06a
movb $0x1, 0x106(%rsp)
movl $0x28, %edi
callq 0x737c0
movq %rax, 0x30(%rsp)
leaq 0x12f(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x7b5f0
movq 0x38(%rsp), %rdx
leaq 0x1e03a(%rip), %rsi     # 0xebf90
leaq 0x130(%rsp), %rdi
callq 0x78e70
jmp 0xcdf65
leaq 0x107(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x7b5f0
movq 0x28(%rsp), %rdx
leaq 0x1e081(%rip), %rsi     # 0xec004
leaq 0x108(%rsp), %rdi
callq 0x78e70
jmp 0xcdf92
movq 0x30(%rsp), %rdi
leaq 0x130(%rsp), %rsi
leaq 0x108(%rsp), %rdx
callq 0x79cd0
jmp 0xcdfae
movq 0x30(%rsp), %rdi
movb $0x0, 0x106(%rsp)
movq 0x43f4e(%rip), %rsi     # 0x111f10
movq 0x43f97(%rip), %rdx     # 0x111f60
callq 0x7b010
jmp 0xce2ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xce042
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xce024
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x7cce8
jmp 0xce022
jmp 0xce024
leaq 0x107(%rsp), %rdi
callq 0x76f80
leaq 0x130(%rsp), %rdi
callq 0x7cce8
jmp 0xce040
jmp 0xce042
leaq 0x12f(%rsp), %rdi
callq 0x76f80
testb $0x1, 0x106(%rsp)
jne 0xce05b
jmp 0xce065
movq 0x30(%rsp), %rdi
callq 0x74e00
jmp 0xce2d9
jmp 0xce06c
movq 0x330(%rsp), %rdi
addq $0x10, %rdi
movq 0x320(%rsp), %rax
subq $0x1, %rax
movzwl %ax, %esi
callq 0x78b10
xorl %eax, %eax
movl %eax, %esi
xorl %edx, %edx
movq %rsi, %rdi
callq 0x74d80
movq %rax, %rcx
movq 0xa0(%rsp), %rax
movl %ecx, 0x100(%rsp)
movl 0x100(%rsp), %ecx
movl %ecx, %edi
movq 0x20(%rax), %rsi
movl 0x328(%rsp), %edx
callq 0x74d80
movl %eax, 0x100(%rsp)
movq 0x330(%rsp), %rdi
movq 0x320(%rsp), %rax
subq $0x8, %rax
addq %rax, %rdi
movl 0x100(%rsp), %esi
callq 0x7c5b0
movq 0x330(%rsp), %rdi
movq 0x320(%rsp), %rax
subq $0x4, %rax
addq %rax, %rdi
movl 0x328(%rsp), %esi
callq 0x7c5b0
movl 0x33c(%rsp), %eax
subl 0x328(%rsp), %eax
movl %eax, 0xfc(%rsp)
cmpl $0x0, 0xfc(%rsp)
jle 0xce2b7
movl 0xfc(%rsp), %eax
cmpl 0x328(%rsp), %eax
jle 0xce28f
movb $0x1, 0xae(%rsp)
movl $0x28, %edi
callq 0x737c0
movq %rax, 0x18(%rsp)
leaq 0xd7(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x7b5f0
movq 0x20(%rsp), %rdx
leaq 0x1de12(%rip), %rsi     # 0xebf90
leaq 0xd8(%rsp), %rdi
callq 0x78e70
jmp 0xce18d
leaq 0xaf(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x7b5f0
movq 0x10(%rsp), %rdx
leaq 0x1de6a(%rip), %rsi     # 0xec015
leaq 0xb0(%rsp), %rdi
callq 0x78e70
jmp 0xce1ba
movq 0x18(%rsp), %rdi
leaq 0xd8(%rsp), %rsi
leaq 0xb0(%rsp), %rdx
callq 0x79cd0
jmp 0xce1d6
movq 0x18(%rsp), %rdi
movb $0x0, 0xae(%rsp)
movq 0x43d26(%rip), %rsi     # 0x111f10
movq 0x43d6f(%rip), %rdx     # 0x111f60
callq 0x7b010
jmp 0xce2ee
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xce26a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
jmp 0xce24c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x270(%rsp)
movl %eax, 0x26c(%rsp)
leaq 0xb0(%rsp), %rdi
callq 0x7cce8
jmp 0xce24a
jmp 0xce24c
leaq 0xaf(%rsp), %rdi
callq 0x76f80
leaq 0xd8(%rsp), %rdi
callq 0x7cce8
jmp 0xce268
jmp 0xce26a
leaq 0xd7(%rsp), %rdi
callq 0x76f80
testb $0x1, 0xae(%rsp)
jne 0xce283
jmp 0xce28d
movq 0x18(%rsp), %rdi
callq 0x74e00
jmp 0xce2d9
movq 0xa0(%rsp), %rax
movq 0x20(%rax), %rdi
movq 0x20(%rax), %rsi
movslq 0x328(%rsp), %rax
addq %rax, %rsi
movslq 0xfc(%rsp), %rdx
callq 0x757c0
movq 0xa0(%rsp), %rax
movl 0xfc(%rsp), %ecx
movl %ecx, 0x4(%rax)
movq 0x320(%rsp), %rax
addq $0x348, %rsp            # imm = 0x348
retq
movq 0x270(%rsp), %rdi
callq 0x7b550
movq %rax, %rdi
callq 0x88ef0
nop