// File: /workspace/github_cpp_makefile_star2_O1/statgen[P]statgen/lib/samtools-0.1.7a-hybrid/bgzf.c
// Function: deflate_block
static
int
deflate_block(BGZF* fp, int block_length)
{
    // Deflate the block in fp->uncompressed_block into fp->compressed_block.
    // Also adds an extra field that stores the compressed block length.

    bgzf_byte_t* buffer = fp->compressed_block;
    int buffer_size = fp->compressed_block_size;

    // Init gzip header
    buffer[0] = GZIP_ID1;
    buffer[1] = GZIP_ID2;
    buffer[2] = CM_DEFLATE;
    buffer[3] = FLG_FEXTRA;
    buffer[4] = 0; // mtime
    buffer[5] = 0;
    buffer[6] = 0;
    buffer[7] = 0;
    buffer[8] = 0;
    buffer[9] = OS_UNKNOWN;
    buffer[10] = BGZF_XLEN;
    buffer[11] = 0;
    buffer[12] = BGZF_ID1;
    buffer[13] = BGZF_ID2;
    buffer[14] = BGZF_LEN;
    buffer[15] = 0;
    buffer[16] = 0; // placeholder for block length
    buffer[17] = 0;

    // loop to retry for blocks that do not compress enough
    int input_length = block_length;
    int compressed_length = 0;
    while (1) {
		int compress_level = fp->is_uncompressed? 0 : Z_DEFAULT_COMPRESSION;
        z_stream zs;
        zs.zalloc = NULL;
        zs.zfree = NULL;
        zs.next_in = fp->uncompressed_block;
        zs.avail_in = input_length;
        zs.next_out = (void*)&buffer[BLOCK_HEADER_LENGTH];
        zs.avail_out = buffer_size - BLOCK_HEADER_LENGTH - BLOCK_FOOTER_LENGTH;

        int status = deflateInit2(&zs, compress_level, Z_DEFLATED,
                                  GZIP_WINDOW_BITS, Z_DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY);
        if (status != Z_OK) {
            report_error(fp, "deflate init failed");
            return -1;
        }
        status = deflate(&zs, Z_FINISH);
        if (status != Z_STREAM_END) {
            deflateEnd(&zs);
            if (status == Z_OK) {
                // Not enough space in buffer.
                // Can happen in the rare case the input doesn't compress enough.
                // Reduce the amount of input until it fits.
                input_length -= 1024;
                if (input_length <= 0) {
                    // should never happen
                    report_error(fp, "input reduction failed");
                    return -1;
                }
                continue;
            }
            report_error(fp, "deflate failed");
            return -1;
        }
        status = deflateEnd(&zs);
        if (status != Z_OK) {
            report_error(fp, "deflate end failed");
            return -1;
        }
        compressed_length = zs.total_out;
        compressed_length += BLOCK_HEADER_LENGTH + BLOCK_FOOTER_LENGTH;
        if (compressed_length > MAX_BLOCK_SIZE) {
            // should never happen
            report_error(fp, "deflate overflow");
            return -1;
        }
        break;
    }

    packInt16((uint8_t*)&buffer[16], compressed_length-1);
    uint32_t crc = crc32(0L, NULL, 0L);
    crc = crc32(crc, fp->uncompressed_block, input_length);
    packInt32((uint8_t*)&buffer[compressed_length-8], crc);
    packInt32((uint8_t*)&buffer[compressed_length-4], input_length);

    int remaining = block_length - input_length;
    if (remaining > 0) {
        if (remaining > input_length) {
            // should never happen (check so we can use memcpy)
            report_error(fp, "remainder too large");
            return -1;
        }
        memcpy(fp->uncompressed_block,
               fp->uncompressed_block + input_length,
               remaining);
    }
    fp->block_offset = remaining;
    return compressed_length;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rdi, %r13
movq 0x20(%rdi), %rdx
movl 0x14(%rdi), %r9d
movq $0x4088b1f, (%rdx)      # imm = 0x4088B1F
xorl %ecx, %ecx
movb %cl, 0x8(%rdx)
movabsq $0x243420006ff, %rax    # imm = 0x243420006FF
movq %rax, 0x9(%rdx)
movq $0x0, 0x28(%rsp)
movb %cl, 0x11(%rdx)
leaq 0x78(%rsp), %r12
movq %rdx, 0x30(%rsp)
leaq 0x12(%rdx), %rbp
addl $-0x1a, %r9d
leaq 0x15f39(%rip), %r15     # 0x2617c
leaq 0x38(%rsp), %rbx
movl %esi, 0x24(%rsp)
movl %esi, %edx
movq %rdi, 0x10(%rsp)
movl %r9d, 0xc(%rsp)
movzbl 0x6(%r13), %esi
xorl $0x1, %esi
negl %esi
xorps %xmm0, %xmm0
movups %xmm0, (%r12)
movq 0x18(%r13), %rax
movq %rax, 0x38(%rsp)
movq %rdx, 0x18(%rsp)
movl %edx, 0x40(%rsp)
movq %rbp, 0x50(%rsp)
movl %r9d, 0x58(%rsp)
movq %rbx, %rdi
movl $0x8, %edx
movl $0xfffffff1, %ecx       # imm = 0xFFFFFFF1
movl $0x8, %r8d
movl %r9d, %r14d
xorl %r9d, %r9d
pushq $0x70
pushq %r15
callq 0x3520
addq $0x10, %rsp
testl %eax, %eax
je 0x102cd
leaq 0x15eef(%rip), %rax     # 0x261a6
movq %rax, 0x40(%r13)
movl $0x1, %eax
movq 0x18(%rsp), %rdx
movl %r14d, %r9d
jmp 0x1035c
movq %rbx, %rdi
movl $0x4, %esi
callq 0x3180
movl %eax, %r13d
movq %rbx, %rdi
callq 0x32f0
cmpl $0x1, %r13d
je 0x1032b
testl %r13d, %r13d
movq 0x18(%rsp), %rdx
movq 0x10(%rsp), %r13
jne 0x10342
leal -0x400(%rdx), %ecx
movl $0x2, %eax
cmpl $0x400, %edx            # imm = 0x400
leaq 0x38(%rsp), %rbx
jg 0x10322
leaq 0x15ea1(%rip), %rax     # 0x261ba
movq %rax, 0x40(%r13)
movl $0x1, %eax
movl %ecx, %edx
movl 0xc(%rsp), %r9d
jmp 0x1035c
testl %eax, %eax
movq 0x18(%rsp), %rdx
movq 0x10(%rsp), %r13
je 0x10367
leaq 0x15ea0(%rip), %rax     # 0x261e0
jmp 0x10349
leaq 0x15e88(%rip), %rax     # 0x261d1
movq %rax, 0x40(%r13)
movl $0x1, %eax
movl 0xc(%rsp), %r9d
leaq 0x38(%rsp), %rbx
cmpl $0x2, %eax
je 0x10258
jmp 0x10397
movl 0x60(%rsp), %ecx
leal 0x1a(%rcx), %eax
movq %rax, 0x28(%rsp)
movl $0x3, %eax
cmpl $0xffe7, %ecx           # imm = 0xFFE7
leaq 0x38(%rsp), %rbx
jl 0x10324
leaq 0x15e67(%rip), %rax     # 0x261f3
movq %rax, 0x40(%r13)
movl $0x1, %eax
jmp 0x10324
cmpl $0x3, %eax
jne 0x1041a
movq 0x28(%rsp), %r15
leal -0x1(%r15), %eax
movq 0x30(%rsp), %rbp
movw %ax, 0x10(%rbp)
xorl %edi, %edi
xorl %esi, %esi
movq %rdx, %rbx
xorl %edx, %edx
callq 0x32e0
movl %eax, %edi
movq 0x18(%r13), %rsi
movl %ebx, %edx
callq 0x32e0
movslq %r15d, %rcx
movb %al, -0x8(%rbp,%rcx)
movb %ah, -0x7(%rbp,%rcx)
movl %eax, %edx
shrl $0x10, %edx
movb %dl, -0x6(%rbp,%rcx)
shrl $0x18, %eax
movb %al, -0x5(%rbp,%rcx)
movb %bl, -0x4(%rbp,%rcx)
movb %bh, -0x3(%rbp,%rcx)
movl %ebx, %eax
shrl $0x10, %eax
movb %al, -0x2(%rbp,%rcx)
movl %ebx, %eax
shrl $0x18, %eax
movb %al, -0x1(%rbp,%rcx)
movl 0x24(%rsp), %ebp
subl %ebx, %ebp
jle 0x10437
cmpl %ebx, %ebp
jle 0x10422
leaq 0x15df3(%rip), %rax     # 0x26204
movq 0x10(%rsp), %rcx
movq %rax, 0x40(%rcx)
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
jmp 0x1043b
movq 0x10(%rsp), %r13
movq 0x18(%r13), %rdi
movl %ebx, %esi
addq %rdi, %rsi
movl %ebp, %edx
callq 0x3680
movl %ebp, 0x34(%r13)
movl %r15d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq