// File: /workspace/github_c_makefile_star2_O3/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, %r15
movq 0x28(%rdi), %rcx
movl 0x1c(%rdi), %r13d
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, %r13d
movl %esi, %ebx
leaq 0x18(%rsp), %r12
leaq 0x58(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movq 0x20(%r15), %rax
movq %rax, 0x18(%rsp)
movl %ebx, 0x20(%rsp)
movq 0x10(%rsp), %rax
movq %rax, 0x30(%rsp)
movl %r13d, 0x38(%rsp)
movswl 0x8(%r15), %esi
movq %r12, %rdi
movl $0x8, %edx
movl $0xfffffff1, %ecx       # imm = 0xFFFFFFF1
movl $0x8, %r8d
xorl %r9d, %r9d
pushq $0x70
leaq 0x9a1e7(%rip), %rax     # 0x3ce7b8
pushq %rax
callq 0x269ccf
addq $0x10, %rsp
testl %eax, %eax
jne 0x33462e
movq %r12, %rdi
movl $0x4, %esi
callq 0x26a93b
movl %eax, %ebp
movq %r12, %rdi
callq 0x269fa2
testl %ebp, %ebp
jne 0x334615
cmpl $0x401, %ebx            # imm = 0x401
jl 0x334637
addq $-0x400, %rbx           # imm = 0xFC00
addq $0x400, %r14            # imm = 0x400
jmp 0x334586
cmpl $0x1, %ebp
leaq 0xb2eda(%rip), %rcx     # 0x3e74f9
jne 0x33463e
testl %eax, %eax
je 0x33465b
leaq 0xb2edc(%rip), %rcx     # 0x3e7508
jmp 0x33463e
leaq 0xb2e99(%rip), %rcx     # 0x3e74ce
jmp 0x33463e
leaq 0xb2ea4(%rip), %rcx     # 0x3e74e2
movq %rcx, 0x48(%r15)
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
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 0x334672
leaq 0xb2eab(%rip), %rcx     # 0x3e751b
jmp 0x33463e
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 0x33f5af
movl %eax, %edi
movq 0x20(%r15), %rsi
movl %ebx, %edx
callq 0x33f5af
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 0x334703
cmpl %ebx, %r14d
jle 0x3346f1
leaq 0xb2e44(%rip), %rax     # 0x3e752c
movq %rax, 0x48(%r15)
jmp 0x334642
movq 0x20(%r15), %rdi
addq %rdi, %rbx
movq %rbx, %rsi
movq %r14, %rdx
callq 0x17660
movl %r14d, 0x3c(%r15)
jmp 0x334647