// File: /workspace/github_c_makefile_star2_O2/genometools[P]genometools/src/external/samtools-0.1.18/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) {
        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, fp->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 $0x88, %rsp
movq %rdi, %rbp
movq 0x28(%rdi), %rcx
movl 0x1c(%rdi), %r15d
movq $0x4088b1f, (%rcx)      # imm = 0x4088B1F
xorl %r14d, %r14d
movb %r14b, 0x8(%rcx)
movabsq $0x243420006ff, %rax    # imm = 0x243420006FF
movq %rax, 0x9(%rcx)
movb %r14b, 0x11(%rcx)
movq %rcx, 0x8(%rsp)
leaq 0x12(%rcx), %rax
movq %rax, 0x10(%rsp)
addl $-0x1a, %r15d
movl %esi, %ebx
leaq 0x18(%rsp), %r12
leaq 0x58(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movq 0x20(%rbp), %rax
movq %rax, 0x18(%rsp)
movl %ebx, 0x20(%rsp)
movq 0x10(%rsp), %rax
movq %rax, 0x30(%rsp)
movl %r15d, 0x38(%rsp)
movswl 0x8(%rbp), %esi
movq %r12, %rdi
pushq $0x8
popq %rdx
pushq $-0xf
popq %rcx
movl %edx, %r8d
xorl %r9d, %r9d
pushq $0x70
leaq 0x980ed(%rip), %rax     # 0x36ebf4
pushq %rax
callq 0x21766a
addq $0x10, %rsp
testl %eax, %eax
jne 0x2d6b6b
movq %rbp, %r13
movq %r12, %rdi
pushq $0x4
popq %rsi
callq 0x21822a
movl %eax, %ebp
movq %r12, %rdi
callq 0x21791e
testl %ebp, %ebp
jne 0x2d6b4f
cmpl $0x401, %ebx            # imm = 0x401
jl 0x2d6b74
addq $-0x400, %rbx           # imm = 0xFC00
addq $0x400, %r14            # imm = 0x400
movq %r13, %rbp
jmp 0x2d6ac4
cmpl $0x1, %ebp
movq %r13, %rbp
leaq 0xb0c8d(%rip), %rcx     # 0x3877e9
jne 0x2d6b7e
testl %eax, %eax
je 0x2d6b99
leaq 0xb0c8f(%rip), %rcx     # 0x3877f8
jmp 0x2d6b7e
leaq 0xb0c4c(%rip), %rcx     # 0x3877be
jmp 0x2d6b7e
leaq 0xb0c57(%rip), %rcx     # 0x3877d2
movq %r13, %rbp
movq %rcx, 0x48(%rbp)
pushq $-0x1
popq %rbp
movl %ebp, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movslq 0x40(%rsp), %rbp
cmpq $0xffe7, %rbp           # imm = 0xFFE7
jl 0x2d6bb0
leaq 0xb0c5d(%rip), %rcx     # 0x38780b
jmp 0x2d6b7b
addq $0x1a, %rbp
leal -0x1(%rbp), %eax
movq 0x8(%rsp), %r12
movw %ax, 0x10(%r12)
xorl %edi, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2de315
movl %eax, %edi
movq %r13, %r15
movq 0x20(%r13), %rsi
movl %ebx, %edx
callq 0x2de315
movq %r12, %rdx
movb %al, -0x8(%r12,%rbp)
movb %ah, -0x7(%rdx,%rbp)
movl %eax, %ecx
shrl $0x10, %ecx
movb %cl, -0x6(%r12,%rbp)
shrl $0x18, %eax
movb %al, -0x5(%r12,%rbp)
movb %bl, -0x4(%r12,%rbp)
movb %bh, -0x3(%rdx,%rbp)
movl %ebx, %eax
shrl $0x10, %eax
movb %al, -0x2(%r12,%rbp)
movl %ebx, %eax
shrl $0x18, %eax
movb %al, -0x1(%r12,%rbp)
testl %r14d, %r14d
jle 0x2d6c47
cmpl %ebx, %r14d
jle 0x2d6c32
leaq 0xb0bf3(%rip), %rax     # 0x38781c
movq %rax, 0x48(%r13)
jmp 0x2d6b82
movq %r13, %r15
movq 0x20(%r13), %rdi
addq %rdi, %rbx
movq %rbx, %rsi
movq %r14, %rdx
callq 0x17630
movl %r14d, 0x3c(%r15)
jmp 0x2d6b85